mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-07-10 09:39:06 +00:00
The two Windows-targeted dev.js launcher tests added in #4728 mock existsSync with forward-slash suffix matching and assert spawn args via forward-slash stringContaining. On a real windows-latest runner dev.js builds these paths with path.join, which yields backslashes, so the existsSync mock never matches, dev.js takes the bare tsx.cmd shell fallback, and both tests fail. On macOS/Linux the platform() mock plus real forward-slash joins keep them green, which is why main CI has been red only on the Windows job since423cac110. Normalize separators in both the existsSync mocks and the received spawn arguments before asserting, so the tests pass on every host OS. Same content as the fix bundled into #4840's merge commit0e104e179, extracted into a standalone test-only change so main recovers without waiting on a core-behavior PR; both merge cleanly in either order. Co-authored-by: qqqys <qys177@gmail.com>
97 lines
2.8 KiB
JavaScript
97 lines
2.8 KiB
JavaScript
/**
|
|
* @license
|
|
* Copyright 2025 Qwen Team
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
const { spawnMock, platformMock, existsSyncMock } = vi.hoisted(() => ({
|
|
spawnMock: vi.fn(() => ({ on: vi.fn() })),
|
|
platformMock: vi.fn(() => 'darwin'),
|
|
existsSyncMock: vi.fn(() => false),
|
|
}));
|
|
|
|
const normalizePath = (filePath) => String(filePath).replaceAll('\\', '/');
|
|
|
|
vi.mock('node:child_process', () => ({
|
|
spawn: spawnMock,
|
|
}));
|
|
|
|
vi.mock('node:os', async (importOriginal) => {
|
|
const actual = await importOriginal();
|
|
return {
|
|
...actual,
|
|
platform: platformMock,
|
|
tmpdir: vi.fn(() => '/tmp'),
|
|
};
|
|
});
|
|
|
|
vi.mock('node:fs', () => ({
|
|
writeFileSync: vi.fn(),
|
|
mkdtempSync: vi.fn(() => '/tmp/qwen-dev-test'),
|
|
rmSync: vi.fn(),
|
|
existsSync: existsSyncMock,
|
|
symlinkSync: vi.fn(),
|
|
mkdirSync: vi.fn(),
|
|
}));
|
|
|
|
describe('scripts/dev.js launcher', () => {
|
|
const originalArgv = process.argv;
|
|
const execPathDescriptor = Object.getOwnPropertyDescriptor(
|
|
process,
|
|
'execPath',
|
|
);
|
|
|
|
beforeEach(() => {
|
|
vi.resetModules();
|
|
vi.clearAllMocks();
|
|
process.argv = ['node', 'scripts/dev.js'];
|
|
});
|
|
|
|
afterEach(() => {
|
|
process.argv = originalArgv;
|
|
if (execPathDescriptor) {
|
|
Object.defineProperty(process, 'execPath', execPathDescriptor);
|
|
}
|
|
});
|
|
|
|
it('spawns Node without a shell on Windows when local tsx cli.mjs exists', async () => {
|
|
platformMock.mockReturnValue('win32');
|
|
existsSyncMock.mockImplementation((filePath) =>
|
|
normalizePath(filePath).endsWith('node_modules/tsx/dist/cli.mjs'),
|
|
);
|
|
Object.defineProperty(process, 'execPath', {
|
|
configurable: true,
|
|
value: 'C:\\Program Files\\nodejs\\node.exe',
|
|
});
|
|
process.argv = ['node', 'scripts/dev.js', '--help'];
|
|
|
|
await import('../dev.js?direct-node');
|
|
|
|
const [command, args, options] = spawnMock.mock.calls[0];
|
|
expect(command).toBe('C:\\Program Files\\nodejs\\node.exe');
|
|
expect(args.map(normalizePath)).toEqual([
|
|
expect.stringContaining('node_modules/tsx/dist/cli.mjs'),
|
|
expect.stringContaining('packages/cli/index.ts'),
|
|
'--help',
|
|
]);
|
|
expect(options).toEqual(expect.objectContaining({ shell: false }));
|
|
});
|
|
|
|
it('keeps shell fallback for Windows tsx.cmd resolution', async () => {
|
|
platformMock.mockReturnValue('win32');
|
|
existsSyncMock.mockImplementation((filePath) =>
|
|
normalizePath(filePath).endsWith('node_modules/.bin/tsx.cmd'),
|
|
);
|
|
|
|
await import('../dev.js?cmd-fallback');
|
|
|
|
const [command, args, options] = spawnMock.mock.calls[0];
|
|
expect(normalizePath(command)).toContain('tsx.cmd');
|
|
expect(args.map(normalizePath)).toEqual([
|
|
expect.stringContaining('packages/cli/index.ts'),
|
|
]);
|
|
expect(options).toEqual(expect.objectContaining({ shell: true }));
|
|
});
|
|
});
|