UNPKG

@logistically/i18n-cli

Version:

Enterprise-grade CLI tool for extracting and managing translations in Logistically microservices

252 lines (208 loc) 7.07 kB
// Mock dependencies before importing jest.mock('../utils/extractor'); jest.mock('../utils/logger', () => { const mockLogger = { setVerbose: jest.fn(), header: jest.fn(), info: jest.fn(), debug: jest.fn(), success: jest.fn(), warning: jest.fn(), error: jest.fn() }; return { Logger: { getInstance: jest.fn(() => mockLogger) } }; }); jest.mock('fs-extra'); import { createExtractCommand, extractTranslationKeys } from './extract'; import { TranslationExtractor } from '../utils/extractor'; import * as fs from 'fs-extra'; const mockExtractor = TranslationExtractor as jest.MockedClass<typeof TranslationExtractor>; const mockFs = fs as jest.Mocked<typeof fs>; describe('Extract Command', () => { let mockLogger: any; beforeEach(() => { mockLogger = { setVerbose: jest.fn(), header: jest.fn(), info: jest.fn(), debug: jest.fn(), success: jest.fn(), warning: jest.fn(), error: jest.fn() }; // Mock the logger instance const { Logger } = require('../utils/logger'); Logger.getInstance.mockReturnValue(mockLogger); // Mock process.exit jest.spyOn(process, 'exit').mockImplementation(() => { throw new Error('process.exit called'); }); // Properly type the mock functions (mockFs.writeFile as any).mockResolvedValue(undefined); (mockFs.writeJson as any).mockResolvedValue(undefined); }); afterEach(() => { jest.clearAllMocks(); }); describe('extractTranslationKeys function', () => { it('should extract translation keys successfully', async () => { const mockKeys = [ { key: 'AUTH.AUTH_SERVICE.EXCEPTION.USER_ALREADY_EXISTS', text: 'User already exists with this email', type: 'EXCEPTION', file: 'auth/src/services/auth.service.ts', line: 10 } ]; mockExtractor.prototype.extract.mockResolvedValue(mockKeys); await extractTranslationKeys({ path: '.', output: 'test-keys.json', ignore: '**/node_modules/**,**/dist/**', verbose: false }); expect(mockExtractor.prototype.extract).toHaveBeenCalledWith({ path: '.', ignore: ['**/node_modules/**', '**/dist/**'], verbose: false }); expect(mockFs.writeJson).toHaveBeenCalledWith( 'test-keys.json', expect.objectContaining({ keys: mockKeys, totalKeys: 1, services: ['auth'], generatedAt: expect.any(String) }), { spaces: 2 } ); }); it('should handle extraction errors', async () => { mockExtractor.prototype.extract.mockRejectedValue(new Error('Extraction failed')); await expect(extractTranslationKeys({ path: '.', output: 'test-keys.json', ignore: '**/node_modules/**', verbose: false })).rejects.toThrow('Extraction failed'); }); it('should handle file writing errors', async () => { const mockKeys = [ { key: 'TEST.KEY', text: 'Test message', type: 'EXCEPTION', file: 'test.ts', line: 1 } ]; mockExtractor.prototype.extract.mockResolvedValue(mockKeys); (mockFs.writeJson as any).mockRejectedValue(new Error('Write failed')); await expect(extractTranslationKeys({ path: '.', output: 'test-keys.json', ignore: '**/node_modules/**', verbose: false })).rejects.toThrow('Write failed'); }); }); describe('extract command', () => { it('should extract translation keys successfully', async () => { const mockKeys = [ { key: 'AUTH.AUTH_SERVICE.EXCEPTION.USER_ALREADY_EXISTS', text: 'User already exists with this email', type: 'EXCEPTION', file: 'auth/src/services/auth.service.ts', line: 10 } ]; mockExtractor.prototype.extract.mockResolvedValue(mockKeys); const command = createExtractCommand(); // Simulate command execution await command.parseAsync(['node', 'test', 'extract', '--path', '.', '--output', 'test-keys.json']); expect(mockExtractor.prototype.extract).toHaveBeenCalledWith({ path: '.', ignore: ['**/node_modules/**', '**/dist/**', '**/coverage/**', '**/*.spec.ts', '**/*.test.ts'], verbose: undefined }); expect(mockFs.writeJson).toHaveBeenCalledWith( 'test-keys.json', expect.objectContaining({ keys: mockKeys, totalKeys: 1, services: ['auth'], generatedAt: expect.any(String) }), { spaces: 2 } ); }); it('should handle extraction errors gracefully', async () => { mockExtractor.prototype.extract.mockRejectedValue(new Error('Extraction failed')); const command = createExtractCommand(); await command.parseAsync(['node', 'test', 'extract']); // Should handle the error gracefully without throwing expect(mockExtractor.prototype.extract).toHaveBeenCalled(); }); it('should handle file writing errors', async () => { const mockKeys = [ { key: 'TEST.KEY', text: 'Test message', type: 'EXCEPTION', file: 'test.ts', line: 1 } ]; mockExtractor.prototype.extract.mockResolvedValue(mockKeys); (mockFs.writeJson as any).mockRejectedValue(new Error('Write failed')); const command = createExtractCommand(); await command.parseAsync(['node', 'test', 'extract']); // Should handle the error gracefully without throwing expect(mockExtractor.prototype.extract).toHaveBeenCalled(); }); it('should use default output file when not specified', async () => { const mockKeys = [ { key: 'TEST.KEY', text: 'Test message', type: 'EXCEPTION', file: 'test.ts', line: 1 } ]; mockExtractor.prototype.extract.mockResolvedValue(mockKeys); const command = createExtractCommand(); await command.parseAsync(['node', 'test', 'extract']); expect(mockFs.writeJson).toHaveBeenCalledWith( 'translation-keys.json', expect.any(Object), { spaces: 2 } ); }); it('should enable verbose mode when specified', async () => { const mockKeys = [ { key: 'TEST.KEY', text: 'Test message', type: 'EXCEPTION', file: 'test.ts', line: 1 } ]; mockExtractor.prototype.extract.mockResolvedValue(mockKeys); const command = createExtractCommand(); await command.parseAsync(['node', 'test', 'extract', '--verbose']); expect(mockExtractor.prototype.extract).toHaveBeenCalledWith({ path: '.', ignore: ['**/node_modules/**', '**/dist/**', '**/coverage/**', '**/*.spec.ts', '**/*.test.ts'], verbose: true }); }); }); });