fix(windows): run bundled openclaw CLI/TUI via node.exe to restore terminal input (#571)
This commit is contained in:
88
tests/unit/openclaw-cli.test.ts
Normal file
88
tests/unit/openclaw-cli.test.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
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<typeof import('node:fs')>('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);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user