Files
makelore/tests/unit/opencode-paths.test.ts
2026-07-29 17:22:35 +08:00

123 lines
3.9 KiB
TypeScript

// @vitest-environment node
import { join } from 'node:path';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import {
getOpencodeBinName,
readOpencodeRuntimeVersion,
resolveOpencodeRuntimePaths,
} from '@electron/opencode/paths';
const fsMock = vi.hoisted(() => ({
packageJson: undefined as string | undefined,
existingPaths: new Set<string>(),
}));
vi.mock('node:fs', () => ({
existsSync: (path: string) => fsMock.packageJson !== undefined || fsMock.existingPaths.has(path),
readFileSync: () => fsMock.packageJson,
}));
describe('opencode runtime paths', () => {
beforeEach(() => {
fsMock.packageJson = undefined;
fsMock.existingPaths.clear();
});
it('resolves packaged darwin runtime paths from resourcesPath', () => {
const resourcesPath = '/Applications/NianCode.app/Contents/Resources';
const paths = resolveOpencodeRuntimePaths({
isPackaged: true,
resourcesPath,
appPath: '/Applications/NianCode.app/Contents/Resources/app.asar',
platform: 'darwin',
});
const runtimeDir = join(resourcesPath, 'opencode-ai');
expect(paths).toEqual({
runtimeDir,
binPath: join(runtimeDir, 'bin', 'opencode'),
packageJsonPath: join(runtimeDir, 'package.json'),
});
});
it('resolves dev linux runtime paths from appPath node_modules', () => {
const appPath = '/home/me/niancode';
const paths = resolveOpencodeRuntimePaths({
isPackaged: false,
resourcesPath: '/unused/resources',
appPath,
platform: 'linux',
arch: 'x64',
});
const runtimeDir = join(appPath, 'node_modules', 'opencode-ai');
expect(paths).toEqual({
runtimeDir,
binPath: join(runtimeDir, 'bin', 'opencode'),
packageJsonPath: join(runtimeDir, 'package.json'),
});
});
it('uses the installed platform-native binary in development when pnpm skips opencode-ai postinstall', () => {
const appPath = '/Users/me/NianCode';
const nativeBinPath = join(appPath, 'node_modules', 'opencode-darwin-arm64', 'bin', 'opencode');
fsMock.existingPaths.add(nativeBinPath);
expect(resolveOpencodeRuntimePaths({
isPackaged: false,
resourcesPath: '/unused/resources',
appPath,
platform: 'darwin',
arch: 'arm64',
})).toMatchObject({
runtimeDir: join(appPath, 'node_modules', 'opencode-ai'),
binPath: nativeBinPath,
packageJsonPath: join(appPath, 'node_modules', 'opencode-ai', 'package.json'),
});
});
it('resolves packaged Windows runtime paths to the bundled native exe', () => {
const resourcesPath = 'C:\\Program Files\\NianCode\\resources';
const paths = resolveOpencodeRuntimePaths({
isPackaged: true,
resourcesPath,
appPath: 'C:\\Program Files\\NianCode\\resources\\app.asar',
platform: 'win32',
});
const runtimeDir = join(resourcesPath, 'opencode-ai');
expect(paths).toEqual({
runtimeDir,
binPath: join(runtimeDir, 'bin', 'opencode.exe'),
packageJsonPath: join(runtimeDir, 'package.json'),
});
});
it('uses the package wrapper path for development runtime paths', () => {
expect(getOpencodeBinName('win32')).toBe('opencode');
expect(getOpencodeBinName('linux')).toBe('opencode');
expect(getOpencodeBinName('win32', true)).toBe('opencode.exe');
});
it('reads the opencode runtime package version when package.json exists', () => {
fsMock.packageJson = JSON.stringify({ version: '1.2.3' });
expect(readOpencodeRuntimeVersion({
runtimeDir: '/runtime/opencode',
binPath: '/runtime/opencode/bin/opencode',
packageJsonPath: '/runtime/opencode/package.json',
})).toBe('1.2.3');
});
it('returns undefined when the runtime package.json is missing', () => {
expect(readOpencodeRuntimeVersion({
runtimeDir: '/runtime/opencode',
binPath: '/runtime/opencode/bin/opencode',
packageJsonPath: '/runtime/opencode/package.json',
})).toBeUndefined();
});
});