Files
Codewalkers/apps/server/agent/lifecycle/signal-manager.test.ts
Lukas May 57784576e4 perf: speed up slow git tests from ~18s to ~5.5s
- branch-manager: beforeEach→beforeAll (all 12 tests are read-only)
- worktree manager: clone template repo per test instead of full init
- signal-manager: reduce setTimeout delay from 100ms to 30ms
2026-03-07 01:07:43 +01:00

180 lines
6.5 KiB
TypeScript

/**
* SignalManager Tests — Verify atomic signal.json operations.
*/
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { mkdtemp, rm, writeFile, mkdir } from 'node:fs/promises';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { FileSystemSignalManager } from './signal-manager.js';
describe('FileSystemSignalManager', () => {
let tempDir: string;
let agentWorkdir: string;
let signalManager: FileSystemSignalManager;
beforeEach(async () => {
tempDir = await mkdtemp(join(tmpdir(), 'signal-manager-test-'));
agentWorkdir = join(tempDir, 'agent-workdir');
await mkdir(join(agentWorkdir, '.cw', 'output'), { recursive: true });
signalManager = new FileSystemSignalManager();
});
afterEach(async () => {
await rm(tempDir, { recursive: true, force: true });
});
describe('clearSignal', () => {
it('should remove existing signal.json file', async () => {
const signalPath = join(agentWorkdir, '.cw/output/signal.json');
await writeFile(signalPath, JSON.stringify({ status: 'done' }));
await signalManager.clearSignal(agentWorkdir);
const exists = await signalManager.checkSignalExists(agentWorkdir);
expect(exists).toBe(false);
});
it('should not throw if signal.json does not exist', async () => {
await expect(signalManager.clearSignal(agentWorkdir)).resolves.not.toThrow();
});
});
describe('checkSignalExists', () => {
it('should return true when signal.json exists', async () => {
const signalPath = join(agentWorkdir, '.cw/output/signal.json');
await writeFile(signalPath, JSON.stringify({ status: 'done' }));
const exists = await signalManager.checkSignalExists(agentWorkdir);
expect(exists).toBe(true);
});
it('should return false when signal.json does not exist', async () => {
const exists = await signalManager.checkSignalExists(agentWorkdir);
expect(exists).toBe(false);
});
});
describe('readSignal', () => {
it('should read valid done signal', async () => {
const signalPath = join(agentWorkdir, '.cw/output/signal.json');
const expectedSignal = { status: 'done' };
await writeFile(signalPath, JSON.stringify(expectedSignal));
const signal = await signalManager.readSignal(agentWorkdir);
expect(signal).toEqual(expectedSignal);
});
it('should read valid questions signal', async () => {
const signalPath = join(agentWorkdir, '.cw/output/signal.json');
const expectedSignal = {
status: 'questions',
questions: [{ id: '1', question: 'What to do?' }]
};
await writeFile(signalPath, JSON.stringify(expectedSignal));
const signal = await signalManager.readSignal(agentWorkdir);
expect(signal).toEqual(expectedSignal);
});
it('should read valid error signal', async () => {
const signalPath = join(agentWorkdir, '.cw/output/signal.json');
const expectedSignal = { status: 'error', error: 'Something went wrong' };
await writeFile(signalPath, JSON.stringify(expectedSignal));
const signal = await signalManager.readSignal(agentWorkdir);
expect(signal).toEqual(expectedSignal);
});
it('should return null for invalid JSON', async () => {
const signalPath = join(agentWorkdir, '.cw/output/signal.json');
await writeFile(signalPath, '{ invalid json');
const signal = await signalManager.readSignal(agentWorkdir);
expect(signal).toBeNull();
});
it('should return null for invalid status', async () => {
const signalPath = join(agentWorkdir, '.cw/output/signal.json');
await writeFile(signalPath, JSON.stringify({ status: 'invalid' }));
const signal = await signalManager.readSignal(agentWorkdir);
expect(signal).toBeNull();
});
it('should return null for empty file', async () => {
const signalPath = join(agentWorkdir, '.cw/output/signal.json');
await writeFile(signalPath, '');
const signal = await signalManager.readSignal(agentWorkdir);
expect(signal).toBeNull();
});
it('should return null when file does not exist', async () => {
const signal = await signalManager.readSignal(agentWorkdir);
expect(signal).toBeNull();
});
});
describe('waitForSignal', () => {
it('should return signal when file already exists', async () => {
const signalPath = join(agentWorkdir, '.cw/output/signal.json');
const expectedSignal = { status: 'done' };
await writeFile(signalPath, JSON.stringify(expectedSignal));
const signal = await signalManager.waitForSignal(agentWorkdir, 1000);
expect(signal).toEqual(expectedSignal);
});
it('should wait for signal to appear', async () => {
const signalPath = join(agentWorkdir, '.cw/output/signal.json');
const expectedSignal = { status: 'done' };
// Write signal after a delay
setTimeout(async () => {
await writeFile(signalPath, JSON.stringify(expectedSignal));
}, 30);
const signal = await signalManager.waitForSignal(agentWorkdir, 1000);
expect(signal).toEqual(expectedSignal);
});
it('should timeout if signal never appears', async () => {
const signal = await signalManager.waitForSignal(agentWorkdir, 100);
expect(signal).toBeNull();
});
});
describe('validateSignalFile', () => {
it('should return true for complete valid JSON file', async () => {
const signalPath = join(agentWorkdir, '.cw/output/signal.json');
await writeFile(signalPath, JSON.stringify({ status: 'done' }));
const isValid = await signalManager.validateSignalFile(signalPath);
expect(isValid).toBe(true);
});
it('should return false for incomplete JSON', async () => {
const signalPath = join(agentWorkdir, '.cw/output/signal.json');
await writeFile(signalPath, '{ "status": "don');
const isValid = await signalManager.validateSignalFile(signalPath);
expect(isValid).toBe(false);
});
it('should return false for empty file', async () => {
const signalPath = join(agentWorkdir, '.cw/output/signal.json');
await writeFile(signalPath, '');
const isValid = await signalManager.validateSignalFile(signalPath);
expect(isValid).toBe(false);
});
it('should return false when file does not exist', async () => {
const signalPath = join(agentWorkdir, '.cw/output/signal.json');
const isValid = await signalManager.validateSignalFile(signalPath);
expect(isValid).toBe(false);
});
});
});