mirror of
https://github.com/jcreek/LivingDexTracker.git
synced 2026-09-16 02:22:17 +00:00
2042e5a65a
Measures the pokédex load against a local Supabase with a generated fixture, and compares runs so a regression shows up as a number rather than a hunch. Wired into test:ci and given its own job so the artifacts survive a failure.
106 lines
3.4 KiB
JavaScript
106 lines
3.4 KiB
JavaScript
import { spawn } from 'node:child_process';
|
|
import { mkdtemp, mkdir, cp, rm, readFile, writeFile } from 'node:fs/promises';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
|
|
const directory = await mkdtemp(path.join(os.tmpdir(), 'livingdex-grid-tests-'));
|
|
const port = process.env.PERF_PORT ?? '4185';
|
|
const env = {
|
|
...process.env,
|
|
NODE_ADAPTER: 'true',
|
|
PUBLIC_USE_LOCAL_POKEMON_SPRITE_FOLDER: 'true',
|
|
POKEDEX_PERFORMANCE: 'true',
|
|
PERF_FIXTURE_DIR: directory,
|
|
PERF_BASE_URL: `http://127.0.0.1:${port}`,
|
|
PORT: port,
|
|
HOST: '127.0.0.1'
|
|
};
|
|
function run(command, args) {
|
|
return new Promise((resolve, reject) => {
|
|
const process = spawn(command, args, { env, stdio: 'inherit' });
|
|
process.once('error', reject);
|
|
process.once('exit', (code) =>
|
|
code === 0 ? resolve() : reject(new Error(`${command} failed (${code})`))
|
|
);
|
|
});
|
|
}
|
|
let server;
|
|
let fixture = false;
|
|
try {
|
|
await run('npm', ['run', 'build-inject-manifest-node']);
|
|
fixture = true;
|
|
await run('node', ['scripts/performance/fixture.mjs']);
|
|
server = spawn('node', ['build'], { env, stdio: 'inherit' });
|
|
await new Promise((resolve, reject) => {
|
|
const timer = setInterval(async () => {
|
|
try {
|
|
if ((await fetch(env.PERF_BASE_URL)).ok) {
|
|
clearInterval(timer);
|
|
clearTimeout(timeout);
|
|
resolve();
|
|
}
|
|
} catch {}
|
|
}, 200);
|
|
const timeout = setTimeout(() => {
|
|
clearInterval(timer);
|
|
reject(new Error('Local production server did not start'));
|
|
}, 15000);
|
|
server.once('error', (error) => {
|
|
clearInterval(timer);
|
|
clearTimeout(timeout);
|
|
reject(error);
|
|
});
|
|
server.once('exit', (code) => {
|
|
clearInterval(timer);
|
|
clearTimeout(timeout);
|
|
reject(new Error(`Local server exited (${code})`));
|
|
});
|
|
});
|
|
if (process.env.PERF_BENCHMARK === 'true') {
|
|
const data = JSON.parse(await readFile(path.join(directory, 'fixture.json'), 'utf8'));
|
|
await writeFile(
|
|
path.join(directory, 'benchmark-config.json'),
|
|
JSON.stringify({
|
|
samples: 30,
|
|
revision: process.env.PERF_REVISION ?? 'local-working-tree',
|
|
databaseLabel: 'local-seeded-supabase',
|
|
clientLocation: 'local-loopback',
|
|
environment: 'local-node',
|
|
hosts: [
|
|
{
|
|
label: 'node',
|
|
url: env.PERF_BASE_URL,
|
|
storageState: path.join(directory, 'storage-state.json'),
|
|
fixtures: data.dexes.map((dex) => ({
|
|
id: dex.id,
|
|
name: dex.name,
|
|
label: dex.gameScope ? 'scoped-forms' : 'national'
|
|
}))
|
|
}
|
|
]
|
|
})
|
|
);
|
|
await run('node', [
|
|
'scripts/performance/benchmark.mjs',
|
|
path.join(directory, 'benchmark-config.json'),
|
|
path.join(directory, 'benchmark.json')
|
|
]);
|
|
await mkdir('test-results/performance', { recursive: true });
|
|
await cp(path.join(directory, 'benchmark.json'), 'test-results/performance/benchmark.json');
|
|
}
|
|
await run('node', ['scripts/performance/verify.mjs']);
|
|
await run('node', ['scripts/performance/verify-behavior.mjs']);
|
|
await mkdir('test-results/performance', { recursive: true });
|
|
for (const file of ['verification.json', 'behavior.json', 'national.png', 'scoped.png'])
|
|
await cp(path.join(directory, file), path.join('test-results/performance', file));
|
|
} finally {
|
|
server?.kill('SIGTERM');
|
|
if (fixture)
|
|
await run('node', ['scripts/performance/fixture.mjs', '--cleanup']).catch((error) => {
|
|
throw new Error(`Fixture cleanup failed; retained recovery files in ${directory}`, {
|
|
cause: error
|
|
});
|
|
});
|
|
await rm(directory, { recursive: true, force: true });
|
|
}
|