Extract Collection helper from Person integration (#30313)

* Add CRUD foundation

* Use collection helper in person integration

* Lint/pytest

* Add tests

* Lint

* Create notification
This commit is contained in:
Paulus Schoutsen 2020-01-03 21:37:11 +01:00 committed by GitHub
parent 3033dbd86c
commit b9aba30a6e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 1074 additions and 396 deletions

View file

@ -1,19 +1,15 @@
"""The tests for the person component."""
from unittest.mock import Mock
import logging
import pytest
from homeassistant.components import person
from homeassistant.components.device_tracker import (
ATTR_SOURCE_TYPE,
SOURCE_TYPE_GPS,
SOURCE_TYPE_ROUTER,
)
from homeassistant.components.person import (
ATTR_SOURCE,
ATTR_USER_ID,
DOMAIN,
PersonManager,
)
from homeassistant.components.person import ATTR_SOURCE, ATTR_USER_ID, DOMAIN
from homeassistant.const import (
ATTR_GPS_ACCURACY,
ATTR_ID,
@ -23,20 +19,29 @@ from homeassistant.const import (
STATE_UNKNOWN,
)
from homeassistant.core import CoreState, State
from homeassistant.helpers import collection
from homeassistant.setup import async_setup_component
from tests.common import (
assert_setup_component,
mock_component,
mock_coro_func,
mock_restore_cache,
)
from tests.common import assert_setup_component, mock_component, mock_restore_cache
DEVICE_TRACKER = "device_tracker.test_tracker"
DEVICE_TRACKER_2 = "device_tracker.test_tracker_2"
# pylint: disable=redefined-outer-name
@pytest.fixture
def storage_collection(hass):
"""Return an empty storage collection."""
id_manager = collection.IDManager()
return person.PersonStorageCollection(
person.PersonStore(hass, person.STORAGE_VERSION, person.STORAGE_KEY),
logging.getLogger(f"{person.__name__}.storage_collection"),
id_manager,
collection.YamlCollection(
logging.getLogger(f"{person.__name__}.yaml_collection"), id_manager
),
)
@pytest.fixture
def storage_setup(hass, hass_storage, hass_admin_user):
"""Storage setup."""
@ -433,21 +438,21 @@ async def test_load_person_storage_two_nonlinked(hass, hass_storage):
async def test_ws_list(hass, hass_ws_client, storage_setup):
"""Test listing via WS."""
manager = hass.data[DOMAIN]
manager = hass.data[DOMAIN][1]
client = await hass_ws_client(hass)
resp = await client.send_json({"id": 6, "type": "person/list"})
resp = await client.receive_json()
assert resp["success"]
assert resp["result"]["storage"] == manager.storage_persons
assert resp["result"]["storage"] == manager.async_items()
assert len(resp["result"]["storage"]) == 1
assert len(resp["result"]["config"]) == 0
async def test_ws_create(hass, hass_ws_client, storage_setup, hass_read_only_user):
"""Test creating via WS."""
manager = hass.data[DOMAIN]
manager = hass.data[DOMAIN][1]
client = await hass_ws_client(hass)
@ -462,7 +467,7 @@ async def test_ws_create(hass, hass_ws_client, storage_setup, hass_read_only_use
)
resp = await client.receive_json()
persons = manager.storage_persons
persons = manager.async_items()
assert len(persons) == 2
assert resp["success"]
@ -474,7 +479,7 @@ async def test_ws_create_requires_admin(
):
"""Test creating via WS requires admin."""
hass_admin_user.groups = []
manager = hass.data[DOMAIN]
manager = hass.data[DOMAIN][1]
client = await hass_ws_client(hass)
@ -489,7 +494,7 @@ async def test_ws_create_requires_admin(
)
resp = await client.receive_json()
persons = manager.storage_persons
persons = manager.async_items()
assert len(persons) == 1
assert not resp["success"]
@ -497,10 +502,10 @@ async def test_ws_create_requires_admin(
async def test_ws_update(hass, hass_ws_client, storage_setup):
"""Test updating via WS."""
manager = hass.data[DOMAIN]
manager = hass.data[DOMAIN][1]
client = await hass_ws_client(hass)
persons = manager.storage_persons
persons = manager.async_items()
resp = await client.send_json(
{
@ -514,7 +519,7 @@ async def test_ws_update(hass, hass_ws_client, storage_setup):
)
resp = await client.receive_json()
persons = manager.storage_persons
persons = manager.async_items()
assert len(persons) == 1
assert resp["success"]
@ -533,10 +538,10 @@ async def test_ws_update_require_admin(
):
"""Test updating via WS requires admin."""
hass_admin_user.groups = []
manager = hass.data[DOMAIN]
manager = hass.data[DOMAIN][1]
client = await hass_ws_client(hass)
original = dict(manager.storage_persons[0])
original = dict(manager.async_items()[0])
resp = await client.send_json(
{
@ -551,23 +556,23 @@ async def test_ws_update_require_admin(
resp = await client.receive_json()
assert not resp["success"]
not_updated = dict(manager.storage_persons[0])
not_updated = dict(manager.async_items()[0])
assert original == not_updated
async def test_ws_delete(hass, hass_ws_client, storage_setup):
"""Test deleting via WS."""
manager = hass.data[DOMAIN]
manager = hass.data[DOMAIN][1]
client = await hass_ws_client(hass)
persons = manager.storage_persons
persons = manager.async_items()
resp = await client.send_json(
{"id": 6, "type": "person/delete", "person_id": persons[0]["id"]}
)
resp = await client.receive_json()
persons = manager.storage_persons
persons = manager.async_items()
assert len(persons) == 0
assert resp["success"]
@ -581,7 +586,7 @@ async def test_ws_delete_require_admin(
):
"""Test deleting via WS requires admin."""
hass_admin_user.groups = []
manager = hass.data[DOMAIN]
manager = hass.data[DOMAIN][1]
client = await hass_ws_client(hass)
@ -589,7 +594,7 @@ async def test_ws_delete_require_admin(
{
"id": 6,
"type": "person/delete",
"person_id": manager.storage_persons[0]["id"],
"person_id": manager.async_items()[0]["id"],
"name": "Updated Name",
"device_trackers": [DEVICE_TRACKER_2],
"user_id": None,
@ -598,61 +603,64 @@ async def test_ws_delete_require_admin(
resp = await client.receive_json()
assert not resp["success"]
persons = manager.storage_persons
persons = manager.async_items()
assert len(persons) == 1
async def test_create_invalid_user_id(hass):
async def test_create_invalid_user_id(hass, storage_collection):
"""Test we do not allow invalid user ID during creation."""
manager = PersonManager(hass, Mock(), [])
await manager.async_initialize()
with pytest.raises(ValueError):
await manager.async_create_person(name="Hello", user_id="non-existing")
await storage_collection.async_create_item(
{"name": "Hello", "user_id": "non-existing"}
)
async def test_create_duplicate_user_id(hass, hass_admin_user):
async def test_create_duplicate_user_id(hass, hass_admin_user, storage_collection):
"""Test we do not allow duplicate user ID during creation."""
manager = PersonManager(hass, Mock(async_add_entities=mock_coro_func()), [])
await manager.async_initialize()
await manager.async_create_person(name="Hello", user_id=hass_admin_user.id)
await storage_collection.async_create_item(
{"name": "Hello", "user_id": hass_admin_user.id}
)
with pytest.raises(ValueError):
await manager.async_create_person(name="Hello", user_id=hass_admin_user.id)
await storage_collection.async_create_item(
{"name": "Hello", "user_id": hass_admin_user.id}
)
async def test_update_double_user_id(hass, hass_admin_user):
async def test_update_double_user_id(hass, hass_admin_user, storage_collection):
"""Test we do not allow double user ID during update."""
manager = PersonManager(hass, Mock(async_add_entities=mock_coro_func()), [])
await manager.async_initialize()
await manager.async_create_person(name="Hello", user_id=hass_admin_user.id)
person = await manager.async_create_person(name="Hello")
await storage_collection.async_create_item(
{"name": "Hello", "user_id": hass_admin_user.id}
)
person = await storage_collection.async_create_item({"name": "Hello"})
with pytest.raises(ValueError):
await manager.async_update_person(
person_id=person["id"], user_id=hass_admin_user.id
await storage_collection.async_update_item(
person["id"], {"user_id": hass_admin_user.id}
)
async def test_update_invalid_user_id(hass):
async def test_update_invalid_user_id(hass, storage_collection):
"""Test updating to invalid user ID."""
manager = PersonManager(hass, Mock(async_add_entities=mock_coro_func()), [])
await manager.async_initialize()
person = await manager.async_create_person(name="Hello")
person = await storage_collection.async_create_item({"name": "Hello"})
with pytest.raises(ValueError):
await manager.async_update_person(
person_id=person["id"], user_id="non-existing"
await storage_collection.async_update_item(
person["id"], {"user_id": "non-existing"}
)
async def test_update_person_when_user_removed(hass, hass_read_only_user):
async def test_update_person_when_user_removed(
hass, storage_setup, hass_read_only_user
):
"""Update person when user is removed."""
manager = PersonManager(hass, Mock(async_add_entities=mock_coro_func()), [])
await manager.async_initialize()
person = await manager.async_create_person(
name="Hello", user_id=hass_read_only_user.id
storage_collection = hass.data[DOMAIN][1]
person = await storage_collection.async_create_item(
{"name": "Hello", "user_id": hass_read_only_user.id}
)
await hass.auth.async_remove_user(hass_read_only_user)
await hass.async_block_till_done()
assert person["user_id"] is None
assert storage_collection.data[person["id"]]["user_id"] is None