103 lines
3.5 KiB
Python
103 lines
3.5 KiB
Python
"""F3+F4 测试:多项目管理 + CLI 工具"""
|
|
|
|
import json
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from src.blackboard.registry import ProjectRegistry
|
|
from src.blackboard.operations import Blackboard
|
|
from src.blackboard.models import Task
|
|
|
|
|
|
# ===================================================================
|
|
# F3: 多项目管理
|
|
# ===================================================================
|
|
|
|
|
|
@pytest.fixture
|
|
def registry(tmp_path):
|
|
return ProjectRegistry(tmp_path)
|
|
|
|
|
|
class TestProjectRegistry:
|
|
def test_create_project(self, registry):
|
|
info = registry.create_project("test-proj", "Test Project",
|
|
agents=["agent1", "agent2"])
|
|
assert info["name"] == "Test Project"
|
|
assert info["agents"] == ["agent1", "agent2"]
|
|
assert info["status"] == "active"
|
|
|
|
def test_create_creates_dirs(self, registry):
|
|
registry.create_project("test-proj", "Test")
|
|
root = registry.root
|
|
assert (root / "test-proj" / "config" / "project.yaml").exists()
|
|
assert (root / "test-proj" / "artifacts").is_dir()
|
|
assert (root / "test-proj" / "experiences").is_dir()
|
|
assert (root / "test-proj" / "skills").is_dir()
|
|
|
|
def test_create_duplicate_fails(self, registry):
|
|
registry.create_project("p1", "P1")
|
|
with pytest.raises(ValueError, match="already exists"):
|
|
registry.create_project("p1", "P1 Duplicate")
|
|
|
|
def test_get_project(self, registry):
|
|
registry.create_project("p1", "P1")
|
|
info = registry.get_project("p1")
|
|
assert info is not None
|
|
assert info["name"] == "P1"
|
|
|
|
def test_get_nonexistent(self, registry):
|
|
assert registry.get_project("nope") is None
|
|
|
|
def test_list_projects(self, registry):
|
|
registry.create_project("p1", "P1")
|
|
registry.create_project("p2", "P2")
|
|
projects = registry.list_projects()
|
|
assert len(projects) == 2
|
|
assert "p1" in projects
|
|
assert "p2" in projects
|
|
|
|
def test_archive_project(self, registry):
|
|
registry.create_project("p1", "P1")
|
|
assert registry.archive_project("p1")
|
|
info = registry.get_project("p1")
|
|
assert info["status"] == "archived"
|
|
|
|
def test_archive_nonexistent(self, registry):
|
|
assert not registry.archive_project("nope")
|
|
|
|
def test_delete_project(self, registry):
|
|
registry.create_project("p1", "P1")
|
|
assert registry.delete_project("p1")
|
|
# v2.8: 逻辑删除,get_project 返回带 status=deleted 的 dict 而非 None
|
|
deleted = registry.get_project("p1")
|
|
assert deleted is not None
|
|
assert deleted["status"] == "deleted"
|
|
|
|
def test_registry_yaml_persists(self, registry):
|
|
registry.create_project("p1", "P1")
|
|
# Reload from disk
|
|
reg2 = ProjectRegistry(registry.root)
|
|
assert reg2.get_project("p1") is not None
|
|
|
|
def test_per_project_blackboard(self, tmp_path):
|
|
"""每个项目有独立的黑板 DB"""
|
|
registry = ProjectRegistry(tmp_path)
|
|
registry.create_project("proj-a", "A")
|
|
registry.create_project("proj-b", "B")
|
|
|
|
db_a = tmp_path / "proj-a" / "blackboard.db"
|
|
db_b = tmp_path / "proj-b" / "blackboard.db"
|
|
|
|
bb_a = Blackboard(db_a)
|
|
bb_b = Blackboard(db_b)
|
|
|
|
bb_a.create_task(Task(id="t1", title="A Task"))
|
|
bb_b.create_task(Task(id="t1", title="B Task"))
|
|
|
|
assert bb_a.get_task("t1").title == "A Task"
|
|
assert bb_b.get_task("t1").title == "B Task"
|