feat(knowledge): auto-publish successful syncs
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
from fastapi import HTTPException
|
||||
from sqlalchemy import create_engine, select
|
||||
@@ -9,7 +12,14 @@ from sqlalchemy.pool import StaticPool
|
||||
from app.api.admin_knowledge_lifecycle import batch_update_metadata, update_metadata
|
||||
from app.models import Base
|
||||
from app.models.admin import Admin, Role
|
||||
from app.models.knowledge import Knowledge, KnowledgeManifest, KnowledgeSourceSnapshot, KnowledgeVersion
|
||||
from app.models.knowledge import (
|
||||
Knowledge,
|
||||
KnowledgeCard,
|
||||
KnowledgeManifest,
|
||||
KnowledgePublishLog,
|
||||
KnowledgeSourceSnapshot,
|
||||
KnowledgeVersion,
|
||||
)
|
||||
from app.schemas.knowledge import KnowledgeBatchMetadataUpdateRequest, KnowledgeMetadataUpdateRequest
|
||||
from app.services.knowledge_agent_service import KnowledgeAgentService
|
||||
from app.services.knowledge_pipeline_service import KnowledgePipelineService
|
||||
@@ -82,7 +92,7 @@ def test_metadata_update_preserves_source_version_and_open_state():
|
||||
original = (item.feishu_space_id, item.feishu_node_id, item.current_version_id, item.status)
|
||||
update_metadata(
|
||||
item.id,
|
||||
KnowledgeMetadataUpdateRequest(name="新后台名称", knowledgeType="course", reviewMode="automatic"),
|
||||
KnowledgeMetadataUpdateRequest(name="新后台名称", knowledgeType="course"),
|
||||
db,
|
||||
_admin(),
|
||||
)
|
||||
@@ -98,7 +108,7 @@ def test_metadata_update_requires_super_admin():
|
||||
with pytest.raises(HTTPException) as exc:
|
||||
update_metadata(
|
||||
item.id,
|
||||
KnowledgeMetadataUpdateRequest(name="新名称", knowledgeType="qa", reviewMode="manual"),
|
||||
KnowledgeMetadataUpdateRequest(name="新名称", knowledgeType="qa"),
|
||||
db,
|
||||
_admin("operator"),
|
||||
)
|
||||
@@ -138,3 +148,76 @@ def test_rollback_switches_published_version_statuses():
|
||||
assert item.current_version_id == target.id
|
||||
assert target.status == "published"
|
||||
assert old_version.status == "superseded"
|
||||
|
||||
|
||||
def test_sync_automatically_replaces_current_version_and_keeps_rollback_history():
|
||||
source_content = (
|
||||
"# 一、课程说明\n这是更新后的课程内容,同步成功后应当立即生效。\n\n"
|
||||
"# 二、练习一:静水流深静心\n选择舒适安全的姿势,觉察呼吸和身体,不适时立即停止。"
|
||||
)
|
||||
with _database() as db:
|
||||
item = _knowledge(db)
|
||||
previous_version_id = item.current_version_id
|
||||
loader = AsyncMock(return_value=[("新源标题", source_content, None)])
|
||||
|
||||
with patch(
|
||||
"app.services.knowledge_pipeline_service.AsyncFeishuKnowledgeService._load_documents",
|
||||
loader,
|
||||
):
|
||||
job = asyncio.run(
|
||||
KnowledgePipelineService.synchronize(
|
||||
db,
|
||||
item,
|
||||
admin_id=1,
|
||||
)
|
||||
)
|
||||
|
||||
db.refresh(item)
|
||||
current = db.get(KnowledgeVersion, item.current_version_id)
|
||||
previous = db.get(KnowledgeVersion, previous_version_id)
|
||||
manifest = db.scalar(select(KnowledgeManifest).where(KnowledgeManifest.version_id == current.id))
|
||||
cards = db.scalars(select(KnowledgeCard).where(KnowledgeCard.version_id == current.id)).all()
|
||||
publish_log = db.scalar(
|
||||
select(KnowledgePublishLog).where(KnowledgePublishLog.to_version_id == current.id)
|
||||
)
|
||||
|
||||
assert job.status == "published"
|
||||
assert job.mode == "replace"
|
||||
assert current.status == "published"
|
||||
assert current.quality_status == "passed"
|
||||
assert previous.status == "superseded"
|
||||
assert item.pending_version_id is None
|
||||
assert item.status == 1
|
||||
assert item.migration_status == "completed"
|
||||
assert manifest.confirmed == 1
|
||||
assert cards and all(card.review_status == "approved" for card in cards)
|
||||
assert publish_log.action == "sync_publish"
|
||||
|
||||
|
||||
def test_sync_validation_failure_keeps_current_version_active():
|
||||
with _database() as db:
|
||||
item = _knowledge(db)
|
||||
previous_version_id = item.current_version_id
|
||||
loader = AsyncMock(return_value=[("无效源内容", "内容过短", None)])
|
||||
|
||||
with patch(
|
||||
"app.services.knowledge_pipeline_service.AsyncFeishuKnowledgeService._load_documents",
|
||||
loader,
|
||||
):
|
||||
with pytest.raises(ValueError, match="质检未通过"):
|
||||
asyncio.run(
|
||||
KnowledgePipelineService.synchronize(
|
||||
db,
|
||||
item,
|
||||
admin_id=1,
|
||||
)
|
||||
)
|
||||
|
||||
db.refresh(item)
|
||||
current = db.get(KnowledgeVersion, previous_version_id)
|
||||
versions = db.scalars(
|
||||
select(KnowledgeVersion).where(KnowledgeVersion.knowledge_id == item.id)
|
||||
).all()
|
||||
assert item.current_version_id == previous_version_id
|
||||
assert current.status == "published"
|
||||
assert len(versions) == 1
|
||||
|
||||
Reference in New Issue
Block a user