You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
5.5 KiB

from __future__ import annotations
import sys
import tempfile
import textwrap
import unittest
from pathlib import Path
TOOLS = Path(__file__).resolve().parents[1] / "tools"
sys.path.insert(0, str(TOOLS))
from validate_dashboards import ValidationError, validate_repository # noqa: E402
HEADER = """\
######################################################################
# @CCOSTAN - Follow Me on X
# For more info visit https://www.vcloudinfo.com/click-here
# Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig
# -------------------------------------------------------------------
"""
class DashboardValidatorTests(unittest.TestCase):
def setUp(self) -> None:
self.tempdir = tempfile.TemporaryDirectory(prefix="dashboard-validator-")
self.root = Path(self.tempdir.name)
(self.root / "tools").mkdir()
(self.root / "config" / "packages").mkdir(parents=True)
(self.root / "config" / "dashboards" / "overview" / "views").mkdir(
parents=True
)
(self.root / "tools" / "dashboard_entity_allowlist.txt").write_text(
"# fixture allowlist\n", encoding="utf-8"
)
self._write(
"config/configuration.yaml",
"""
lovelace:
resource_mode: yaml
resources: !include dashboards/resources.yaml
dashboards:
lovelace:
mode: yaml
filename: ui-lovelace.yaml
""",
)
self._write(
"config/ui-lovelace.yaml",
"!include /config/dashboards/overview/dashboard.yaml\n",
dedent=False,
)
self._write("config/dashboards/resources.yaml", HEADER + "[]\n", dedent=False)
self._write(
"config/dashboards/overview/dashboard.yaml",
HEADER
+ "views: !include_dir_list /config/dashboards/overview/views\n",
dedent=False,
)
self._write(
"config/dashboards/overview/views/01_home.yaml",
HEADER
+ """\
title: Home
path: home
type: sections
sections:
- type: grid
cards:
- type: entity
entity: sensor.real
""",
dedent=False,
)
self._write(
"config/packages/entities.yaml",
"sensor.real\n",
dedent=False,
)
def tearDown(self) -> None:
self.tempdir.cleanup()
def _write(self, relative: str, content: str, *, dedent: bool = True) -> Path:
path = self.root / relative
path.parent.mkdir(parents=True, exist_ok=True)
value = textwrap.dedent(content).lstrip() if dedent else content
path.write_text(value, encoding="utf-8")
return path
def test_valid_fixture_builds_routes(self) -> None:
result = validate_repository(self.root)
self.assertEqual(result.routes, ("/lovelace", "/lovelace/home"))
self.assertIn("sensor.real", result.entity_references)
def test_malformed_dashboard_yaml_fails(self) -> None:
path = self.root / "config/dashboards/overview/dashboard.yaml"
path.write_text(path.read_text(encoding="utf-8") + "broken: [\n", encoding="utf-8")
with self.assertRaisesRegex(ValidationError, "invalid YAML"):
validate_repository(self.root)
def test_missing_entrypoint_include_fails(self) -> None:
self._write(
"config/ui-lovelace.yaml",
"!include /config/dashboards/overview/missing.yaml\n",
dedent=False,
)
with self.assertRaisesRegex(ValidationError, "missing include file"):
validate_repository(self.root)
def test_nonexistent_static_entity_fails(self) -> None:
path = self.root / "config/dashboards/overview/views/01_home.yaml"
path.write_text(
path.read_text(encoding="utf-8").replace("sensor.real", "sensor.missing"),
encoding="utf-8",
)
with self.assertRaisesRegex(ValidationError, "sensor.missing"):
validate_repository(self.root)
def test_commented_include_is_ignored(self) -> None:
path = self.root / "config/dashboards/overview/dashboard.yaml"
path.write_text(
path.read_text(encoding="utf-8")
+ "# ignored: !include /config/dashboards/overview/missing.yaml\n",
encoding="utf-8",
)
validate_repository(self.root)
def test_duplicate_view_path_fails(self) -> None:
self._write(
"config/dashboards/overview/views/02_duplicate.yaml",
HEADER + "title: Duplicate\npath: home\ntype: sections\nsections: []\n",
dedent=False,
)
with self.assertRaisesRegex(ValidationError, "duplicate view path"):
validate_repository(self.root)
def test_orphaned_dashboard_file_fails(self) -> None:
self._write(
"config/dashboards/overview/orphan.yaml",
HEADER + "type: entity\nentity: sensor.real\n",
dedent=False,
)
with self.assertRaisesRegex(ValidationError, "orphaned dashboard YAML"):
validate_repository(self.root)
def test_duplicate_yaml_key_fails(self) -> None:
path = self.root / "config/dashboards/overview/views/01_home.yaml"
path.write_text(
path.read_text(encoding="utf-8") + "path: duplicate\n",
encoding="utf-8",
)
with self.assertRaisesRegex(ValidationError, "duplicate key"):
validate_repository(self.root)
if __name__ == "__main__":
unittest.main()

Powered by TurnKey Linux.