"""Unit tests for domain services using stubbed repositories (no DB needed).""" from __future__ import annotations from datetime import datetime, timezone from typing import Any from uuid import UUID, uuid4 import pytest from unittest.mock import AsyncMock from asf_domain import ( OrganizationCreate, ProjectCreate, ArtifactCreate, ArtifactType, ArtifactRelationshipCreate, RelationshipType, JobCreate, JobType, JobStatus, ) from app.services import ( OrganizationService, ProjectService, ArtifactService, RelationshipService, JobService, ) NOW = datetime(2026, 9, 7, 12, 0, 0, tzinfo=timezone.utc) TENANT = uuid4() USER = uuid4() pytestmark = pytest.mark.anyio class _StubAudit: def __init__(self) -> None: self.events: list[Any] = [] async def append(self, tenant_id: UUID, body: Any): self.events.append(body) return body # stub # ---------- Organizations ---------- async def test_org_service_create_returns_org(): org_repo = AsyncMock() from asf_domain import Organization created = Organization( id=uuid4(), name="Contoso", slug="contoso", plan="team", is_active=True, created_at=NOW, updated_at=NOW, ) org_repo.create = AsyncMock(return_value=created) svc = OrganizationService(org_repo, _StubAudit(), actor_id=USER) result = await svc.create(OrganizationCreate(name="Contoso", slug="contoso", plan="team")) assert result.slug == "contoso" org_repo.create.assert_awaited_once() # ---------- Projects ---------- async def test_project_service_create_checks_org_exists(): project_repo = AsyncMock() org_repo = AsyncMock() org_repo.get = AsyncMock(return_value=None) svc = ProjectService(project_repo, org_repo, _StubAudit(), tenant_id=TENANT, actor_id=USER) from app.repositories import NotFoundError with pytest.raises(NotFoundError): await svc.create(ProjectCreate(name="Demo", key="DEMO")) # ---------- Artifacts ---------- async def test_artifact_service_create_checks_project(): artifact_repo = AsyncMock() project_repo = AsyncMock() project_repo.get = AsyncMock(return_value=None) svc = ArtifactService( artifact_repo, project_repo, _StubAudit(), tenant_id=TENANT, actor_id=USER ) from app.repositories import NotFoundError with pytest.raises(NotFoundError): await svc.create( ArtifactCreate( project_id=uuid4(), type=ArtifactType.REQUIREMENT, title="Need MFA", ) ) # ---------- Jobs ---------- async def test_job_service_submit_creates_record(): job_repo = AsyncMock() project_repo = AsyncMock() from asf_domain import Job project_repo.get = AsyncMock(return_value=object()) # truthy new_job = Job( id=uuid4(), tenant_id=TENANT, project_id=uuid4(), type=JobType.AI_INTERACTIVE, status=JobStatus.QUEUED, payload={"question": "hi"}, created_at=NOW, usage={}, ) job_repo.create = AsyncMock(return_value=new_job) svc = JobService(job_repo, project_repo, _StubAudit(), tenant_id=TENANT, actor_id=USER) result = await svc.submit( JobCreate( type=JobType.AI_INTERACTIVE, payload={"question": "hi"}, project_id=uuid4(), ) ) assert result.status == JobStatus.QUEUED job_repo.create.assert_awaited_once()