mirror of
https://github.com/home-assistant/core.git
synced 2026-04-18 07:56:03 +01:00
Add hassfest check to make sure new integrations have an integration type (#164001)
This commit is contained in:
committed by
GitHub
parent
56b4d2c015
commit
b1578a0c8c
@@ -21,6 +21,7 @@ from . import (
|
||||
docker,
|
||||
icons,
|
||||
integration_info,
|
||||
integration_type,
|
||||
json,
|
||||
labs,
|
||||
manifest,
|
||||
@@ -48,6 +49,7 @@ INTEGRATION_PLUGINS = [
|
||||
dhcp,
|
||||
icons,
|
||||
integration_info,
|
||||
integration_type,
|
||||
json,
|
||||
labs,
|
||||
manifest,
|
||||
|
||||
100
script/hassfest/integration_type.py
Normal file
100
script/hassfest/integration_type.py
Normal file
@@ -0,0 +1,100 @@
|
||||
"""Validate integration type is set for config flow integrations."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from .model import Config, Integration
|
||||
|
||||
# Integrations with config_flow that are missing integration_type.
|
||||
# These need to be fixed; do not add new entries to this list.
|
||||
MISSING_INTEGRATION_TYPE = {
|
||||
"abode",
|
||||
"acmeda",
|
||||
"adax",
|
||||
"awair",
|
||||
"bluetooth",
|
||||
"bthome",
|
||||
"chacon_dio",
|
||||
"color_extractor",
|
||||
"crownstone",
|
||||
"deako",
|
||||
"dialogflow",
|
||||
"dynalite",
|
||||
"elmax",
|
||||
"emulated_roku",
|
||||
"ezviz",
|
||||
"file",
|
||||
"filesize",
|
||||
"fluss",
|
||||
"flux_led",
|
||||
"folder_watcher",
|
||||
"forked_daapd",
|
||||
"geniushub",
|
||||
"gentex_homelink",
|
||||
"geofency",
|
||||
"govee_light_local",
|
||||
"gpsd",
|
||||
"gpslogger",
|
||||
"gree",
|
||||
"holiday",
|
||||
"homekit",
|
||||
"html5",
|
||||
"ifttt",
|
||||
"influxdb",
|
||||
"ios",
|
||||
"jewish_calendar",
|
||||
"local_calendar",
|
||||
"local_file",
|
||||
"local_ip",
|
||||
"local_todo",
|
||||
"locative",
|
||||
"mcp",
|
||||
"media_extractor",
|
||||
"mill",
|
||||
"mjpeg",
|
||||
"modern_forms",
|
||||
"ness_alarm",
|
||||
"nmap_tracker",
|
||||
"otp",
|
||||
"orvibo",
|
||||
"profiler",
|
||||
"proximity",
|
||||
"rhasspy",
|
||||
"risco",
|
||||
"rpi_power",
|
||||
"scrape",
|
||||
"shopping_list",
|
||||
"sql",
|
||||
"sunweg",
|
||||
"systemmonitor",
|
||||
"tasmota",
|
||||
"traccar",
|
||||
"traccar_server",
|
||||
"upb",
|
||||
"version",
|
||||
"volvooncall",
|
||||
"wemo",
|
||||
"zodiac",
|
||||
}
|
||||
|
||||
|
||||
def validate(integrations: dict[str, Integration], config: Config) -> None:
|
||||
"""Validate that all config flow integrations declare an integration type."""
|
||||
for integration in integrations.values():
|
||||
if not integration.config_flow or not integration.core:
|
||||
continue
|
||||
|
||||
if "integration_type" in integration.manifest:
|
||||
if integration.domain in MISSING_INTEGRATION_TYPE:
|
||||
integration.add_error(
|
||||
"integration_type",
|
||||
"Integration has an `integration_type` in the manifest but is still listed in MISSING_INTEGRATION_TYPE",
|
||||
)
|
||||
continue
|
||||
|
||||
if integration.domain in MISSING_INTEGRATION_TYPE:
|
||||
continue
|
||||
|
||||
integration.add_error(
|
||||
"integration_type",
|
||||
"Integration has a config flow but is missing an `integration_type` in the manifest",
|
||||
)
|
||||
92
tests/hassfest/test_integration_type.py
Normal file
92
tests/hassfest/test_integration_type.py
Normal file
@@ -0,0 +1,92 @@
|
||||
"""Tests for hassfest integration_type."""
|
||||
|
||||
import pytest
|
||||
|
||||
from script.hassfest import integration_type
|
||||
from script.hassfest.model import Config, Integration
|
||||
|
||||
from . import get_integration
|
||||
|
||||
|
||||
def _get_integration(domain: str, config: Config, manifest_extra: dict) -> Integration:
|
||||
"""Helper to create an integration with extra manifest keys."""
|
||||
integration = get_integration(domain, config)
|
||||
integration.manifest.update(manifest_extra)
|
||||
return integration
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_core_integration")
|
||||
def test_integration_with_config_flow_and_integration_type(config: Config) -> None:
|
||||
"""Integration with config_flow and integration_type should pass without errors."""
|
||||
integrations = {
|
||||
"test": _get_integration(
|
||||
"test",
|
||||
config,
|
||||
{"config_flow": True, "integration_type": "device"},
|
||||
)
|
||||
}
|
||||
integration_type.validate(integrations, config)
|
||||
assert integrations["test"].errors == []
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_core_integration")
|
||||
def test_integration_with_config_flow_missing_integration_type(config: Config) -> None:
|
||||
"""Integration with config_flow but no integration_type and not in allowlist should error."""
|
||||
integrations = {
|
||||
"test": _get_integration(
|
||||
"test",
|
||||
config,
|
||||
{"config_flow": True},
|
||||
)
|
||||
}
|
||||
integration_type.validate(integrations, config)
|
||||
assert len(integrations["test"].errors) == 1
|
||||
assert "missing an `integration_type`" in integrations["test"].errors[0].error
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_core_integration")
|
||||
def test_integration_with_config_flow_in_allowlist(config: Config) -> None:
|
||||
"""Integration with config_flow but no integration_type and in allowlist should pass."""
|
||||
domain = next(iter(integration_type.MISSING_INTEGRATION_TYPE))
|
||||
integrations = {
|
||||
domain: _get_integration(
|
||||
domain,
|
||||
config,
|
||||
{"config_flow": True},
|
||||
)
|
||||
}
|
||||
integration_type.validate(integrations, config)
|
||||
assert integrations[domain].errors == []
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_core_integration")
|
||||
def test_integration_with_integration_type_still_in_allowlist(config: Config) -> None:
|
||||
"""Integration with integration_type but still in allowlist should error."""
|
||||
domain = next(iter(integration_type.MISSING_INTEGRATION_TYPE))
|
||||
integrations = {
|
||||
domain: _get_integration(
|
||||
domain,
|
||||
config,
|
||||
{"config_flow": True, "integration_type": "device"},
|
||||
)
|
||||
}
|
||||
integration_type.validate(integrations, config)
|
||||
assert len(integrations[domain].errors) == 1
|
||||
assert (
|
||||
"still listed in MISSING_INTEGRATION_TYPE"
|
||||
in integrations[domain].errors[0].error
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_core_integration")
|
||||
def test_integration_without_config_flow_skipped(config: Config) -> None:
|
||||
"""Integration without config_flow should be skipped regardless of integration_type."""
|
||||
integrations = {
|
||||
"test": _get_integration(
|
||||
"test",
|
||||
config,
|
||||
{},
|
||||
)
|
||||
}
|
||||
integration_type.validate(integrations, config)
|
||||
assert integrations["test"].errors == []
|
||||
Reference in New Issue
Block a user