agent-ecosystem/test/features/member-work-sync/main/JsonMemberWorkSyncStore.test.ts

72 lines
2.6 KiB
TypeScript

import { mkdir, mkdtemp, readFile, readdir, rm, writeFile } from 'fs/promises';
import { join } from 'path';
import { tmpdir } from 'os';
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
import { JsonMemberWorkSyncStore } from '@features/member-work-sync/main/infrastructure/JsonMemberWorkSyncStore';
import { MemberWorkSyncStorePaths } from '@features/member-work-sync/main/infrastructure/MemberWorkSyncStorePaths';
describe('JsonMemberWorkSyncStore', () => {
let root: string;
let store: JsonMemberWorkSyncStore;
beforeEach(async () => {
root = await mkdtemp(join(tmpdir(), 'member-work-sync-store-'));
store = new JsonMemberWorkSyncStore(new MemberWorkSyncStorePaths(root));
});
afterEach(async () => {
await rm(root, { recursive: true, force: true });
});
it('quarantines invalid status JSON and returns empty state', async () => {
const statusPath = join(root, 'team-a', '.member-work-sync', 'status.json');
await mkdir(join(root, 'team-a', '.member-work-sync'), { recursive: true });
await writeFile(statusPath, '{bad json', 'utf8');
await expect(store.read({ teamName: 'team-a', memberName: 'bob' })).resolves.toBeNull();
const teamDir = join(root, 'team-a', '.member-work-sync');
const entries = await readdir(teamDir);
expect(entries.some((entry) => entry.startsWith('status.json.invalid.'))).toBe(true);
});
it('deduplicates pending report intents and marks them processed', async () => {
const request = {
teamName: 'team-a',
memberName: 'bob',
state: 'still_working' as const,
agendaFingerprint: 'agenda:v1:abc',
reportToken: 'wrs:v1.test',
taskIds: ['task-2', 'task-1', 'task-1'],
source: 'mcp' as const,
};
await store.appendPendingReport(request, 'control_api_unavailable');
await store.appendPendingReport({ ...request, taskIds: ['task-1', 'task-2'] }, 'duplicate');
const pending = await store.listPendingReports('team-a');
expect(pending).toHaveLength(1);
expect(pending[0]).toMatchObject({
teamName: 'team-a',
memberName: 'bob',
reason: 'control_api_unavailable',
status: 'pending',
});
await store.markPendingReportProcessed('team-a', pending[0].id, {
status: 'accepted',
resultCode: 'accepted',
processedAt: '2026-04-29T00:00:00.000Z',
});
expect(await store.listPendingReports('team-a')).toEqual([]);
const file = JSON.parse(
await readFile(join(root, 'team-a', '.member-work-sync', 'pending-reports.json'), 'utf8')
);
expect(file.intents[pending[0].id]).toMatchObject({
status: 'accepted',
resultCode: 'accepted',
});
});
});