- Add logger/error-utils mocks to cleaner-handler test to suppress IPC error log noise - Move setupServiceMocks into beforeEach for consistent default mocking in cleaner tests - Replace vi.waitFor (2s timeout) with setImmediate microtask flush in extractor test - Remove dead activeType assignments in validation-database test - Align TestUser.id type with UserInfo.id (string → number) and use deterministic counter Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
196 lines
5.9 KiB
TypeScript
196 lines
5.9 KiB
TypeScript
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
|
import { IPC_CHANNELS } from '../../../src/shared/ipc-channels'
|
|
|
|
// Mock logger to prevent real winston initialization and console noise
|
|
vi.mock('../../../src/main/services/logger', () => ({
|
|
createLogger: () => ({
|
|
info: vi.fn(),
|
|
warn: vi.fn(),
|
|
error: vi.fn(),
|
|
debug: vi.fn()
|
|
}),
|
|
logError: vi.fn()
|
|
}))
|
|
|
|
vi.mock('../../../src/main/services/logger/error-utils', () => ({
|
|
serializeError: (err: any) => err,
|
|
sanitizeError: (err: any) => err
|
|
}))
|
|
|
|
// In-memory storage for registered IPC handlers
|
|
const registeredHandlers: Map<string, Function> = new Map()
|
|
|
|
// Mock Electron's ipcMain to capture registered handlers
|
|
vi.mock('electron', () => {
|
|
return {
|
|
app: {
|
|
isPackaged: false,
|
|
getVersion: () => '1.0.0-test'
|
|
},
|
|
ipcMain: {
|
|
handle: (channel: string, listener: any) => {
|
|
registeredHandlers.set(channel, listener)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
// Mock CleanerApplicationService to isolate IPC layer
|
|
vi.doMock('../../../src/main/services/cleaner/cleaner-application-service', () => {
|
|
return {
|
|
CleanerApplicationService: class {
|
|
async runCleaner(_eventSender: any, input: any) {
|
|
const count = input?.orderNumbers?.length ?? 0
|
|
return {
|
|
ordersProcessed: count,
|
|
materialsDeleted: count,
|
|
materialsSkipped: 0,
|
|
errors: [],
|
|
details: [],
|
|
retriedOrders: 0,
|
|
successfulRetries: 0
|
|
} as any
|
|
}
|
|
async exportResults(_input: any) {
|
|
return { success: true, filePath: '/tmp/results.txt' } as any
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
// Load IPC handler module after mocks are in place
|
|
describe('Cleaner IPC Handler', () => {
|
|
beforeEach(() => {
|
|
registeredHandlers.clear()
|
|
})
|
|
|
|
it('should register and handle cleaner:execute (CLEANER_RUN) IPC call', async () => {
|
|
const mod = await import('../../../src/main/ipc/cleaner-handler')
|
|
mod.registerCleanerHandlers()
|
|
|
|
const handler = registeredHandlers.get(IPC_CHANNELS.CLEANER_RUN)
|
|
expect(handler).toBeDefined()
|
|
expect(typeof handler).toBe('function')
|
|
|
|
const event: any = { sender: { id: 'renderer-1' } }
|
|
const input: any = {
|
|
orderNumbers: ['SC1', 'SC2'],
|
|
materialCodes: [],
|
|
dryRun: false,
|
|
queryBatchSize: 100,
|
|
processConcurrency: 1,
|
|
onProgress: vi.fn()
|
|
}
|
|
|
|
const result = await (handler as any)(event, input)
|
|
expect(result.success).toBe(true)
|
|
expect(result.data.ordersProcessed).toBe(2)
|
|
})
|
|
|
|
it('should handle cleaner:run with dryRun true', async () => {
|
|
const mod = await import('../../../src/main/ipc/cleaner-handler')
|
|
mod.registerCleanerHandlers()
|
|
|
|
const handler = registeredHandlers.get(IPC_CHANNELS.CLEANER_RUN)
|
|
expect(handler).toBeDefined()
|
|
|
|
const event: any = { sender: { id: 'renderer-2' } }
|
|
const input: any = {
|
|
orderNumbers: ['SC1'],
|
|
materialCodes: [],
|
|
dryRun: true,
|
|
queryBatchSize: 50,
|
|
processConcurrency: 1,
|
|
onProgress: vi.fn()
|
|
}
|
|
const result = await (handler as any)(event, input)
|
|
expect(result.success).toBe(true)
|
|
expect(result.data.ordersProcessed).toBe(1)
|
|
})
|
|
|
|
it('should return { success: false } when runCleaner throws', async () => {
|
|
vi.resetModules()
|
|
vi.doMock('../../../src/main/services/cleaner/cleaner-application-service', () => {
|
|
return {
|
|
CleanerApplicationService: class {
|
|
async runCleaner() {
|
|
throw new Error('boom')
|
|
}
|
|
}
|
|
}
|
|
})
|
|
const mod = await import('../../../src/main/ipc/cleaner-handler')
|
|
mod.registerCleanerHandlers()
|
|
|
|
const handler = registeredHandlers.get(IPC_CHANNELS.CLEANER_RUN)
|
|
expect(handler).toBeDefined()
|
|
|
|
const event: any = { sender: { id: 'renderer-3' } }
|
|
const input: any = {
|
|
orderNumbers: ['SC1'],
|
|
materialCodes: [],
|
|
dryRun: false,
|
|
queryBatchSize: 20,
|
|
processConcurrency: 1,
|
|
onProgress: vi.fn()
|
|
}
|
|
const result = await (handler as any)(event, input)
|
|
expect(result.success).toBe(false)
|
|
expect(result.error).toBe('boom')
|
|
})
|
|
|
|
it('should register and handle cleaner:exportResults (CLEANER_EXPORT_RESULTS) IPC call', async () => {
|
|
vi.resetModules()
|
|
vi.doMock('../../../src/main/services/cleaner/cleaner-application-service', () => {
|
|
return {
|
|
CleanerApplicationService: class {
|
|
async exportResults(items: any[]) {
|
|
return {
|
|
success: true,
|
|
filePath: '/tmp/exported.xlsx',
|
|
recordCount: items.length
|
|
} as any
|
|
}
|
|
}
|
|
}
|
|
})
|
|
const mod = await import('../../../src/main/ipc/cleaner-handler')
|
|
mod.registerCleanerHandlers()
|
|
|
|
const handler = registeredHandlers.get(IPC_CHANNELS.CLEANER_EXPORT_RESULTS)
|
|
expect(handler).toBeDefined()
|
|
expect(typeof handler).toBe('function')
|
|
|
|
const event: any = { sender: { id: 'renderer-4' } }
|
|
const items = [
|
|
{ materialCode: 'M1', materialName: 'Mat A' },
|
|
{ materialCode: 'M2', materialName: 'Mat B' }
|
|
]
|
|
|
|
const result = await (handler as any)(event, items)
|
|
expect(result.success).toBe(true)
|
|
expect(result.data.recordCount).toBe(2)
|
|
})
|
|
|
|
it('should return { success: false } when exportResults throws', async () => {
|
|
vi.resetModules()
|
|
vi.doMock('../../../src/main/services/cleaner/cleaner-application-service', () => {
|
|
return {
|
|
CleanerApplicationService: class {
|
|
async exportResults() {
|
|
throw new Error('export failed')
|
|
}
|
|
}
|
|
}
|
|
})
|
|
const mod = await import('../../../src/main/ipc/cleaner-handler')
|
|
mod.registerCleanerHandlers()
|
|
|
|
const handler = registeredHandlers.get(IPC_CHANNELS.CLEANER_EXPORT_RESULTS)
|
|
const event: any = { sender: { id: 'renderer-5' } }
|
|
const result = await (handler as any)(event, [])
|
|
expect(result.success).toBe(false)
|
|
expect(result.error).toBe('export failed')
|
|
})
|
|
})
|