Improve seventeentrack (#25454)
* Code improvement + tests * review * review + moving to pytest test function * move test to async * remove code comment
This commit is contained in:
parent
da53e0a836
commit
4936e55979
5 changed files with 382 additions and 78 deletions
311
tests/components/seventeentrack/test_sensor.py
Normal file
311
tests/components/seventeentrack/test_sensor.py
Normal file
|
@ -0,0 +1,311 @@
|
|||
"""Tests for the seventeentrack sensor."""
|
||||
import datetime
|
||||
from typing import Union
|
||||
|
||||
import pytest
|
||||
import mock
|
||||
from py17track.package import Package
|
||||
|
||||
from homeassistant.components.seventeentrack.sensor \
|
||||
import CONF_SHOW_ARCHIVED, CONF_SHOW_DELIVERED
|
||||
from homeassistant.const import CONF_USERNAME, CONF_PASSWORD
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.util import utcnow
|
||||
from tests.common import MockDependency, async_fire_time_changed
|
||||
|
||||
VALID_CONFIG_MINIMAL = {
|
||||
'sensor': {
|
||||
'platform': 'seventeentrack',
|
||||
CONF_USERNAME: 'test',
|
||||
CONF_PASSWORD: 'test'
|
||||
}
|
||||
}
|
||||
|
||||
INVALID_CONFIG = {
|
||||
'sensor': {
|
||||
'platform': 'seventeentrack',
|
||||
'boom': 'test',
|
||||
}
|
||||
}
|
||||
|
||||
VALID_CONFIG_FULL = {
|
||||
'sensor': {
|
||||
'platform': 'seventeentrack',
|
||||
CONF_USERNAME: 'test',
|
||||
CONF_PASSWORD: 'test',
|
||||
CONF_SHOW_ARCHIVED: True,
|
||||
CONF_SHOW_DELIVERED: True
|
||||
}
|
||||
}
|
||||
|
||||
VALID_CONFIG_FULL_NO_DELIVERED = {
|
||||
'sensor': {
|
||||
'platform': 'seventeentrack',
|
||||
CONF_USERNAME: 'test',
|
||||
CONF_PASSWORD: 'test',
|
||||
CONF_SHOW_ARCHIVED: False,
|
||||
CONF_SHOW_DELIVERED: False
|
||||
}
|
||||
}
|
||||
|
||||
DEFAULT_SUMMARY = {
|
||||
"Not Found": 0,
|
||||
"In Transit": 0,
|
||||
"Expired": 0,
|
||||
"Ready to be Picked Up": 0,
|
||||
"Undelivered": 0,
|
||||
"Delivered": 0,
|
||||
"Returned": 0
|
||||
}
|
||||
|
||||
NEW_SUMMARY_DATA = {
|
||||
"Not Found": 1,
|
||||
"In Transit": 1,
|
||||
"Expired": 1,
|
||||
"Ready to be Picked Up": 1,
|
||||
"Undelivered": 1,
|
||||
"Delivered": 1,
|
||||
"Returned": 1
|
||||
}
|
||||
|
||||
|
||||
class ClientMock:
|
||||
"""Mock the py17track client to inject the ProfileMock."""
|
||||
|
||||
def __init__(self, websession) -> None:
|
||||
"""Mock the profile."""
|
||||
self.profile = ProfileMock()
|
||||
|
||||
|
||||
class ProfileMock:
|
||||
"""ProfileMock will mock data coming from 17track."""
|
||||
|
||||
package_list = []
|
||||
login_result = True
|
||||
summary_data = DEFAULT_SUMMARY
|
||||
account_id = '123'
|
||||
|
||||
@classmethod
|
||||
def reset(cls):
|
||||
"""Reset data to defaults."""
|
||||
cls.package_list = []
|
||||
cls.login_result = True
|
||||
cls.summary_data = DEFAULT_SUMMARY
|
||||
cls.account_id = '123'
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Override Account id."""
|
||||
self.account_id = self.__class__.account_id
|
||||
|
||||
async def login(self, email: str, password: str) -> bool:
|
||||
"""Login mock."""
|
||||
return self.__class__.login_result
|
||||
|
||||
async def packages(self, package_state: Union[int, str] = '',
|
||||
show_archived: bool = False) -> list:
|
||||
"""Packages mock."""
|
||||
return self.__class__.package_list[:]
|
||||
|
||||
async def summary(self, show_archived: bool = False) -> dict:
|
||||
"""Summary mock."""
|
||||
return self.__class__.summary_data
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, name="mock_py17track")
|
||||
def fixture_mock_py17track():
|
||||
"""Mock py17track dependency."""
|
||||
with MockDependency('py17track'):
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, name="mock_client")
|
||||
def fixture_mock_client(mock_py17track):
|
||||
"""Mock py17track client."""
|
||||
with mock.patch('py17track.Client', new=ClientMock):
|
||||
yield
|
||||
ProfileMock.reset()
|
||||
|
||||
|
||||
async def _setup_seventeentrack(hass, config=None, summary_data=None):
|
||||
"""Set up component using config."""
|
||||
if not config:
|
||||
config = VALID_CONFIG_MINIMAL
|
||||
if not summary_data:
|
||||
summary_data = {}
|
||||
|
||||
ProfileMock.summary_data = summary_data
|
||||
assert await async_setup_component(hass, 'sensor', config)
|
||||
|
||||
|
||||
async def _goto_future(hass, future=None):
|
||||
"""Move to future."""
|
||||
if not future:
|
||||
future = utcnow() + datetime.timedelta(minutes=10)
|
||||
with mock.patch('homeassistant.util.utcnow', return_value=future):
|
||||
async_fire_time_changed(hass, future)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
async def test_full_valid_config(hass):
|
||||
"""Ensure everything starts correctly."""
|
||||
assert await async_setup_component(hass, 'sensor', VALID_CONFIG_FULL)
|
||||
assert len(hass.states.async_entity_ids()) == len(
|
||||
ProfileMock.summary_data.keys())
|
||||
|
||||
|
||||
async def test_valid_config(hass):
|
||||
"""Ensure everything starts correctly."""
|
||||
assert await async_setup_component(hass, 'sensor', VALID_CONFIG_MINIMAL)
|
||||
|
||||
assert len(hass.states.async_entity_ids()) == len(
|
||||
ProfileMock.summary_data.keys())
|
||||
|
||||
|
||||
async def test_invalid_config(hass):
|
||||
"""Ensure nothing is created when config is wrong."""
|
||||
assert await async_setup_component(hass, 'sensor', INVALID_CONFIG)
|
||||
|
||||
assert not hass.states.async_entity_ids()
|
||||
|
||||
|
||||
async def test_add_package(hass):
|
||||
"""Ensure package is added correctly when user add a new package."""
|
||||
package = Package('456', 206, 'friendly name 1', 'info text 1',
|
||||
'location 1', 206, 2)
|
||||
ProfileMock.package_list = [package]
|
||||
|
||||
await _setup_seventeentrack(hass)
|
||||
assert hass.states.get(
|
||||
'sensor.seventeentrack_package_456') is not None
|
||||
assert len(hass.states.async_entity_ids()) == 1
|
||||
|
||||
package2 = Package('789', 206, 'friendly name 2', 'info text 2',
|
||||
'location 2', 206, 2)
|
||||
ProfileMock.package_list = [package, package2]
|
||||
|
||||
await _goto_future(hass)
|
||||
|
||||
assert hass.states.get(
|
||||
'sensor.seventeentrack_package_789') is not None
|
||||
assert len(hass.states.async_entity_ids()) == 2
|
||||
|
||||
|
||||
async def test_remove_package(hass):
|
||||
"""Ensure entity is not there anymore if package is not there."""
|
||||
package1 = Package('456', 206, 'friendly name 1', 'info text 1',
|
||||
'location 1', 206, 2)
|
||||
package2 = Package('789', 206, 'friendly name 2', 'info text 2',
|
||||
'location 2', 206, 2)
|
||||
|
||||
ProfileMock.package_list = [package1, package2]
|
||||
|
||||
await _setup_seventeentrack(hass)
|
||||
|
||||
assert hass.states.get(
|
||||
'sensor.seventeentrack_package_456') is not None
|
||||
assert hass.states.get(
|
||||
'sensor.seventeentrack_package_789') is not None
|
||||
assert len(hass.states.async_entity_ids()) == 2
|
||||
|
||||
ProfileMock.package_list = [package2]
|
||||
|
||||
await _goto_future(hass)
|
||||
|
||||
assert hass.states.get(
|
||||
'sensor.seventeentrack_package_456') is None
|
||||
assert hass.states.get(
|
||||
'sensor.seventeentrack_package_789') is not None
|
||||
assert len(hass.states.async_entity_ids()) == 1
|
||||
|
||||
|
||||
async def test_friendly_name_changed(hass):
|
||||
"""Test friendly name change."""
|
||||
package = Package('456', 206, 'friendly name 1', 'info text 1',
|
||||
'location 1', 206, 2)
|
||||
ProfileMock.package_list = [package]
|
||||
|
||||
await _setup_seventeentrack(hass)
|
||||
|
||||
assert hass.states.get(
|
||||
'sensor.seventeentrack_package_456') is not None
|
||||
assert len(hass.states.async_entity_ids()) == 1
|
||||
|
||||
package = Package('456', 206, 'friendly name 2', 'info text 1',
|
||||
'location 1', 206, 2)
|
||||
ProfileMock.package_list = [package]
|
||||
|
||||
await _goto_future(hass)
|
||||
|
||||
assert hass.states.get(
|
||||
'sensor.seventeentrack_package_456') is not None
|
||||
entity = hass.data['entity_components']['sensor'].get_entity(
|
||||
'sensor.seventeentrack_package_456')
|
||||
assert entity.name == 'Seventeentrack Package: friendly name 2'
|
||||
assert len(hass.states.async_entity_ids()) == 1
|
||||
|
||||
|
||||
async def test_delivered_not_shown(hass):
|
||||
"""Ensure delivered packages are not shown."""
|
||||
package = Package('456', 206, 'friendly name 1', 'info text 1',
|
||||
'location 1', 206, 2, 40)
|
||||
ProfileMock.package_list = [package]
|
||||
|
||||
hass.components.persistent_notification = mock.MagicMock()
|
||||
await _setup_seventeentrack(hass, VALID_CONFIG_FULL_NO_DELIVERED)
|
||||
assert not hass.states.async_entity_ids()
|
||||
hass.components.persistent_notification.create.assert_called()
|
||||
|
||||
|
||||
async def test_delivered_shown(hass):
|
||||
"""Ensure delivered packages are show when user choose to show them."""
|
||||
package = Package('456', 206, 'friendly name 1', 'info text 1',
|
||||
'location 1', 206, 2, 40)
|
||||
ProfileMock.package_list = [package]
|
||||
|
||||
hass.components.persistent_notification = mock.MagicMock()
|
||||
await _setup_seventeentrack(hass, VALID_CONFIG_FULL)
|
||||
|
||||
assert hass.states.get(
|
||||
'sensor.seventeentrack_package_456') is not None
|
||||
assert len(hass.states.async_entity_ids()) == 1
|
||||
hass.components.persistent_notification.create.assert_not_called()
|
||||
|
||||
|
||||
async def test_becomes_delivered_not_shown_notification(hass):
|
||||
"""Ensure notification is triggered when package becomes delivered."""
|
||||
package = Package('456', 206, 'friendly name 1', 'info text 1',
|
||||
'location 1', 206, 2)
|
||||
ProfileMock.package_list = [package]
|
||||
|
||||
await _setup_seventeentrack(hass, VALID_CONFIG_FULL_NO_DELIVERED)
|
||||
|
||||
assert hass.states.get(
|
||||
'sensor.seventeentrack_package_456') is not None
|
||||
assert len(hass.states.async_entity_ids()) == 1
|
||||
|
||||
package_delivered = Package('456', 206, 'friendly name 1',
|
||||
'info text 1', 'location 1', 206, 2, 40)
|
||||
ProfileMock.package_list = [package_delivered]
|
||||
|
||||
hass.components.persistent_notification = mock.MagicMock()
|
||||
await _goto_future(hass)
|
||||
|
||||
hass.components.persistent_notification.create.assert_called()
|
||||
assert not hass.states.async_entity_ids()
|
||||
|
||||
|
||||
async def test_summary_correctly_updated(hass):
|
||||
"""Ensure summary entities are not duplicated."""
|
||||
await _setup_seventeentrack(hass, summary_data=DEFAULT_SUMMARY)
|
||||
|
||||
assert len(hass.states.async_entity_ids()) == 7
|
||||
for state in hass.states.async_all():
|
||||
assert state.state == '0'
|
||||
|
||||
ProfileMock.summary_data = NEW_SUMMARY_DATA
|
||||
|
||||
await _goto_future(hass)
|
||||
|
||||
assert len(hass.states.async_entity_ids()) == 7
|
||||
for state in hass.states.async_all():
|
||||
assert state.state == '1'
|
Loading…
Add table
Add a link
Reference in a new issue