feat: add Pi process and RPC foundation
This commit is contained in:
137
tests/unit/pi-runtime-bundle.test.ts
Normal file
137
tests/unit/pi-runtime-bundle.test.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
// @vitest-environment node
|
||||
|
||||
import { afterEach, describe, expect, it } from 'vitest';
|
||||
import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
import YAML from 'yaml';
|
||||
import {
|
||||
assertPackageIdentities,
|
||||
installProductionShrinkwrap,
|
||||
preparePublishedPackageRoot,
|
||||
requiredPackageIdentities,
|
||||
} from '../../scripts/lib/pi-runtime-bundle.mjs';
|
||||
import { parseBundleArgs } from '../../scripts/bundle-pi-runtime.mjs';
|
||||
|
||||
const scratchRoots: string[] = [];
|
||||
|
||||
async function scratch(prefix: string): Promise<string> {
|
||||
const root = await mkdtemp(join(tmpdir(), prefix));
|
||||
scratchRoots.push(root);
|
||||
return root;
|
||||
}
|
||||
|
||||
afterEach(async () => {
|
||||
await Promise.all(scratchRoots.splice(0).map((root) => rm(root, {
|
||||
recursive: true,
|
||||
force: true,
|
||||
maxRetries: 3,
|
||||
})));
|
||||
});
|
||||
|
||||
describe('Pi runtime production bundler', () => {
|
||||
it('turns the published root dev mismatch into a reproducible npm 11 production install', async () => {
|
||||
const root = await scratch('makelore-pi-bundle-mismatch-');
|
||||
const source = join(root, 'published');
|
||||
const stage = join(root, 'stage');
|
||||
await mkdir(source);
|
||||
await writeFile(join(source, 'package.json'), `${JSON.stringify({
|
||||
name: '@fixture/pi-runtime',
|
||||
version: '1.0.0',
|
||||
devDependencies: { 'missing-from-production-lock': '1.0.0' },
|
||||
}, null, 2)}\n`);
|
||||
await writeFile(join(source, 'npm-shrinkwrap.json'), `${JSON.stringify({
|
||||
name: '@fixture/pi-runtime',
|
||||
version: '1.0.0',
|
||||
lockfileVersion: 3,
|
||||
requires: true,
|
||||
packages: {
|
||||
'': { name: '@fixture/pi-runtime', version: '1.0.0' },
|
||||
},
|
||||
}, null, 2)}\n`);
|
||||
|
||||
const prepared = await preparePublishedPackageRoot(source, stage);
|
||||
expect(prepared.omittedDevDependencies).toEqual(['missing-from-production-lock']);
|
||||
expect(JSON.parse(await readFile(join(stage, 'package.json'), 'utf8')))
|
||||
.not.toHaveProperty('devDependencies');
|
||||
await expect(installProductionShrinkwrap({
|
||||
projectRoot: process.cwd(),
|
||||
stageRoot: stage,
|
||||
target: { platform: process.platform, arch: process.arch },
|
||||
})).resolves.toMatchObject({});
|
||||
}, 15_000);
|
||||
|
||||
it('accepts same-version nested-to-root flattening by identity instead of physical lock path', () => {
|
||||
const shrinkwrap = {
|
||||
packages: {
|
||||
'node_modules/p-retry/node_modules/@types/retry': {
|
||||
version: '0.12.0',
|
||||
},
|
||||
},
|
||||
};
|
||||
const required = requiredPackageIdentities(shrinkwrap, {
|
||||
platform: process.platform,
|
||||
arch: process.arch,
|
||||
});
|
||||
|
||||
expect(required.identities).toEqual(['@types/retry@0.12.0']);
|
||||
expect(() => assertPackageIdentities(required.identities, [
|
||||
'@types/retry@0.12.0',
|
||||
])).not.toThrow();
|
||||
});
|
||||
|
||||
it('keeps target selection explicit and rejects cross-OS staging', () => {
|
||||
const current = `${process.platform}-${process.arch}`;
|
||||
expect(parseBundleArgs(['--target', current]).targets).toEqual([
|
||||
expect.objectContaining({ platform: process.platform, arch: process.arch }),
|
||||
]);
|
||||
const foreign = process.platform === 'win32' ? 'linux-x64' : 'win32-x64';
|
||||
expect(() => parseBundleArgs(['--target', foreign])).toThrow(/must be staged on/);
|
||||
expect(() => parseBundleArgs(['--target', 'unknown-x64'])).toThrow(/Unsupported/);
|
||||
});
|
||||
|
||||
it('wires every package target to its matching staged Pi runtime', async () => {
|
||||
const packageJson = JSON.parse(await readFile('package.json', 'utf8')) as {
|
||||
scripts: Record<string, string>;
|
||||
};
|
||||
const builder = YAML.parse(await readFile('electron-builder.yml', 'utf8')) as Record<
|
||||
string,
|
||||
{ extraResources?: Array<{ from: string; to: string }> }
|
||||
>;
|
||||
|
||||
expect(packageJson.scripts.build).toContain('bundle-pi-runtime.mjs --release-targets');
|
||||
expect(packageJson.scripts.package).toContain('bundle-pi-runtime.mjs --release-targets');
|
||||
expect(packageJson.scripts['package:stage:win-x64'])
|
||||
.toContain('bundle-pi-runtime.mjs --target win32-x64');
|
||||
expect(builder.mac.extraResources).toContainEqual({
|
||||
from: 'build/pi-runtime/darwin-${arch}',
|
||||
to: 'pi-runtime',
|
||||
filter: ['**/*', '!node_modules{,/**/*}'],
|
||||
});
|
||||
expect(builder.mac.extraResources).toContainEqual({
|
||||
from: 'build/pi-runtime/darwin-${arch}/node_modules',
|
||||
to: 'pi-runtime/node_modules',
|
||||
filter: ['**/*'],
|
||||
});
|
||||
expect(builder.win.extraResources).toContainEqual({
|
||||
from: 'build/pi-runtime/win32-${arch}',
|
||||
to: 'pi-runtime',
|
||||
filter: ['**/*', '!node_modules{,/**/*}'],
|
||||
});
|
||||
expect(builder.win.extraResources).toContainEqual({
|
||||
from: 'build/pi-runtime/win32-${arch}/node_modules',
|
||||
to: 'pi-runtime/node_modules',
|
||||
filter: ['**/*'],
|
||||
});
|
||||
expect(builder.linux.extraResources).toContainEqual({
|
||||
from: 'build/pi-runtime/linux-${arch}',
|
||||
to: 'pi-runtime',
|
||||
filter: ['**/*', '!node_modules{,/**/*}'],
|
||||
});
|
||||
expect(builder.linux.extraResources).toContainEqual({
|
||||
from: 'build/pi-runtime/linux-${arch}/node_modules',
|
||||
to: 'pi-runtime/node_modules',
|
||||
filter: ['**/*'],
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user