"""Offline safety and completeness checks for the cross-product UI review program.""" import importlib.util from pathlib import Path import socket import sys import pytest ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT / "tools/gitea")) SPEC = importlib.util.spec_from_file_location("ui_review_program", ROOT / "tools/gitea/gitea-ui-review-program.py") assert SPEC and SPEC.loader program = importlib.util.module_from_spec(SPEC) sys.modules[SPEC.name] = program SPEC.loader.exec_module(program) def scope(scope_id="campaigns", kind="manifest"): return { "scope_id": scope_id, "name": "Campaigns", "repository": "govoplan-campaign", "kind": kind, "manifest_paths": ["src/govoplan_campaign/backend/manifest.py"], "frontend": { "routes": [{"path": "/campaigns/:campaignId/*", "component": "CampaignWorkspace"}], "public_routes": [{"path": "/public/example", "component": "PublicExample"}], "settings_routes": [{"path": "/settings/example", "component": "ExampleSettings"}], "nav_items": [{"path": "/campaigns", "label": "Campaigns"}], "view_surfaces": [{"id": "campaigns.widget.activity", "label": "Activity widget"}], }, "source_groups": {"Dialogs and embedded editing surfaces": ["webui/src/ExampleDialog.tsx"]}, "ui_source_count": 1, } def test_catalog_includes_core_all_manifests_and_each_placeholder(tmp_path): names = ["govoplan", "govoplan-core", "govoplan-campaign", "govoplan-ledger", "govoplan-xoev", "website"] for name in names: (tmp_path / name).mkdir() catalog = {"repositories": [ {"name": name, "path": name, "category": "website" if name == "website" else "system" if name in {"govoplan", "govoplan-core"} else "connector" if name == "govoplan-xoev" else "module"} for name in names ]} manifests = [{"id": "campaigns", "name": "Campaigns", "repository": "govoplan-campaign", "frontend": None}] scopes = program.build_scopes(catalog, tmp_path, manifests) assert {item["scope_id"] for item in scopes} == {"core", "campaigns", "catalog:govoplan-ledger", "catalog:govoplan-xoev"} assert sum(item["kind"] == "placeholder" for item in scopes) == 2 assert next(item for item in scopes if item["scope_id"] == "campaigns")["kind"] == "manifest" def test_missing_checkout_or_implementation_without_manifest_is_not_called_placeholder(tmp_path): catalog = {"repositories": [{"name": "govoplan-example", "path": "govoplan-example", "category": "module"}]} with pytest.raises(program.GiteaError, match="Missing source checkout"): program.build_scopes(catalog, tmp_path, []) root = tmp_path / "govoplan-example" root.mkdir() (root / "pyproject.toml").touch() with pytest.raises(program.GiteaError, match="implementation but no extracted manifest"): program.build_scopes(catalog, tmp_path, []) def test_duplicate_or_uncatalogued_manifest_is_rejected(tmp_path): manifest = {"id": "example", "name": "Example", "repository": "govoplan-example", "frontend": None} with pytest.raises(program.GiteaError, match="Duplicate source manifest"): program.build_scopes({"repositories": []}, tmp_path, [manifest, manifest]) with pytest.raises(program.GiteaError, match="absent from the module review catalog"): program.build_scopes({"repositories": []}, tmp_path, [manifest]) def test_existing_closed_issue_is_found_and_unchanged(): issue = {"number": 4, "title": "Reviewer renamed it", "state": "closed", "body": program.marker("campaigns") + "\nHuman findings\n- [x] Done"} before = issue.copy() assert program.find_existing([issue], "campaigns", program.issue_title(scope())) is issue assert issue == before def test_gitea_null_pull_request_field_is_an_ordinary_issue(): issue = {"number": 25, "title": "UI review", "state": "open", "body": program.marker("mail"), "pull_request": None} assert program.find_existing([issue], "mail", "UI review") is issue def test_unmanaged_title_and_ambiguous_marker_stop_without_overwrite(): title = program.issue_title(scope()) with pytest.raises(program.GiteaError, match="Unmanaged exact-title"): program.find_existing([{"title": " " + title.upper() + " ", "body": "user content"}], "campaigns", title) duplicate = {"title": title, "body": program.marker("campaigns")} with pytest.raises(program.GiteaError, match="Ambiguous"): program.find_existing([duplicate, duplicate.copy()], "campaigns", title) def test_pr_not_used_as_matching_issue(): issue = {"title": program.issue_title(scope()), "body": program.marker("campaigns"), "pull_request": {}} assert program.find_existing([issue], "campaigns", issue["title"]) is None def test_child_inventory_and_all_principles_start_pending(): body = program.issue_body(scope(), "https://example.test/epic/56") assert "**Pending / not reviewed.**" in body assert "https://example.test/epic/56" in body assert "/campaigns/:campaignId/*" in body assert "/public/example" in body assert "/settings/example" in body assert "campaigns.widget.activity" in body assert "webui/src/ExampleDialog.tsx" in body assert "compact read-only campaign settings dashboard" in body assert "Save/Cancel" in body and "dirty-state protection" in body assert "- [x]" not in body assert body.count("| Pending inventory | Pending review | Not yet recorded | None approved |") == 9 for identity, _ in program.PRINCIPLES: assert identity in body assert "Reopen this issue or link an owned follow-up" in body def test_headless_and_placeholder_scopes_are_not_automatic_completions(): headless = scope("rest") headless["frontend"] = None assert "No standalone frontend is declared" in program.issue_body(headless, "epic") assert "**The review is still pending:**" in program.issue_body(headless, "epic") placeholder = scope("catalog:govoplan-ledger", "placeholder") body = program.issue_body(placeholder, "epic") assert "there is no runtime module ID, manifest or standalone WebUI" in body assert "Keep the future interface review pending" in body assert "- [x]" not in body def test_source_grouping_uses_real_files_and_clearly_bounds_large_seeds(tmp_path): source = tmp_path / "webui/src" source.mkdir(parents=True) for name in ["ExamplePage.tsx", "EditDialog.tsx", "TenantSettings.tsx", "ActivityWidget.tsx", "Button.tsx"]: (source / name).touch() groups = program.source_groups(tmp_path) assert sum(map(len, groups.values())) == 5 assert groups["Dialogs and embedded editing surfaces"] == ["webui/src/EditDialog.tsx"] large = scope() large["source_groups"] = {"Pages": [f"webui/src/Page{index}.tsx" for index in range(45)]} large["ui_source_count"] = 45 seed = program.source_seed(large) assert "5 further files" in seed assert "not a completed runtime audit" in seed def test_epic_initialization_preserves_surrounding_text_and_keeps_all_unchecked(): body = program.EPIC_MARKER + "\nHuman introduction\n" + program.LIST_START + "\n" + program.INITIAL_LIST + "\n" + program.LIST_END + "\nHuman evidence" records = [ {"name": "Core", "scope_id": "core", "repository": "govoplan-core", "kind": "core", "url": "https://example.test/core/1"}, {"name": "Ledger", "scope_id": "catalog:govoplan-ledger", "repository": "govoplan-ledger", "kind": "placeholder", "url": "https://example.test/ledger/2"}, ] result = program.initialized_epic_body(body, records) assert "Human introduction" in result and "Human evidence" in result assert result.count("- [ ]") == 2 assert "Catalogued placeholders" in result assert program.initialized_epic_body(result, records) == result human_progress = result.replace("- [ ] [Core]", "- [x] [Core]") assert program.initialized_epic_body(human_progress, records) == human_progress def test_epic_edited_or_ambiguous_lists_are_never_overwritten(): records = [{"name": "Core", "scope_id": "core", "repository": "govoplan-core", "kind": "core", "url": "https://example.test/core/1"}] body = program.EPIC_MARKER + program.LIST_START + "User-managed content" + program.LIST_END with pytest.raises(program.GiteaError, match="already edited"): program.initialized_epic_body(body, records) with pytest.raises(program.GiteaError, match="absent or ambiguous"): program.initialized_epic_body(body + program.LIST_START, records) with pytest.raises(program.GiteaError, match="incomplete issue link inventory"): program.render_links([{**records[0], "url": None}]) def test_ipv4_override_is_host_scoped_and_restored(monkeypatch): calls = [] def original(host, port, family=0, type=0, proto=0, flags=0): calls.append((host, family)) return [] monkeypatch.setattr(socket, "getaddrinfo", original) with program.ipv4_for_target(True): socket.getaddrinfo("git.add-ideas.de", 443) socket.getaddrinfo("unrelated.example", 443) assert calls == [("git.add-ideas.de", socket.AF_INET), ("unrelated.example", 0)] assert socket.getaddrinfo is original def test_snapshot_covers_every_current_catalog_module(): import json catalog = json.loads((ROOT / "repositories.json").read_text()) inventory_path = ROOT / "docs/project/ui-review-issue-inventory.json" snapshot = json.loads(inventory_path.read_text()) expected = {repo["name"] for repo in catalog["repositories"] if repo["category"] in {"module", "connector"} or repo["name"] == "govoplan-core"} assert {issue["repository"] for issue in snapshot["issues"]} == expected assert len(snapshot["issues"]) == len(expected) assert len({issue["url"] for issue in snapshot["issues"]}) == len(expected) assert snapshot["scope_count"] == 77 assert snapshot["implemented_scopes"] == 73 assert snapshot["manifest_modules"] == 72 assert snapshot["catalogued_placeholders"] == 4 assert all(issue["number"] and issue["url"].startswith("https://git.add-ideas.de/GovOPlaN/") for issue in snapshot["issues"])