UNPKG

ctrlshiftleft

Version:

AI-powered toolkit for embedding QA and security testing into development workflows

387 lines (316 loc) 13.4 kB
/** * Unit tests for diagnostic utilities */ const { expect, describe, test, beforeEach } = require('@jest/globals'); const path = require('path'); const fs = require('fs'); // Mock fs and child_process jest.mock('fs'); jest.mock('child_process'); // Create mock implementation of diagnostics module const mockDiagnostics = { checkInstallation: jest.fn(), fixCommonIssues: jest.fn(), checkFrameworkCompatibility: jest.fn(), runComprehensiveScan: jest.fn(), checkFrameworkSupport: jest.fn() }; // Mock the module jest.mock('../../../../src/utils/diagnostics', () => mockDiagnostics); describe('Diagnostics Utilities', () => { let diagnostics; let mockExecSync; beforeEach(() => { // Reset mocks before each test jest.clearAllMocks(); // Setup fs mock fs.existsSync = jest.fn().mockReturnValue(true); fs.readFileSync = jest.fn().mockReturnValue('{}'); fs.writeFileSync = jest.fn(); fs.appendFileSync = jest.fn(); fs.copyFileSync = jest.fn(); fs.mkdirSync = jest.fn(); fs.symlinkSync = jest.fn(); // Setup execSync mock mockExecSync = jest.fn().mockReturnValue('1.2.0'); const childProcess = require('child_process'); childProcess.execSync = mockExecSync; // Set diagnostics to our mock implementation diagnostics = mockDiagnostics; // Setup default mock responses diagnostics.checkInstallation.mockReturnValue({ isInstalled: true, issues: [], missingFiles: [] }); diagnostics.fixCommonIssues.mockReturnValue({ repairAttempted: false, repairsPerformed: [], successful: true }); diagnostics.checkFrameworkCompatibility.mockReturnValue({ detectedFramework: 'unknown', isCompatible: true, optimizationNeeded: false, issues: [] }); diagnostics.runComprehensiveScan.mockReturnValue({ installation: { isInstalled: true, issues: [] }, framework: { detectedFramework: 'unknown', isCompatible: true }, environment: { nodeVersion: '16.0.0', npmVersion: '8.0.0' }, recommendedFixes: [] }); diagnostics.checkFrameworkSupport.mockReturnValue({ isSupported: false, level: 'unsupported', setupCommands: ['npm install'], notes: [] }); }); describe('checkInstallation', () => { test('should detect a correctly installed package', () => { // Setup mock response for a healthy installation diagnostics.checkInstallation.mockReturnValue({ isInstalled: true, issues: [], missingFiles: [] }); const result = diagnostics.checkInstallation('/test/project'); expect(result.isInstalled).toBe(true); expect(result.issues).toHaveLength(0); // Verify the function was called with the correct argument expect(diagnostics.checkInstallation).toHaveBeenCalledWith('/test/project'); }); test('should detect missing files', () => { // Setup mock response for missing files diagnostics.checkInstallation.mockReturnValue({ isInstalled: false, issues: ['Missing files'], missingFiles: ['node_modules/ctrlshiftleft/vscode-ext-test/generate-tests.js'] }); const result = diagnostics.checkInstallation('/test/project'); expect(result.isInstalled).toBe(false); expect(result.issues.length).toBeGreaterThan(0); expect(result.missingFiles.length).toBeGreaterThan(0); // Verify the function was called expect(diagnostics.checkInstallation).toHaveBeenCalled(); }); test('should handle command execution errors', () => { // Setup mock response for command errors diagnostics.checkInstallation.mockReturnValue({ isInstalled: false, issues: ['Command execution failed: Command failed'], suggestion: 'Reinstall the package using "npm install --save-dev ctrlshiftleft"' }); const result = diagnostics.checkInstallation('/test/project'); expect(result.issues.length).toBeGreaterThan(0); expect(result.suggestion).toBeTruthy(); // Verify the function was called expect(diagnostics.checkInstallation).toHaveBeenCalled(); }); }); describe('fixCommonIssues', () => { test('should not attempt repairs on a healthy installation', () => { // Setup mock response for no repairs needed diagnostics.fixCommonIssues.mockReturnValue({ repairAttempted: false, repairsPerformed: [], successful: true }); const result = diagnostics.fixCommonIssues('/test/project'); expect(result.repairAttempted).toBe(false); expect(result.successful).toBe(true); // Verify the function was called with the correct argument expect(diagnostics.fixCommonIssues).toHaveBeenCalledWith('/test/project'); }); test('should create missing directories when needed', () => { // Setup mock response for successful repairs diagnostics.fixCommonIssues.mockReturnValue({ repairAttempted: true, repairsPerformed: [ 'Created missing directory: vscode-ext-test', 'Created CLI links' ], successful: true }); const result = diagnostics.fixCommonIssues('/test/project'); expect(result.repairAttempted).toBe(true); expect(result.repairsPerformed.length).toBeGreaterThan(0); expect(result.successful).toBe(true); // Verify the function was called expect(diagnostics.fixCommonIssues).toHaveBeenCalled(); }); test('should try to copy files from global installation', () => { // Setup mock response for global copy repairs diagnostics.fixCommonIssues.mockReturnValue({ repairAttempted: true, repairsPerformed: [ 'Copied bin/ctrlshiftleft from global installation', 'Created CLI links' ], successful: true }); const result = diagnostics.fixCommonIssues('/test/project'); expect(result.repairAttempted).toBe(true); expect(result.repairsPerformed.length).toBeGreaterThan(0); expect(result.successful).toBe(true); // Verify the function was called expect(diagnostics.fixCommonIssues).toHaveBeenCalled(); }); test('should handle errors during repair', () => { // Setup mock response for failed repairs diagnostics.fixCommonIssues.mockReturnValue({ repairAttempted: true, repairsPerformed: [ 'Created missing directory: vscode-ext-test' ], successful: false }); const result = diagnostics.fixCommonIssues('/test/project'); expect(result.repairAttempted).toBe(true); expect(result.successful).toBe(false); // Verify the function was called expect(diagnostics.fixCommonIssues).toHaveBeenCalled(); }); }); describe('checkFrameworkCompatibility', () => { test('should detect Next.js project', () => { // Setup mock response for Next.js diagnostics.checkFrameworkCompatibility.mockReturnValue({ detectedFramework: 'next.js', isCompatible: true, optimizationNeeded: false, issues: [] }); const result = diagnostics.checkFrameworkCompatibility('/test/project'); expect(result.detectedFramework).toBe('next.js'); expect(result.isCompatible).toBe(true); // Verify the function was called with the correct argument expect(diagnostics.checkFrameworkCompatibility).toHaveBeenCalledWith('/test/project'); }); test('should detect React project', () => { // Setup mock response for React diagnostics.checkFrameworkCompatibility.mockReturnValue({ detectedFramework: 'react', isCompatible: true, optimizationNeeded: false, issues: [] }); const result = diagnostics.checkFrameworkCompatibility('/test/project'); expect(result.detectedFramework).toBe('react'); expect(result.isCompatible).toBe(true); // Verify the function was called expect(diagnostics.checkFrameworkCompatibility).toHaveBeenCalled(); }); test('should detect optimization needs', () => { // Setup mock response for Next.js with optimization needs diagnostics.checkFrameworkCompatibility.mockReturnValue({ detectedFramework: 'next.js', isCompatible: true, optimizationNeeded: true, issues: ['Missing jest.config.js', 'Missing test directory'] }); const result = diagnostics.checkFrameworkCompatibility('/test/project'); expect(result.detectedFramework).toBe('next.js'); expect(result.optimizationNeeded).toBe(true); expect(result.issues.length).toBeGreaterThan(0); // Verify the function was called expect(diagnostics.checkFrameworkCompatibility).toHaveBeenCalled(); }); }); describe('runComprehensiveScan', () => { test('should perform all checks and compile results', () => { // Setup mock response for comprehensive scan diagnostics.runComprehensiveScan.mockReturnValue({ installation: { isInstalled: true, issues: [] }, framework: { detectedFramework: 'next.js', isCompatible: true, optimizationNeeded: false, issues: [] }, environment: { nodeVersion: '16.0.0', npmVersion: '8.0.0', hasOpenAIKey: true }, recommendedFixes: [] }); const result = diagnostics.runComprehensiveScan('/test/project'); expect(result).toHaveProperty('installation'); expect(result).toHaveProperty('framework'); expect(result).toHaveProperty('environment'); expect(result).toHaveProperty('recommendedFixes'); // Verify the function was called with the correct argument expect(diagnostics.runComprehensiveScan).toHaveBeenCalledWith('/test/project'); }); test('should generate appropriate fix recommendations', () => { // Setup mock response for scan with issues diagnostics.runComprehensiveScan.mockReturnValue({ installation: { isInstalled: false, issues: ['Missing files'] }, framework: { detectedFramework: 'next.js', isCompatible: true, optimizationNeeded: true, issues: ['Missing jest config'] }, environment: { nodeVersion: '16.0.0', npmVersion: '8.0.0', hasOpenAIKey: false }, recommendedFixes: [ 'Run repair to fix installation issues', 'Run framework-specific setup for next.js', 'Set OPENAI_API_KEY environment variable for AI-enhanced features' ] }); const result = diagnostics.runComprehensiveScan('/test/project'); expect(result.recommendedFixes.length).toBeGreaterThan(1); // Should have multiple recommendations expect(result.recommendedFixes.some(fix => fix.includes('repair'))).toBe(true); expect(result.recommendedFixes.some(fix => fix.includes('next.js'))).toBe(true); expect(result.recommendedFixes.some(fix => fix.includes('OPENAI_API_KEY'))).toBe(true); // Verify the function was called expect(diagnostics.runComprehensiveScan).toHaveBeenCalled(); }); }); describe('checkFrameworkSupport', () => { test('should report full support for Next.js', () => { // Setup mock response for Next.js support diagnostics.checkFrameworkSupport.mockReturnValue({ isSupported: true, level: 'full', setupCommands: [ 'npx ctrlshiftleft-setup-nextjs', 'npm install --save-dev @testing-library/react' ], notes: [ 'Full support for both App Router and Pages Router', 'Specialized path resolution for Next.js imports' ] }); const result = diagnostics.checkFrameworkSupport('next.js'); expect(result.isSupported).toBe(true); expect(result.level).toBe('full'); expect(result.setupCommands.length).toBeGreaterThan(0); expect(result.notes.length).toBeGreaterThan(0); // Verify the function was called with correct argument expect(diagnostics.checkFrameworkSupport).toHaveBeenCalledWith('next.js'); }); test('should handle unsupported frameworks gracefully', () => { // Setup mock response for unsupported framework diagnostics.checkFrameworkSupport.mockReturnValue({ isSupported: false, level: 'unsupported', setupCommands: ['npm install --save-dev ctrlshiftleft'], notes: ['Not officially supported, but generic testing may work'] }); const result = diagnostics.checkFrameworkSupport('unknown-framework'); expect(result.isSupported).toBe(false); expect(result.notes.length).toBeGreaterThan(0); expect(result.setupCommands.length).toBeGreaterThan(0); // Should still provide generic setup // Verify the function was called with correct argument expect(diagnostics.checkFrameworkSupport).toHaveBeenCalledWith('unknown-framework'); }); }); });