Files
electron-universal/test/index.spec.ts
2024-06-17 15:15:20 -07:00

162 lines
5.8 KiB
TypeScript

import { spawn } from '@malept/cross-spawn-promise';
import * as fs from 'fs-extra';
import * as path from 'path';
import { makeUniversalApp } from '../dist/cjs/index';
const appsPath = path.resolve(__dirname, 'fixtures', 'apps');
const appsOutPath = path.resolve(__dirname, 'fixtures', 'apps', 'out');
async function ensureUniversal(app: string) {
const exe = path.resolve(app, 'Contents', 'MacOS', 'Electron');
const result = await spawn(exe);
expect(result).toContain('arm64');
const result2 = await spawn('arch', ['-x86_64', exe]);
expect(result2).toContain('x64');
}
// See `jest.setup.ts` for app fixture setup process
describe('makeUniversalApp', () => {
afterEach(async () => {
await fs.emptyDir(appsOutPath);
});
it('throws an error if asar is only detected in one arch', async () => {
const out = path.resolve(appsOutPath, 'Error.app');
await expect(
makeUniversalApp({
x64AppPath: path.resolve(appsPath, 'X64Asar.app'),
arm64AppPath: path.resolve(appsPath, 'Arm64NoAsar.app'),
outAppPath: out,
}),
).rejects.toThrow(
'Both the x64 and arm64 versions of your application need to have been built with the same asar settings (enabled vs disabled)',
);
});
it.todo('works for lipo binary resources');
describe('force', () => {
it('throws an error if `out` bundle already exists and `force` is `false`', async () => {
const out = path.resolve(appsOutPath, 'Error.app');
await fs.mkdirp(out);
await expect(
makeUniversalApp({
x64AppPath: path.resolve(appsPath, 'X64Asar.app'),
arm64AppPath: path.resolve(appsPath, 'Arm64Asar.app'),
outAppPath: out,
}),
).rejects.toThrow(/The out path ".*" already exists and force is not set to true/);
});
it('packages successfully if `out` bundle already exists and `force` is `true`', async () => {
const out = path.resolve(appsOutPath, 'Error.app');
await fs.mkdirp(out);
await makeUniversalApp({
x64AppPath: path.resolve(appsPath, 'X64Asar.app'),
arm64AppPath: path.resolve(appsPath, 'Arm64Asar.app'),
outAppPath: out,
force: true,
});
await ensureUniversal(out);
// Only a single asar as they were identical
expect(
(await fs.readdir(path.resolve(out, 'Contents', 'Resources'))).filter((p) =>
p.endsWith('asar'),
),
).toEqual(['app.asar']);
}, 60000);
});
describe('asar mode', () => {
it('should correctly merge two identical asars', async () => {
const out = path.resolve(appsOutPath, 'MergedAsar.app');
await makeUniversalApp({
x64AppPath: path.resolve(appsPath, 'X64Asar.app'),
arm64AppPath: path.resolve(appsPath, 'Arm64Asar.app'),
outAppPath: out,
});
await ensureUniversal(out);
// Only a single asar as they were identical
expect(
(await fs.readdir(path.resolve(out, 'Contents', 'Resources'))).filter((p) =>
p.endsWith('asar'),
),
).toEqual(['app.asar']);
}, 60000);
it('should create a shim if asars are different between architectures', async () => {
const out = path.resolve(appsOutPath, 'ShimmedAsar.app');
await makeUniversalApp({
x64AppPath: path.resolve(appsPath, 'X64Asar.app'),
arm64AppPath: path.resolve(appsPath, 'Arm64AsarExtraFile.app'),
outAppPath: out,
});
await ensureUniversal(out);
// We have three asars including the arch-agnostic shim
expect(
(await fs.readdir(path.resolve(out, 'Contents', 'Resources')))
.filter((p) => p.endsWith('asar'))
.sort(),
).toEqual(['app.asar', 'app-x64.asar', 'app-arm64.asar'].sort());
}, 60000);
it('should merge two different asars when `mergeASARs` is enabled', async () => {
const out = path.resolve(appsOutPath, 'MergedAsar.app');
await makeUniversalApp({
x64AppPath: path.resolve(appsPath, 'X64Asar.app'),
arm64AppPath: path.resolve(appsPath, 'Arm64AsarExtraFile.app'),
outAppPath: out,
mergeASARs: true,
singleArchFiles: 'extra-file.txt',
});
await ensureUniversal(out);
// Only a single merged asar
expect(
(await fs.readdir(path.resolve(out, 'Contents', 'Resources'))).filter((p) =>
p.endsWith('asar'),
),
).toEqual(['app.asar']);
}, 60000);
it('throws an error if `mergeASARs` is enabled and `singleArchFiles` is missing a unique file', async () => {
const out = path.resolve(appsOutPath, 'Error.app');
await expect(
makeUniversalApp({
x64AppPath: path.resolve(appsPath, 'X64Asar.app'),
arm64AppPath: path.resolve(appsPath, 'Arm64AsarExtraFile.app'),
outAppPath: out,
mergeASARs: true,
singleArchFiles: 'bad-rule',
}),
).rejects.toThrow(/Detected unique file "extra-file\.txt"/);
}, 60000);
it.todo('should not inject ElectronAsarIntegrity into `infoPlistsToIgnore`');
});
describe('no asar mode', () => {
it('should correctly merge two identical app folders', async () => {
const out = path.resolve(appsOutPath, 'MergedNoAsar.app');
await makeUniversalApp({
x64AppPath: path.resolve(appsPath, 'X64NoAsar.app'),
arm64AppPath: path.resolve(appsPath, 'Arm64NoAsar.app'),
outAppPath: out,
});
await ensureUniversal(out);
// Only a single app folder as they were identical
expect(
(await fs.readdir(path.resolve(out, 'Contents', 'Resources'))).filter((p) =>
p.startsWith('app'),
),
).toEqual(['app']);
}, 60000);
it.todo('should shim two different app folders');
});
// TODO: Add tests for
// * different app dirs with different macho files
// * identical app dirs with universal macho files
});