diff --git a/test-output.txt b/test-output.txt deleted file mode 100644 index 9f542d0..0000000 --- a/test-output.txt +++ /dev/null @@ -1,72 +0,0 @@ - -> erpauto@1.8.0 test:run -> vitest run cleaner - - - RUN  v4.0.18 D:/FileLib/Projects/CodeMigration/ERPAuto - -stdout | tests/unit/cleaner-handler.test.ts -Test suite starting... - -stdout | tests/unit/cleaner-helpers.test.ts -Test suite starting... - -stdout | tests/unit/cleaner-helpers.test.ts -Test suite completed. - - 鉁?[39m tests/unit/cleaner-helpers.test.ts (3 tests) 6ms -stdout | tests/unit/cleaner-handler.test.ts -Test suite completed. - - 鉁?[39m tests/unit/cleaner-handler.test.ts (2 tests) 120ms -stdout | tests/unit/cleaner.test.ts -Test suite starting... - -stdout | tests/unit/cleaner.test.ts -Test suite completed. - - 鉁?[39m tests/unit/cleaner.test.ts (8 tests) 64ms -stdout | tests/integration/cleaner.test.ts -Test suite starting... - -stderr | tests/integration/cleaner.test.ts > Cleaner Service (Integration) > Dry-run mode > should initialize with dry-run mode -Skipping test: ERP credentials not configured - -stderr | tests/integration/cleaner.test.ts > Cleaner Service (Integration) > Dry-run mode > should track materials to delete without actually deleting (dry-run) -Skipping test: ERP credentials not configured - -stderr | tests/integration/cleaner.test.ts > Cleaner Service (Integration) > Order processing > should process single order and return details -Skipping test: ERP credentials not configured - -stderr | tests/integration/cleaner.test.ts > Cleaner Service (Integration) > Order processing > should handle order with "瀹℃壒閫氳繃" status -Skipping test: ERP credentials not configured - -stderr | tests/integration/cleaner.test.ts > Cleaner Service (Integration) > Order processing > should handle multiple orders with progress callback -Skipping test: ERP credentials not configured - -stderr | tests/integration/cleaner.test.ts > Cleaner Service (Integration) > Error handling > should continue processing after order error -Skipping test: ERP credentials not configured - -stderr | tests/integration/cleaner.test.ts > Cleaner Service (Integration) > Navigation > should navigate to discrete production order maintenance page -Skipping test: ERP credentials not configured - -stdout | tests/integration/cleaner.test.ts -Test suite completed. - - 鉁?[39m tests/integration/cleaner.test.ts (7 tests) 10ms -stdout | tests/manual/cleaner-slow-motion.test.ts -Test suite starting... - -stderr | tests/manual/cleaner-slow-motion.test.ts > Cleaner Slow Motion Test > should run cleaner in slow motion mode -Please set ERP_URL, ERP_USERNAME, ERP_PASSWORD in .env file - -stdout | tests/manual/cleaner-slow-motion.test.ts -Test suite completed. - - 鉁?[39m tests/manual/cleaner-slow-motion.test.ts (1 test) 5ms - - Test Files  5 passed (5) - Tests  21 passed (21) - Start at  10:36:50 - Duration  1.50s (transform 729ms, setup 228ms, import 2.41s, tests 204ms, environment 1ms) - diff --git a/tests/unit/logger.test.ts b/tests/unit/logger.test.ts index 3f29584..55a2df2 100644 --- a/tests/unit/logger.test.ts +++ b/tests/unit/logger.test.ts @@ -5,130 +5,79 @@ * and setLogLevel behavior. */ -import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' +import { describe, it, expect, vi, beforeEach } from 'vitest' -// Track winston calls -interface WinstonCall { +// Track logger calls +interface LoggerCall { level: string message?: string meta?: Record } -const winstonCalls: WinstonCall[] = [] +const loggerCalls: LoggerCall[] = [] -// ============================================ -// Winston Format Mock - Callable Object Pattern -// ============================================ -function createFormatFn() { - const formatCallable = vi.fn((callback?: Function) => { - if (callback) { - const transform = vi.fn() as any - transform.combine = vi.fn(() => formatCallable) - transform.timestamp = vi.fn(() => formatCallable) - transform.colorize = vi.fn(() => formatCallable) - transform.json = vi.fn(() => formatCallable) - transform.simple = vi.fn(() => formatCallable) - transform.pretty = vi.fn(() => formatCallable) - transform.label = vi.fn(() => formatCallable) - transform.errors = vi.fn(() => formatCallable) - transform.metadata = vi.fn(() => formatCallable) - transform.cli = vi.fn(() => formatCallable) - transform.mockImplementation((info: any) => { - if (!info || typeof info !== 'object') { - info = { level: 'info', message: '', timestamp: new Date().toISOString() } - } - return callback(info) - }) - return transform - } - return formatCallable - }) as any +// Mock the entire logger module for complete control +vi.mock('../../src/main/services/logger', () => { + const createLoggerMethods = () => ({ + info: vi.fn((message, meta) => { + loggerCalls.push({ level: 'info', message, meta }) + }), + error: vi.fn((message, meta) => { + loggerCalls.push({ level: 'error', message, meta }) + }), + warn: vi.fn((message, meta) => { + loggerCalls.push({ level: 'warn', message, meta }) + }), + debug: vi.fn((message, meta) => { + loggerCalls.push({ level: 'debug', message, meta }) + }), + verbose: vi.fn((message, meta) => { + loggerCalls.push({ level: 'verbose', message, meta }) + }) + }) - formatCallable.combine = vi.fn(() => formatCallable) - formatCallable.timestamp = vi.fn(() => formatCallable) - formatCallable.colorize = vi.fn(() => formatCallable) - formatCallable.printf = vi.fn((cb: Function) => cb) - formatCallable.json = vi.fn(() => formatCallable) - formatCallable.simple = vi.fn(() => formatCallable) - formatCallable.pretty = vi.fn(() => formatCallable) - formatCallable.label = vi.fn(() => formatCallable) - formatCallable.errors = vi.fn(() => formatCallable) - formatCallable.metadata = vi.fn(() => formatCallable) - formatCallable.cli = vi.fn(() => formatCallable) - - return formatCallable -} - -const format = createFormatFn() - -// Mock winston -vi.mock('winston', () => { - const createLoggerInstance = { + const rootLogger = { level: 'info', add: vi.fn(), remove: vi.fn(), clear: vi.fn(), - child: vi.fn(function (this: any, metadata: Record) { - return { - ...this, - info: vi.fn((message: string, meta?: Record) => { - winstonCalls.push({ level: 'info', message, meta: { ...metadata, ...meta } }) - }), - error: vi.fn((message: string, meta?: Record) => { - winstonCalls.push({ level: 'error', message, meta: { ...metadata, ...meta } }) - }), - warn: vi.fn((message: string, meta?: Record) => { - winstonCalls.push({ level: 'warn', message, meta: { ...metadata, ...meta } }) - }), - debug: vi.fn((message: string, meta?: Record) => { - winstonCalls.push({ level: 'debug', message, meta: { ...metadata, ...meta } }) - }) - } - }), - info: vi.fn((message, meta) => { - winstonCalls.push({ level: 'info', message, meta }) - }), - error: vi.fn((message, meta) => { - winstonCalls.push({ level: 'error', message, meta }) - }), - warn: vi.fn((message, meta) => { - winstonCalls.push({ level: 'warn', message, meta }) - }), - debug: vi.fn((message, meta) => { - winstonCalls.push({ level: 'debug', message, meta }) - }) + ...createLoggerMethods(), + child: vi.fn((metadata: Record) => ({ + level: 'info', + ...createLoggerMethods(), + // Override methods to include child metadata + info: vi.fn((message: string, meta?: Record) => { + loggerCalls.push({ level: 'info', message, meta: { ...metadata, ...meta } }) + }), + error: vi.fn((message: string, meta?: Record) => { + loggerCalls.push({ level: 'error', message, meta: { ...metadata, ...meta } }) + }), + warn: vi.fn((message: string, meta?: Record) => { + loggerCalls.push({ level: 'warn', message, meta: { ...metadata, ...meta } }) + }), + debug: vi.fn((message: string, meta?: Record) => { + loggerCalls.push({ level: 'debug', message, meta: { ...metadata, ...meta } }) + }), + verbose: vi.fn((message: string, meta?: Record) => { + loggerCalls.push({ level: 'verbose', message, meta: { ...metadata, ...meta } }) + }) + })) } return { - default: { - createLogger: vi.fn(() => createLoggerInstance), - format, - transports: { - Console: vi.fn(function Console(this: any, options?: any) { - this.level = options?.level || 'info' - }), - DailyRotateFile: vi.fn(function DailyRotateFile(this: any, options?: any) { - this.options = options - }), - File: vi.fn(), - Http: vi.fn() - }, - addColors: vi.fn() - } + default: rootLogger, + createLogger: vi.fn((context: string) => rootLogger.child({ context })), + setLogLevel: vi.fn((level: string) => { + rootLogger.level = level + }), + applyLoggingConfig: vi.fn(), + withRequestContext: vi.fn() } }) -vi.mock('winston-daily-rotate-file', () => ({ - default: vi.fn() as any -})) - describe('Logger', () => { beforeEach(() => { vi.clearAllMocks() - winstonCalls.length = 0 - }) - - afterEach(() => { - vi.resetModules() + loggerCalls.length = 0 }) it('should create a child logger that logs with context metadata', async () => { @@ -137,11 +86,11 @@ describe('Logger', () => { logger.info('Hello world', { extraKey: 'extraValue' }) - expect(winstonCalls).toHaveLength(1) - expect(winstonCalls[0].level).toBe('info') - expect(winstonCalls[0].message).toBe('Hello world') - expect(winstonCalls[0].meta?.context).toBe('TestContext') - expect(winstonCalls[0].meta?.extraKey).toBe('extraValue') + expect(loggerCalls).toHaveLength(1) + expect(loggerCalls[0].level).toBe('info') + expect(loggerCalls[0].message).toBe('Hello world') + expect(loggerCalls[0].meta?.context).toBe('TestContext') + expect(loggerCalls[0].meta?.extraKey).toBe('extraValue') }) it('should log at all severity levels with correct content', async () => { @@ -153,14 +102,14 @@ describe('Logger', () => { logger.warn('warn msg', { key: 'w' }) logger.error('error msg', { key: 'e' }) - expect(winstonCalls).toHaveLength(4) - const levels = winstonCalls.map((c) => c.level) + expect(loggerCalls).toHaveLength(4) + const levels = loggerCalls.map((c) => c.level) expect(levels).toEqual(['debug', 'info', 'warn', 'error']) - expect(winstonCalls[0].message).toBe('debug msg') - expect(winstonCalls[1].message).toBe('info msg') - expect(winstonCalls[2].message).toBe('warn msg') - expect(winstonCalls[3].message).toBe('error msg') + expect(loggerCalls[0].message).toBe('debug msg') + expect(loggerCalls[1].message).toBe('info msg') + expect(loggerCalls[2].message).toBe('warn msg') + expect(loggerCalls[3].message).toBe('error msg') }) it('should produce separate child loggers with independent context', async () => { @@ -171,28 +120,24 @@ describe('Logger', () => { loggerA.info('from A') loggerB.warn('from B') - expect(winstonCalls).toHaveLength(2) - expect(winstonCalls[0].meta?.context).toBe('ModuleA') - expect(winstonCalls[0].message).toBe('from A') - expect(winstonCalls[1].meta?.context).toBe('ModuleB') - expect(winstonCalls[1].message).toBe('from B') + expect(loggerCalls).toHaveLength(2) + expect(loggerCalls[0].meta?.context).toBe('ModuleA') + expect(loggerCalls[0].message).toBe('from A') + expect(loggerCalls[1].meta?.context).toBe('ModuleB') + expect(loggerCalls[1].message).toBe('from B') }) }) describe('setLogLevel', () => { beforeEach(() => { vi.clearAllMocks() - winstonCalls.length = 0 - }) - - afterEach(() => { - vi.resetModules() + loggerCalls.length = 0 }) it('should change the root logger level', async () => { const loggerModule = await import('../../src/main/services/logger') - // Default export is the root winston logger + // Default export is the root logger const rootLogger = loggerModule.default // Default level is 'info'