Files
mt5cli/tests/test_examples.py
T

93 lines
3.4 KiB
Python
Raw Permalink Normal View History

"""Tests for example files in examples/grafana/."""
from __future__ import annotations
import json
from pathlib import Path
from typing import TYPE_CHECKING
import pytest
if TYPE_CHECKING:
from collections.abc import Iterator
_EXAMPLES_DIR = Path(__file__).parent.parent / "examples" / "grafana"
_DASHBOARDS_DIR = _EXAMPLES_DIR / "dashboards"
def _dashboard_json_files() -> list[Path]:
"""Return bundled Grafana dashboard JSON files in deterministic order."""
return sorted(_DASHBOARDS_DIR.glob("*.json"))
@pytest.fixture(params=_dashboard_json_files(), ids=lambda path: path.name)
def dashboard_path(request: pytest.FixtureRequest) -> Iterator[Path]:
"""Yield one bundled Grafana dashboard JSON file per test case."""
return request.param
class TestGrafanaExamples:
"""Validate structure and content of bundled Grafana example files."""
def test_dashboard_json_files_are_present(self) -> None:
"""At least one dashboard JSON file is bundled."""
assert _dashboard_json_files(), "No dashboard JSON files found"
def test_dashboard_json_file_is_valid_json(self, dashboard_path: Path) -> None:
"""Each dashboard JSON file parses to a JSON object."""
content = dashboard_path.read_text(encoding="utf-8")
obj = json.loads(content)
assert isinstance(obj, dict), (
f"{dashboard_path.name} root must be a JSON object"
)
@pytest.mark.parametrize("private_pattern", ["password", "api_key", "apikey"])
def test_dashboard_json_has_no_private_placeholders(
self,
dashboard_path: Path,
private_pattern: str,
) -> None:
"""Dashboard JSON files contain no obvious credential placeholders."""
content = dashboard_path.read_text(encoding="utf-8").lower()
assert private_pattern not in content, (
f"{dashboard_path.name} contains {private_pattern!r}"
)
def test_dashboard_json_uses_grafana_views(self, dashboard_path: Path) -> None:
"""Each dashboard JSON file queries grafana_* views."""
content = dashboard_path.read_text(encoding="utf-8")
assert "grafana_" in content, (
f"{dashboard_path.name} must contain queries against grafana_* views"
)
@pytest.mark.parametrize("field", ["uid", "title"])
def test_dashboard_json_has_required_field(
self,
dashboard_path: Path,
field: str,
) -> None:
"""Each dashboard JSON file has a non-empty uid and title field."""
obj = json.loads(dashboard_path.read_text(encoding="utf-8"))
assert obj.get(field), f"{dashboard_path.name} must have a {field}"
def test_expected_dashboards_present(self) -> None:
"""The three expected dashboard files are present."""
names = {p.name for p in _dashboard_json_files()}
assert "mt5cli-overview.json" in names
assert "mt5cli-trades.json" in names
assert "mt5cli-market.json" in names
@pytest.mark.parametrize(
"relative_path",
[
"README.md",
"compose.yml",
"provisioning/datasources/mt5cli-sqlite.yml",
"provisioning/dashboards/mt5cli.yml",
],
ids=["readme", "compose", "datasource-provisioning", "dashboard-provisioning"],
)
def test_expected_file_exists(self, relative_path: str) -> None:
"""Bundled Grafana example support files are present."""
assert (_EXAMPLES_DIR / relative_path).is_file()