async def test_smartapp_install_creates_flow(hass, smartthings_mock, config_entry, location, device_factory): """Test installation creates flow.""" # Arrange config_entry.add_to_hass(hass) app = Mock() app.app_id = config_entry.data["app_id"] request = Mock() request.installed_app_id = str(uuid4()) request.auth_token = str(uuid4()) request.refresh_token = str(uuid4()) request.location_id = location.location_id devices = [ device_factory("", [Capability.battery, "ping"]), device_factory("", [Capability.switch, Capability.switch_level]), device_factory("", [Capability.switch]), ] smartthings_mock.devices.return_value = devices # Act await smartapp.smartapp_install(hass, request, None, app) # Assert await hass.async_block_till_done() entries = hass.config_entries.async_entries("smartthings") assert len(entries) == 2 assert entries[1].data["app_id"] == app.app_id assert entries[1].data["installed_app_id"] == request.installed_app_id assert entries[1].data["location_id"] == request.location_id assert entries[1].data["access_token"] == config_entry.data["access_token"] assert entries[1].data["refresh_token"] == request.refresh_token assert entries[1].data["client_secret"] == config_entry.data[ "client_secret"] assert entries[1].data["client_id"] == config_entry.data["client_id"] assert entries[1].title == location.name
async def test_smartapp_install_creates_flow(hass, smartthings_mock, config_entry, location, device_factory): """Test installation creates flow.""" # Arrange setattr(hass.config_entries, '_entries', [config_entry]) app = Mock() app.app_id = config_entry.data['app_id'] request = Mock() request.installed_app_id = str(uuid4()) request.auth_token = str(uuid4()) request.refresh_token = str(uuid4()) request.location_id = location.location_id devices = [ device_factory('', [Capability.battery, 'ping']), device_factory('', [Capability.switch, Capability.switch_level]), device_factory('', [Capability.switch]) ] smartthings_mock.devices.return_value = devices # Act await smartapp.smartapp_install(hass, request, None, app) # Assert await hass.async_block_till_done() entries = hass.config_entries.async_entries('smartthings') assert len(entries) == 2 assert entries[1].data['app_id'] == app.app_id assert entries[1].data['installed_app_id'] == request.installed_app_id assert entries[1].data['location_id'] == request.location_id assert entries[1].data['access_token'] == \ config_entry.data['access_token'] assert entries[1].data['refresh_token'] == request.refresh_token assert entries[1].data['client_secret'] == \ config_entry.data['client_secret'] assert entries[1].data['client_id'] == config_entry.data['client_id'] assert entries[1].title == location.name
async def test_smartapp_update_configures_flow(hass): """Test update event continues an existing flow.""" # Arrange flow_id = str(uuid4()) flows = [{"flow_id": flow_id, "handler": DOMAIN}] app = Mock() app.app_id = uuid4() request = Mock() request.installed_app_id = str(uuid4()) request.auth_token = str(uuid4()) request.location_id = str(uuid4()) request.refresh_token = str(uuid4()) # Act with patch.object( hass.config_entries.flow, "async_progress", return_value=flows ), patch.object(hass.config_entries.flow, "async_configure") as configure_mock: await smartapp.smartapp_update(hass, request, None, app) configure_mock.assert_called_once_with( flow_id, { CONF_INSTALLED_APP_ID: request.installed_app_id, CONF_LOCATION_ID: request.location_id, CONF_REFRESH_TOKEN: request.refresh_token, }, )
async def test_smartapp_install_store_if_no_other(hass, smartthings_mock, device_factory): """Test aborts if no other app was configured already.""" # Arrange app = Mock() app.app_id = uuid4() request = Mock() request.installed_app_id = str(uuid4()) request.auth_token = str(uuid4()) request.location_id = str(uuid4()) request.refresh_token = str(uuid4()) # Act await smartapp.smartapp_install(hass, request, None, app) # Assert entries = hass.config_entries.async_entries("smartthings") assert not entries data = hass.data[DOMAIN][CONF_INSTALLED_APPS][0] assert data[CONF_REFRESH_TOKEN] == request.refresh_token assert data[CONF_LOCATION_ID] == request.location_id assert data[CONF_INSTALLED_APP_ID] == request.installed_app_id
async def test_smartapp_update_saves_token(hass, smartthings_mock, location, device_factory): """Test update saves token.""" # Arrange entry = Mock() entry.data = {'installed_app_id': str(uuid4()), 'app_id': str(uuid4())} entry.domain = DOMAIN setattr(hass.config_entries, '_entries', [entry]) app = Mock() app.app_id = entry.data['app_id'] request = Mock() request.installed_app_id = entry.data['installed_app_id'] request.auth_token = str(uuid4()) request.refresh_token = str(uuid4()) request.location_id = location.location_id # Act await smartapp.smartapp_update(hass, request, None, app) # Assert assert entry.data[CONF_REFRESH_TOKEN] == request.refresh_token
async def test_smartapp_update_saves_token( hass, smartthings_mock, location, device_factory ): """Test update saves token.""" # Arrange entry = MockConfigEntry( domain=DOMAIN, data={"installed_app_id": str(uuid4()), "app_id": str(uuid4())} ) entry.add_to_hass(hass) app = Mock() app.app_id = entry.data["app_id"] request = Mock() request.installed_app_id = entry.data["installed_app_id"] request.auth_token = str(uuid4()) request.refresh_token = str(uuid4()) request.location_id = location.location_id # Act await smartapp.smartapp_update(hass, request, None, app) # Assert assert entry.data[CONF_REFRESH_TOKEN] == request.refresh_token
async def test_entry_created(hass, app, app_oauth_client, location, smartthings_mock): """Test local webhook, new app, install event creates entry.""" token = str(uuid4()) installed_app_id = str(uuid4()) refresh_token = str(uuid4()) smartthings_mock.apps.return_value = [] smartthings_mock.create_app.return_value = (app, app_oauth_client) smartthings_mock.locations.return_value = [location] request = Mock() request.installed_app_id = installed_app_id request.auth_token = token request.location_id = location.location_id request.refresh_token = refresh_token # Webhook confirmation shown result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": "user"}) assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["step_id"] == "user" assert result["description_placeholders"][ "webhook_url"] == smartapp.get_webhook_url(hass) # Advance to PAT screen result = await hass.config_entries.flow.async_configure( result["flow_id"], {}) assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["step_id"] == "pat" assert "token_url" in result["description_placeholders"] assert "component_url" in result["description_placeholders"] # Enter token and advance to location screen result = await hass.config_entries.flow.async_configure( result["flow_id"], {CONF_ACCESS_TOKEN: token}) assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["step_id"] == "select_location" # Select location and advance to external auth result = await hass.config_entries.flow.async_configure( result["flow_id"], {CONF_LOCATION_ID: location.location_id}) assert result["type"] == data_entry_flow.RESULT_TYPE_EXTERNAL_STEP assert result["step_id"] == "authorize" assert result["url"] == format_install_url(app.app_id, location.location_id) # Complete external auth and advance to install await smartapp.smartapp_install(hass, request, None, app) # Finish result = await hass.config_entries.flow.async_configure(result["flow_id"]) assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY assert result["data"]["app_id"] == app.app_id assert result["data"]["installed_app_id"] == installed_app_id assert result["data"]["location_id"] == location.location_id assert result["data"]["access_token"] == token assert result["data"]["refresh_token"] == request.refresh_token assert result["data"]["client_secret"] == app_oauth_client.client_secret assert result["data"]["client_id"] == app_oauth_client.client_id assert result["title"] == location.name entry = next( (entry for entry in hass.config_entries.async_entries(DOMAIN)), None, ) assert entry.unique_id == smartapp.format_unique_id( app.app_id, location.location_id)
async def test_entry_created_existing_app_copies_oauth_client( hass, app, location, smartthings_mock): """Test entry is created with an existing app and copies the oauth client from another entry.""" token = str(uuid4()) installed_app_id = str(uuid4()) refresh_token = str(uuid4()) oauth_client_id = str(uuid4()) oauth_client_secret = str(uuid4()) smartthings_mock.apps.return_value = [app] smartthings_mock.locations.return_value = [location] request = Mock() request.installed_app_id = installed_app_id request.auth_token = token request.location_id = location.location_id request.refresh_token = refresh_token entry = MockConfigEntry( domain=DOMAIN, data={ CONF_APP_ID: app.app_id, CONF_OAUTH_CLIENT_ID: oauth_client_id, CONF_OAUTH_CLIENT_SECRET: oauth_client_secret, CONF_LOCATION_ID: str(uuid4()), CONF_INSTALLED_APP_ID: str(uuid4()), CONF_ACCESS_TOKEN: token, }, ) entry.add_to_hass(hass) # Webhook confirmation shown result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": "user"}) assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["step_id"] == "user" assert result["description_placeholders"][ "webhook_url"] == smartapp.get_webhook_url(hass) # Advance to PAT screen result = await hass.config_entries.flow.async_configure( result["flow_id"], {}) assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["step_id"] == "pat" assert "token_url" in result["description_placeholders"] assert "component_url" in result["description_placeholders"] # Assert access token is defaulted to an existing entry for convenience. assert result["data_schema"]({}) == {CONF_ACCESS_TOKEN: token} # Enter token and advance to location screen result = await hass.config_entries.flow.async_configure( result["flow_id"], {CONF_ACCESS_TOKEN: token}) assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["step_id"] == "select_location" # Select location and advance to external auth result = await hass.config_entries.flow.async_configure( result["flow_id"], {CONF_LOCATION_ID: location.location_id}) assert result["type"] == data_entry_flow.RESULT_TYPE_EXTERNAL_STEP assert result["step_id"] == "authorize" assert result["url"] == format_install_url(app.app_id, location.location_id) # Complete external auth and advance to install await smartapp.smartapp_install(hass, request, None, app) # Finish result = await hass.config_entries.flow.async_configure(result["flow_id"]) assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY assert result["data"]["app_id"] == app.app_id assert result["data"]["installed_app_id"] == installed_app_id assert result["data"]["location_id"] == location.location_id assert result["data"]["access_token"] == token assert result["data"]["refresh_token"] == request.refresh_token assert result["data"]["client_secret"] == oauth_client_secret assert result["data"]["client_id"] == oauth_client_id assert result["title"] == location.name entry = next( (entry for entry in hass.config_entries.async_entries(DOMAIN) if entry.data[CONF_INSTALLED_APP_ID] == installed_app_id), None, ) assert entry.unique_id == smartapp.format_unique_id( app.app_id, location.location_id)