test_formal_state_models.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. from __future__ import annotations
  2. from uuid import uuid4
  3. import pytest
  4. from pydantic import ValidationError
  5. from app.schemas import (
  6. AcquisitionRunSummarySchema,
  7. CandidateItemSchema,
  8. ErrorResponse,
  9. Page,
  10. )
  11. from core.config import CreationDbConfig
  12. from decode_content.models import (
  13. IngestRecord,
  14. KnowledgeParticle,
  15. PayloadDraft,
  16. ReadResult,
  17. ScopeResult,
  18. )
  19. from pipeline.models import PipelineJob, PipelineRun, ResumeCursor
  20. def test_creation_db_config_reads_ck_db_without_open_aigc(tmp_path):
  21. env_file = tmp_path / ".env"
  22. env_file.write_text(
  23. "\n".join(
  24. [
  25. "OPEN_AIGC_PG_HOST=wrong-open-aigc",
  26. "OPEN_AIGC_PG_USER=wrong-user",
  27. "CK_DB_HOST=127.0.0.1",
  28. "CK_DB_PORT=6543",
  29. "CK_DB_NAME=creation_knowledge_prod",
  30. "CK_DB_USER=ck_app",
  31. "CK_DB_PASSWORD=secret",
  32. "CK_DB_SCHEMA=creation_knowledge",
  33. ]
  34. ),
  35. encoding="utf-8",
  36. )
  37. cfg = CreationDbConfig.from_env(env_file)
  38. assert cfg.host == "127.0.0.1"
  39. assert cfg.port == 6543
  40. assert cfg.user == "ck_app"
  41. assert cfg.database == "creation_knowledge_prod"
  42. assert cfg.schema == "creation_knowledge"
  43. def test_decode_content_models_are_contract_shaped():
  44. item_id = uuid4()
  45. read = ReadResult(
  46. text="一条创作判断",
  47. cards=[{"index": 1, "kind": "image", "content": "构图说明"}],
  48. media={"platform": "xiaohongshu"},
  49. )
  50. knowledge = KnowledgeParticle(
  51. item_id=item_id,
  52. particle_type="how",
  53. title="先定受众再写脚本",
  54. content={"steps": [{"input": "目标受众", "directive": "收窄", "output": "脚本方向"}]},
  55. )
  56. scope = ScopeResult(
  57. item_id=item_id,
  58. particle_id=uuid4(),
  59. scope_type="意图",
  60. scope_value="吸引注意",
  61. is_reused=True,
  62. )
  63. payload = PayloadDraft(item_id=item_id, particle_id=knowledge.id, payload={"kind": "how"})
  64. ingest = IngestRecord(
  65. payload_draft_id=payload.id,
  66. target_system="creation-knowledge-db",
  67. target_id="remote-1",
  68. )
  69. assert read.cards[0].content == "构图说明"
  70. assert knowledge.particle_type == "how"
  71. assert scope.scope_value == "吸引注意"
  72. assert payload.review_status == "pending"
  73. assert ingest.status == "pending"
  74. def test_decode_content_rejects_unknown_particle_type():
  75. with pytest.raises(ValidationError):
  76. KnowledgeParticle(particle_type="idea", title="错误类型")
  77. def test_pipeline_models_capture_resume_boundary():
  78. run_id = uuid4()
  79. run = PipelineRun(id=run_id, run_key="formal-run", current_stage="decode")
  80. job = PipelineJob(run_id=run_id, stage="decode", target_id=uuid4())
  81. cursor = ResumeCursor(stage="decode", last_successful_job_id=job.id)
  82. assert run.status == "pending"
  83. assert job.status == "pending"
  84. assert cursor.stage == "decode"
  85. def test_app_schemas_cover_formal_workbench_shapes():
  86. run_id = uuid4()
  87. item_id = uuid4()
  88. summary = AcquisitionRunSummarySchema(
  89. id=run_id,
  90. status="running",
  91. query_count=3,
  92. job_count=9,
  93. candidate_count=21,
  94. creation_hit_count=5,
  95. )
  96. item = CandidateItemSchema(
  97. id=item_id,
  98. platform="douyin",
  99. title="短视频脚本创作",
  100. status="candidate",
  101. )
  102. page = Page(total=1, items=[{"id": str(item_id)}])
  103. error = ErrorResponse(code="not_found", message="missing")
  104. assert summary.creation_hit_count == 5
  105. assert item.media_assets == []
  106. assert page.total == 1
  107. assert error.detail == {}