import { describe, it, expect } from 'vitest' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels' import { configGet, configSet, configGetAll, configReset, onConfigChanged, } from '../../src/main/services/ConfigService' import { registerConfigHandlers } from '../../src/main/ipc/config-handlers' import { invokeIpc, useRedHarness } from './harness' useRedHarness() describe('유스케이스: 설정 토글 / 테마 / 언어 / 핫키 플래그 / IPC', () => { it('기본 테마를 읽는다', () => { expect(configGet('theme')).toBe('auto') }) it('테마를 dark 로 바꾸면 다시 읽힌다', () => { configSet('theme', 'dark') expect(configGet('theme')).toBe('dark') }) it('테마를 light 로 바꾼다', () => { configSet('theme', 'light') expect(configGet('theme')).toBe('light') }) it('언어를 en 으로 바꾼다', () => { configSet('language', 'en') expect(configGet('language')).toBe('en') }) it('언어를 ko 로 되돌린다', () => { configSet('language', 'en') configSet('language', 'ko') expect(configGet('language')).toBe('ko') }) it('사운드 토글이 저장된다', () => { configSet('soundEnabled', false) expect(configGet('soundEnabled')).toBe(false) configSet('soundEnabled', true) expect(configGet('soundEnabled')).toBe(true) }) it('트레이로 닫기 토글이 저장된다', () => { configSet('closeToTray', false) expect(configGet('closeToTray')).toBe(false) }) it('자동 삽입 토글이 저장된다', () => { configSet('autoInsert', false) expect(configGet('autoInsert')).toBe(false) }) it('핫키 활성 토글이 저장된다', () => { configSet('hotkeyEnabled', false) expect(configGet('hotkeyEnabled')).toBe(false) }) it('온보딩 완료 플래그가 저장된다', () => { configSet('onboardingCompleted', true) expect(configGet('onboardingCompleted')).toBe(true) }) it('STT 언어를 en 으로 바꾼다', () => { configSet('sttLanguage', 'en') expect(configGet('sttLanguage')).toBe('en') }) it('기본 LLM 액션을 none 으로 바꾼다', () => { configSet('defaultLLMAction', 'none') expect(configGet('defaultLLMAction')).toBe('none') }) it('설정 변경 이벤트가 이전값과 새값을 담는다', () => { const seen: Array<{ key: string; value: unknown; previousValue: unknown }> = [] const off = onConfigChanged((e) => seen.push(e)) configSet('theme', 'dark') off() expect(seen.some((e) => e.key === 'theme' && e.value === 'dark')).toBe(true) }) it('configGetAll 은 방금 쓴 키를 포함한다', () => { configSet('userEmail', 'a@b.c') expect(configGetAll().userEmail).toBe('a@b.c') }) it('단일 키 reset 은 기본값으로 되돌린다', () => { configSet('theme', 'dark') configReset('theme') expect(configGet('theme')).toBe('auto') }) it('전체 reset 은 커스텀 이메일도 지운다', () => { configSet('userEmail', 'a@b.c') configReset() expect(configGet('userEmail')).toBeNull() }) it('IPC config:get / set 왕복', async () => { registerConfigHandlers() const set = await invokeIpc(IPC_CHANNELS.CONFIG.SET, { key: 'theme', value: 'dark' }) expect(set.success).toBe(true) const get = await invokeIpc(IPC_CHANNELS.CONFIG.GET, { key: 'theme' }) expect(get.success).toBe(true) if (get.success) expect(get.data).toBe('dark') }) it('IPC config:getTheme / setTheme', async () => { registerConfigHandlers() const set = await invokeIpc(IPC_CHANNELS.CONFIG.SET_THEME, { theme: 'light' }) expect(set.success).toBe(true) const get = await invokeIpc(IPC_CHANNELS.CONFIG.GET_THEME) expect(get.success).toBe(true) if (get.success) expect(get.data).toBe('light') }) it('IPC config:setLanguage / getLanguage', async () => { registerConfigHandlers() await invokeIpc(IPC_CHANNELS.CONFIG.SET_LANGUAGE, { language: 'en' }) const get = await invokeIpc(IPC_CHANNELS.CONFIG.GET_LANGUAGE) expect(get.success).toBe(true) if (get.success) expect(get.data).toBe('en') }) it('IPC config:setCloseToTray / getCloseToTray', async () => { registerConfigHandlers() await invokeIpc(IPC_CHANNELS.CONFIG.SET_CLOSE_TO_TRAY, { enabled: false }) const get = await invokeIpc(IPC_CHANNELS.CONFIG.GET_CLOSE_TO_TRAY) expect(get.success).toBe(true) if (get.success) expect(get.data).toBe(false) }) it('IPC config:getAll 은 객체다', async () => { registerConfigHandlers() const res = await invokeIpc(IPC_CHANNELS.CONFIG.GET_ALL) expect(res.success).toBe(true) if (res.success) expect(res.data).toHaveProperty('theme') }) })