Skip to main content
Glama
MIT License
27,120
19,780
  • Linux
  • Apple
defaultAction.test.ts8.61 kB
import process from 'node:process'; import { afterEach, beforeEach, describe, expect, it, type MockedFunction, vi } from 'vitest'; import { buildCliConfig, runDefaultAction } from '../../../src/cli/actions/defaultAction.js'; import { Spinner } from '../../../src/cli/cliSpinner.js'; import type { CliOptions } from '../../../src/cli/types.js'; 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 processConcurrency from '../../../src/shared/processConcurrency.js'; import { createMockConfig } from '../../testing/testUtils.js'; vi.mock('../../../src/core/packager'); vi.mock('../../../src/config/configLoad'); vi.mock('../../../src/core/file/packageJsonParse'); vi.mock('../../../src/core/file/fileStdin'); vi.mock('../../../src/shared/logger'); vi.mock('../../../src/shared/processConcurrency'); const mockSpinner = { start: vi.fn() as MockedFunction<() => void>, update: vi.fn() as MockedFunction<(message: string) => void>, succeed: vi.fn() as MockedFunction<(message: string) => void>, fail: vi.fn() as MockedFunction<(message: string) => void>, stop: vi.fn() as MockedFunction<() => void>, message: 'test', currentFrame: 0, interval: null, isQuiet: false, } as unknown as Spinner; vi.mock('../../../src/cli/cliSpinner', () => ({ Spinner: vi.fn().mockImplementation(() => mockSpinner), })); vi.mock('../../../src/cli/cliReport'); describe('defaultAction', () => { beforeEach(() => { vi.resetAllMocks(); // Reset mockSpinner functions vi.clearAllMocks(); // Ensure Spinner constructor returns mockSpinner vi.mocked(Spinner).mockImplementation(() => mockSpinner); vi.mocked(packageJsonParser.getVersion).mockResolvedValue('1.0.0'); vi.mocked(configLoader.loadFileConfig).mockResolvedValue({}); vi.mocked(configLoader.mergeConfigs).mockReturnValue( createMockConfig({ cwd: process.cwd(), input: { maxFileSize: 50 * 1024 * 1024, }, output: { filePath: 'output.txt', style: 'plain', parsableStyle: false, fileSummary: true, directoryStructure: true, topFilesLength: 5, showLineNumbers: false, removeComments: false, removeEmptyLines: false, compress: false, copyToClipboard: false, stdout: false, git: { sortByChanges: true, sortByChangesMaxCommits: 100, includeDiffs: false, }, files: true, }, ignore: { useGitignore: true, useDefaultPatterns: true, customPatterns: [], }, include: [], security: { enableSecurityCheck: true, }, tokenCount: { encoding: 'o200k_base', }, }), ); vi.mocked(fileStdin.readFilePathsFromStdin).mockResolvedValue({ filePaths: ['test1.txt', 'test2.txt'], emptyDirPaths: [], }); vi.mocked(packager.pack).mockResolvedValue({ totalFiles: 10, totalCharacters: 1000, totalTokens: 200, fileCharCounts: {}, fileTokenCounts: {}, suspiciousFilesResults: [], suspiciousGitDiffResults: [], suspiciousGitLogResults: [], processedFiles: [], safeFilePaths: [], gitDiffTokenCount: 0, gitLogTokenCount: 0, skippedFiles: [], }); // Mock initTaskRunner to return a simple task runner const mockTaskRunner = { run: vi.fn().mockResolvedValue({ packResult: { totalFiles: 10, totalCharacters: 1000, totalTokens: 200, fileCharCounts: {}, fileTokenCounts: {}, suspiciousFilesResults: [], suspiciousGitDiffResults: [], suspiciousGitLogResults: [], processedFiles: [], safeFilePaths: [], gitDiffTokenCount: 0, gitLogTokenCount: 0, skippedFiles: [], }, config: createMockConfig({ cwd: process.cwd(), }), }), cleanup: vi.fn().mockResolvedValue(undefined), }; vi.mocked(processConcurrency.initTaskRunner).mockReturnValue(mockTaskRunner); }); afterEach(() => { vi.resetAllMocks(); }); it('should run the default command successfully', async () => { const options: CliOptions = { output: 'custom-output.txt', verbose: true, }; await runDefaultAction(['.'], process.cwd(), options); expect(processConcurrency.initTaskRunner).toHaveBeenCalledWith({ numOfTasks: 1, workerPath: expect.stringContaining('defaultActionWorker.js'), runtime: 'child_process', }); const taskRunner = vi.mocked(processConcurrency.initTaskRunner).mock.results[0].value; expect(taskRunner.run).toHaveBeenCalled(); expect(taskRunner.cleanup).toHaveBeenCalled(); }); it('should handle custom include patterns', async () => { const options: CliOptions = { include: '*.js,*.ts', }; await runDefaultAction(['.'], process.cwd(), options); const taskRunner = vi.mocked(processConcurrency.initTaskRunner).mock.results[0].value; const task = taskRunner.run.mock.calls[0][0]; expect(task).toMatchObject({ directories: ['.'], cwd: process.cwd(), cliOptions: expect.objectContaining({ include: '*.js,*.ts', }), }); }); it('should handle stdin mode', async () => { const options: CliOptions = { stdin: true, }; await runDefaultAction(['.'], process.cwd(), options); const taskRunner = vi.mocked(processConcurrency.initTaskRunner).mock.results[0].value; const task = taskRunner.run.mock.calls[0][0]; expect(task).toMatchObject({ directories: ['.'], cwd: process.cwd(), cliOptions: expect.objectContaining({ stdin: true, }), stdinFilePaths: expect.any(Array), }); }); it('should handle errors gracefully', async () => { // Create a fresh mock task runner that will fail const failingTaskRunner = { run: vi.fn().mockRejectedValue(new Error('Test error')), cleanup: vi.fn().mockResolvedValue(undefined), }; vi.mocked(processConcurrency.initTaskRunner).mockReturnValue(failingTaskRunner); const options: CliOptions = {}; await expect(runDefaultAction(['.'], process.cwd(), options)).rejects.toThrow('Test error'); expect(failingTaskRunner.cleanup).toHaveBeenCalled(); }); describe('buildCliConfig', () => { it('should handle custom include patterns', () => { const options = { include: '*.js,*.ts', }; const config = buildCliConfig(options); expect(config.include).toEqual(['*.js', '*.ts']); }); it('should handle custom ignore patterns', () => { const options = { ignore: 'node_modules,*.log', }; const config = buildCliConfig(options); expect(config.ignore?.customPatterns).toEqual(['node_modules', '*.log']); }); it('should handle custom output style', () => { const options: CliOptions = { style: 'xml' as const, }; const config = buildCliConfig(options); expect(config.output?.style).toBe('xml'); }); it('should properly trim whitespace from comma-separated patterns', () => { const options = { include: 'src/**/*, tests/**/*, examples/**/*', ignore: 'node_modules/**, dist/**, coverage/**', }; const config = buildCliConfig(options); expect(config.include).toEqual(['src/**/*', 'tests/**/*', 'examples/**/*']); expect(config.ignore?.customPatterns).toEqual(['node_modules/**', 'dist/**', 'coverage/**']); }); it('should handle --no-security-check flag', () => { const options = { securityCheck: false, }; const config = buildCliConfig(options); expect(config.security?.enableSecurityCheck).toBe(false); }); it('should handle --no-file-summary flag', () => { const options = { fileSummary: false, }; const config = buildCliConfig(options); expect(config.output?.fileSummary).toBe(false); }); it('should handle --remove-comments flag', () => { const options = { removeComments: true, }; const config = buildCliConfig(options); expect(config.output?.removeComments).toBe(true); }); }); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/yamadashy/repomix'

If you have feedback or need assistance with the MCP directory API, please join our Discord server