async def test_ignore_flow(hass, hass_ws_client):
    """Test we can ignore a flow."""
    assert await async_setup_component(hass, "config", {})
    mock_integration(
        hass, MockModule("test", async_setup_entry=AsyncMock(return_value=True))
    )
    mock_entity_platform(hass, "config_flow.test", None)

    class TestFlow(core_ce.ConfigFlow):
        VERSION = 1

        async def async_step_user(self, user_input=None):
            await self.async_set_unique_id("mock-unique-id")
            return self.async_show_form(step_id="account", data_schema=vol.Schema({}))

    ws_client = await hass_ws_client(hass)

    with patch.dict(HANDLERS, {"test": TestFlow}):
        result = await hass.config_entries.flow.async_init(
            "test", context={"source": core_ce.SOURCE_USER}
        )
        assert result["type"] == data_entry_flow.RESULT_TYPE_FORM

        await ws_client.send_json(
            {
                "id": 5,
                "type": "config_entries/ignore_flow",
                "flow_id": result["flow_id"],
                "title": "Test Integration",
            }
        )
        response = await ws_client.receive_json()

        assert response["success"]

    assert len(hass.config_entries.flow.async_progress()) == 0

    entry = hass.config_entries.async_entries("test")[0]
    assert entry.source == "ignore"
    assert entry.unique_id == "mock-unique-id"
    assert entry.title == "Test Integration"
Example #2
0
    def test_setup_two_platforms(self):
        """Test with bad configuration."""
        # Test if switch component returns 0 switches
        test_platform = getattr(self.hass.components, "test.switch")
        test_platform.init(True)

        mock_entity_platform(self.hass, "switch.test2", test_platform)
        test_platform.init(False)

        assert setup_component(
            self.hass,
            switch.DOMAIN,
            {
                switch.DOMAIN: {
                    CONF_PLATFORM: "test"
                },
                "{} 2".format(switch.DOMAIN): {
                    CONF_PLATFORM: "test2"
                },
            },
        )
Example #3
0
async def test_call_async_migrate_entry(hass):
    """Test we call <component>.async_migrate_entry when version mismatch."""
    entry = MockConfigEntry(domain='comp')
    entry.version = 2
    entry.add_to_hass(hass)

    mock_migrate_entry = MagicMock(return_value=mock_coro(True))
    mock_setup_entry = MagicMock(return_value=mock_coro(True))

    mock_integration(
        hass,
        MockModule('comp',
                   async_setup_entry=mock_setup_entry,
                   async_migrate_entry=mock_migrate_entry))
    mock_entity_platform(hass, 'config_flow.comp', None)

    result = await async_setup_component(hass, 'comp', {})
    assert result
    assert len(mock_migrate_entry.mock_calls) == 1
    assert len(mock_setup_entry.mock_calls) == 1
    assert entry.state == config_entries.ENTRY_STATE_LOADED
Example #4
0
async def test_platform_warn_slow_setup(hass):
    """Warn we log when platform setup takes a long time."""
    platform = MockPlatform()

    mock_entity_platform(hass, "test_domain.platform", platform)

    component = EntityComponent(_LOGGER, DOMAIN, hass)

    with patch.object(hass.loop, "call_later") as mock_call:
        await component.async_setup({DOMAIN: {"platform": "platform"}})
        await hass.async_block_till_done()
        assert mock_call.called

        # mock_calls[0] is the warning message for component setup
        # mock_calls[4] is the warning message for platform setup
        timeout, logger_method = mock_call.mock_calls[4][1][:2]

        assert timeout == entity_platform.SLOW_SETUP_WARNING
        assert logger_method == _LOGGER.warning

        assert mock_call().cancel.called
Example #5
0
    def test_set_scan_interval_via_config(self, mock_track):
        """Test the setting of the scan interval via configuration."""
        def platform_setup(hass, config, add_entities, discovery_info=None):
            """Test the platform setup."""
            add_entities([MockEntity(should_poll=True)])

        mock_entity_platform(self.hass, 'test_domain.platform',
                             MockPlatform(platform_setup))

        component = EntityComponent(_LOGGER, DOMAIN, self.hass)

        component.setup({
            DOMAIN: {
                'platform': 'platform',
                'scan_interval': timedelta(seconds=30),
            }
        })

        self.hass.block_till_done()
        assert mock_track.called
        assert timedelta(seconds=30) == mock_track.call_args[0][2]
async def test_set_scan_interval_via_config(mock_track, hass):
    """Test the setting of the scan interval via configuration."""
    def platform_setup(hass, config, add_entities, discovery_info=None):
        """Test the platform setup."""
        add_entities([MockEntity(should_poll=True)])

    mock_entity_platform(hass, "test_domain.platform",
                         MockPlatform(platform_setup))

    component = EntityComponent(_LOGGER, DOMAIN, hass)

    component.setup({
        DOMAIN: {
            "platform": "platform",
            "scan_interval": timedelta(seconds=30)
        }
    })

    await hass.async_block_till_done()
    assert mock_track.called
    assert timedelta(seconds=30) == mock_track.call_args[0][2]
async def test_setup_loads_platforms(hass):
    """Test the loading of the platforms."""
    component_setup = Mock(return_value=True)
    platform_setup = Mock(return_value=None)

    mock_integration(hass, MockModule("test_component", setup=component_setup))
    # mock the dependencies
    mock_integration(hass, MockModule("mod2", dependencies=["test_component"]))
    mock_entity_platform(hass, "test_domain.mod2",
                         MockPlatform(platform_setup))

    component = EntityComponent(_LOGGER, DOMAIN, hass)

    assert not component_setup.called
    assert not platform_setup.called

    component.setup({DOMAIN: {"platform": "mod2"}})

    await hass.async_block_till_done()
    assert component_setup.called
    assert platform_setup.called
async def test_set_entity_namespace_via_config(opp):
    """Test setting an entity namespace."""

    def platform_setup(opp, config, add_entities, discovery_info=None):
        """Test the platform setup."""
        add_entities([MockEntity(name="beer"), MockEntity(name=None)])

    platform = MockPlatform(platform_setup)

    mock_entity_platform(opp, "test_domain.platform", platform)

    component = EntityComponent(_LOGGER, DOMAIN, opp)

    component.setup({DOMAIN: {"platform": "platform", "entity_namespace": "yummy"}})

    await opp.async_block_till_done()

    assert sorted(opp.states.async_entity_ids()) == [
        "test_domain.yummy_beer",
        "test_domain.yummy_unnamed_device",
    ]
async def test_setup_entry(hass):
    """Test setup entry calls async_setup_entry on platform."""
    mock_setup_entry = AsyncMock(return_value=True)
    mock_entity_platform(
        hass,
        "test_domain.entry_domain",
        MockPlatform(async_setup_entry=mock_setup_entry,
                     scan_interval=timedelta(seconds=5)),
    )

    component = EntityComponent(_LOGGER, DOMAIN, hass)
    entry = MockConfigEntry(domain="entry_domain")

    assert await component.async_setup_entry(entry)
    assert len(mock_setup_entry.mock_calls) == 1
    p_hass, p_entry, _ = mock_setup_entry.mock_calls[0][1]
    assert p_hass is hass
    assert p_entry is entry

    assert component._platforms[entry.entry_id].scan_interval == timedelta(
        seconds=5)
Example #10
0
async def test_platforms_shutdown_on_stop(hass):
    """Test that we shutdown platforms on stop."""
    platform1_setup = Mock(
        side_effect=[PlatformNotReady, PlatformNotReady, None])
    mock_integration(hass, MockModule("mod1"))
    mock_entity_platform(hass, "test_domain.mod1",
                         MockPlatform(platform1_setup))

    component = EntityComponent(_LOGGER, DOMAIN, hass)

    await component.async_setup({DOMAIN: {"platform": "mod1"}})
    await hass.async_block_till_done()
    assert len(platform1_setup.mock_calls) == 1
    assert "test_domain.mod1" not in hass.config.components

    with patch.object(component._platforms[DOMAIN],
                      "async_shutdown") as mock_async_shutdown:
        hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
        await hass.async_block_till_done()

    assert mock_async_shutdown.called
async def test_abort(hass, client):
    """Test a flow that aborts."""
    mock_entity_platform(hass, "config_flow.test", None)

    class TestFlow(core_ce.ConfigFlow):
        async def async_step_user(self, user_input=None):
            return self.async_abort(reason="bla")

    with patch.dict(HANDLERS, {"test": TestFlow}):
        resp = await client.post("/api/config/config_entries/flow",
                                 json={"handler": "test"})

    assert resp.status == 200
    data = await resp.json()
    data.pop("flow_id")
    assert data == {
        "description_placeholders": None,
        "handler": "test",
        "reason": "bla",
        "type": "abort",
    }
Example #12
0
def test_setup_dependencies_platform(hass):
    """Test we setup the dependencies of a platform.

    We're explictely testing that we process dependencies even if a component
    with the same name has already been loaded.
    """
    mock_integration(
        hass, MockModule('test_component', dependencies=['test_component2']))
    mock_integration(hass, MockModule('test_component2'))
    mock_entity_platform(hass, 'test_domain.test_component', MockPlatform())

    component = EntityComponent(_LOGGER, DOMAIN, hass)

    yield from component.async_setup(
        {DOMAIN: {
            'platform': 'test_component',
        }})

    assert 'test_component' in hass.config.components
    assert 'test_component2' in hass.config.components
    assert 'test_domain.test_component' in hass.config.components
async def test_entry_setup_succeed(hass, manager):
    """Test that we can setup an entry."""
    entry = MockConfigEntry(domain="comp",
                            state=config_entries.ENTRY_STATE_NOT_LOADED)
    entry.add_to_hass(hass)

    mock_setup = MagicMock(return_value=mock_coro(True))
    mock_setup_entry = MagicMock(return_value=mock_coro(True))

    mock_integration(
        hass,
        MockModule("comp",
                   async_setup=mock_setup,
                   async_setup_entry=mock_setup_entry),
    )
    mock_entity_platform(hass, "config_flow.comp", None)

    assert await manager.async_setup(entry.entry_id)
    assert len(mock_setup.mock_calls) == 1
    assert len(mock_setup_entry.mock_calls) == 1
    assert entry.state == config_entries.ENTRY_STATE_LOADED
async def test_call_async_migrate_entry_failure_not_bool(hass):
    """Test migration fails if boolean not returned."""
    entry = MockConfigEntry(domain='comp')
    entry.version = 2
    entry.add_to_hass(hass)

    mock_migrate_entry = MagicMock(
        return_value=mock_coro())
    mock_setup_entry = MagicMock(return_value=mock_coro(True))

    mock_integration(
        hass,
        MockModule('comp', async_setup_entry=mock_setup_entry,
                   async_migrate_entry=mock_migrate_entry))
    mock_entity_platform(hass, 'config_flow.comp', None)

    result = await async_setup_component(hass, 'comp', {})
    assert result
    assert len(mock_migrate_entry.mock_calls) == 1
    assert len(mock_setup_entry.mock_calls) == 0
    assert entry.state == config_entries.ENTRY_STATE_MIGRATION_ERROR
Example #15
0
async def test_continue_flow_unauth(hass, client, hass_admin_user):
    """Test we can't finish a two step flow."""
    mock_integration(hass, MockModule("test", async_setup_entry=mock_coro_func(True)))
    mock_entity_platform(hass, "config_flow.test", None)

    class TestFlow(core_ce.ConfigFlow):
        VERSION = 1

        async def async_step_user(self, user_input=None):
            return self.async_show_form(
                step_id="account", data_schema=vol.Schema({"user_title": str})
            )

        async def async_step_account(self, user_input=None):
            return self.async_create_entry(
                title=user_input["user_title"], data={"secret": "account_token"}
            )

    with patch.dict(HANDLERS, {"test": TestFlow}):
        resp = await client.post(
            "/api/config/config_entries/flow", json={"handler": "test"}
        )
        assert resp.status == 200
        data = await resp.json()
        flow_id = data.pop("flow_id")
        assert data == {
            "type": "form",
            "handler": "test",
            "step_id": "account",
            "data_schema": [{"name": "user_title", "type": "string"}],
            "description_placeholders": None,
            "errors": None,
        }

    hass_admin_user.groups = []

    resp = await client.post(
        f"/api/config/config_entries/flow/{flow_id}", json={"user_title": "user-title"},
    )
    assert resp.status == 401
async def test_parallel_updates_sync_platform(hass):
    """Test sync platform parallel_updates default set to 1."""
    platform = MockPlatform()

    mock_entity_platform(hass, "test_domain.platform", platform)

    component = EntityComponent(_LOGGER, DOMAIN, hass)
    component._platforms = {}

    await component.async_setup({DOMAIN: {"platform": "platform"}})

    handle = list(component._platforms.values())[-1]

    class SyncEntity(MockEntity):
        """Mock entity that has update."""
        async def update(self):
            pass

    entity = SyncEntity()
    await handle.async_add_entities([entity])
    assert entity.parallel_updates is not None
    assert entity.parallel_updates._value == 1
Example #17
0
def test_abort(hass, client):
    """Test a flow that aborts."""
    mock_entity_platform(hass, 'config_flow.test', None)

    class TestFlow(core_ce.ConfigFlow):
        @asyncio.coroutine
        def async_step_user(self, user_input=None):
            return self.async_abort(reason='bla')

    with patch.dict(HANDLERS, {'test': TestFlow}):
        resp = yield from client.post('/api/config/config_entries/flow',
                                      json={'handler': 'test'})

    assert resp.status == 200
    data = yield from resp.json()
    data.pop('flow_id')
    assert data == {
        'description_placeholders': None,
        'handler': 'test',
        'reason': 'bla',
        'type': 'abort'
    }
async def test_platform_not_ready(hass, legacy_patchable_time):
    """Test that we retry when platform not ready."""
    platform1_setup = Mock(
        side_effect=[PlatformNotReady, PlatformNotReady, None])
    mock_integration(hass, MockModule("mod1"))
    mock_entity_platform(hass, "test_domain.mod1",
                         MockPlatform(platform1_setup))

    component = EntityComponent(_LOGGER, DOMAIN, hass)

    await component.async_setup({DOMAIN: {"platform": "mod1"}})
    await hass.async_block_till_done()
    assert len(platform1_setup.mock_calls) == 1
    assert "test_domain.mod1" not in hass.config.components

    utcnow = dt_util.utcnow()

    with patch("homeassistant.util.dt.utcnow", return_value=utcnow):
        # Should not trigger attempt 2
        async_fire_time_changed(hass, utcnow + timedelta(seconds=29))
        await hass.async_block_till_done()
        assert len(platform1_setup.mock_calls) == 1

        # Should trigger attempt 2
        async_fire_time_changed(hass, utcnow + timedelta(seconds=30))
        await hass.async_block_till_done()
        assert len(platform1_setup.mock_calls) == 2
        assert "test_domain.mod1" not in hass.config.components

        # This should not trigger attempt 3
        async_fire_time_changed(hass, utcnow + timedelta(seconds=59))
        await hass.async_block_till_done()
        assert len(platform1_setup.mock_calls) == 2

        # Trigger attempt 3, which succeeds
        async_fire_time_changed(hass, utcnow + timedelta(seconds=60))
        await hass.async_block_till_done()
        assert len(platform1_setup.mock_calls) == 3
        assert "test_domain.mod1" in hass.config.components
Example #19
0
async def test_entry_reload_not_loaded(hass, manager, state):
    """Test that we can reload an entry."""
    entry = MockConfigEntry(domain='comp', state=state)
    entry.add_to_hass(hass)

    async_setup = MagicMock(return_value=mock_coro(True))
    async_setup_entry = MagicMock(return_value=mock_coro(True))
    async_unload_entry = MagicMock(return_value=mock_coro(True))

    mock_integration(
        hass,
        MockModule('comp',
                   async_setup=async_setup,
                   async_setup_entry=async_setup_entry,
                   async_unload_entry=async_unload_entry))
    mock_entity_platform(hass, 'config_flow.comp', None)

    assert await manager.async_reload(entry.entry_id)
    assert len(async_unload_entry.mock_calls) == 0
    assert len(async_setup.mock_calls) == 1
    assert len(async_setup_entry.mock_calls) == 1
    assert entry.state == config_entries.ENTRY_STATE_LOADED
async def test_unload_entry_resets_platform(hass):
    """Test unloading an entry removes all entities."""
    mock_setup_entry = AsyncMock(return_value=True)
    mock_entity_platform(
        hass,
        "test_domain.entry_domain",
        MockPlatform(async_setup_entry=mock_setup_entry),
    )

    component = EntityComponent(_LOGGER, DOMAIN, hass)
    entry = MockConfigEntry(domain="entry_domain")

    assert await component.async_setup_entry(entry)
    assert len(mock_setup_entry.mock_calls) == 1
    add_entities = mock_setup_entry.mock_calls[0][1][2]
    add_entities([MockEntity()])
    await hass.async_block_till_done()

    assert len(hass.states.async_entity_ids()) == 1

    assert await component.async_unload_entry(entry)
    assert len(hass.states.async_entity_ids()) == 0
async def test_parallel_updates_async_platform(hass):
    """Test async platform does not have parallel_updates limit by default."""
    platform = MockPlatform()

    mock_entity_platform(hass, "test_domain.platform", platform)

    component = EntityComponent(_LOGGER, DOMAIN, hass)
    component._platforms = {}

    await component.async_setup({DOMAIN: {"platform": "platform"}})

    handle = list(component._platforms.values())[-1]
    assert handle.parallel_updates is None

    class AsyncEntity(MockEntity):
        """Mock entity that has async_update."""
        async def async_update(self):
            pass

    entity = AsyncEntity()
    await handle.async_add_entities([entity])
    assert entity.parallel_updates is None
Example #22
0
async def test_mqtt_integration_discovery_subscribe_unsubscribe(
        hass, mqtt_client_mock, mqtt_mock_entry_no_yaml_config):
    """Check MQTT integration discovery subscribe and unsubscribe."""
    mqtt_mock = await mqtt_mock_entry_no_yaml_config()
    mock_entity_platform(hass, "config_flow.comp", None)

    entry = hass.config_entries.async_entries("mqtt")[0]
    mqtt_mock().connected = True

    with patch(
            "homeassistant.components.mqtt.discovery.async_get_mqtt",
            return_value={"comp": ["comp/discovery/#"]},
    ):
        await async_start(hass, "homeassistant", entry)
        await hass.async_block_till_done()

    mqtt_client_mock.subscribe.assert_any_call("comp/discovery/#", 0)
    assert not mqtt_client_mock.unsubscribe.called

    class TestFlow(config_entries.ConfigFlow):
        """Test flow."""
        async def async_step_mqtt(self, discovery_info):
            """Test mqtt step."""
            return self.async_abort(reason="already_configured")

    with patch.dict(config_entries.HANDLERS, {"comp": TestFlow}):
        mqtt_client_mock.subscribe.assert_any_call("comp/discovery/#", 0)
        assert not mqtt_client_mock.unsubscribe.called

        async_fire_mqtt_message(hass, "comp/discovery/bla/config", "")
        await hass.async_block_till_done()
        mqtt_client_mock.unsubscribe.assert_called_once_with(
            "comp/discovery/#")
        mqtt_client_mock.unsubscribe.reset_mock()

        async_fire_mqtt_message(hass, "comp/discovery/bla/config", "")
        await hass.async_block_till_done()
        assert not mqtt_client_mock.unsubscribe.called
def test_create_account(hass, client):
    """Test a flow that creates an account."""
    mock_entity_platform(hass, 'config_flow.test', None)

    mock_integration(
        hass,
        MockModule('test', async_setup_entry=mock_coro_func(True)))

    class TestFlow(core_ce.ConfigFlow):
        VERSION = 1

        @asyncio.coroutine
        def async_step_user(self, user_input=None):
            return self.async_create_entry(
                title='Test Entry',
                data={'secret': 'account_token'}
            )

    with patch.dict(HANDLERS, {'test': TestFlow}):
        resp = yield from client.post('/api/config/config_entries/flow',
                                      json={'handler': 'test'})

    assert resp.status == 200

    entries = hass.config_entries.async_entries('test')
    assert len(entries) == 1

    data = yield from resp.json()
    data.pop('flow_id')
    assert data == {
        'handler': 'test',
        'title': 'Test Entry',
        'type': 'create_entry',
        'version': 1,
        'result': entries[0].entry_id,
        'description': None,
        'description_placeholders': None,
    }
Example #24
0
async def test_unique_id_ignore(hass, manager):
    """Test that we can ignore flows that are in progress and have a unique ID."""
    async_setup_entry = MagicMock(return_value=mock_coro(False))
    mock_integration(hass,
                     MockModule("comp", async_setup_entry=async_setup_entry))
    mock_entity_platform(hass, "config_flow.comp", None)

    class TestFlow(config_entries.ConfigFlow):

        VERSION = 1

        async def async_step_user(self, user_input=None):
            await self.async_set_unique_id("mock-unique-id")
            return self.async_show_form(step_id="discovery")

    with patch.dict(config_entries.HANDLERS, {"comp": TestFlow}):
        # Create one to be in progress
        result = await manager.flow.async_init(
            "comp", context={"source": config_entries.SOURCE_USER})
        assert result["type"] == data_entry_flow.RESULT_TYPE_FORM

        result2 = await manager.flow.async_init(
            "comp",
            context={"source": config_entries.SOURCE_IGNORE},
            data={"unique_id": "mock-unique-id"},
        )

    assert result2["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY

    # assert len(hass.config_entries.flow.async_progress()) == 0

    # We should never set up an ignored entry.
    assert len(async_setup_entry.mock_calls) == 0

    entry = hass.config_entries.async_entries("comp")[0]

    assert entry.source == "ignore"
    assert entry.unique_id == "mock-unique-id"
async def test_parallel_updates_async_platform_with_constant(hass):
    """Test async platform can set parallel_updates limit."""
    platform = MockPlatform()
    platform.PARALLEL_UPDATES = 2

    mock_entity_platform(hass, "test_domain.platform", platform)

    component = EntityComponent(_LOGGER, DOMAIN, hass)
    component._platforms = {}

    await component.async_setup({DOMAIN: {"platform": "platform"}})

    handle = list(component._platforms.values())[-1]

    class AsyncEntity(MockEntity):
        """Mock entity that has async_update."""
        async def async_update(self):
            pass

    entity = AsyncEntity()
    await handle.async_add_entities([entity])
    assert entity.parallel_updates is not None
    assert entity.parallel_updates._value == 2
async def test_user_has_confirmation(opp, discovery_flow_conf):
    """Test user requires confirmation to setup."""
    discovery_flow_conf["discovered"] = True
    mock_entity_platform(opp, "config_flow.test", None)

    result = await opp.config_entries.flow.async_init(
        "test", context={"source": config_entries.SOURCE_USER}, data={})

    assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
    assert result["step_id"] == "confirm"

    progress = opp.config_entries.flow.async_progress()
    assert len(progress) == 1
    assert progress[0]["flow_id"] == result["flow_id"]
    assert progress[0]["context"] == {
        "confirm_only": True,
        "source": config_entries.SOURCE_USER,
        "unique_id": "test",
    }

    result = await opp.config_entries.flow.async_configure(
        result["flow_id"], {})
    assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
async def test_call_setup_entry(hass):
    """Test we call <component>.setup_entry."""
    entry = MockConfigEntry(domain="comp")
    entry.add_to_hass(hass)

    mock_setup_entry = MagicMock(return_value=mock_coro(True))
    mock_migrate_entry = MagicMock(return_value=mock_coro(True))

    mock_integration(
        hass,
        MockModule(
            "comp",
            async_setup_entry=mock_setup_entry,
            async_migrate_entry=mock_migrate_entry,
        ),
    )
    mock_entity_platform(hass, "config_flow.comp", None)

    result = await async_setup_component(hass, "comp", {})
    assert result
    assert len(mock_migrate_entry.mock_calls) == 0
    assert len(mock_setup_entry.mock_calls) == 1
    assert entry.state == config_entries.ENTRY_STATE_LOADED
async def test_only_one_in_progress(hass, discovery_flow_conf):
    """Test a user initialized one will finish and cancel discovered one."""
    mock_entity_platform(hass, "config_flow.test", None)

    # Discovery starts flow
    result = await hass.config_entries.flow.async_init(
        "test", context={"source": config_entries.SOURCE_DISCOVERY}, data={})
    assert result["type"] == data_entry_flow.RESULT_TYPE_FORM

    # User starts flow
    result = await hass.config_entries.flow.async_init(
        "test", context={"source": config_entries.SOURCE_USER}, data={})

    assert result["type"] == data_entry_flow.RESULT_TYPE_FORM

    # Discovery flow has not been aborted
    assert len(hass.config_entries.flow.async_progress()) == 2

    # Discovery should be aborted once user confirms
    result = await hass.config_entries.flow.async_configure(
        result["flow_id"], {})
    assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
    assert len(hass.config_entries.flow.async_progress()) == 0
def test_platform_warn_slow_setup(hass):
    """Warn we log when platform setup takes a long time."""
    platform = MockPlatform()

    mock_entity_platform(hass, 'test_domain.platform', platform)

    component = EntityComponent(_LOGGER, DOMAIN, hass)

    with patch.object(hass.loop, 'call_later', MagicMock()) \
            as mock_call:
        yield from component.async_setup({DOMAIN: {
            'platform': 'platform',
        }})
        assert mock_call.called

        # mock_calls[0] is the warning message for component setup
        # mock_calls[3] is the warning message for platform setup
        timeout, logger_method = mock_call.mock_calls[3][1][:2]

        assert timeout == entity_platform.SLOW_SETUP_WARNING
        assert logger_method == _LOGGER.warning

        assert mock_call().cancel.called
async def test_discovery_notification(hass):
    """Test that we create/dismiss a notification when source is discovery."""
    mock_integration(hass, MockModule('test'))
    mock_entity_platform(hass, 'config_flow.test', None)
    await async_setup_component(hass, 'persistent_notification', {})

    class TestFlow(config_entries.ConfigFlow):
        VERSION = 5

        async def async_step_discovery(self, user_input=None):
            if user_input is not None:
                return self.async_create_entry(
                    title='Test Title',
                    data={
                        'token': 'abcd'
                    }
                )
            return self.async_show_form(
                step_id='discovery',
            )

    with patch.dict(config_entries.HANDLERS, {'test': TestFlow}):
        result = await hass.config_entries.flow.async_init(
            'test', context={'source': config_entries.SOURCE_DISCOVERY})

    await hass.async_block_till_done()
    state = hass.states.get('persistent_notification.config_entry_discovery')
    assert state is not None

    result = await hass.config_entries.flow.async_configure(
        result['flow_id'], {})
    assert result['type'] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY

    await hass.async_block_till_done()
    state = hass.states.get('persistent_notification.config_entry_discovery')
    assert state is None