Improve type hints in axis tests (#119260)

* Improve type hints in axis tests

* A couple more

* One more

* Improve light

* Improve hub

* Improve config-flow
This commit is contained in:
epenet 2024-06-10 08:49:43 +02:00 committed by GitHub
parent 2d2f5de191
commit d9362a2f2f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 101 additions and 71 deletions

View file

@ -111,10 +111,10 @@ def config_entry_options_fixture() -> MappingProxyType[str, Any]:
@pytest.fixture(name="mock_vapix_requests")
def default_request_fixture(
respx_mock: respx,
respx_mock: respx.MockRouter,
port_management_payload: dict[str, Any],
param_properties_payload: dict[str, Any],
param_ports_payload: dict[str, Any],
param_properties_payload: str,
param_ports_payload: str,
mqtt_status_code: int,
) -> Callable[[str], None]:
"""Mock default Vapix requests responses."""
@ -230,19 +230,19 @@ def io_port_management_data_fixture() -> dict[str, Any]:
@pytest.fixture(name="param_properties_payload")
def param_properties_data_fixture() -> dict[str, Any]:
def param_properties_data_fixture() -> str:
"""Property parameter data."""
return PROPERTIES_RESPONSE
@pytest.fixture(name="param_ports_payload")
def param_ports_data_fixture() -> dict[str, Any]:
def param_ports_data_fixture() -> str:
"""Property parameter data."""
return PORTS_RESPONSE
@pytest.fixture(name="mqtt_status_code")
def mqtt_status_code_fixture():
def mqtt_status_code_fixture() -> int:
"""Property parameter data."""
return 200

View file

@ -1,6 +1,7 @@
"""Axis binary sensor platform tests."""
from collections.abc import Callable
from typing import Any
import pytest
@ -8,7 +9,6 @@ from homeassistant.components.binary_sensor import (
DOMAIN as BINARY_SENSOR_DOMAIN,
BinarySensorDeviceClass,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import STATE_OFF, STATE_ON
from homeassistant.core import HomeAssistant
@ -173,12 +173,12 @@ from .const import NAME
),
],
)
@pytest.mark.usefixtures("setup_config_entry")
async def test_binary_sensors(
hass: HomeAssistant,
setup_config_entry: ConfigEntry,
mock_rtsp_event: Callable[[str, str, str, str, str, str], None],
event: dict[str, str],
entity: dict[str, str],
entity: dict[str, Any],
) -> None:
"""Test that sensors are loaded properly."""
mock_rtsp_event(**event)
@ -225,9 +225,9 @@ async def test_binary_sensors(
},
],
)
@pytest.mark.usefixtures("setup_config_entry")
async def test_unsupported_events(
hass: HomeAssistant,
setup_config_entry: ConfigEntry,
mock_rtsp_event: Callable[[str, str, str, str, str, str], None],
event: dict[str, str],
) -> None:

View file

@ -30,7 +30,8 @@ async def test_platform_manually_configured(hass: HomeAssistant) -> None:
assert AXIS_DOMAIN not in hass.data
async def test_camera(hass: HomeAssistant, setup_config_entry: ConfigEntry) -> None:
@pytest.mark.usefixtures("setup_config_entry")
async def test_camera(hass: HomeAssistant) -> None:
"""Test that Axis camera platform is loaded properly."""
assert len(hass.states.async_entity_ids(CAMERA_DOMAIN)) == 1
@ -50,9 +51,8 @@ async def test_camera(hass: HomeAssistant, setup_config_entry: ConfigEntry) -> N
@pytest.mark.parametrize("config_entry_options", [{CONF_STREAM_PROFILE: "profile_1"}])
async def test_camera_with_stream_profile(
hass: HomeAssistant, setup_config_entry: ConfigEntry
) -> None:
@pytest.mark.usefixtures("setup_config_entry")
async def test_camera_with_stream_profile(hass: HomeAssistant) -> None:
"""Test that Axis camera entity is using the correct path with stream profike."""
assert len(hass.states.async_entity_ids(CAMERA_DOMAIN)) == 1
@ -74,7 +74,7 @@ async def test_camera_with_stream_profile(
)
property_data = f"""root.Properties.API.HTTP.Version=3
PROPERTY_DATA = f"""root.Properties.API.HTTP.Version=3
root.Properties.API.Metadata.Metadata=yes
root.Properties.API.Metadata.Version=1.0
root.Properties.EmbeddedDevelopment.Version=2.16
@ -85,7 +85,7 @@ root.Properties.System.SerialNumber={MAC}
"""
@pytest.mark.parametrize("param_properties_payload", [property_data])
@pytest.mark.parametrize("param_properties_payload", [PROPERTY_DATA])
async def test_camera_disabled(
hass: HomeAssistant, prepare_config_entry: Callable[[], ConfigEntry]
) -> None:

View file

@ -1,7 +1,8 @@
"""Test Axis config flow."""
from collections.abc import Callable
from ipaddress import ip_address
from unittest.mock import patch
from unittest.mock import AsyncMock, patch
import pytest
@ -22,6 +23,7 @@ from homeassistant.config_entries import (
SOURCE_SSDP,
SOURCE_USER,
SOURCE_ZEROCONF,
ConfigEntry,
)
from homeassistant.const import (
CONF_HOST,
@ -33,7 +35,7 @@ from homeassistant.const import (
CONF_USERNAME,
)
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from homeassistant.data_entry_flow import BaseServiceInfo, FlowResultType
from homeassistant.helpers import device_registry as dr
from .const import DEFAULT_HOST, MAC, MODEL, NAME
@ -44,16 +46,17 @@ DHCP_FORMATTED_MAC = dr.format_mac(MAC).replace(":", "")
@pytest.fixture(name="mock_config_entry")
async def mock_config_entry_fixture(hass, config_entry, mock_setup_entry):
async def mock_config_entry_fixture(
hass: HomeAssistant, config_entry: MockConfigEntry, mock_setup_entry: AsyncMock
) -> MockConfigEntry:
"""Mock config entry and setup entry."""
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
return config_entry
async def test_flow_manual_configuration(
hass: HomeAssistant, setup_default_vapix_requests, mock_setup_entry
) -> None:
@pytest.mark.usefixtures("setup_default_vapix_requests", "mock_setup_entry")
async def test_flow_manual_configuration(hass: HomeAssistant) -> None:
"""Test that config flow works."""
MockConfigEntry(domain=AXIS_DOMAIN, source=SOURCE_IGNORE).add_to_hass(hass)
@ -89,7 +92,9 @@ async def test_flow_manual_configuration(
async def test_manual_configuration_update_configuration(
hass: HomeAssistant, mock_config_entry, mock_vapix_requests
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_vapix_requests: Callable[[str], None],
) -> None:
"""Test that config flow fails on already configured device."""
assert mock_config_entry.data[CONF_HOST] == "1.2.3.4"
@ -173,8 +178,9 @@ async def test_flow_fails_cannot_connect(hass: HomeAssistant) -> None:
assert result["errors"] == {"base": "cannot_connect"}
@pytest.mark.usefixtures("setup_default_vapix_requests", "mock_setup_entry")
async def test_flow_create_entry_multiple_existing_entries_of_same_model(
hass: HomeAssistant, setup_default_vapix_requests, mock_setup_entry
hass: HomeAssistant,
) -> None:
"""Test that create entry can generate a name with other entries."""
entry = MockConfigEntry(
@ -222,7 +228,9 @@ async def test_flow_create_entry_multiple_existing_entries_of_same_model(
async def test_reauth_flow_update_configuration(
hass: HomeAssistant, mock_config_entry, mock_vapix_requests
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_vapix_requests: Callable[[str], None],
) -> None:
"""Test that config flow fails on already configured device."""
assert mock_config_entry.data[CONF_HOST] == "1.2.3.4"
@ -261,7 +269,9 @@ async def test_reauth_flow_update_configuration(
async def test_reconfiguration_flow_update_configuration(
hass: HomeAssistant, mock_config_entry, mock_vapix_requests
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_vapix_requests: Callable[[str], None],
) -> None:
"""Test that config flow reconfiguration updates configured device."""
assert mock_config_entry.data[CONF_HOST] == "1.2.3.4"
@ -362,12 +372,11 @@ async def test_reconfiguration_flow_update_configuration(
),
],
)
@pytest.mark.usefixtures("setup_default_vapix_requests", "mock_setup_entry")
async def test_discovery_flow(
hass: HomeAssistant,
setup_default_vapix_requests,
source: str,
discovery_info: dict,
mock_setup_entry,
discovery_info: BaseServiceInfo,
) -> None:
"""Test the different discovery flows for new devices work."""
result = await hass.config_entries.flow.async_init(
@ -445,7 +454,10 @@ async def test_discovery_flow(
],
)
async def test_discovered_device_already_configured(
hass: HomeAssistant, mock_config_entry, source: str, discovery_info: dict
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
source: str,
discovery_info: BaseServiceInfo,
) -> None:
"""Test that discovery doesn't setup already configured devices."""
assert mock_config_entry.data[CONF_HOST] == DEFAULT_HOST
@ -501,10 +513,10 @@ async def test_discovered_device_already_configured(
)
async def test_discovery_flow_updated_configuration(
hass: HomeAssistant,
mock_config_entry,
mock_vapix_requests,
mock_config_entry: MockConfigEntry,
mock_vapix_requests: Callable[[str], None],
source: str,
discovery_info: dict,
discovery_info: BaseServiceInfo,
expected_port: int,
) -> None:
"""Test that discovery flow update configuration with new parameters."""
@ -573,7 +585,7 @@ async def test_discovery_flow_updated_configuration(
],
)
async def test_discovery_flow_ignore_non_axis_device(
hass: HomeAssistant, source: str, discovery_info: dict
hass: HomeAssistant, source: str, discovery_info: BaseServiceInfo
) -> None:
"""Test that discovery flow ignores devices with non Axis OUI."""
result = await hass.config_entries.flow.async_init(
@ -622,7 +634,7 @@ async def test_discovery_flow_ignore_non_axis_device(
],
)
async def test_discovery_flow_ignore_link_local_address(
hass: HomeAssistant, source: str, discovery_info: dict
hass: HomeAssistant, source: str, discovery_info: BaseServiceInfo
) -> None:
"""Test that discovery flow ignores devices with link local addresses."""
result = await hass.config_entries.flow.async_init(
@ -633,7 +645,9 @@ async def test_discovery_flow_ignore_link_local_address(
assert result["reason"] == "link_local_address"
async def test_option_flow(hass: HomeAssistant, setup_config_entry) -> None:
async def test_option_flow(
hass: HomeAssistant, setup_config_entry: ConfigEntry
) -> None:
"""Test config flow options."""
assert CONF_STREAM_PROFILE not in setup_config_entry.options
assert CONF_VIDEO_SOURCE not in setup_config_entry.options

View file

@ -3,6 +3,7 @@
import pytest
from syrupy import SnapshotAssertion
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from .const import API_DISCOVERY_BASIC_DEVICE_INFO
@ -15,7 +16,7 @@ from tests.typing import ClientSessionGenerator
async def test_entry_diagnostics(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
setup_config_entry,
setup_config_entry: ConfigEntry,
snapshot: SnapshotAssertion,
) -> None:
"""Test config entry diagnostics."""

View file

@ -1,16 +1,20 @@
"""Test Axis device."""
from collections.abc import Callable
from ipaddress import ip_address
from types import MappingProxyType
from typing import Any
from unittest import mock
from unittest.mock import ANY, Mock, call, patch
from unittest.mock import ANY, AsyncMock, Mock, call, patch
import axis as axislib
import pytest
from typing_extensions import Generator
from homeassistant.components import axis, zeroconf
from homeassistant.components.axis.const import DOMAIN as AXIS_DOMAIN
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
from homeassistant.config_entries import SOURCE_ZEROCONF
from homeassistant.config_entries import SOURCE_ZEROCONF, ConfigEntry
from homeassistant.const import (
CONF_HOST,
CONF_MODEL,
@ -35,7 +39,7 @@ from tests.typing import MqttMockHAClient
@pytest.fixture(name="forward_entry_setups")
def hass_mock_forward_entry_setup(hass):
def hass_mock_forward_entry_setup(hass: HomeAssistant) -> Generator[AsyncMock]:
"""Mock async_forward_entry_setups."""
with patch.object(
hass.config_entries, "async_forward_entry_setups"
@ -44,10 +48,9 @@ def hass_mock_forward_entry_setup(hass):
async def test_device_setup(
hass: HomeAssistant,
forward_entry_setups,
config_entry_data,
setup_config_entry,
forward_entry_setups: AsyncMock,
config_entry_data: MappingProxyType[str, Any],
setup_config_entry: ConfigEntry,
device_registry: dr.DeviceRegistry,
) -> None:
"""Successful setup."""
@ -75,7 +78,7 @@ async def test_device_setup(
@pytest.mark.parametrize("api_discovery_items", [API_DISCOVERY_BASIC_DEVICE_INFO])
async def test_device_info(hass: HomeAssistant, setup_config_entry) -> None:
async def test_device_info(setup_config_entry: ConfigEntry) -> None:
"""Verify other path of device information works."""
hub = setup_config_entry.runtime_data
@ -86,8 +89,9 @@ async def test_device_info(hass: HomeAssistant, setup_config_entry) -> None:
@pytest.mark.parametrize("api_discovery_items", [API_DISCOVERY_MQTT])
@pytest.mark.usefixtures("setup_config_entry")
async def test_device_support_mqtt(
hass: HomeAssistant, mqtt_mock: MqttMockHAClient, setup_config_entry
hass: HomeAssistant, mqtt_mock: MqttMockHAClient
) -> None:
"""Successful setup."""
mqtt_call = call(f"axis/{MAC}/#", mock.ANY, 0, "utf-8", ANY)
@ -111,16 +115,17 @@ async def test_device_support_mqtt(
@pytest.mark.parametrize("api_discovery_items", [API_DISCOVERY_MQTT])
@pytest.mark.parametrize("mqtt_status_code", [401])
async def test_device_support_mqtt_low_privilege(
hass: HomeAssistant, mqtt_mock: MqttMockHAClient, setup_config_entry
) -> None:
@pytest.mark.usefixtures("setup_config_entry")
async def test_device_support_mqtt_low_privilege(mqtt_mock: MqttMockHAClient) -> None:
"""Successful setup."""
mqtt_call = call(f"{MAC}/#", mock.ANY, 0, "utf-8")
assert mqtt_call not in mqtt_mock.async_subscribe.call_args_list
async def test_update_address(
hass: HomeAssistant, setup_config_entry, mock_vapix_requests
hass: HomeAssistant,
setup_config_entry: ConfigEntry,
mock_vapix_requests: Callable[[str], None],
) -> None:
"""Test update address works."""
hub = setup_config_entry.runtime_data
@ -145,8 +150,11 @@ async def test_update_address(
assert hub.api.config.host == "2.3.4.5"
@pytest.mark.usefixtures("setup_config_entry")
async def test_device_unavailable(
hass: HomeAssistant, setup_config_entry, mock_rtsp_event, mock_rtsp_signal_state
hass: HomeAssistant,
mock_rtsp_event: Callable[[str, str, str, str, str, str], None],
mock_rtsp_signal_state: Callable[[bool], None],
) -> None:
"""Successful setup."""
# Provide an entity that can be used to verify connection state on
@ -179,8 +187,9 @@ async def test_device_unavailable(
assert hass.states.get(f"{BINARY_SENSOR_DOMAIN}.{NAME}_sound_1").state == STATE_OFF
@pytest.mark.usefixtures("setup_default_vapix_requests")
async def test_device_not_accessible(
hass: HomeAssistant, config_entry, setup_default_vapix_requests
hass: HomeAssistant, config_entry: ConfigEntry
) -> None:
"""Failed setup schedules a retry of setup."""
with patch.object(axis, "get_axis_api", side_effect=axis.errors.CannotConnect):
@ -189,8 +198,9 @@ async def test_device_not_accessible(
assert hass.data[AXIS_DOMAIN] == {}
@pytest.mark.usefixtures("setup_default_vapix_requests")
async def test_device_trigger_reauth_flow(
hass: HomeAssistant, config_entry, setup_default_vapix_requests
hass: HomeAssistant, config_entry: ConfigEntry
) -> None:
"""Failed authentication trigger a reauthentication flow."""
with (
@ -205,8 +215,9 @@ async def test_device_trigger_reauth_flow(
assert hass.data[AXIS_DOMAIN] == {}
@pytest.mark.usefixtures("setup_default_vapix_requests")
async def test_device_unknown_error(
hass: HomeAssistant, config_entry, setup_default_vapix_requests
hass: HomeAssistant, config_entry: ConfigEntry
) -> None:
"""Unknown errors are handled."""
with patch.object(axis, "get_axis_api", side_effect=Exception):
@ -215,7 +226,7 @@ async def test_device_unknown_error(
assert hass.data[AXIS_DOMAIN] == {}
async def test_shutdown(config_entry_data) -> None:
async def test_shutdown(config_entry_data: MappingProxyType[str, Any]) -> None:
"""Successful shutdown."""
hass = Mock()
entry = Mock()
@ -230,7 +241,9 @@ async def test_shutdown(config_entry_data) -> None:
assert len(axis_device.api.stream.stop.mock_calls) == 1
async def test_get_device_fails(hass: HomeAssistant, config_entry_data) -> None:
async def test_get_device_fails(
hass: HomeAssistant, config_entry_data: MappingProxyType[str, Any]
) -> None:
"""Device unauthorized yields authentication required error."""
with (
patch(
@ -242,7 +255,7 @@ async def test_get_device_fails(hass: HomeAssistant, config_entry_data) -> None:
async def test_get_device_device_unavailable(
hass: HomeAssistant, config_entry_data
hass: HomeAssistant, config_entry_data: MappingProxyType[str, Any]
) -> None:
"""Device unavailable yields cannot connect error."""
with (
@ -252,7 +265,9 @@ async def test_get_device_device_unavailable(
await axis.hub.get_axis_api(hass, config_entry_data)
async def test_get_device_unknown_error(hass: HomeAssistant, config_entry_data) -> None:
async def test_get_device_unknown_error(
hass: HomeAssistant, config_entry_data: MappingProxyType[str, Any]
) -> None:
"""Device yield unknown error."""
with (
patch("axis.interfaces.vapix.Vapix.request", side_effect=axislib.AxisException),

View file

@ -5,16 +5,18 @@ from unittest.mock import AsyncMock, Mock, patch
import pytest
from homeassistant.components import axis
from homeassistant.config_entries import ConfigEntryState
from homeassistant.config_entries import ConfigEntry, ConfigEntryState
from homeassistant.core import HomeAssistant
async def test_setup_entry(hass: HomeAssistant, setup_config_entry) -> None:
async def test_setup_entry(setup_config_entry: ConfigEntry) -> None:
"""Test successful setup of entry."""
assert setup_config_entry.state is ConfigEntryState.LOADED
async def test_setup_entry_fails(hass: HomeAssistant, config_entry) -> None:
async def test_setup_entry_fails(
hass: HomeAssistant, config_entry: ConfigEntry
) -> None:
"""Test successful setup of entry."""
mock_device = Mock()
mock_device.async_setup = AsyncMock(return_value=False)
@ -27,7 +29,9 @@ async def test_setup_entry_fails(hass: HomeAssistant, config_entry) -> None:
assert config_entry.state is ConfigEntryState.SETUP_ERROR
async def test_unload_entry(hass: HomeAssistant, setup_config_entry) -> None:
async def test_unload_entry(
hass: HomeAssistant, setup_config_entry: ConfigEntry
) -> None:
"""Test successful unload of entry."""
assert setup_config_entry.state is ConfigEntryState.LOADED
@ -36,7 +40,7 @@ async def test_unload_entry(hass: HomeAssistant, setup_config_entry) -> None:
@pytest.mark.parametrize("config_entry_version", [1])
async def test_migrate_entry(hass: HomeAssistant, config_entry) -> None:
async def test_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> None:
"""Test successful migration of entry data."""
assert config_entry.version == 1

View file

@ -9,7 +9,6 @@ import pytest
import respx
from homeassistant.components.light import ATTR_BRIGHTNESS, DOMAIN as LIGHT_DOMAIN
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_ENTITY_ID,
SERVICE_TURN_OFF,
@ -70,9 +69,9 @@ def light_control_fixture(light_control_items: list[dict[str, Any]]) -> None:
@pytest.mark.parametrize("api_discovery_items", [API_DISCOVERY_LIGHT_CONTROL])
@pytest.mark.parametrize("light_control_items", [[]])
@pytest.mark.usefixtures("setup_config_entry")
async def test_no_light_entity_without_light_control_representation(
hass: HomeAssistant,
setup_config_entry: ConfigEntry,
mock_rtsp_event: Callable[[str, str, str, str, str, str], None],
) -> None:
"""Verify no lights entities get created without light control representation."""
@ -89,12 +88,10 @@ async def test_no_light_entity_without_light_control_representation(
@pytest.mark.parametrize("api_discovery_items", [API_DISCOVERY_LIGHT_CONTROL])
@pytest.mark.usefixtures("setup_config_entry")
async def test_lights(
hass: HomeAssistant,
respx_mock: respx,
setup_config_entry: ConfigEntry,
mock_rtsp_event: Callable[[str, str, str, str, str, str], None],
api_discovery_items: dict[str, Any],
) -> None:
"""Test that lights are loaded properly."""
# Add light

View file

@ -7,7 +7,6 @@ from axis.models.api import CONTEXT
import pytest
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_ENTITY_ID,
SERVICE_TURN_OFF,
@ -31,9 +30,9 @@ root.IOPort.I1.Output.Active=open
@pytest.mark.parametrize("param_ports_payload", [PORT_DATA])
@pytest.mark.usefixtures("setup_config_entry")
async def test_switches_with_port_cgi(
hass: HomeAssistant,
setup_config_entry: ConfigEntry,
mock_rtsp_event: Callable[[str, str, str, str, str, str], None],
) -> None:
"""Test that switches are loaded properly using port.cgi."""
@ -116,9 +115,9 @@ PORT_MANAGEMENT_RESPONSE = {
@pytest.mark.parametrize("api_discovery_items", [API_DISCOVERY_PORT_MANAGEMENT])
@pytest.mark.parametrize("port_management_payload", [PORT_MANAGEMENT_RESPONSE])
@pytest.mark.usefixtures("setup_config_entry")
async def test_switches_with_port_management(
hass: HomeAssistant,
setup_config_entry: ConfigEntry,
mock_rtsp_event: Callable[[str, str, str, str, str, str], None],
) -> None:
"""Test that switches are loaded properly using port management."""