feat(openapi): complete upload preview and UI evidence

This commit is contained in:
2026-08-28 15:38:14 +03:00
parent d2849ea3fe
commit 2c94af6791
35 changed files with 3655 additions and 537 deletions
+21 -2
View File
@@ -10,14 +10,17 @@ COLLECTOR = ROOT / "scripts" / "collect-capability-baseline.py"
class CapabilityBaselineCollectorTests(unittest.TestCase):
def run_playwright(self, report: object) -> tuple[subprocess.CompletedProcess[str], Path, tempfile.TemporaryDirectory[str]]:
def run_playwright(self, report: object, required: list[str] | None = None) -> tuple[subprocess.CompletedProcess[str], Path, tempfile.TemporaryDirectory[str]]:
temporary = tempfile.TemporaryDirectory()
root = Path(temporary.name)
report_path = root / "report.json"
output_path = root / "candidate.json"
report_path.write_text(json.dumps(report), encoding="utf-8")
command = ["python3", str(COLLECTOR), "playwright", "--report", str(report_path), "--output", str(output_path), "--source-revision", "0" * 40, "--environment-class", "community-test", "--flow-id", "ui-operations"]
for title in required or []:
command.extend(["--required-test", title])
result = subprocess.run(
["python3", str(COLLECTOR), "playwright", "--report", str(report_path), "--output", str(output_path), "--source-revision", "0" * 40, "--environment-class", "community-test", "--flow-id", "ui-operations"],
command,
text=True,
capture_output=True,
check=False,
@@ -51,6 +54,22 @@ class CapabilityBaselineCollectorTests(unittest.TestCase):
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(json.loads(output.read_text(encoding="utf-8"))["execution_verdict"], "skipped")
def test_required_openapi_tests_fail_closed_when_missing_skipped_or_flaky(self) -> None:
required = ["OpenAPI required scenario"]
reports = [
{"suites": [{"specs": [{"title": "another scenario", "tests": [{"status": "expected", "results": [{"status": "passed", "retry": 0}]}]}]}]},
{"suites": [{"specs": [{"title": required[0], "tests": [{"status": "skipped", "results": []}]}]}]},
{"suites": [{"specs": [{"title": required[0], "tests": [{"status": "flaky", "results": [{"status": "failed", "retry": 0}, {"status": "passed", "retry": 1}]}]}]}]},
]
for report in reports:
with self.subTest(report=report):
result, output, temporary = self.run_playwright(report, required)
self.addCleanup(temporary.cleanup)
self.assertEqual(result.returncode, 0, result.stderr)
candidate = json.loads(output.read_text(encoding="utf-8"))
self.assertEqual(candidate["execution_verdict"], "fail")
self.assertFalse(candidate["accepted"])
def test_raw_report_content_never_reaches_candidate_or_error(self) -> None:
canary = "Bearer secret-canary /home/private/workspace https://private.invalid?q=secret"
report = {"suites": [], "errors": [{"message": canary}], "stdout": [canary]}
@@ -0,0 +1,99 @@
import json
import subprocess
import tempfile
import unittest
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
SCHEMA = ROOT / "docs" / "schemas" / "capability-baseline.schema.json"
VALIDATOR = ROOT / "scripts" / "validate-capability-run.py"
def candidate() -> dict[str, object]:
return {
"id": "run-ui-playwright-0123456789ab",
"command_id": "ui-playwright",
"flow_ids": ["openapi-upload-ui"],
"execution_verdict": "pass",
"evidence_mode": "automated",
"accepted": True,
"source_report_sha256": "a" * 64,
"source_revision": "0" * 40,
"environment_class": "ci",
"collector": "capability-baseline-collector-v1",
"summary": {"passed": 1},
}
class CapabilityRunValidatorTests(unittest.TestCase):
def validate(self, contents: str | bytes, require_accepted: bool = False) -> subprocess.CompletedProcess[str]:
with tempfile.TemporaryDirectory() as directory:
candidate_path = Path(directory) / "candidate.json"
if isinstance(contents, bytes):
candidate_path.write_bytes(contents)
else:
candidate_path.write_text(contents, encoding="utf-8")
command = ["python3", str(VALIDATOR), "--schema", str(SCHEMA), "--candidate", str(candidate_path)]
if require_accepted:
command.append("--require-accepted")
return subprocess.run(
command,
text=True,
capture_output=True,
check=False,
)
def test_valid_candidate_matches_run_definition(self) -> None:
result = self.validate(json.dumps(candidate()))
self.assertEqual(result.returncode, 0, result.stderr)
self.assertIn("matches $defs/run", result.stdout)
def test_missing_required_property_is_rejected(self) -> None:
value = candidate()
value.pop("id")
result = self.validate(json.dumps(value))
self.assertNotEqual(result.returncode, 0)
self.assertIn("missing required property id", result.stderr)
def test_extra_property_is_rejected(self) -> None:
value = candidate()
value["raw_report"] = "must-not-be-accepted"
result = self.validate(json.dumps(value))
self.assertNotEqual(result.returncode, 0)
self.assertIn("unexpected property raw_report", result.stderr)
def test_wrong_type_and_pattern_are_rejected(self) -> None:
type_error = candidate()
type_error["accepted"] = "true"
pattern_error = candidate()
pattern_error["source_revision"] = "not-a-revision"
for value, expected in ((type_error, "expected boolean"), (pattern_error, "string does not match pattern")):
with self.subTest(expected=expected):
result = self.validate(json.dumps(value))
self.assertNotEqual(result.returncode, 0)
self.assertIn(expected, result.stderr)
def test_duplicate_json_key_is_rejected(self) -> None:
encoded = json.dumps(candidate())
duplicate = encoded.replace('"id": "run-ui-playwright-0123456789ab",', '"id": "run-ui-playwright-0123456789ab", "id": "other",')
result = self.validate(duplicate)
self.assertNotEqual(result.returncode, 0)
self.assertIn("duplicate JSON key", result.stderr)
def test_oversized_candidate_is_rejected(self) -> None:
result = self.validate(b" " * (65_536 + 1))
self.assertNotEqual(result.returncode, 0)
self.assertIn("input exceeds 64 KiB", result.stderr)
def test_require_accepted_rejects_schema_valid_negative_evidence(self) -> None:
value = candidate()
value["accepted"] = False
value["execution_verdict"] = "fail"
result = self.validate(json.dumps(value), require_accepted=True)
self.assertNotEqual(result.returncode, 0)
self.assertIn("accepted evidence is required", result.stderr)
if __name__ == "__main__":
unittest.main()