Files
mosaic/packages/queue/tests/cli.test.ts
2026-03-06 22:44:05 +00:00

220 lines
4.7 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest';
import { runQueueCli, type QueueCliDependencies, type QueueRepository } from '../src/cli.js';
import type { Task } from '@mosaic/types';
function createRepositoryMock(): QueueRepository {
return {
create: vi.fn(() =>
Promise.resolve<Task>({
id: 'MQ-005',
project: 'queue',
mission: 'phase1',
taskId: 'MQ-005',
title: 'Build CLI',
status: 'pending',
priority: 'medium',
dependencies: [],
lane: 'any',
retryCount: 0,
createdAt: 1,
updatedAt: 1,
}),
),
list: vi.fn(() => Promise.resolve([])),
get: vi.fn(() => Promise.resolve(null)),
claim: vi.fn(() =>
Promise.resolve<Task>({
id: 'MQ-005',
project: 'queue',
mission: 'phase1',
taskId: 'MQ-005',
title: 'Build CLI',
status: 'claimed',
priority: 'medium',
dependencies: [],
lane: 'any',
claimedBy: 'agent-a',
claimedAt: 2,
claimTTL: 60,
retryCount: 0,
createdAt: 1,
updatedAt: 2,
}),
),
release: vi.fn(() =>
Promise.resolve<Task>({
id: 'MQ-005',
project: 'queue',
mission: 'phase1',
taskId: 'MQ-005',
title: 'Build CLI',
status: 'pending',
priority: 'medium',
dependencies: [],
lane: 'any',
retryCount: 0,
createdAt: 1,
updatedAt: 3,
}),
),
complete: vi.fn(() =>
Promise.resolve<Task>({
id: 'MQ-005',
project: 'queue',
mission: 'phase1',
taskId: 'MQ-005',
title: 'Build CLI',
status: 'completed',
priority: 'medium',
dependencies: [],
lane: 'any',
completionSummary: 'done',
retryCount: 0,
createdAt: 1,
updatedAt: 4,
completedAt: 4,
}),
),
};
}
function createDependencies(
repository: QueueRepository,
): QueueCliDependencies & { outputs: string[]; errors: string[] } {
const outputs: string[] = [];
const errors: string[] = [];
const close = vi.fn(() => Promise.resolve(undefined));
return {
openSession: () =>
Promise.resolve({
repository,
close,
}),
stdout: (line) => {
outputs.push(line);
},
stderr: (line) => {
errors.push(line);
},
outputs,
errors,
};
}
describe('runQueueCli', () => {
it('creates a task from command options', async () => {
const repository = createRepositoryMock();
const dependencies = createDependencies(repository);
const exitCode = await runQueueCli(
[
'node',
'mosaic',
'queue',
'create',
'queue',
'phase1',
'MQ-005',
'--title',
'Build CLI',
'--priority',
'high',
'--lane',
'coding',
'--dependency',
'MQ-002',
'MQ-003',
],
dependencies,
);
expect(exitCode).toBe(0);
expect(repository.create).toHaveBeenCalledWith({
project: 'queue',
mission: 'phase1',
taskId: 'MQ-005',
title: 'Build CLI',
description: undefined,
priority: 'high',
dependencies: ['MQ-002', 'MQ-003'],
lane: 'coding',
});
});
it('lists tasks with filters', async () => {
const repository = createRepositoryMock();
const dependencies = createDependencies(repository);
const exitCode = await runQueueCli(
[
'node',
'mosaic',
'queue',
'list',
'--project',
'queue',
'--mission',
'phase1',
'--status',
'pending',
],
dependencies,
);
expect(exitCode).toBe(0);
expect(repository.list).toHaveBeenCalledWith({
project: 'queue',
mission: 'phase1',
status: 'pending',
});
});
it('claims and completes tasks with typed options', async () => {
const repository = createRepositoryMock();
const dependencies = createDependencies(repository);
const claimExitCode = await runQueueCli(
[
'node',
'mosaic',
'queue',
'claim',
'MQ-005',
'--agent',
'agent-a',
'--ttl',
'60',
],
dependencies,
);
const completeExitCode = await runQueueCli(
[
'node',
'mosaic',
'queue',
'complete',
'MQ-005',
'--agent',
'agent-a',
'--summary',
'done',
],
dependencies,
);
expect(claimExitCode).toBe(0);
expect(completeExitCode).toBe(0);
expect(repository.claim).toHaveBeenCalledWith('MQ-005', {
agentId: 'agent-a',
ttlSeconds: 60,
});
expect(repository.complete).toHaveBeenCalledWith('MQ-005', {
agentId: 'agent-a',
summary: 'done',
});
});
});