diff --git a/.coveragerc b/.coveragerc index 54cc470ac63..cbabcb7733d 100644 --- a/.coveragerc +++ b/.coveragerc @@ -108,8 +108,6 @@ omit = homeassistant/components/avea/light.py homeassistant/components/avion/light.py homeassistant/components/awair/coordinator.py - homeassistant/components/azure_devops/__init__.py - homeassistant/components/azure_devops/sensor.py homeassistant/components/azure_service_bus/* homeassistant/components/baf/__init__.py homeassistant/components/baf/climate.py diff --git a/tests/components/azure_devops/__init__.py b/tests/components/azure_devops/__init__.py index da15bc6723d..fb0817671b5 100644 --- a/tests/components/azure_devops/__init__.py +++ b/tests/components/azure_devops/__init__.py @@ -1 +1,82 @@ """Tests for the Azure DevOps integration.""" + +from typing import Final + +from aioazuredevops.builds import DevOpsBuild, DevOpsBuildDefinition +from aioazuredevops.core import DevOpsProject + +from homeassistant.components.azure_devops.const import CONF_ORG, CONF_PAT, CONF_PROJECT +from homeassistant.core import HomeAssistant + +from tests.common import MockConfigEntry + +ORGANIZATION: Final[str] = "testorg" +PROJECT: Final[str] = "testproject" +PAT: Final[str] = "abc123" + +UNIQUE_ID = f"{ORGANIZATION}_{PROJECT}" + + +FIXTURE_USER_INPUT = { + CONF_ORG: ORGANIZATION, + CONF_PROJECT: PROJECT, + CONF_PAT: PAT, +} + +FIXTURE_REAUTH_INPUT = { + CONF_PAT: PAT, +} + + +DEVOPS_PROJECT = DevOpsProject( + project_id="1234", + name=PROJECT, + description="Test Description", + url=f"https://dev.azure.com/{ORGANIZATION}/{PROJECT}", + state="wellFormed", + revision=1, + visibility="private", + last_updated=None, + default_team=None, + links=None, +) + +DEVOPS_BUILD_DEFINITION = DevOpsBuildDefinition( + build_id=9876, + name="Test Build", + url=f"https://dev.azure.com/{ORGANIZATION}/{PROJECT}/_apis/build/definitions/1", + path="", + build_type="build", + queue_status="enabled", + revision=1, +) + +DEVOPS_BUILD = DevOpsBuild( + build_id=5678, + build_number="1", + status="completed", + result="succeeded", + source_branch="main", + source_version="123", + priority="normal", + reason="manual", + queue_time="2021-01-01T00:00:00Z", + start_time="2021-01-01T00:00:00Z", + finish_time="2021-01-01T00:00:00Z", + definition=DEVOPS_BUILD_DEFINITION, + project=DEVOPS_PROJECT, + links=None, +) + + +async def setup_integration( + hass: HomeAssistant, + config_entry: MockConfigEntry, +) -> bool: + """Fixture for setting up the component.""" + config_entry.add_to_hass(hass) + + result = await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + return result diff --git a/tests/components/azure_devops/conftest.py b/tests/components/azure_devops/conftest.py new file mode 100644 index 00000000000..d51142cdced --- /dev/null +++ b/tests/components/azure_devops/conftest.py @@ -0,0 +1,58 @@ +"""Test fixtures for Azure DevOps.""" + +from collections.abc import AsyncGenerator, Generator +from unittest.mock import AsyncMock, MagicMock, patch + +import pytest + +from homeassistant.components.azure_devops.const import DOMAIN + +from . import DEVOPS_BUILD, DEVOPS_PROJECT, FIXTURE_USER_INPUT, PAT, UNIQUE_ID + +from tests.common import MockConfigEntry + + +@pytest.fixture +async def mock_devops_client() -> AsyncGenerator[MagicMock, None]: + """Mock the Azure DevOps client.""" + + with ( + patch( + "homeassistant.components.azure_devops.DevOpsClient", autospec=True + ) as mock_client, + patch( + "homeassistant.components.azure_devops.config_flow.DevOpsClient", + new=mock_client, + ), + ): + devops_client = mock_client.return_value + devops_client.authorized = True + devops_client.pat = PAT + devops_client.authorize.return_value = True + devops_client.get_project.return_value = DEVOPS_PROJECT + devops_client.get_builds.return_value = [DEVOPS_BUILD] + devops_client.get_build.return_value = DEVOPS_BUILD + devops_client.get_work_items_ids_all.return_value = None + devops_client.get_work_items.return_value = None + + yield devops_client + + +@pytest.fixture +async def mock_config_entry() -> MockConfigEntry: + """Create a mock config entry.""" + return MockConfigEntry( + domain=DOMAIN, + data=FIXTURE_USER_INPUT, + unique_id=UNIQUE_ID, + ) + + +@pytest.fixture +def mock_setup_entry() -> Generator[AsyncMock, None, None]: + """Override async_setup_entry.""" + with patch( + "homeassistant.components.azure_devops.async_setup_entry", + return_value=True, + ) as mock_setup_entry: + yield mock_setup_entry diff --git a/tests/components/azure_devops/snapshots/test_sensor.ambr b/tests/components/azure_devops/snapshots/test_sensor.ambr new file mode 100644 index 00000000000..b99d2c4e49d --- /dev/null +++ b/tests/components/azure_devops/snapshots/test_sensor.ambr @@ -0,0 +1,59 @@ +# serializer version: 1 +# name: test_sensors[sensor.testproject_test_build_latest_build-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.testproject_test_build_latest_build', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Test Build latest build', + 'platform': 'azure_devops', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'latest_build', + 'unique_id': 'testorg_1234_9876_latest_build', + 'unit_of_measurement': None, + }) +# --- +# name: test_sensors[sensor.testproject_test_build_latest_build-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'definition_id': 9876, + 'definition_name': 'Test Build', + 'finish_time': '2021-01-01T00:00:00Z', + 'friendly_name': 'testproject Test Build latest build', + 'id': 5678, + 'queue_time': '2021-01-01T00:00:00Z', + 'reason': 'manual', + 'result': 'succeeded', + 'source_branch': 'main', + 'source_version': '123', + 'start_time': '2021-01-01T00:00:00Z', + 'status': 'completed', + 'url': None, + }), + 'context': , + 'entity_id': 'sensor.testproject_test_build_latest_build', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '1', + }) +# --- diff --git a/tests/components/azure_devops/test_config_flow.py b/tests/components/azure_devops/test_config_flow.py index 84c2b5d3cca..8d36b731ff2 100644 --- a/tests/components/azure_devops/test_config_flow.py +++ b/tests/components/azure_devops/test_config_flow.py @@ -1,26 +1,18 @@ """Test the Azure DevOps config flow.""" -from unittest.mock import patch +from unittest.mock import AsyncMock from aioazuredevops.core import DevOpsProject import aiohttp from homeassistant import config_entries, data_entry_flow -from homeassistant.components.azure_devops.const import ( - CONF_ORG, - CONF_PAT, - CONF_PROJECT, - DOMAIN, -) +from homeassistant.components.azure_devops.const import CONF_ORG, CONF_PROJECT, DOMAIN from homeassistant.core import HomeAssistant +from . import FIXTURE_REAUTH_INPUT, FIXTURE_USER_INPUT + from tests.common import MockConfigEntry -FIXTURE_REAUTH_INPUT = {CONF_PAT: "abc123"} -FIXTURE_USER_INPUT = {CONF_ORG: "random", CONF_PROJECT: "project", CONF_PAT: "abc123"} - -UNIQUE_ID = "random_project" - async def test_show_user_form(hass: HomeAssistant) -> None: """Test that the setup form is served.""" @@ -32,259 +24,238 @@ async def test_show_user_form(hass: HomeAssistant) -> None: assert result["step_id"] == "user" -async def test_authorization_error(hass: HomeAssistant) -> None: +async def test_authorization_error( + hass: HomeAssistant, + mock_devops_client: AsyncMock, +) -> None: """Test we show user form on Azure DevOps authorization error.""" - with patch( - "homeassistant.components.azure_devops.config_flow.DevOpsClient.authorize", - return_value=False, - ): - result = await hass.config_entries.flow.async_init( - DOMAIN, context={"source": config_entries.SOURCE_USER} - ) + mock_devops_client.authorize.return_value = False + mock_devops_client.authorized = False - assert result["type"] == data_entry_flow.FlowResultType.FORM - assert result["step_id"] == "user" + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_USER}, + ) - result2 = await hass.config_entries.flow.async_configure( - result["flow_id"], - FIXTURE_USER_INPUT, - ) - await hass.async_block_till_done() + assert result["type"] == data_entry_flow.FlowResultType.FORM + assert result["step_id"] == "user" - assert result2["type"] == data_entry_flow.FlowResultType.FORM - assert result2["step_id"] == "user" - assert result2["errors"] == {"base": "invalid_auth"} + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + FIXTURE_USER_INPUT, + ) + await hass.async_block_till_done() + + assert result2["type"] == data_entry_flow.FlowResultType.FORM + assert result2["step_id"] == "user" + assert result2["errors"] == {"base": "invalid_auth"} -async def test_reauth_authorization_error(hass: HomeAssistant) -> None: +async def test_reauth_authorization_error( + hass: HomeAssistant, + mock_devops_client: AsyncMock, +) -> None: """Test we show user form on Azure DevOps authorization error.""" - with patch( - "homeassistant.components.azure_devops.config_flow.DevOpsClient.authorize", - return_value=False, - ): - result = await hass.config_entries.flow.async_init( - DOMAIN, - context={"source": config_entries.SOURCE_REAUTH}, - data=FIXTURE_USER_INPUT, - ) + mock_devops_client.authorize.return_value = False + mock_devops_client.authorized = False - assert result["type"] == data_entry_flow.FlowResultType.FORM - assert result["step_id"] == "reauth" + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_REAUTH}, + data=FIXTURE_USER_INPUT, + ) - result2 = await hass.config_entries.flow.async_configure( - result["flow_id"], - FIXTURE_REAUTH_INPUT, - ) - await hass.async_block_till_done() + assert result["type"] == data_entry_flow.FlowResultType.FORM + assert result["step_id"] == "reauth" - assert result2["type"] == data_entry_flow.FlowResultType.FORM - assert result2["step_id"] == "reauth" - assert result2["errors"] == {"base": "invalid_auth"} + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + FIXTURE_REAUTH_INPUT, + ) + await hass.async_block_till_done() + + assert result2["type"] == data_entry_flow.FlowResultType.FORM + assert result2["step_id"] == "reauth" + assert result2["errors"] == {"base": "invalid_auth"} -async def test_connection_error(hass: HomeAssistant) -> None: +async def test_connection_error( + hass: HomeAssistant, + mock_devops_client: AsyncMock, +) -> None: """Test we show user form on Azure DevOps connection error.""" - with patch( - "homeassistant.components.azure_devops.config_flow.DevOpsClient.authorize", - side_effect=aiohttp.ClientError, - ): - result = await hass.config_entries.flow.async_init( - DOMAIN, context={"source": config_entries.SOURCE_USER} - ) + mock_devops_client.authorize.side_effect = aiohttp.ClientError + mock_devops_client.authorized = False - assert result["type"] == data_entry_flow.FlowResultType.FORM - assert result["step_id"] == "user" + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_USER}, + ) - result2 = await hass.config_entries.flow.async_configure( - result["flow_id"], - FIXTURE_USER_INPUT, - ) - await hass.async_block_till_done() + assert result["type"] == data_entry_flow.FlowResultType.FORM + assert result["step_id"] == "user" - assert result2["type"] == data_entry_flow.FlowResultType.FORM - assert result2["step_id"] == "user" - assert result2["errors"] == {"base": "cannot_connect"} + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + FIXTURE_USER_INPUT, + ) + await hass.async_block_till_done() + + assert result2["type"] == data_entry_flow.FlowResultType.FORM + assert result2["step_id"] == "user" + assert result2["errors"] == {"base": "cannot_connect"} -async def test_reauth_connection_error(hass: HomeAssistant) -> None: +async def test_reauth_connection_error( + hass: HomeAssistant, + mock_devops_client: AsyncMock, +) -> None: """Test we show user form on Azure DevOps connection error.""" - with patch( - "homeassistant.components.azure_devops.config_flow.DevOpsClient.authorize", - side_effect=aiohttp.ClientError, - ): - result = await hass.config_entries.flow.async_init( - DOMAIN, - context={"source": config_entries.SOURCE_REAUTH}, - data=FIXTURE_USER_INPUT, - ) + mock_devops_client.authorize.side_effect = aiohttp.ClientError + mock_devops_client.authorized = False - assert result["type"] == data_entry_flow.FlowResultType.FORM - assert result["step_id"] == "reauth" + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_REAUTH}, + data=FIXTURE_USER_INPUT, + ) - result2 = await hass.config_entries.flow.async_configure( - result["flow_id"], - FIXTURE_REAUTH_INPUT, - ) - await hass.async_block_till_done() + assert result["type"] == data_entry_flow.FlowResultType.FORM + assert result["step_id"] == "reauth" - assert result2["type"] == data_entry_flow.FlowResultType.FORM - assert result2["step_id"] == "reauth" - assert result2["errors"] == {"base": "cannot_connect"} + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + FIXTURE_REAUTH_INPUT, + ) + await hass.async_block_till_done() + + assert result2["type"] == data_entry_flow.FlowResultType.FORM + assert result2["step_id"] == "reauth" + assert result2["errors"] == {"base": "cannot_connect"} -async def test_project_error(hass: HomeAssistant) -> None: +async def test_project_error( + hass: HomeAssistant, + mock_devops_client: AsyncMock, +) -> None: """Test we show user form on Azure DevOps connection error.""" - with ( - patch( - "homeassistant.components.azure_devops.config_flow.DevOpsClient.authorized", - return_value=True, - ), - patch( - "homeassistant.components.azure_devops.config_flow.DevOpsClient.authorize", - ), - patch( - "homeassistant.components.azure_devops.config_flow.DevOpsClient.get_project", - return_value=None, - ), - ): - result = await hass.config_entries.flow.async_init( - DOMAIN, context={"source": config_entries.SOURCE_USER} - ) + mock_devops_client.authorize.return_value = True + mock_devops_client.authorized = True + mock_devops_client.get_project.return_value = None - assert result["type"] == data_entry_flow.FlowResultType.FORM - assert result["step_id"] == "user" + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_USER}, + ) - result2 = await hass.config_entries.flow.async_configure( - result["flow_id"], - FIXTURE_USER_INPUT, - ) - await hass.async_block_till_done() + assert result["type"] == data_entry_flow.FlowResultType.FORM + assert result["step_id"] == "user" - assert result2["type"] == data_entry_flow.FlowResultType.FORM - assert result2["step_id"] == "user" - assert result2["errors"] == {"base": "project_error"} + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + FIXTURE_USER_INPUT, + ) + await hass.async_block_till_done() + + assert result2["type"] == data_entry_flow.FlowResultType.FORM + assert result2["step_id"] == "user" + assert result2["errors"] == {"base": "project_error"} -async def test_reauth_project_error(hass: HomeAssistant) -> None: +async def test_reauth_project_error( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + mock_devops_client: AsyncMock, +) -> None: """Test we show user form on Azure DevOps project error.""" - with ( - patch( - "homeassistant.components.azure_devops.config_flow.DevOpsClient.authorize", - ), - patch( - "homeassistant.components.azure_devops.config_flow.DevOpsClient.authorized", - return_value=True, - ), - patch( - "homeassistant.components.azure_devops.config_flow.DevOpsClient.get_project", - return_value=None, - ), - ): - result = await hass.config_entries.flow.async_init( - DOMAIN, - context={"source": config_entries.SOURCE_REAUTH}, - data=FIXTURE_USER_INPUT, - ) + mock_devops_client.authorize.return_value = True + mock_devops_client.authorized = True + mock_devops_client.get_project.return_value = None - assert result["type"] == data_entry_flow.FlowResultType.FORM - assert result["step_id"] == "reauth" + mock_config_entry.add_to_hass(hass) - result2 = await hass.config_entries.flow.async_configure( - result["flow_id"], - FIXTURE_REAUTH_INPUT, - ) - await hass.async_block_till_done() + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_REAUTH}, + data=FIXTURE_USER_INPUT, + ) - assert result2["type"] == data_entry_flow.FlowResultType.FORM - assert result2["step_id"] == "reauth" - assert result2["errors"] == {"base": "project_error"} + assert result["type"] == data_entry_flow.FlowResultType.FORM + assert result["step_id"] == "reauth" + + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + FIXTURE_REAUTH_INPUT, + ) + await hass.async_block_till_done() + + assert result2["type"] == data_entry_flow.FlowResultType.FORM + assert result2["step_id"] == "reauth" + assert result2["errors"] == {"base": "project_error"} -async def test_reauth_flow(hass: HomeAssistant) -> None: +async def test_reauth_flow( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + mock_devops_client: AsyncMock, +) -> None: """Test reauth works.""" - with patch( - "homeassistant.components.azure_devops.config_flow.DevOpsClient.authorize", - return_value=False, - ): - mock_config = MockConfigEntry( - domain=DOMAIN, unique_id=UNIQUE_ID, data=FIXTURE_USER_INPUT - ) - mock_config.add_to_hass(hass) + mock_devops_client.authorize.return_value = False + mock_devops_client.authorized = False - result = await hass.config_entries.flow.async_init( - DOMAIN, - context={"source": config_entries.SOURCE_REAUTH}, - data=FIXTURE_USER_INPUT, - ) + mock_config_entry.add_to_hass(hass) - assert result["type"] == data_entry_flow.FlowResultType.FORM - assert result["step_id"] == "reauth" - assert result["errors"] == {"base": "invalid_auth"} + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_REAUTH}, + data=FIXTURE_USER_INPUT, + ) - with ( - patch( - "homeassistant.components.azure_devops.config_flow.DevOpsClient.authorize", - ), - patch( - "homeassistant.components.azure_devops.config_flow.DevOpsClient.authorized", - return_value=True, - ), - patch( - "homeassistant.components.azure_devops.config_flow.DevOpsClient.get_project", - return_value=DevOpsProject( - "abcd-abcd-abcd-abcd", FIXTURE_USER_INPUT[CONF_PROJECT] - ), - ), - ): - result2 = await hass.config_entries.flow.async_configure( - result["flow_id"], - FIXTURE_REAUTH_INPUT, - ) - await hass.async_block_till_done() + assert result["type"] == data_entry_flow.FlowResultType.FORM + assert result["step_id"] == "reauth" + assert result["errors"] == {"base": "invalid_auth"} - assert result2["type"] == data_entry_flow.FlowResultType.ABORT - assert result2["reason"] == "reauth_successful" + mock_devops_client.authorize.return_value = True + mock_devops_client.authorized = True + mock_devops_client.get_project.return_value = DevOpsProject( + "abcd-abcd-abcd-abcd", FIXTURE_USER_INPUT[CONF_PROJECT] + ) + + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + FIXTURE_REAUTH_INPUT, + ) + await hass.async_block_till_done() + + assert result2["type"] == data_entry_flow.FlowResultType.ABORT + assert result2["reason"] == "reauth_successful" -async def test_full_flow_implementation(hass: HomeAssistant) -> None: +async def test_full_flow_implementation( + hass: HomeAssistant, + mock_setup_entry: AsyncMock, + mock_devops_client: AsyncMock, +) -> None: """Test registering an integration and finishing flow works.""" - with ( - patch( - "homeassistant.components.azure_devops.async_setup_entry", - return_value=True, - ) as mock_setup_entry, - patch( - "homeassistant.components.azure_devops.config_flow.DevOpsClient.authorized", - return_value=True, - ), - patch( - "homeassistant.components.azure_devops.config_flow.DevOpsClient.authorize", - ), - patch( - "homeassistant.components.azure_devops.config_flow.DevOpsClient.get_project", - return_value=DevOpsProject( - "abcd-abcd-abcd-abcd", FIXTURE_USER_INPUT[CONF_PROJECT] - ), - ), - ): - result = await hass.config_entries.flow.async_init( - DOMAIN, context={"source": config_entries.SOURCE_USER} - ) + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_USER}, + ) - assert result["type"] == data_entry_flow.FlowResultType.FORM - assert result["step_id"] == "user" + assert result["type"] == data_entry_flow.FlowResultType.FORM + assert result["step_id"] == "user" - result2 = await hass.config_entries.flow.async_configure( - result["flow_id"], - FIXTURE_USER_INPUT, - ) - await hass.async_block_till_done() - assert len(mock_setup_entry.mock_calls) == 1 + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + FIXTURE_USER_INPUT, + ) + await hass.async_block_till_done() + assert len(mock_setup_entry.mock_calls) == 1 - assert result2["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY - assert ( - result2["title"] - == f"{FIXTURE_USER_INPUT[CONF_ORG]}/{FIXTURE_USER_INPUT[CONF_PROJECT]}" - ) - assert result2["data"][CONF_ORG] == FIXTURE_USER_INPUT[CONF_ORG] - assert result2["data"][CONF_PROJECT] == FIXTURE_USER_INPUT[CONF_PROJECT] + assert result2["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY + assert ( + result2["title"] + == f"{FIXTURE_USER_INPUT[CONF_ORG]}/{FIXTURE_USER_INPUT[CONF_PROJECT]}" + ) + assert result2["data"][CONF_ORG] == FIXTURE_USER_INPUT[CONF_ORG] + assert result2["data"][CONF_PROJECT] == FIXTURE_USER_INPUT[CONF_PROJECT] diff --git a/tests/components/azure_devops/test_init.py b/tests/components/azure_devops/test_init.py new file mode 100644 index 00000000000..58e3621914d --- /dev/null +++ b/tests/components/azure_devops/test_init.py @@ -0,0 +1,78 @@ +"""Tests for init of Azure DevOps.""" + +from unittest.mock import AsyncMock, MagicMock + +import aiohttp + +from homeassistant.config_entries import ConfigEntryState +from homeassistant.core import HomeAssistant + +from . import setup_integration + +from tests.common import MockConfigEntry + + +async def test_load_unload_entry( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + mock_devops_client: MagicMock, +) -> None: + """Test a successful setup entry.""" + assert await setup_integration(hass, mock_config_entry) + + assert mock_devops_client.authorized + assert mock_devops_client.authorize.call_count == 1 + assert mock_devops_client.get_builds.call_count == 2 + + assert mock_config_entry.state == ConfigEntryState.LOADED + + await hass.config_entries.async_remove(mock_config_entry.entry_id) + await hass.async_block_till_done() + + assert mock_config_entry.state == ConfigEntryState.NOT_LOADED + + +async def test_auth_failed( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + mock_devops_client: AsyncMock, +) -> None: + """Test a failed setup entry.""" + mock_devops_client.authorize.return_value = False + mock_devops_client.authorized = False + + await setup_integration(hass, mock_config_entry) + + assert not mock_devops_client.authorized + + assert mock_config_entry.state == ConfigEntryState.SETUP_ERROR + + +async def test_update_failed( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + mock_devops_client: MagicMock, +) -> None: + """Test a failed update entry.""" + mock_devops_client.get_builds.side_effect = aiohttp.ClientError + + await setup_integration(hass, mock_config_entry) + + assert mock_devops_client.get_builds.call_count == 1 + + assert mock_config_entry.state == ConfigEntryState.SETUP_RETRY + + +async def test_no_builds( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + mock_devops_client: MagicMock, +) -> None: + """Test a failed update entry.""" + mock_devops_client.get_builds.return_value = None + + await setup_integration(hass, mock_config_entry) + + assert mock_devops_client.get_builds.call_count == 1 + + assert mock_config_entry.state == ConfigEntryState.SETUP_RETRY diff --git a/tests/components/azure_devops/test_sensor.py b/tests/components/azure_devops/test_sensor.py new file mode 100644 index 00000000000..1c518d919c2 --- /dev/null +++ b/tests/components/azure_devops/test_sensor.py @@ -0,0 +1,33 @@ +"""Tests for init of Azure DevOps.""" + +from unittest.mock import AsyncMock + +import pytest +from syrupy.assertion import SnapshotAssertion + +from homeassistant.core import HomeAssistant +from homeassistant.helpers import entity_registry as er + +from . import setup_integration + +from tests.common import MockConfigEntry + + +@pytest.mark.usefixtures("entity_registry_enabled_by_default") +async def test_sensors( + hass: HomeAssistant, + snapshot: SnapshotAssertion, + entity_registry: er.EntityRegistry, + mock_config_entry: MockConfigEntry, + mock_devops_client: AsyncMock, +) -> None: + """Test the sensor entities.""" + assert await setup_integration(hass, mock_config_entry) + + assert ( + entry := entity_registry.async_get("sensor.testproject_test_build_latest_build") + ) + + assert entry == snapshot(name=f"{entry.entity_id}-entry") + + assert hass.states.get(entry.entity_id) == snapshot(name=f"{entry.entity_id}-state")