170 lines
4.7 KiB
TypeScript
170 lines
4.7 KiB
TypeScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
|
|
import {
|
|
MutationValidationError,
|
|
buildBdMutationArgs,
|
|
validateMutationPayload,
|
|
executeMutation,
|
|
} from '../../src/lib/mutations';
|
|
|
|
const root = 'C:/Users/test/project/beadboard';
|
|
|
|
test('validateMutationPayload rejects invalid payloads', () => {
|
|
assert.throws(
|
|
() => validateMutationPayload('create', { projectRoot: '', title: '' }),
|
|
(error: unknown) => error instanceof MutationValidationError,
|
|
);
|
|
});
|
|
|
|
test('buildBdMutationArgs maps reopen correctly', () => {
|
|
const payload = validateMutationPayload('reopen', {
|
|
projectRoot: root,
|
|
id: 'bb-123',
|
|
reason: 'retry work',
|
|
});
|
|
|
|
const args = buildBdMutationArgs('reopen', payload);
|
|
assert.deepEqual(args, ['reopen', 'bb-123', '-r', 'retry work', '--json']);
|
|
});
|
|
|
|
test('buildBdMutationArgs maps update issue type correctly', () => {
|
|
const payload = validateMutationPayload('update', {
|
|
projectRoot: root,
|
|
id: 'bb-123',
|
|
issueType: 'feature',
|
|
});
|
|
|
|
const args = buildBdMutationArgs('update', payload);
|
|
assert.deepEqual(args, ['update', 'bb-123', '-t', 'feature', '--json']);
|
|
});
|
|
|
|
test('buildBdMutationArgs maps comment correctly', () => {
|
|
const payload = validateMutationPayload('comment', {
|
|
projectRoot: root,
|
|
id: 'bb-123',
|
|
text: 'Added notes',
|
|
});
|
|
|
|
const args = buildBdMutationArgs('comment', payload);
|
|
assert.deepEqual(args, ['comments', 'add', 'bb-123', 'Added notes', '--json']);
|
|
});
|
|
|
|
test('executeMutation surfaces bridge failures in normalized response', async () => {
|
|
const payload = validateMutationPayload('close', {
|
|
projectRoot: root,
|
|
id: 'bb-123',
|
|
reason: 'completed',
|
|
});
|
|
|
|
const result = await executeMutation('close', payload, {
|
|
runBdCommand: async ({ args }) => {
|
|
assert.deepEqual(args, ['close', 'bb-123', '-r', 'completed', '--json']);
|
|
return {
|
|
success: false,
|
|
classification: 'non_zero_exit',
|
|
command: 'bd',
|
|
args,
|
|
cwd: root,
|
|
stdout: '',
|
|
stderr: 'cannot close',
|
|
code: 1,
|
|
durationMs: 3,
|
|
error: 'cannot close',
|
|
};
|
|
},
|
|
});
|
|
|
|
assert.equal(result.ok, false);
|
|
assert.equal(result.error?.classification, 'non_zero_exit');
|
|
});
|
|
|
|
test('executeMutation returns successful normalized response', async () => {
|
|
const payload = validateMutationPayload('update', {
|
|
projectRoot: root,
|
|
id: 'bb-123',
|
|
status: 'in_progress',
|
|
priority: 1,
|
|
});
|
|
|
|
const result = await executeMutation('update', payload, {
|
|
runBdCommand: async ({ args }) => {
|
|
assert.deepEqual(args, ['update', 'bb-123', '-s', 'in_progress', '-p', '1', '--json']);
|
|
return {
|
|
success: true,
|
|
classification: null,
|
|
command: 'bd',
|
|
args,
|
|
cwd: root,
|
|
stdout: '{"id":"bb-123"}',
|
|
stderr: '',
|
|
code: 0,
|
|
durationMs: 2,
|
|
error: null,
|
|
};
|
|
},
|
|
});
|
|
|
|
assert.equal(result.ok, true);
|
|
assert.equal(result.operation, 'update');
|
|
assert.equal(result.command.success, true);
|
|
});
|
|
|
|
test('executeMutation includes --actor when provided in payload', async () => {
|
|
const payload = validateMutationPayload('comment', {
|
|
projectRoot: root,
|
|
id: 'bb-123',
|
|
text: 'Operator note',
|
|
actor: 'zenchant',
|
|
});
|
|
|
|
const result = await executeMutation('comment', payload, {
|
|
runBdCommand: async ({ args }) => {
|
|
assert.deepEqual(args, ['--actor', 'zenchant', 'comments', 'add', 'bb-123', 'Operator note', '--json']);
|
|
return {
|
|
success: true,
|
|
classification: null,
|
|
command: 'bd',
|
|
args,
|
|
cwd: root,
|
|
stdout: '{"ok":true}',
|
|
stderr: '',
|
|
code: 0,
|
|
durationMs: 2,
|
|
error: null,
|
|
};
|
|
},
|
|
});
|
|
|
|
assert.equal(result.ok, true);
|
|
});
|
|
|
|
test('executeMutation ignores bdPath and uses default runner contract', async () => {
|
|
const payload = validateMutationPayload('update', {
|
|
projectRoot: root,
|
|
id: 'bb-123',
|
|
status: 'in_progress',
|
|
bdPath: 'C:/Tools/beads/bd.exe',
|
|
});
|
|
|
|
const result = await executeMutation('update', payload, {
|
|
runBdCommand: async (options) => {
|
|
assert.equal(options.explicitBdPath, undefined);
|
|
assert.deepEqual(options.args, ['update', 'bb-123', '-s', 'in_progress', '--json']);
|
|
return {
|
|
success: true,
|
|
classification: null,
|
|
command: 'bd',
|
|
args: options.args,
|
|
cwd: root,
|
|
stdout: '{"ok":true}',
|
|
stderr: '',
|
|
code: 0,
|
|
durationMs: 2,
|
|
error: null,
|
|
};
|
|
},
|
|
});
|
|
|
|
assert.equal(result.ok, true);
|
|
});
|