UNPKG

sourcesailor

Version:

A CLI tool for analyzing and documenting codebases

147 lines (146 loc) 7.17 kB
/* eslint-disable @typescript-eslint/no-explicit-any */ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import yargs from 'yargs'; import { hideBin } from "yargs/helpers"; import { command, describe as commandDescribe, builder, handler } from '../commands/getDirStructure.mjs'; import * as directoryProcessor from '../directoryProcessor.mjs'; import * as utils from '../utils.mjs'; import * as inquirer from '@inquirer/prompts'; import * as setExpertise from '../commands/setExpertise.mjs'; const yargsSetup = yargs(hideBin(process.argv)); describe("Get Directory Structure Command Tests", () => { const mockProjectPath = '/mock/project/path'; const mockFileStructure = { name: 'root', type: 'directory', children: [ { name: 'file1.txt', type: 'file', content: 'File 1 content' }, { name: 'dir1', type: 'directory', children: [ { name: 'file2.txt', type: 'file', content: 'File 2 content' } ] } ] }; beforeEach(() => { vi.mock('fs'); vi.mock('../directoryProcessor.mjs'); vi.mock('../utils.mjs'); vi.mock('@inquirer/prompts'); vi.mock('../commands/setExpertise.mjs'); vi.spyOn(console, 'log').mockImplementation(() => { }); vi.spyOn(console, 'error').mockImplementation(() => { }); directoryProcessor.getDirStructure.mockResolvedValue(mockFileStructure); vi.mocked(utils.readConfig).mockReturnValue({ ANALYSIS_DIR: '/test', userExpertise: 'intermediate' }); vi.mocked(inquirer.confirm).mockResolvedValue(false); vi.mocked(setExpertise.handler).mockResolvedValue(undefined); }); afterEach(() => { vi.restoreAllMocks(); }); it("returns help output", async () => { const parser = yargsSetup.command({ command, describe: commandDescribe, builder, handler }).help(); const output = await new Promise((resolve) => { parser.parse("dirStructure --help", (_err, _argv, output) => { resolve(output); }); }); expect(output).toContain("Get Directory Structure"); expect(output).toContain("--verbose"); expect(output).toContain("--withContent"); expect(output).toContain("--ignore"); }); it("calls getDirStructure with correct parameters", async () => { const parser = yargsSetup.command({ command, describe: commandDescribe, builder, handler }); await new Promise((resolve) => { parser.parse(`dirStructure ${mockProjectPath} --verbose --withContent --ignore node_modules dist`, (_err, argv) => { resolve(argv); }); }); expect(directoryProcessor.getDirStructure).toHaveBeenCalledWith(mockProjectPath, ['node_modules', 'dist'], true); }); it("logs directory structure with content when withContent is true", async () => { const parser = yargsSetup.command({ command, describe: commandDescribe, builder, handler }); await new Promise((resolve) => { parser.parse(`dirStructure ${mockProjectPath} --withContent`, (_err, argv) => { resolve(argv); }); }); expect(console.log).toHaveBeenCalledWith(JSON.stringify(mockFileStructure)); }); it("logs directory structure without content when withContent is false", async () => { const expectedStructureWithoutContent = JSON.parse(JSON.stringify(mockFileStructure)); const removeContent = (node) => { delete node.content; if (node.children) { node.children.forEach(removeContent); } }; removeContent(expectedStructureWithoutContent); const parser = yargsSetup.command({ command, describe: commandDescribe, builder, handler }); await new Promise((resolve) => { parser.parse(`dirStructure ${mockProjectPath} --withContent false`, (_err, argv) => { resolve(argv); }); }); expect(console.log).toHaveBeenCalledWith(JSON.stringify(expectedStructureWithoutContent)); }); it("uses default values when not provided", async () => { const parser = yargsSetup.command({ command, describe: commandDescribe, builder, handler }); await new Promise((resolve) => { parser.parse(`dirStructure ${mockProjectPath}`, (_err, argv) => { resolve(argv); }); }); expect(directoryProcessor.getDirStructure).toHaveBeenCalledWith(mockProjectPath, [], false); }); it("handles errors from getDirStructure", async () => { const mockError = new Error("Mock error"); const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => { }); directoryProcessor.getDirStructure.mockRejectedValue(mockError); const parser = yargsSetup.command({ command, describe: commandDescribe, builder, handler }); await new Promise((resolve) => { parser.parse(`dirStructure ${mockProjectPath}`, (_err, argv) => { resolve(argv); }); }); expect(consoleSpy).toHaveBeenCalledWith("Error analyzing directory structure:", mockError); }); // it("handles invalid project path", async () => { // const parser = yargsSetup.command({command, describe: commandDescribe, builder, handler}) // const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => { }) // await new Promise((resolve) => { // parser.parse(`dirStructure`, (_err: any, argv: unknown) => { // console.log({argv}) // resolve(argv) // }) // }) // expect(consoleSpy).toHaveBeenCalledWith("Error: Project path is required") // }) it('should prompt for user expertise if not set', async () => { vi.mocked(utils.readConfig).mockReturnValue({ ANALYSIS_DIR: '/test' }); vi.mocked(inquirer.confirm).mockResolvedValue(true); const parser = yargsSetup.command({ command, describe: commandDescribe, builder, handler }); await new Promise((resolve) => { parser.parse(`dirStructure ${mockProjectPath}`, (_err, argv) => { resolve(argv); }); }); expect(inquirer.confirm).toHaveBeenCalledWith({ message: "Would you like to set your expertise now?", default: true }); expect(setExpertise.handler).toHaveBeenCalled(); }); it('should not prompt for user expertise if already set', async () => { vi.mocked(utils.readConfig).mockReturnValue({ ANALYSIS_DIR: '/test', userExpertise: 'intermediate' }); const parser = yargsSetup.command({ command, describe: commandDescribe, builder, handler }); await new Promise((resolve) => { parser.parse(`dirStructure ${mockProjectPath}`, (_err, argv) => { resolve(argv); }); }); expect(inquirer.confirm).not.toHaveBeenCalled(); expect(setExpertise.handler).not.toHaveBeenCalled(); }); });