mirror of
https://github.com/eyaltoledano/claude-task-master.git
synced 2025-11-21 04:27:34 +00:00
95 lines
2.5 KiB
JavaScript
95 lines
2.5 KiB
JavaScript
|
|
import { jest } from '@jest/globals';
|
||
|
|
|
||
|
|
// --- Mocks ---
|
||
|
|
jest.unstable_mockModule('../../../../../scripts/modules/utils.js', () => ({
|
||
|
|
readJSON: jest.fn(),
|
||
|
|
writeJSON: jest.fn(),
|
||
|
|
log: jest.fn(),
|
||
|
|
setTasksForTag: jest.fn(),
|
||
|
|
truncate: jest.fn((t) => t),
|
||
|
|
isSilentMode: jest.fn(() => false)
|
||
|
|
}));
|
||
|
|
|
||
|
|
jest.unstable_mockModule(
|
||
|
|
'../../../../../scripts/modules/task-manager/generate-task-files.js',
|
||
|
|
() => ({
|
||
|
|
default: jest.fn().mockResolvedValue()
|
||
|
|
})
|
||
|
|
);
|
||
|
|
|
||
|
|
jest.unstable_mockModule(
|
||
|
|
'../../../../../scripts/modules/task-manager.js',
|
||
|
|
() => ({
|
||
|
|
isTaskDependentOn: jest.fn(() => false)
|
||
|
|
})
|
||
|
|
);
|
||
|
|
|
||
|
|
// fs not needed since move-task uses writeJSON
|
||
|
|
|
||
|
|
const { readJSON, writeJSON, log } = await import(
|
||
|
|
'../../../../../scripts/modules/utils.js'
|
||
|
|
);
|
||
|
|
const generateTaskFiles = (
|
||
|
|
await import(
|
||
|
|
'../../../../../scripts/modules/task-manager/generate-task-files.js'
|
||
|
|
)
|
||
|
|
).default;
|
||
|
|
|
||
|
|
const { default: moveTask } = await import(
|
||
|
|
'../../../../../scripts/modules/task-manager/move-task.js'
|
||
|
|
);
|
||
|
|
|
||
|
|
const sampleTagged = () => ({
|
||
|
|
master: {
|
||
|
|
tasks: [
|
||
|
|
{ id: 1, title: 'A' },
|
||
|
|
{ id: 2, title: 'B', subtasks: [{ id: 1, title: 'B.1' }] }
|
||
|
|
],
|
||
|
|
metadata: {}
|
||
|
|
},
|
||
|
|
feature: {
|
||
|
|
tasks: [{ id: 10, title: 'X' }],
|
||
|
|
metadata: {}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
const clone = () => JSON.parse(JSON.stringify(sampleTagged()));
|
||
|
|
|
||
|
|
describe('moveTask (unit)', () => {
|
||
|
|
beforeEach(() => {
|
||
|
|
jest.clearAllMocks();
|
||
|
|
readJSON.mockImplementation((path, projectRoot, tag) => {
|
||
|
|
const data = clone();
|
||
|
|
return { ...data[tag], tag, _rawTaggedData: data };
|
||
|
|
});
|
||
|
|
writeJSON.mockResolvedValue();
|
||
|
|
log.mockImplementation(() => {});
|
||
|
|
});
|
||
|
|
|
||
|
|
test('moves task to new ID in same tag', async () => {
|
||
|
|
await moveTask('tasks.json', '1', '3', false, { tag: 'master' });
|
||
|
|
expect(writeJSON).toHaveBeenCalled();
|
||
|
|
const written = writeJSON.mock.calls[0][1];
|
||
|
|
const ids = written.master.tasks.map((t) => t.id);
|
||
|
|
expect(ids).toEqual(expect.arrayContaining([2, 3]));
|
||
|
|
expect(ids).not.toContain(1);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('throws when counts of source and dest mismatch', async () => {
|
||
|
|
await expect(
|
||
|
|
moveTask('tasks.json', '1,2', '3', {}, { tag: 'master' })
|
||
|
|
).rejects.toThrow(/Number of source IDs/);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('batch move calls generateTaskFiles once when flag true', async () => {
|
||
|
|
await moveTask('tasks.json', '1,2', '3,4', true, { tag: 'master' });
|
||
|
|
expect(generateTaskFiles).toHaveBeenCalledTimes(1);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('error when tag invalid', async () => {
|
||
|
|
await expect(
|
||
|
|
moveTask('tasks.json', '1', '2', false, { tag: 'ghost' })
|
||
|
|
).rejects.toThrow(/tag "ghost" not found/);
|
||
|
|
});
|
||
|
|
});
|