78 lines
2.5 KiB
Python
78 lines
2.5 KiB
Python
from __future__ import annotations
|
|
|
|
import sys
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
from pydantic import ValidationError
|
|
|
|
|
|
BACKEND_ROOT = Path(__file__).resolve().parents[2]
|
|
sys.path.insert(0, str(BACKEND_ROOT))
|
|
|
|
from src.domain.contracts import ( # noqa: E402
|
|
ARTICLE_WORKFLOW_STATUSES,
|
|
ARTICLE_WORKFLOW_TRANSITIONS,
|
|
ArticleCreateRequest,
|
|
ArticleWorkflowStatus,
|
|
Role,
|
|
UserSummary,
|
|
)
|
|
|
|
|
|
class DomainContractTest(unittest.TestCase):
|
|
def test_role_enum_is_canonical(self) -> None:
|
|
self.assertEqual(["ADMIN", "EDITOR"], [role.value for role in Role])
|
|
|
|
with self.assertRaises(ValidationError):
|
|
UserSummary.model_validate(
|
|
{
|
|
"id": "00000000-0000-0000-0000-000000000001",
|
|
"display_name": "Writer",
|
|
"role": "WRITER",
|
|
}
|
|
)
|
|
|
|
def test_article_create_rejects_missing_required_fields(self) -> None:
|
|
with self.assertRaises(ValidationError) as error:
|
|
ArticleCreateRequest.model_validate({})
|
|
|
|
missing_fields = {
|
|
issue["loc"][0]
|
|
for issue in error.exception.errors()
|
|
if issue["type"] == "missing"
|
|
}
|
|
self.assertEqual({"brief_description", "target_site_id"}, missing_fields)
|
|
|
|
def test_workflow_statuses_and_transitions_are_shared_constants(self) -> None:
|
|
self.assertEqual(
|
|
[
|
|
"ARTICLE_BRIEF_CREATED",
|
|
"BOUNDARY_QUESTIONS_GENERATED",
|
|
"BOUNDARY_ANSWERS_SUBMITTED",
|
|
"PLAN_GENERATED",
|
|
"PLAN_REVIEW_REQUIRED",
|
|
"PLAN_REVISION_REQUIRED",
|
|
"RESEARCH_RUNNING",
|
|
"EVIDENCE_MATRIX_READY",
|
|
"PARALLEL_PRODUCTION_RUNNING",
|
|
"DRAFT_ASSEMBLED",
|
|
"SEO_AND_LANGUAGE_REVIEW_READY",
|
|
"FINAL_REVIEW_REQUIRED",
|
|
"FINAL_REVISION_REQUIRED",
|
|
"PUBLISH_DRY_RUN_REQUIRED",
|
|
"PUBLISH_COMMIT_READY",
|
|
"PUBLISH_COMMIT_CREATED",
|
|
],
|
|
[status.value for status in ARTICLE_WORKFLOW_STATUSES],
|
|
)
|
|
self.assertEqual(set(ArticleWorkflowStatus), set(ARTICLE_WORKFLOW_TRANSITIONS))
|
|
for status, next_statuses in ARTICLE_WORKFLOW_TRANSITIONS.items():
|
|
self.assertIsInstance(status, ArticleWorkflowStatus)
|
|
for next_status in next_statuses:
|
|
self.assertIsInstance(next_status, ArticleWorkflowStatus)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|