from __future__ import annotations import math import unittest from claridoc.models import ( REVIEW_DIMENSIONS, Brief, DocumentType, ModelReview, PipelineConfig, QualityGate, SourcePack, ValidationError, ) from claridoc.templates import mock_pipeline_config from tests.helpers import brief_dict, source_dict class ModelTests(unittest.TestCase): def test_valid_brief_round_trip(self) -> None: brief = Brief.from_dict(brief_dict()) self.assertEqual(brief.document_type, DocumentType.TECHNICAL_BLOG) self.assertEqual(Brief.from_dict(brief.to_dict()).title, brief.title) def test_readme_brief_round_trip(self) -> None: brief = Brief.from_dict(brief_dict("readme")) self.assertEqual(brief.document_type, DocumentType.README) self.assertEqual( Brief.from_dict(brief.to_dict()).document_type, DocumentType.README, ) def test_invalid_document_type_is_rejected(self) -> None: data = brief_dict() data["document_type"] = "essay" with self.assertRaises(ValidationError): Brief.from_dict(data) def test_duplicate_source_ids_are_rejected(self) -> None: data = source_dict() data["sources"].append(dict(data["sources"][0])) with self.assertRaises(ValidationError): SourcePack.from_dict(data) def test_target_words_range_is_enforced(self) -> None: data = brief_dict() data["constraints"]["target_words"] = 50 with self.assertRaises(ValidationError): Brief.from_dict(data) def test_quality_gate_rejects_non_finite_weights(self) -> None: with self.assertRaises(ValidationError): QualityGate.from_dict({"deterministic_weight": math.nan, "model_weight": math.nan}) def test_pipeline_requires_explicit_reviewers(self) -> None: data = mock_pipeline_config() data["reviewers"] = [] with self.assertRaises(ValidationError): PipelineConfig.from_dict(data) def test_pipeline_rejects_duplicate_reviewer_roles(self) -> None: data = mock_pipeline_config() data["reviewers"].append({"role": "logic", "provider": "mock"}) with self.assertRaises(ValidationError): PipelineConfig.from_dict(data) def test_review_requires_every_scoring_dimension(self) -> None: review = self._valid_review() del review["dimension_scores"][REVIEW_DIMENSIONS[0]] with self.assertRaises(ValidationError): ModelReview.from_dict(review, role="logic", provider="mock") def test_review_rejects_unknown_issue_severity(self) -> None: review = self._valid_review() review["issues"] = [ { "section": "Mechanism", "problem": "A causal step is missing.", "why_it_matters": "The conclusion cannot be reproduced.", "fix": "Add the missing state transition.", "severity": "critical", } ] with self.assertRaises(ValidationError): ModelReview.from_dict(review, role="logic", provider="mock") @staticmethod def _valid_review() -> dict: return { "score": 90, "dimension_scores": {name: 90 for name in REVIEW_DIMENSIONS}, "issues": [], "strengths": ["The structure is explicit."], "questions": [], } if __name__ == "__main__": unittest.main()