설계 개편

This commit is contained in:
DongHyeonka
2026-07-24 16:31:12 +09:00
parent f43e909162
commit 8daa568746
70 changed files with 6554 additions and 956 deletions
+84
View File
@@ -0,0 +1,84 @@
from __future__ import annotations
import json
import unittest
from copy import deepcopy
from pathlib import Path
from techviz.layout import build_layout
from techviz.renderers.svg import render_svg
from techviz.spec import VizSpec
from techviz.validate import has_errors, validate_spec
ROOT = Path(__file__).resolve().parents[1]
class CompositionTests(unittest.TestCase):
def setUp(self) -> None:
self.spec_data = json.loads((ROOT / "examples/work/payment/spec.json").read_text(encoding="utf-8"))
self.context = json.loads((ROOT / "examples/work/payment/context.json").read_text(encoding="utf-8"))
def test_disconnected_cards_are_rejected(self) -> None:
data = deepcopy(self.spec_data)
data["nodes"] = data["nodes"][:3]
data["edges"] = []
data["composition"] = {
"profile": "component-flow",
"diagram_only": True,
"reference_ids": ["payment-event-flow"],
"rationale": "Synthetic disconnected case.",
}
issues = validate_spec(VizSpec.from_dict(data), self.context)
self.assertTrue(any(issue.code == "missing-central-relation" for issue in issues), issues)
def test_comparison_requires_comparable_details(self) -> None:
data = deepcopy(self.spec_data)
data["type"] = "concept"
data["nodes"] = data["nodes"][:2]
data["edges"] = []
data["composition"] = {
"profile": "comparison",
"diagram_only": True,
"reference_ids": ["contract-comparison"],
"rationale": "Compare two explicit contracts.",
}
for node in data["nodes"]:
node["role"] = "contract"
node["details"] = ["responsibility", "lifecycle"]
issues = validate_spec(VizSpec.from_dict(data))
self.assertFalse(has_errors(issues), issues)
del data["nodes"][0]["details"]
issues = validate_spec(VizSpec.from_dict(data))
self.assertTrue(any(issue.code == "comparison-missing-details" for issue in issues), issues)
def test_svg_is_diagram_only(self) -> None:
spec = VizSpec.from_dict(self.spec_data)
svg = render_svg(spec, build_layout(spec))
self.assertNotIn('class="diagram-title"', svg)
self.assertNotIn('class="diagram-question"', svg)
self.assertNotIn('class="footer"', svg)
self.assertNotIn("Generated from grounded VizSpec", svg)
self.assertNotIn("<filter", svg)
self.assertNotIn("<linearGradient", svg)
self.assertIn("<title id=", svg)
self.assertIn("<desc id=", svg)
def test_reference_profile_mismatch_is_rejected(self) -> None:
data = deepcopy(self.spec_data)
data["composition"]["profile"] = "ports-adapters"
data["composition"]["reference_ids"] = ["payment-event-flow"]
issues = validate_spec(VizSpec.from_dict(data), self.context)
self.assertTrue(any(issue.code == "reference-profile-mismatch" for issue in issues), issues)
def test_context_rejects_unselected_profile(self) -> None:
data = deepcopy(self.spec_data)
data["composition"]["profile"] = "ports-adapters"
data["composition"]["reference_ids"] = ["order-ports-adapters"]
issues = validate_spec(VizSpec.from_dict(data), self.context)
self.assertTrue(any(issue.code == "profile-not-supported-by-context" for issue in issues), issues)
if __name__ == "__main__":
unittest.main()