import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; const originalPlatform = process.platform; const originalResourcesPath = process.resourcesPath; const { mockExistsSync, mockIsPackagedGetter, } = vi.hoisted(() => ({ mockExistsSync: vi.fn<(path: string) => boolean>(), mockIsPackagedGetter: { value: false }, })); function setPlatform(platform: string) { Object.defineProperty(process, 'platform', { value: platform, writable: true }); } vi.mock('node:fs', async () => { const actual = await vi.importActual('node:fs'); return { ...actual, existsSync: mockExistsSync, default: { ...actual, existsSync: mockExistsSync, }, }; }); vi.mock('electron', () => ({ app: { get isPackaged() { return mockIsPackagedGetter.value; }, }, })); vi.mock('@electron/utils/paths', () => ({ getOpenClawDir: () => '/tmp/openclaw', getOpenClawEntryPath: () => 'C:\\Program Files\\ClawX\\resources\\openclaw\\openclaw.mjs', })); describe('getOpenClawCliCommand (Windows packaged)', () => { beforeEach(() => { vi.resetModules(); vi.clearAllMocks(); setPlatform('win32'); mockIsPackagedGetter.value = true; Object.defineProperty(process, 'resourcesPath', { value: 'C:\\Program Files\\ClawX\\resources', configurable: true, writable: true, }); }); afterEach(() => { Object.defineProperty(process, 'platform', { value: originalPlatform, writable: true }); Object.defineProperty(process, 'resourcesPath', { value: originalResourcesPath, configurable: true, writable: true, }); }); it('prefers bundled node.exe when present', async () => { mockExistsSync.mockImplementation((p: string) => /[\\/]cli[\\/]openclaw\.cmd$/i.test(p) || /[\\/]bin[\\/]node\.exe$/i.test(p)); const { getOpenClawCliCommand } = await import('@electron/utils/openclaw-cli'); expect(getOpenClawCliCommand()).toBe( "& 'C:\\Program Files\\ClawX\\resources/cli/openclaw.cmd'", ); }); it('falls back to bundled node.exe when openclaw.cmd is missing', async () => { mockExistsSync.mockImplementation((p: string) => /[\\/]bin[\\/]node\.exe$/i.test(p)); const { getOpenClawCliCommand } = await import('@electron/utils/openclaw-cli'); expect(getOpenClawCliCommand()).toBe( "& 'C:\\Program Files\\ClawX\\resources/bin/node.exe' 'C:\\Program Files\\ClawX\\resources\\openclaw\\openclaw.mjs'", ); }); it('falls back to ELECTRON_RUN_AS_NODE command when wrappers are missing', async () => { mockExistsSync.mockReturnValue(false); const { getOpenClawCliCommand } = await import('@electron/utils/openclaw-cli'); const command = getOpenClawCliCommand(); expect(command.startsWith('$env:ELECTRON_RUN_AS_NODE=1; & ')).toBe(true); expect(command.endsWith("'C:\\Program Files\\ClawX\\resources\\openclaw\\openclaw.mjs'")).toBe(true); }); });