diff --git a/tests/components/simplisafe/conftest.py b/tests/components/simplisafe/conftest.py new file mode 100644 index 00000000000..b793ee8656e --- /dev/null +++ b/tests/components/simplisafe/conftest.py @@ -0,0 +1,81 @@ +"""Define test fixtures for SimpliSafe.""" +from unittest.mock import AsyncMock, Mock, patch + +import pytest + +from homeassistant.components.simplisafe.config_flow import CONF_AUTH_CODE +from homeassistant.components.simplisafe.const import CONF_USER_ID, DOMAIN +from homeassistant.const import CONF_TOKEN +from homeassistant.setup import async_setup_component + +from tests.common import MockConfigEntry + +REFRESH_TOKEN = "token123" +USER_ID = "12345" + + +@pytest.fixture(name="api") +def api_fixture(websocket): + """Define a fixture for a simplisafe-python API object.""" + return Mock( + async_get_systems=AsyncMock(), + refresh_token=REFRESH_TOKEN, + user_id=USER_ID, + websocket=websocket, + ) + + +@pytest.fixture(name="config_entry") +def config_entry_fixture(hass, config): + """Define a config entry fixture.""" + entry = MockConfigEntry(domain=DOMAIN, unique_id=USER_ID, data=config) + entry.add_to_hass(hass) + return entry + + +@pytest.fixture(name="config") +def config_fixture(hass): + """Define a config entry data fixture.""" + return { + CONF_USER_ID: USER_ID, + CONF_TOKEN: REFRESH_TOKEN, + } + + +@pytest.fixture(name="config_code") +def config_code_fixture(hass): + """Define a authorization code.""" + return { + CONF_AUTH_CODE: "code123", + } + + +@pytest.fixture(name="setup_simplisafe") +async def setup_simplisafe_fixture(hass, api, config): + """Define a fixture to set up SimpliSafe.""" + with patch( + "homeassistant.components.simplisafe.API.async_from_auth", return_value=api + ), patch( + "homeassistant.components.simplisafe.API.async_from_refresh_token", + return_value=api, + ), patch( + "homeassistant.components.simplisafe.SimpliSafe.async_init" + ), patch( + "homeassistant.components.simplisafe.config_flow.API.async_from_auth", + return_value=api, + ), patch( + "homeassistant.components.simplisafe.PLATFORMS", [] + ): + assert await async_setup_component(hass, DOMAIN, config) + await hass.async_block_till_done() + yield + + +@pytest.fixture(name="websocket") +def websocket_fixture(): + """Define a fixture for a simplisafe-python websocket object.""" + return Mock( + async_connect=AsyncMock(), + async_disconnect=AsyncMock(), + async_listen=AsyncMock(), + ) diff --git a/tests/components/simplisafe/test_config_flow.py b/tests/components/simplisafe/test_config_flow.py index 0597ad377cf..2e8fe309ff2 100644 --- a/tests/components/simplisafe/test_config_flow.py +++ b/tests/components/simplisafe/test_config_flow.py @@ -1,51 +1,39 @@ """Define tests for the SimpliSafe config flow.""" -from unittest.mock import AsyncMock, Mock, patch +from unittest.mock import patch import pytest from simplipy.errors import InvalidCredentialsError, SimplipyError from homeassistant import data_entry_flow from homeassistant.components.simplisafe import DOMAIN -from homeassistant.components.simplisafe.config_flow import CONF_AUTH_CODE -from homeassistant.components.simplisafe.const import CONF_USER_ID from homeassistant.config_entries import SOURCE_REAUTH, SOURCE_USER -from homeassistant.const import CONF_CODE, CONF_PASSWORD, CONF_TOKEN, CONF_USERNAME - -from tests.common import MockConfigEntry +from homeassistant.const import CONF_CODE -@pytest.fixture(name="api") -def api_fixture(): - """Define a fixture for simplisafe-python API object.""" - api = Mock() - api.refresh_token = "token123" - api.user_id = "12345" - return api - - -@pytest.fixture(name="mock_async_from_auth") -def mock_async_from_auth_fixture(api): - """Define a fixture for simplipy.API.async_from_auth.""" - with patch( - "homeassistant.components.simplisafe.config_flow.API.async_from_auth", - ) as mock_async_from_auth: - mock_async_from_auth.side_effect = AsyncMock(return_value=api) - yield mock_async_from_auth - - -async def test_duplicate_error(hass, mock_async_from_auth): +async def test_duplicate_error(hass, config_entry, config_code, setup_simplisafe): """Test that errors are shown when duplicates are added.""" - MockConfigEntry( - domain=DOMAIN, - unique_id="12345", - data={ - CONF_USER_ID: "12345", - CONF_TOKEN: "token123", - }, - ).add_to_hass(hass) + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": SOURCE_USER} + ) + assert result["step_id"] == "user" + assert result["type"] == data_entry_flow.RESULT_TYPE_FORM + result = await hass.config_entries.flow.async_configure( + result["flow_id"], user_input=config_code + ) + assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT + assert result["reason"] == "already_configured" + + +@pytest.mark.parametrize( + "exc,error_string", + [(InvalidCredentialsError, "invalid_auth"), (SimplipyError, "unknown")], +) +async def test_errors(hass, config_code, exc, error_string): + """Test that exceptions show the appropriate error.""" with patch( - "homeassistant.components.simplisafe.async_setup_entry", return_value=True + "homeassistant.components.simplisafe.API.async_from_auth", + side_effect=exc, ): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_USER} @@ -54,135 +42,75 @@ async def test_duplicate_error(hass, mock_async_from_auth): assert result["type"] == data_entry_flow.RESULT_TYPE_FORM result = await hass.config_entries.flow.async_configure( - result["flow_id"], user_input={CONF_AUTH_CODE: "code123"} + result["flow_id"], user_input=config_code ) - assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT - assert result["reason"] == "already_configured" + assert result["type"] == data_entry_flow.RESULT_TYPE_FORM + assert result["errors"] == {"base": error_string} -async def test_invalid_credentials(hass, mock_async_from_auth): - """Test that invalid credentials show the correct error.""" - mock_async_from_auth.side_effect = AsyncMock(side_effect=InvalidCredentialsError) - - result = await hass.config_entries.flow.async_init( - DOMAIN, context={"source": SOURCE_USER} - ) - assert result["step_id"] == "user" - assert result["type"] == data_entry_flow.RESULT_TYPE_FORM - - result = await hass.config_entries.flow.async_configure( - result["flow_id"], user_input={CONF_AUTH_CODE: "code123"} - ) - assert result["type"] == data_entry_flow.RESULT_TYPE_FORM - assert result["errors"] == {"base": "invalid_auth"} - - -async def test_options_flow(hass): +async def test_options_flow(hass, config_entry): """Test config flow options.""" - entry = MockConfigEntry( - domain=DOMAIN, - unique_id="abcde12345", - data={CONF_USER_ID: "12345", CONF_TOKEN: "token456"}, - options={CONF_CODE: "1234"}, - ) - entry.add_to_hass(hass) - with patch( "homeassistant.components.simplisafe.async_setup_entry", return_value=True ): - await hass.config_entries.async_setup(entry.entry_id) - result = await hass.config_entries.options.async_init(entry.entry_id) - + await hass.config_entries.async_setup(config_entry.entry_id) + result = await hass.config_entries.options.async_init(config_entry.entry_id) assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["step_id"] == "init" result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={CONF_CODE: "4321"} ) - assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY - assert entry.options == {CONF_CODE: "4321"} + assert config_entry.options == {CONF_CODE: "4321"} -async def test_step_reauth_old_format(hass, mock_async_from_auth): +async def test_step_reauth_old_format( + hass, config, config_code, config_entry, setup_simplisafe +): """Test the re-auth step with "old" config entries (those with user IDs).""" - MockConfigEntry( - domain=DOMAIN, - unique_id="user@email.com", - data={ - CONF_USERNAME: "user@email.com", - CONF_PASSWORD: "password", - }, - ).add_to_hass(hass) - result = await hass.config_entries.flow.async_init( - DOMAIN, - context={"source": SOURCE_REAUTH}, - data={CONF_USERNAME: "user@email.com", CONF_PASSWORD: "password"}, + DOMAIN, context={"source": SOURCE_REAUTH}, data=config ) assert result["step_id"] == "user" - with patch( - "homeassistant.components.simplisafe.async_setup_entry", return_value=True - ), patch("homeassistant.config_entries.ConfigEntries.async_reload"): - result = await hass.config_entries.flow.async_configure( - result["flow_id"], user_input={CONF_AUTH_CODE: "code123"} - ) - assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT - assert result["reason"] == "reauth_successful" + result = await hass.config_entries.flow.async_configure( + result["flow_id"], user_input=config_code + ) + assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT + assert result["reason"] == "reauth_successful" assert len(hass.config_entries.async_entries()) == 1 [config_entry] = hass.config_entries.async_entries(DOMAIN) - assert config_entry.data == {CONF_USER_ID: "12345", CONF_TOKEN: "token123"} + assert config_entry.data == config -async def test_step_reauth_new_format(hass, mock_async_from_auth): +async def test_step_reauth_new_format( + hass, config, config_code, config_entry, setup_simplisafe +): """Test the re-auth step with "new" config entries (those with user IDs).""" - MockConfigEntry( - domain=DOMAIN, - unique_id="12345", - data={ - CONF_USER_ID: "12345", - CONF_TOKEN: "token123", - }, - ).add_to_hass(hass) - result = await hass.config_entries.flow.async_init( - DOMAIN, - context={"source": SOURCE_REAUTH}, - data={CONF_USER_ID: "12345", CONF_TOKEN: "token123"}, + DOMAIN, context={"source": SOURCE_REAUTH}, data=config ) assert result["step_id"] == "user" - with patch( - "homeassistant.components.simplisafe.async_setup_entry", return_value=True - ), patch("homeassistant.config_entries.ConfigEntries.async_reload"): - result = await hass.config_entries.flow.async_configure( - result["flow_id"], user_input={CONF_AUTH_CODE: "code123"} - ) - assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT - assert result["reason"] == "reauth_successful" + result = await hass.config_entries.flow.async_configure( + result["flow_id"], user_input=config_code + ) + assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT + assert result["reason"] == "reauth_successful" assert len(hass.config_entries.async_entries()) == 1 [config_entry] = hass.config_entries.async_entries(DOMAIN) - assert config_entry.data == {CONF_USER_ID: "12345", CONF_TOKEN: "token123"} + assert config_entry.data == config -async def test_step_reauth_wrong_account(hass, api, mock_async_from_auth): +async def test_step_reauth_wrong_account( + hass, api, config, config_code, config_entry, setup_simplisafe +): """Test the re-auth step returning a different account from this one.""" - MockConfigEntry( - domain=DOMAIN, - unique_id="12345", - data={ - CONF_USER_ID: "12345", - CONF_TOKEN: "token123", - }, - ).add_to_hass(hass) - result = await hass.config_entries.flow.async_init( - DOMAIN, - context={"source": SOURCE_REAUTH}, - data={CONF_USER_ID: "12345", CONF_TOKEN: "token123"}, + DOMAIN, context={"source": SOURCE_REAUTH}, data=config ) assert result["step_id"] == "user" @@ -190,52 +118,29 @@ async def test_step_reauth_wrong_account(hass, api, mock_async_from_auth): # identified as this entry's unique ID: api.user_id = "67890" - with patch( - "homeassistant.components.simplisafe.async_setup_entry", return_value=True - ), patch("homeassistant.config_entries.ConfigEntries.async_reload"): - result = await hass.config_entries.flow.async_configure( - result["flow_id"], user_input={CONF_AUTH_CODE: "code123"} - ) - assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT - assert result["reason"] == "wrong_account" + result = await hass.config_entries.flow.async_configure( + result["flow_id"], user_input=config_code + ) + assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT + assert result["reason"] == "wrong_account" assert len(hass.config_entries.async_entries()) == 1 [config_entry] = hass.config_entries.async_entries(DOMAIN) assert config_entry.unique_id == "12345" -async def test_step_user(hass, mock_async_from_auth): +async def test_step_user(hass, config, config_code, setup_simplisafe): """Test the user step.""" result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_USER} ) assert result["step_id"] == "user" - with patch( - "homeassistant.components.simplisafe.async_setup_entry", return_value=True - ), patch("homeassistant.config_entries.ConfigEntries.async_reload"): - result = await hass.config_entries.flow.async_configure( - result["flow_id"], user_input={CONF_AUTH_CODE: "code123"} - ) - assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY + result = await hass.config_entries.flow.async_configure( + result["flow_id"], user_input=config_code + ) + assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY assert len(hass.config_entries.async_entries()) == 1 [config_entry] = hass.config_entries.async_entries(DOMAIN) - assert config_entry.data == {CONF_USER_ID: "12345", CONF_TOKEN: "token123"} - - -async def test_unknown_error(hass, mock_async_from_auth): - """Test that an unknown error shows ohe correct error.""" - mock_async_from_auth.side_effect = AsyncMock(side_effect=SimplipyError) - - result = await hass.config_entries.flow.async_init( - DOMAIN, context={"source": SOURCE_USER} - ) - assert result["step_id"] == "user" - assert result["type"] == data_entry_flow.RESULT_TYPE_FORM - - result = await hass.config_entries.flow.async_configure( - result["flow_id"], user_input={CONF_AUTH_CODE: "code123"} - ) - assert result["type"] == data_entry_flow.RESULT_TYPE_FORM - assert result["errors"] == {"base": "unknown"} + assert config_entry.data == config