mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-07-10 01:29:17 +00:00
* feat(web-shell): show the qwen-code version in the sidebar footer The Web Shell had no visible version. Show the running qwen-code version (from the daemon capabilities) in the sidebar footer, inline with the Settings button so it stays visible without taking its own row. Render the version consistently wherever it appears: - Prefix "v" only for a real semver release; a non-semver fallback such as "unknown" is shown as-is, so we never render a bogus "vunknown". Applied to the Web Shell badge and the TUI header. - Dev builds (scripts/dev.js) now report the real package version instead of the "dev" sentinel, matching scripts/start.js, so the UI shows the actual version (e.g. v0.19.4). DEV=true / NODE_ENV=development remain the signals that mark a dev build. * test: add readFileSync to node:fs mock in dev.test.js scripts/dev.js now reads package.json via readFileSync at module load to report the real CLI_VERSION, but the node:fs mock in dev.test.js did not export readFileSync, causing vitest to throw "No readFileSync export is defined on the node:fs mock" and failing the suite.
98 lines
2.9 KiB
JavaScript
98 lines
2.9 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),
|
|
}));
|
|
|
|
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(),
|
|
readFileSync: vi.fn(() => JSON.stringify({ version: '0.0.0-test' })),
|
|
}));
|
|
|
|
const normalizePath = (path) => String(path).replaceAll('\\', '/');
|
|
|
|
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 }));
|
|
});
|
|
});
|