hass-core/tests/components/lovelace/test_init.py
Bram Kragten 33860bf23c Adding id to lovelace cards in ui-lovelace.yaml (#17498)
* ID is added to cards without ID in ui-lovelace.yaml when loaded

* Hound

* Remove ui-lovelace.yaml

* Nicer get

* Update tests

* If YAML dump fails, config not gone

* Add tests

* Woof!

* Remove nosetests

* Address comments

* Woof...

* Delete test.yaml

* update rights to saved file

* fix

* line break
2018-10-17 16:31:06 +02:00

274 lines
8.5 KiB
Python

"""Test the Lovelace initialization."""
import os
import unittest
from unittest.mock import patch
from tempfile import mkdtemp
from ruamel.yaml import YAML
from homeassistant.exceptions import HomeAssistantError
from homeassistant.setup import async_setup_component
from homeassistant.components.websocket_api.const import TYPE_RESULT
from homeassistant.components.lovelace import (load_yaml,
save_yaml, load_config)
TEST_YAML_A = """\
title: My Awesome Home
# Include external resources
resources:
- url: /local/my-custom-card.js
type: js
- url: /local/my-webfont.css
type: css
# Exclude entities from "Unused entities" view
excluded_entities:
- weblink.router
views:
# View tab title.
- title: Example
# Optional unique id for direct access /lovelace/${id}
id: example
# Optional background (overwrites the global background).
background: radial-gradient(crimson, skyblue)
# Each view can have a different theme applied.
theme: dark-mode
# The cards to show on this view.
cards:
# The filter card will filter entities for their state
- type: entity-filter
entities:
- device_tracker.paulus
- device_tracker.anne_there
state_filter:
- 'home'
card:
type: glance
title: People that are home
# The picture entity card will represent an entity with a picture
- type: picture-entity
image: https://www.home-assistant.io/images/default-social.png
entity: light.bed_light
# Specify a tab icon if you want the view tab to be an icon.
- icon: mdi:home-assistant
# Title of the view. Will be used as the tooltip for tab icon
title: Second view
cards:
# Entities card will take a list of entities and show their state.
- type: entities
# Title of the entities card
title: Example
# The entities here will be shown in the same order as specified.
# Each entry is an entity ID or a map with extra options.
entities:
- light.kitchen
- switch.ac
- entity: light.living_room
# Override the name to use
name: LR Lights
# The markdown card will render markdown text.
- type: markdown
title: Lovelace
content: >
Welcome to your **Lovelace UI**.
"""
TEST_YAML_B = """\
title: Home
views:
- title: Dashboard
icon: mdi:home
cards:
- id: testid
type: vertical-stack
cards:
- type: picture-entity
entity: group.sample
name: Sample
image: /local/images/sample.jpg
tap_action: toggle
"""
# Test data that can not be loaded as YAML
TEST_BAD_YAML = """\
title: Home
views:
- title: Dashboard
icon: mdi:home
cards:
- id: testid
type: vertical-stack
"""
class TestYAML(unittest.TestCase):
"""Test lovelace.yaml save and load."""
def setUp(self):
"""Set up for tests."""
self.tmp_dir = mkdtemp()
self.yaml = YAML(typ='rt')
def tearDown(self):
"""Clean up after tests."""
for fname in os.listdir(self.tmp_dir):
os.remove(os.path.join(self.tmp_dir, fname))
os.rmdir(self.tmp_dir)
def _path_for(self, leaf_name):
return os.path.join(self.tmp_dir, leaf_name+".yaml")
def test_save_and_load(self):
"""Test saving and loading back."""
fname = self._path_for("test1")
save_yaml(fname, self.yaml.load(TEST_YAML_A))
data = load_yaml(fname)
self.assertEqual(data, self.yaml.load(TEST_YAML_A))
def test_overwrite_and_reload(self):
"""Test that we can overwrite an existing file and read back."""
fname = self._path_for("test3")
save_yaml(fname, self.yaml.load(TEST_YAML_A))
save_yaml(fname, self.yaml.load(TEST_YAML_B))
data = load_yaml(fname)
self.assertEqual(data, self.yaml.load(TEST_YAML_B))
def test_load_bad_data(self):
"""Test error from trying to load unserialisable data."""
fname = self._path_for("test5")
with open(fname, "w") as fh:
fh.write(TEST_BAD_YAML)
with self.assertRaises(HomeAssistantError):
load_yaml(fname)
def test_add_id(self):
"""Test if id is added."""
fname = self._path_for("test6")
with patch('homeassistant.components.lovelace.load_yaml',
return_value=self.yaml.load(TEST_YAML_A)):
data = load_config(fname)
assert 'id' in data['views'][0]['cards'][0]
def test_id_not_changed(self):
"""Test if id is not changed if already exists."""
fname = self._path_for("test7")
with patch('homeassistant.components.lovelace.load_yaml',
return_value=self.yaml.load(TEST_YAML_B)):
data = load_config(fname)
self.assertEqual(data, self.yaml.load(TEST_YAML_B))
async def test_deprecated_lovelace_ui(hass, hass_ws_client):
"""Test lovelace_ui command."""
await async_setup_component(hass, 'lovelace')
client = await hass_ws_client(hass)
with patch('homeassistant.components.lovelace.load_config',
return_value={'hello': 'world'}):
await client.send_json({
'id': 5,
'type': 'frontend/lovelace_config',
})
msg = await client.receive_json()
assert msg['id'] == 5
assert msg['type'] == TYPE_RESULT
assert msg['success']
assert msg['result'] == {'hello': 'world'}
async def test_deprecated_lovelace_ui_not_found(hass, hass_ws_client):
"""Test lovelace_ui command cannot find file."""
await async_setup_component(hass, 'lovelace')
client = await hass_ws_client(hass)
with patch('homeassistant.components.lovelace.load_config',
side_effect=FileNotFoundError):
await client.send_json({
'id': 5,
'type': 'frontend/lovelace_config',
})
msg = await client.receive_json()
assert msg['id'] == 5
assert msg['type'] == TYPE_RESULT
assert msg['success'] is False
assert msg['error']['code'] == 'file_not_found'
async def test_deprecated_lovelace_ui_load_err(hass, hass_ws_client):
"""Test lovelace_ui command cannot find file."""
await async_setup_component(hass, 'lovelace')
client = await hass_ws_client(hass)
with patch('homeassistant.components.lovelace.load_config',
side_effect=HomeAssistantError):
await client.send_json({
'id': 5,
'type': 'frontend/lovelace_config',
})
msg = await client.receive_json()
assert msg['id'] == 5
assert msg['type'] == TYPE_RESULT
assert msg['success'] is False
assert msg['error']['code'] == 'load_error'
async def test_lovelace_ui(hass, hass_ws_client):
"""Test lovelace_ui command."""
await async_setup_component(hass, 'lovelace')
client = await hass_ws_client(hass)
with patch('homeassistant.components.lovelace.load_config',
return_value={'hello': 'world'}):
await client.send_json({
'id': 5,
'type': 'lovelace/config',
})
msg = await client.receive_json()
assert msg['id'] == 5
assert msg['type'] == TYPE_RESULT
assert msg['success']
assert msg['result'] == {'hello': 'world'}
async def test_lovelace_ui_not_found(hass, hass_ws_client):
"""Test lovelace_ui command cannot find file."""
await async_setup_component(hass, 'lovelace')
client = await hass_ws_client(hass)
with patch('homeassistant.components.lovelace.load_config',
side_effect=FileNotFoundError):
await client.send_json({
'id': 5,
'type': 'lovelace/config',
})
msg = await client.receive_json()
assert msg['id'] == 5
assert msg['type'] == TYPE_RESULT
assert msg['success'] is False
assert msg['error']['code'] == 'file_not_found'
async def test_lovelace_ui_load_err(hass, hass_ws_client):
"""Test lovelace_ui command cannot find file."""
await async_setup_component(hass, 'lovelace')
client = await hass_ws_client(hass)
with patch('homeassistant.components.lovelace.load_config',
side_effect=HomeAssistantError):
await client.send_json({
'id': 5,
'type': 'lovelace/config',
})
msg = await client.receive_json()
assert msg['id'] == 5
assert msg['type'] == TYPE_RESULT
assert msg['success'] is False
assert msg['error']['code'] == 'load_error'