mirror of
https://github.com/yamadashy/repomix.git
synced 2026-05-30 11:18:53 +02:00
test(core): Add test coverage for progressCallback in runDefaultAction
Add three test cases for handleProgress: - Callback is invoked with progress messages from pack() - Async callback rejection is isolated (pack completes, error logged) - Spinner still updates when callback throws synchronously Also restore the outer try-catch for sync errors — Promise.resolve() only catches async rejections, not synchronous throws from the callback invocation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -118,9 +118,13 @@ export const runDefaultAction = async (
|
||||
const handleProgress: RepomixProgressCallback = (message) => {
|
||||
spinner.update(message);
|
||||
if (progressCallback) {
|
||||
Promise.resolve(progressCallback(message)).catch((error) => {
|
||||
try {
|
||||
Promise.resolve(progressCallback(message)).catch((error) => {
|
||||
logger.trace('progressCallback error:', error);
|
||||
});
|
||||
} catch (error) {
|
||||
logger.trace('progressCallback error:', error);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import * as configLoader from '../../../src/config/configLoad.js';
|
||||
import * as fileStdin from '../../../src/core/file/fileStdin.js';
|
||||
import * as packageJsonParser from '../../../src/core/file/packageJsonParse.js';
|
||||
import * as packager from '../../../src/core/packager.js';
|
||||
import * as loggerModule from '../../../src/shared/logger.js';
|
||||
import { createMockConfig } from '../../testing/testUtils.js';
|
||||
|
||||
vi.mock('../../../src/core/packager');
|
||||
@@ -156,6 +157,95 @@ describe('defaultAction', () => {
|
||||
expect(mockSpinner.fail).toHaveBeenCalledWith('Error during packing');
|
||||
});
|
||||
|
||||
describe('progressCallback', () => {
|
||||
it('should forward progress messages to the provided callback', async () => {
|
||||
// Configure pack mock to invoke its 3rd argument (progressCallback)
|
||||
vi.mocked(packager.pack).mockImplementation(async (_paths, _config, progressCallback = () => {}) => {
|
||||
progressCallback('Searching for files...');
|
||||
progressCallback('Processing files...');
|
||||
return {
|
||||
totalFiles: 10,
|
||||
totalCharacters: 1000,
|
||||
totalTokens: 200,
|
||||
fileCharCounts: {},
|
||||
fileTokenCounts: {},
|
||||
suspiciousFilesResults: [],
|
||||
suspiciousGitDiffResults: [],
|
||||
suspiciousGitLogResults: [],
|
||||
processedFiles: [],
|
||||
safeFilePaths: [],
|
||||
gitDiffTokenCount: 0,
|
||||
gitLogTokenCount: 0,
|
||||
skippedFiles: [],
|
||||
};
|
||||
});
|
||||
|
||||
const callback = vi.fn();
|
||||
await runDefaultAction(['.'], process.cwd(), {}, callback);
|
||||
|
||||
expect(callback).toHaveBeenCalledWith('Searching for files...');
|
||||
expect(callback).toHaveBeenCalledWith('Processing files...');
|
||||
});
|
||||
|
||||
it('should isolate async callback errors without affecting pack flow', async () => {
|
||||
vi.mocked(packager.pack).mockImplementation(async (_paths, _config, progressCallback = () => {}) => {
|
||||
progressCallback('test message');
|
||||
// Allow microtask to process the rejected promise
|
||||
await new Promise((resolve) => setTimeout(resolve, 10));
|
||||
return {
|
||||
totalFiles: 10,
|
||||
totalCharacters: 1000,
|
||||
totalTokens: 200,
|
||||
fileCharCounts: {},
|
||||
fileTokenCounts: {},
|
||||
suspiciousFilesResults: [],
|
||||
suspiciousGitDiffResults: [],
|
||||
suspiciousGitLogResults: [],
|
||||
processedFiles: [],
|
||||
safeFilePaths: [],
|
||||
gitDiffTokenCount: 0,
|
||||
gitLogTokenCount: 0,
|
||||
skippedFiles: [],
|
||||
};
|
||||
});
|
||||
|
||||
const rejectingCallback = vi.fn().mockRejectedValue(new Error('callback error'));
|
||||
const result = await runDefaultAction(['.'], process.cwd(), {}, rejectingCallback);
|
||||
|
||||
expect(result.packResult.totalFiles).toBe(10);
|
||||
expect(loggerModule.logger.trace).toHaveBeenCalledWith('progressCallback error:', expect.any(Error));
|
||||
});
|
||||
|
||||
it('should still update spinner even when callback throws synchronously', async () => {
|
||||
vi.mocked(packager.pack).mockImplementation(async (_paths, _config, progressCallback = () => {}) => {
|
||||
progressCallback('test message');
|
||||
return {
|
||||
totalFiles: 10,
|
||||
totalCharacters: 1000,
|
||||
totalTokens: 200,
|
||||
fileCharCounts: {},
|
||||
fileTokenCounts: {},
|
||||
suspiciousFilesResults: [],
|
||||
suspiciousGitDiffResults: [],
|
||||
suspiciousGitLogResults: [],
|
||||
processedFiles: [],
|
||||
safeFilePaths: [],
|
||||
gitDiffTokenCount: 0,
|
||||
gitLogTokenCount: 0,
|
||||
skippedFiles: [],
|
||||
};
|
||||
});
|
||||
|
||||
const throwingCallback = vi.fn().mockImplementation(() => {
|
||||
throw new Error('sync error');
|
||||
});
|
||||
await runDefaultAction(['.'], process.cwd(), {}, throwingCallback);
|
||||
|
||||
// Spinner should still be updated despite callback failure
|
||||
expect(mockSpinner.update).toHaveBeenCalledWith('test message');
|
||||
});
|
||||
});
|
||||
|
||||
describe('buildCliConfig', () => {
|
||||
it('should handle custom include patterns', () => {
|
||||
const options = {
|
||||
|
||||
Reference in New Issue
Block a user