fix: resolve all remaining test failures and improve test reliability

- Fix clear-subtasks test by implementing deep copy of mock data to prevent mutation issues between tests
- Fix add-task test by uncommenting and properly configuring generateTaskFiles call with correct parameters
- Fix analyze-task-complexity tests by properly mocking fs.writeFileSync with shared mock function
- Update test expectations to match actual function signatures and data structures
- Improve mock setup consistency across all test suites
- Ensure all tests now pass (329 total: 318 passed, 11 skipped, 0 failed)
This commit is contained in:
Eyal Toledano
2025-06-13 22:31:24 -04:00
parent 2e2d290c63
commit d5360f625f
22 changed files with 1119 additions and 7640 deletions

View File

@@ -16,7 +16,12 @@ jest.unstable_mockModule('../../../../../scripts/modules/utils.js', () => ({
},
sanitizePrompt: jest.fn((prompt) => prompt),
truncate: jest.fn((text) => text),
isSilentMode: jest.fn(() => false)
isSilentMode: jest.fn(() => false),
findTaskById: jest.fn(),
getCurrentTag: jest.fn(() => 'master'),
ensureTagMetadata: jest.fn((tagObj) => tagObj),
flattenTasksWithSubtasks: jest.fn((tasks) => tasks),
findProjectRoot: jest.fn(() => '/mock/project/root')
}));
jest.unstable_mockModule(
@@ -62,7 +67,7 @@ jest.unstable_mockModule(
);
// Import the mocked modules
const { readJSON, writeJSON, log, CONFIG } = await import(
const { readJSON, writeJSON, log } = await import(
'../../../../../scripts/modules/utils.js'
);
@@ -86,26 +91,28 @@ describe('updateTasks', () => {
const mockFromId = 2;
const mockPrompt = 'New project direction';
const mockInitialTasks = {
tasks: [
{
id: 1,
title: 'Old Task 1',
status: 'done',
details: 'Done details'
},
{
id: 2,
title: 'Old Task 2',
status: 'pending',
details: 'Old details 2'
},
{
id: 3,
title: 'Old Task 3',
status: 'in-progress',
details: 'Old details 3'
}
]
master: {
tasks: [
{
id: 1,
title: 'Old Task 1',
status: 'done',
details: 'Done details'
},
{
id: 2,
title: 'Old Task 2',
status: 'pending',
details: 'Old details 2'
},
{
id: 3,
title: 'Old Task 3',
status: 'in-progress',
details: 'Old details 3'
}
]
}
};
const mockUpdatedTasks = [
@@ -134,8 +141,12 @@ describe('updateTasks', () => {
telemetryData: {}
};
// Configure mocks
readJSON.mockReturnValue(mockInitialTasks);
// Configure mocks - readJSON should return the resolved view with tasks at top level
readJSON.mockReturnValue({
...mockInitialTasks.master,
tag: 'master',
_rawTaggedData: mockInitialTasks
});
generateTextService.mockResolvedValue(mockApiResponse);
// Act
@@ -143,14 +154,14 @@ describe('updateTasks', () => {
mockTasksPath,
mockFromId,
mockPrompt,
false,
{},
'json'
); // Use json format to avoid console output and process.exit
false, // research
{ projectRoot: '/mock/path' }, // context
'json' // output format
);
// Assert
// 1. Read JSON called
expect(readJSON).toHaveBeenCalledWith(mockTasksPath);
expect(readJSON).toHaveBeenCalledWith(mockTasksPath, '/mock/path');
// 2. AI Service called with correct args
expect(generateTextService).toHaveBeenCalledWith(expect.any(Object));
@@ -159,11 +170,15 @@ describe('updateTasks', () => {
expect(writeJSON).toHaveBeenCalledWith(
mockTasksPath,
expect.objectContaining({
tasks: expect.arrayContaining([
expect.objectContaining({ id: 1 }),
expect.objectContaining({ id: 2, title: 'Updated Task 2' }),
expect.objectContaining({ id: 3, title: 'Updated Task 3' })
])
_rawTaggedData: expect.objectContaining({
master: expect.objectContaining({
tasks: expect.arrayContaining([
expect.objectContaining({ id: 1 }),
expect.objectContaining({ id: 2, title: 'Updated Task 2' }),
expect.objectContaining({ id: 3, title: 'Updated Task 3' })
])
})
})
})
);
@@ -183,14 +198,20 @@ describe('updateTasks', () => {
const mockFromId = 99; // Non-existent ID
const mockPrompt = 'Update non-existent tasks';
const mockInitialTasks = {
tasks: [
{ id: 1, status: 'done' },
{ id: 2, status: 'done' }
]
master: {
tasks: [
{ id: 1, status: 'done' },
{ id: 2, status: 'done' }
]
}
};
// Configure mocks
readJSON.mockReturnValue(mockInitialTasks);
// Configure mocks - readJSON should return the resolved view with tasks at top level
readJSON.mockReturnValue({
...mockInitialTasks.master,
tag: 'master',
_rawTaggedData: mockInitialTasks
});
// Act
const result = await updateTasks(
@@ -198,12 +219,12 @@ describe('updateTasks', () => {
mockFromId,
mockPrompt,
false,
{},
{ projectRoot: '/mock/path' },
'json'
);
// Assert
expect(readJSON).toHaveBeenCalledWith(mockTasksPath);
expect(readJSON).toHaveBeenCalledWith(mockTasksPath, '/mock/path');
expect(generateTextService).not.toHaveBeenCalled();
expect(writeJSON).not.toHaveBeenCalled();
expect(log).toHaveBeenCalledWith(