Files
trezor-suite/packages/connect/e2e/run.ts
2026-01-29 15:36:31 +01:00

165 lines
5.3 KiB
TypeScript

import { getVersion as getJestVersion, runCLI } from 'jest';
import karma from 'karma';
import path from 'path';
import webpack from 'webpack';
import {
EmuStartOptsType,
Firmwares,
Model,
TrezorUserEnvLink,
} from '@trezor/trezor-user-env-link';
import { typedObjectKeys } from '@trezor/utils';
import argv from './jest.config';
const firmwareArg = process.env.TESTS_FIRMWARE;
const firmwareUrl = process.env.TESTS_FIRMWARE_URL;
const firmwareModel = process.env.TESTS_FIRMWARE_MODEL as Model;
const firmwareBranch = process.env.TESTS_FIRMWARE_BRANCH;
const firmwareBtcOnly = process.env.TESTS_FIRMWARE_BTC_ONLY === 'true';
/**
* Translate test command arguments into trezor-user-env options.
* TODO: this code might be refactored and moved into TrezorUserEnvLink class later
*/
const getEmulatorOptions = (availableFirmwares: Firmwares) => {
const getLatestFirmware = (model: keyof Firmwares) =>
availableFirmwares[model].find(fw => {
const withoutArm = fw.replace('-arm', '');
const semverVersion = !withoutArm.includes('-'); // there are only 2-main-arm or 2.9.0-arm
const mainVersion = withoutArm.endsWith('-main');
return semverVersion || mainVersion; // return named (semver) version, or 'main' version fallback - this happens when new model is created but it has no stable firmware release yet.
});
const model =
firmwareModel && typedObjectKeys(availableFirmwares).includes(firmwareModel)
? firmwareModel
: Model.T2T1;
const latest = getLatestFirmware(model);
if (firmwareArg?.endsWith('-latest') && !latest) {
// should never happen
throw new Error('could not translate n-latest into specific firmware version');
}
let emulatorStartOpts: EmuStartOptsType;
if (firmwareUrl) {
emulatorStartOpts = {
type: 'emulator-start-from-url',
url: firmwareUrl,
wipe: true,
model,
};
} else if (firmwareBranch) {
emulatorStartOpts = {
type: 'emulator-start-from-branch',
branch: firmwareBranch,
btcOnly: firmwareBtcOnly,
wipe: true,
model,
};
} else {
let version;
if (firmwareArg) {
version = firmwareArg.endsWith('-latest') ? latest : firmwareArg;
} else {
version = latest;
}
emulatorStartOpts = {
type: 'emulator-start',
wipe: true,
version,
model,
};
}
if (
'version' in emulatorStartOpts &&
emulatorStartOpts.version?.startsWith('1') &&
emulatorStartOpts.model !== 'T1B1'
) {
throw new Error('firmware version 1.x is only supported for T1B1 model');
}
return emulatorStartOpts;
};
(async () => {
// Before actual tests start, establish connection with trezor-user-env
await TrezorUserEnvLink.connect();
// Trezor-user-env loads available firmwares upon start allowing us to translate process.env variables
// into specific firmware versions
if (!TrezorUserEnvLink.firmwares) {
throw new Error('firmwares not loaded');
}
const emulatorStartOpts = getEmulatorOptions(TrezorUserEnvLink.firmwares);
argv.globals = {
emulatorStartOpts,
};
// @ts-expect-error there is some mismatch between jest implementation and definitely typed package.
argv.runInBand = true;
if (process.env.TESTS_PATTERN) {
// @ts-expect-error
argv.testMatch = process.env.TESTS_PATTERN.split(' ').map(p => `**/${p}*`);
}
if (process.argv[2] === 'node') {
// eslint-disable-next-line no-console
console.log('jest version: ', getJestVersion());
if (process.env.TESTS_RANDOM === 'true') {
// @ts-expect-error
argv.showSeed = true;
// @ts-expect-error
argv.randomize = true;
}
// @ts-expect-error
const { results } = await runCLI(argv, [__dirname]).catch(err => {
console.error(err);
process.exit(1);
});
process.exit(results.numFailedTestSuites);
} else if (process.argv[2] === 'web') {
const { parseConfig } = karma.config;
const { Server } = karma;
parseConfig(
path.join(__dirname, 'karma.config.js'),
{ port: 8099 },
{ promiseConfig: true, throwErrors: true },
).then(
karmaConfig => {
// @ts-expect-error
karmaConfig.webpack.plugins.push(
new webpack.DefinePlugin({
'process.env.emulatorStartOpts': JSON.stringify(
// @ts-expect-error
argv.globals.emulatorStartOpts,
),
}),
);
const server = new Server(karmaConfig, exitCode => {
process.exit(exitCode);
});
server.start();
},
rejectReason => {
// eslint-disable-next-line no-console
console.log('reject reason', rejectReason);
process.exit(1);
},
);
} else {
throw new Error('no env specified (web or node)');
}
})();