Files
waggle-os/app/scripts/bundle-runtimes.test.ts
Oleg Maslov 0c3e2ead3b
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled
moving
2026-09-02 10:10:29 +02:00

181 lines
6.5 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import path from 'node:path';
import {
getNodeDownloadUrl,
getPythonDownloadUrl,
getResourcePaths,
getBundleStatus,
parseVersion,
isValidVersion,
} from './bundle-utils.js';
// ─── getNodeDownloadUrl ──────────────────────────────────────────────────────
describe('getNodeDownloadUrl', () => {
it('returns Windows x64 URL by default', () => {
const url = getNodeDownloadUrl('20.11.1');
expect(url).toBe('https://nodejs.org/dist/v20.11.1/win-x64/node.exe');
});
it('returns Windows arm64 URL', () => {
const url = getNodeDownloadUrl('20.11.1', 'win32', 'arm64');
expect(url).toBe('https://nodejs.org/dist/v20.11.1/win-arm64/node.exe');
});
it('returns macOS tar.gz URL', () => {
const url = getNodeDownloadUrl('20.11.1', 'darwin', 'x64');
expect(url).toContain('darwin-x64.tar.gz');
});
it('returns Linux tar.xz URL', () => {
const url = getNodeDownloadUrl('20.11.1', 'linux', 'x64');
expect(url).toContain('linux-x64.tar.xz');
});
it('includes the version in the URL', () => {
const url = getNodeDownloadUrl('18.19.0');
expect(url).toContain('v18.19.0');
});
});
// ─── getPythonDownloadUrl ────────────────────────────────────────────────────
describe('getPythonDownloadUrl', () => {
it('returns Windows amd64 embed URL by default', () => {
const url = getPythonDownloadUrl('3.11.8');
expect(url).toBe(
'https://www.python.org/ftp/python/3.11.8/python-3.11.8-embed-amd64.zip',
);
});
it('returns Windows arm64 URL', () => {
const url = getPythonDownloadUrl('3.11.8', 'win32', 'arm64');
expect(url).toContain('embed-arm64.zip');
});
it('returns macOS pkg URL', () => {
const url = getPythonDownloadUrl('3.11.8', 'darwin', 'x64');
expect(url).toContain('macos11.pkg');
});
it('returns Linux source URL', () => {
const url = getPythonDownloadUrl('3.11.8', 'linux', 'x64');
expect(url).toContain('Python-3.11.8.tar.xz');
});
it('includes the version in the URL', () => {
const url = getPythonDownloadUrl('3.12.1');
expect(url).toContain('3.12.1');
});
});
// ─── getResourcePaths ────────────────────────────────────────────────────────
describe('getResourcePaths', () => {
it('returns correct Windows paths when platform is win32', () => {
const dir = '/app/src-tauri/resources';
const paths = getResourcePaths(dir, 'win32');
expect(paths.node).toBe(path.join(dir, 'node', 'node.exe'));
expect(paths.python).toBe(path.join(dir, 'python', 'python.exe'));
expect(paths.litellm).toBe(
path.join(dir, 'python', 'Lib', 'site-packages', 'litellm'),
);
});
it('handles Windows-style paths', () => {
const dir = 'C:\\Users\\user\\app\\resources';
const paths = getResourcePaths(dir, 'win32');
expect(paths.node).toContain('node.exe');
expect(paths.python).toContain('python.exe');
expect(paths.litellm).toContain('litellm');
});
it('returns correct Unix paths when platform is darwin', () => {
const dir = '/app/src-tauri/resources';
const paths = getResourcePaths(dir, 'darwin');
expect(paths.node).toBe(path.join(dir, 'node', 'bin', 'node'));
expect(paths.python).toBe(path.join(dir, 'python', 'bin', 'python3'));
expect(paths.litellm).toBe(
path.join(dir, 'python', 'lib', 'python3.11', 'site-packages', 'litellm'),
);
});
it('returns correct Unix paths when platform is linux', () => {
const dir = '/app/src-tauri/resources';
const paths = getResourcePaths(dir, 'linux');
expect(paths.node).toBe(path.join(dir, 'node', 'bin', 'node'));
expect(paths.python).toBe(path.join(dir, 'python', 'bin', 'python3'));
expect(paths.litellm).toBe(
path.join(dir, 'python', 'lib', 'python3.11', 'site-packages', 'litellm'),
);
});
});
// ─── getBundleStatus ─────────────────────────────────────────────────────────
describe('getBundleStatus', () => {
it('reports all missing when nothing exists', () => {
const mockExists = () => false;
const status = getBundleStatus('/fake/dir', mockExists);
expect(status.nodeReady).toBe(false);
expect(status.pythonReady).toBe(false);
expect(status.litellmReady).toBe(false);
});
it('reports all ready when all exist', () => {
const mockExists = () => true;
const status = getBundleStatus('/fake/dir', mockExists);
expect(status.nodeReady).toBe(true);
expect(status.pythonReady).toBe(true);
expect(status.litellmReady).toBe(true);
});
it('reports partial status correctly', () => {
const paths = getResourcePaths('/fake/dir', process.platform);
const existingPaths = new Set([paths.node, paths.python]);
const mockExists = (p: string) => existingPaths.has(p);
const status = getBundleStatus('/fake/dir', mockExists);
expect(status.nodeReady).toBe(true);
expect(status.pythonReady).toBe(true);
expect(status.litellmReady).toBe(false);
});
});
// ─── parseVersion ────────────────────────────────────────────────────────────
describe('parseVersion', () => {
it('parses a standard semver string', () => {
const v = parseVersion('20.11.1');
expect(v).toEqual({ major: 20, minor: 11, patch: 1 });
});
it('parses a version with zeros', () => {
const v = parseVersion('3.0.0');
expect(v).toEqual({ major: 3, minor: 0, patch: 0 });
});
});
// ─── isValidVersion ──────────────────────────────────────────────────────────
describe('isValidVersion', () => {
it('accepts a valid version', () => {
expect(isValidVersion('20.11.1')).toBe(true);
expect(isValidVersion('3.11.8')).toBe(true);
});
it('rejects invalid versions', () => {
expect(isValidVersion('20.11')).toBe(false);
expect(isValidVersion('abc')).toBe(false);
expect(isValidVersion('20.11.1.2')).toBe(false);
expect(isValidVersion('')).toBe(false);
});
});