import { beforeEach, describe, expect, it, vi } from 'vitest' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels' const handlers = vi.hoisted( () => new Map Promise>() ) const eventHandlers = vi.hoisted(() => new Map void>()) const configSet = vi.hoisted(() => vi.fn()) const suggestion = vi.hoisted(() => ({ setEnabled: vi.fn(), applyConfig: vi.fn(), dismiss: vi.fn(), getState: vi.fn(() => ({ enabled: true })) })) const hideSuggestionOverlay = vi.hoisted(() => vi.fn()) vi.mock('electron', () => ({ ipcMain: { handle: vi.fn((channel: string, handler: (event: unknown, params: unknown) => Promise) => { handlers.set(channel, handler) }), on: vi.fn((channel: string, handler: (...args: unknown[]) => void) => { eventHandlers.set(channel, handler) }) } })) vi.mock('../../../src/main/services/ConfigService', () => ({ configSet })) vi.mock('../../../src/main/services/SuggestionService', () => ({ getSuggestionService: () => suggestion })) vi.mock('../../../src/main/windows/WindowManager', () => ({ applySuggestionOverlayConfig: vi.fn(), hideSuggestionOverlay })) beforeEach(async () => { vi.resetModules() vi.clearAllMocks() handlers.clear() eventHandlers.clear() const mod = await import('../../../src/main/ipc/suggestion-handlers') mod.registerSuggestionHandlers() }) describe('SUGGESTION.SET_CONFIG', () => { it('명시적으로 활성화할 때 서비스의 warm-up 경로를 사용한다', async () => { const handler = handlers.get(IPC_CHANNELS.SUGGESTION.SET_CONFIG) if (!handler) throw new Error('suggestion config handler was not registered') await handler({}, { enabled: true }) expect(suggestion.setEnabled).toHaveBeenCalledWith(true) expect(configSet).not.toHaveBeenCalledWith('suggestionEnabled', true) }) it('분당 요청 상한을 12로 강제한다', async () => { const handler = handlers.get(IPC_CHANNELS.SUGGESTION.SET_CONFIG) if (!handler) throw new Error('suggestion config handler was not registered') await handler({}, { maxRequestsPerMinute: 99 }) expect(configSet).toHaveBeenCalledWith('suggestionMaxRequestsPerMinute', 12) }) }) describe('POPUP_SUGGESTION.DISMISS', () => { it('서비스 이벤트를 기다리지 않고 창을 숨긴 뒤 제안을 취소한다', () => { const handler = eventHandlers.get(IPC_CHANNELS.POPUP_SUGGESTION.DISMISS) if (!handler) throw new Error('suggestion dismiss handler was not registered') handler({}) expect(hideSuggestionOverlay).toHaveBeenCalledTimes(1) expect(suggestion.dismiss).toHaveBeenCalledWith('dismissed') expect(hideSuggestionOverlay.mock.invocationCallOrder[0]).toBeLessThan( suggestion.dismiss.mock.invocationCallOrder[0] ) }) })