Files
devclaw-gitea/test/projects.test.ts
2026-02-10 15:48:16 +08:00

190 lines
5.8 KiB
TypeScript

/**
* Tests for projects.ts session persistence
* Run with: npm test
*/
import { describe, it, before, after } from "node:test";
import assert from "node:assert";
import fs from "node:fs/promises";
import path from "node:path";
import os from "node:os";
import {
type ProjectsData,
activateWorker,
deactivateWorker,
readProjects,
writeProjects,
} from "../lib/projects.js";
describe("Session persistence", () => {
let tempDir: string;
let testWorkspaceDir: string;
before(async () => {
// Create temp directory for test workspace
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "devclaw-test-"));
testWorkspaceDir = tempDir;
await fs.mkdir(path.join(testWorkspaceDir, "memory"), { recursive: true });
// Create initial projects.json
const initialData: ProjectsData = {
projects: {
"-test-group": {
name: "test-project",
repo: "~/git/test-project",
groupName: "Test Project",
deployUrl: "https://test.example.com",
baseBranch: "main",
deployBranch: "main",
autoChain: false,
channel: "telegram",
dev: {
active: false,
issueId: null,
startTime: null,
model: null,
sessions: {
junior: null,
medior: null,
senior: null,
},
},
qa: {
active: false,
issueId: null,
startTime: null,
model: null,
sessions: {
qa: null,
},
},
},
},
};
await writeProjects(testWorkspaceDir, initialData);
});
after(async () => {
// Clean up temp directory
await fs.rm(tempDir, { recursive: true, force: true });
});
it("should preserve sessions after task completion (single tier)", async () => {
// Simulate task pickup: activate worker with senior tier
await activateWorker(testWorkspaceDir, "-test-group", "dev", {
issueId: "42",
model: "senior",
sessionKey: "agent:test:subagent:senior-session-123",
startTime: new Date().toISOString(),
});
// Verify session was stored
let data = await readProjects(testWorkspaceDir);
assert.strictEqual(
data.projects["-test-group"].dev.sessions.senior,
"agent:test:subagent:senior-session-123",
"Senior session should be stored after activation",
);
assert.strictEqual(
data.projects["-test-group"].dev.active,
true,
"Worker should be active",
);
// Simulate task completion: deactivate worker
await deactivateWorker(testWorkspaceDir, "-test-group", "dev");
// Verify session persists after deactivation
data = await readProjects(testWorkspaceDir);
assert.strictEqual(
data.projects["-test-group"].dev.sessions.senior,
"agent:test:subagent:senior-session-123",
"Senior session should persist after deactivation",
);
assert.strictEqual(
data.projects["-test-group"].dev.active,
false,
"Worker should be inactive",
);
assert.strictEqual(
data.projects["-test-group"].dev.issueId,
null,
"Issue ID should be cleared",
);
});
it("should preserve all tier sessions after completion (multiple tiers)", async () => {
// Setup: create sessions for multiple tiers
await activateWorker(testWorkspaceDir, "-test-group", "dev", {
issueId: "10",
model: "junior",
sessionKey: "agent:test:subagent:junior-session-111",
startTime: new Date().toISOString(),
});
await deactivateWorker(testWorkspaceDir, "-test-group", "dev");
await activateWorker(testWorkspaceDir, "-test-group", "dev", {
issueId: "20",
model: "medior",
sessionKey: "agent:test:subagent:medior-session-222",
startTime: new Date().toISOString(),
});
await deactivateWorker(testWorkspaceDir, "-test-group", "dev");
await activateWorker(testWorkspaceDir, "-test-group", "dev", {
issueId: "30",
model: "senior",
sessionKey: "agent:test:subagent:senior-session-333",
startTime: new Date().toISOString(),
});
await deactivateWorker(testWorkspaceDir, "-test-group", "dev");
// Verify all sessions persisted
const data = await readProjects(testWorkspaceDir);
assert.strictEqual(
data.projects["-test-group"].dev.sessions.junior,
"agent:test:subagent:junior-session-111",
"Junior session should persist",
);
assert.strictEqual(
data.projects["-test-group"].dev.sessions.medior,
"agent:test:subagent:medior-session-222",
"Medior session should persist",
);
assert.strictEqual(
data.projects["-test-group"].dev.sessions.senior,
"agent:test:subagent:senior-session-333",
"Senior session should persist",
);
});
it("should reuse existing session when picking up new task", async () => {
// Setup: create a session for senior tier
await activateWorker(testWorkspaceDir, "-test-group", "dev", {
issueId: "100",
model: "senior",
sessionKey: "agent:test:subagent:senior-reuse-999",
startTime: new Date().toISOString(),
});
await deactivateWorker(testWorkspaceDir, "-test-group", "dev");
// Pick up new task with same tier (no sessionKey = reuse)
await activateWorker(testWorkspaceDir, "-test-group", "dev", {
issueId: "200",
model: "senior",
});
// Verify session was preserved (not overwritten)
const data = await readProjects(testWorkspaceDir);
assert.strictEqual(
data.projects["-test-group"].dev.sessions.senior,
"agent:test:subagent:senior-reuse-999",
"Senior session should be reused (not cleared)",
);
assert.strictEqual(
data.projects["-test-group"].dev.issueId,
"200",
"Issue ID should be updated to new task",
);
});
});