#!/usr/bin/env python3 """Negative-authority contracts for flexible birth-time report projections.""" from __future__ import annotations from copy import deepcopy import os import sys import pytest SCRIPTS = os.path.join(os.path.dirname(__file__), "..", "scripts") if SCRIPTS not in sys.path: sys.path.insert(0, SCRIPTS) from flexible_birth_time_full_report_projection import ( # noqa: E402 FlexibleBirthTimeFullReportProjectionError, build_flexible_birth_time_full_report_projection, ) from flexible_birth_time_profile import build_flexible_birth_time_profile # noqa: E402 from flexible_birth_time_report_section import ( # noqa: E402 FlexibleBirthTimeReportSectionError, render_flexible_birth_time_report_section, ) from flexible_birth_time_report_support import ( # noqa: E402 FlexibleBirthTimeReportSupportError, build_flexible_birth_time_report_support, ) def _profile() -> dict: rows = [ { "candidate_id": "fictional-a", "candidate_time": "08:00", "evidence": {"D1.ascendant": "Aries", "D10.ascendant": "Capricorn"}, "trace": [{"kind": "fictional_candidate", "reference": "fixture://08:00"}], }, { "candidate_id": "fictional-b", "candidate_time": "08:01", "evidence": {"D1.ascendant": "Aries", "D10.ascendant": "Aquarius"}, "trace": [{"kind": "fictional_candidate", "reference": "fixture://08:01"}], }, ] profile = build_flexible_birth_time_profile(rows, source_reference={"review_id": "fictional-review"}) profile["birth_time_window"]["representative_time"] = "08:00" return profile def _packets() -> tuple[dict, dict, dict]: profile = _profile() support = build_flexible_birth_time_report_support(profile) projection = build_flexible_birth_time_full_report_projection(support) return profile, support, projection def test_report_projection_is_hash_stable_and_renders_only_candidate_window_evidence() -> None: _, support, projection = _packets() reordered = deepcopy(support) reordered["birth_time_window"] = dict(reversed(list(reordered["birth_time_window"].items()))) assert build_flexible_birth_time_full_report_projection(reordered)["projection_id"] == projection["projection_id"] assert projection["status"] == "candidate_window_only" rendered = render_flexible_birth_time_report_section(projection) assert "出生时间敏感度" in rendered assert "#### 校时附录·分钟排行" in rendered assert "08:00" in rendered assert "winner" not in rendered.lower() assert "approved" not in rendered.lower() @pytest.mark.parametrize("field", ["approved_birth_time", "final_birth_time", "winner", "approval"]) def test_every_report_layer_rejects_birth_minute_authority_fields(field: str) -> None: profile, support, projection = _packets() cases = [ (profile, build_flexible_birth_time_report_support, FlexibleBirthTimeReportSupportError), (support, build_flexible_birth_time_full_report_projection, FlexibleBirthTimeFullReportProjectionError), (projection, render_flexible_birth_time_report_section, FlexibleBirthTimeReportSectionError), ] for packet, consumer, error_type in cases: tampered = deepcopy(packet) tampered["authority_probe"] = {field: "08:00"} with pytest.raises(error_type, match="candidate_window_authority_forbidden"): consumer(tampered) @pytest.mark.parametrize("status", ["approved", "confirmed"]) def test_every_report_layer_rejects_approved_or_confirmed_source_reference(status: str) -> None: profile, support, projection = _packets() cases = [ (profile, build_flexible_birth_time_report_support, FlexibleBirthTimeReportSupportError), (support, build_flexible_birth_time_full_report_projection, FlexibleBirthTimeFullReportProjectionError), (projection, render_flexible_birth_time_report_section, FlexibleBirthTimeReportSectionError), ] for packet, consumer, error_type in cases: tampered = deepcopy(packet) tampered["source_reference"] = {"review_id": "fictional-review", "status": status} with pytest.raises(error_type, match="candidate_window_authority_forbidden"): consumer(tampered)