import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; const { mockApp, mockExecFile } = vi.hoisted(() => ({ mockApp: { getLoginItemSettings: vi.fn() }, mockExecFile: vi.fn() })); vi.mock('electron', () => ({ default: { app: mockApp } })); vi.mock('node:child_process', () => ({ execFile: mockExecFile })); import { collectAutostartState } from '../../src/main/services/AutostartDiagnostic'; const ORIGINAL_PLATFORM = process.platform; function setPlatform(p: NodeJS.Platform): void { Object.defineProperty(process, 'platform', { value: p, configurable: true }); } describe('AutostartDiagnostic — collectAutostartState', () => { beforeEach(() => { mockApp.getLoginItemSettings.mockReset(); mockExecFile.mockReset(); }); afterEach(() => { setPlatform(ORIGINAL_PLATFORM); }); it('returns withArgs / noArgs / execPath structure', async () => { setPlatform('darwin'); mockApp.getLoginItemSettings .mockReturnValueOnce({ openAtLogin: true, executableWillLaunchAtLogin: true }) .mockReturnValueOnce({ openAtLogin: false, executableWillLaunchAtLogin: true }); const state = await collectAutostartState(); expect(state.withArgs).toEqual({ openAtLogin: true, executableWillLaunchAtLogin: true }); expect(state.noArgs).toEqual({ openAtLogin: false, executableWillLaunchAtLogin: true }); expect(state.execPath).toBe(process.execPath); }); it('passes args=["--hidden"] for the first call, no args for the second', async () => { setPlatform('darwin'); mockApp.getLoginItemSettings .mockReturnValueOnce({ openAtLogin: true, executableWillLaunchAtLogin: true }) .mockReturnValueOnce({ openAtLogin: true, executableWillLaunchAtLogin: true }); await collectAutostartState(); expect(mockApp.getLoginItemSettings).toHaveBeenNthCalledWith(1, { args: ['--hidden'] }); expect(mockApp.getLoginItemSettings).toHaveBeenNthCalledWith(2); }); it('non-win32: does not set registryPath/registryValue', async () => { setPlatform('darwin'); mockApp.getLoginItemSettings.mockReturnValue({ openAtLogin: true, executableWillLaunchAtLogin: true }); const state = await collectAutostartState(); expect(state.registryPath).toBeUndefined(); expect(state.registryValue).toBeUndefined(); expect(mockExecFile).not.toHaveBeenCalled(); }); it('Windows: returns registryPath + registryValue when reg.exe succeeds', async () => { setPlatform('win32'); mockApp.getLoginItemSettings.mockReturnValue({ openAtLogin: true, executableWillLaunchAtLogin: true }); mockExecFile.mockImplementation((_cmd: string, _args: string[], cb: (err: Error | null, stdout: string, stderr: string) => void) => { cb(null, '\r\nHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\r\n Inkling REG_SZ "C:\\Users\\u\\Inkling.exe" --hidden\r\n', ''); }); const state = await collectAutostartState(); expect(state.registryPath).toBe('HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\Inkling'); expect(state.registryValue).toContain('Inkling.exe'); expect(state.registryValue).toContain('--hidden'); }); it('Windows: silent fallback on reg.exe error', async () => { setPlatform('win32'); mockApp.getLoginItemSettings.mockReturnValue({ openAtLogin: true, executableWillLaunchAtLogin: true }); mockExecFile.mockImplementation((_cmd: string, _args: string[], cb: (err: Error | null, stdout: string, stderr: string) => void) => { cb(new Error('not found'), '', ''); }); const state = await collectAutostartState(); expect(state.registryPath).toBe('HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\Inkling'); expect(state.registryValue).toBeNull(); }); });