"""Tests for core domain invariants around artifacts & relationships.""" from datetime import datetime, timezone from uuid import uuid4 import pytest from pydantic import ValidationError from asf_domain import ( Artifact, ArtifactCreate, ArtifactRelationshipCreate, ArtifactRelationship, ArtifactType, RelationshipType, generate_id, ) NOW = datetime(2026, 9, 7, 12, 0, 0, tzinfo=timezone.utc) def test_generate_id_returns_unique_uuid4() -> None: a = generate_id() b = generate_id() assert a != b assert a.version == 4 def test_artifact_create_minimal() -> None: body = ArtifactCreate( project_id=uuid4(), type=ArtifactType.REQUIREMENT, title="Login page must support MFA", ) assert body.type == ArtifactType.REQUIREMENT assert body.metadata == {} def test_artifact_stored_round_trip() -> None: tenant_id = uuid4() project_id = uuid4() a = Artifact( tenant_id=tenant_id, project_id=project_id, type=ArtifactType.TASK, title="Wire MFA provider", content="- [ ] choose TOTP lib\n- [ ] enroll flow", metadata={"estimated_points": 5, "labels": ["auth", "security"]}, created_at=NOW, updated_at=NOW, ) d = a.model_dump(mode="json") # ensure UTC serialization works assert d["created_at"].endswith("Z") assert d["metadata"]["labels"] == ["auth", "security"] def test_artifact_rejects_empty_title() -> None: with pytest.raises(ValidationError): ArtifactCreate(project_id=uuid4(), type=ArtifactType.STORY, title="") def test_relationship_create() -> None: a = uuid4() b = uuid4() rel = ArtifactRelationshipCreate( relationship_type=RelationshipType.IMPLEMENTED_BY, source_artifact_id=a, target_artifact_id=b, ) assert rel.source_artifact_id == a def test_relationship_stored_enforces_tenancy() -> None: tenant_id = uuid4() a, b = uuid4(), uuid4() pa, pb = uuid4(), uuid4() rel = ArtifactRelationship( tenant_id=tenant_id, source_project_id=pa, target_project_id=pb, relationship_type=RelationshipType.VERIFIED_BY, source_artifact_id=a, target_artifact_id=b, created_at=NOW, updated_at=NOW, ) # a relationship carries both project ids for tenant isolation queries assert rel.tenant_id == tenant_id assert rel.source_project_id == pa assert rel.target_project_id == pb