"""
Module 11 — HTML Improvements tests.
All tests are deterministic: no API calls, no disk access.
html_improvements.generate() is a pure function tested with controlled
AnalysisResult fixtures.
"""
from __future__ import annotations
from backend.models.analysis import AnalysisResult
from backend.models.issue import Category, Issue, Severity
from backend.services import html_improvements
# ── helpers ───────────────────────────────────────────────────────────────────
def _result(issues: list[Issue]) -> AnalysisResult:
return AnalysisResult(overall_score=70.0, category_scores=[], issues=issues)
def _issue(rule_id: str, cat: Category = Category.ACCESSIBILITY) -> Issue:
return Issue(
rule_id=rule_id,
category=cat,
severity=Severity.HIGH,
confidence=0.9,
message="test",
recommendation="fix it",
evidence="none",
estimated_time="5 minutes",
estimated_gain=2.0,
)
def _clean() -> AnalysisResult:
return _result([])
# ── always-present elements ───────────────────────────────────────────────────
class TestAlwaysPresent:
def test_output_is_string(self):
assert isinstance(html_improvements.generate(_clean()), str)
def test_doctype_always_included(self):
assert "" in html_improvements.generate(_clean())
def test_lang_attribute_always_included(self):
assert 'lang="en"' in html_improvements.generate(_clean())
def test_viewport_meta_always_included(self):
assert 'name="viewport"' in html_improvements.generate(_clean())
def test_charset_meta_always_included(self):
assert 'charset="UTF-8"' in html_improvements.generate(_clean())
def test_landmark_roles_always_included(self):
out = html_improvements.generate(_clean())
assert 'role="banner"' in out
assert 'role="contentinfo"' in out
def test_main_id_always_included(self):
assert 'id="main-content"' in html_improvements.generate(_clean())
def test_score_appears_in_header(self):
assert "70.0/100" in html_improvements.generate(_clean())
# ── skip link ─────────────────────────────────────────────────────────────────
class TestSkipLink:
def test_skip_link_present_when_a11y_issue_exists(self):
result = _result([_issue("F1_missing_label")])
assert "skip-link" in html_improvements.generate(result)
def test_skip_link_present_when_focus_issue(self):
result = _result([_issue("B3_focus_style")])
assert "skip-link" in html_improvements.generate(result)
def test_skip_link_present_when_touch_target_issue(self):
result = _result([_issue("B4_touch_target")])
assert "skip-link" in html_improvements.generate(result)
# ── form patterns ─────────────────────────────────────────────────────────────
class TestFormPatterns:
def test_label_pattern_when_f1_fires(self):
result = _result([_issue("F1_missing_label")])
out = html_improvements.generate(result)
assert '