Files
core/tests/scripts/test_gen_integration_paths.py
T

123 lines
3.8 KiB
Python

"""Test the gen_integration_paths script."""
from collections.abc import Generator
import json
from pathlib import Path
from unittest.mock import patch
import pytest
from script import gen_integration_paths
from script.gen_integration_paths import (
generate,
get_core_integrations,
get_transitive_dependencies,
main,
)
CORE_FILES = """
base_platforms: &base_platforms
- homeassistant/components/sensor/**
components: &components
# http is used by a lot of integrations
- homeassistant/components/http/**
"""
@pytest.fixture
def components_dir(tmp_path: Path) -> Generator[Path]:
"""Create integrations with a dependency on each other."""
dependencies = {
"http": [],
"twilio": ["http"],
"twilio_call": ["twilio"],
"twilio_sms": ["twilio"],
}
components_dir = tmp_path / "homeassistant" / "components"
for integration, integration_dependencies in dependencies.items():
manifest_path = components_dir / integration / "manifest.json"
manifest_path.parent.mkdir(parents=True)
manifest_path.write_text(
json.dumps(
{"domain": integration, "dependencies": integration_dependencies}
)
)
with patch.object(gen_integration_paths, "COMPONENTS_DIR", components_dir):
yield components_dir
@pytest.fixture
def core_files(tmp_path: Path) -> Generator[Path]:
"""Create a core files config."""
core_files = tmp_path / ".core_files.yaml"
core_files.write_text(CORE_FILES)
with patch.object(gen_integration_paths, "CORE_FILES", core_files):
yield core_files
@pytest.mark.usefixtures("core_files")
def test_get_core_integrations() -> None:
"""Test that both base platforms and components are picked up."""
assert get_core_integrations() == {"http", "sensor"}
@pytest.mark.parametrize(
("dependencies", "expected"),
[
pytest.param(
{"a": ["b"], "b": [], "c": []},
{"a": {"b"}, "b": set(), "c": set()},
id="direct",
),
pytest.param(
{"a": ["b"], "b": ["c"], "c": []},
{"a": {"b", "c"}, "b": {"c"}, "c": set()},
id="transitive",
),
pytest.param(
{"a": ["b"], "b": ["a"]},
{"a": {"b"}, "b": {"a"}},
id="cycle",
),
pytest.param(
{"a": ["a"]},
{"a": set()},
id="self",
),
pytest.param(
{"a": ["missing"]},
{"a": set()},
id="unknown-dependency",
),
],
)
def test_get_transitive_dependencies(
dependencies: dict[str, list[str]], expected: dict[str, set[str]]
) -> None:
"""Test that dependencies are resolved recursively."""
assert get_transitive_dependencies(dependencies) == expected
@pytest.mark.usefixtures("components_dir", "core_files")
def test_generate() -> None:
"""Test that dependencies are added, except the ones triggering a full run."""
assert generate() == (
"http: [homeassistant/components/http/**, tests/components/http/**]\n"
"twilio: [homeassistant/components/twilio/**, tests/components/twilio/**]\n"
"twilio_call: [homeassistant/components/twilio_call/**, "
"tests/components/twilio_call/**, homeassistant/components/twilio/**]\n"
"twilio_sms: [homeassistant/components/twilio_sms/**, "
"tests/components/twilio_sms/**, homeassistant/components/twilio/**]\n"
)
@pytest.mark.usefixtures("components_dir", "core_files")
def test_main(tmp_path: Path) -> None:
"""Test that the config is written to the output file."""
output_file = tmp_path / ".integration_paths.yaml"
with patch.object(gen_integration_paths, "OUTPUT_FILE", output_file):
main()
assert output_file.read_text() == generate()