mirror of
https://github.com/BradGroux/veritas-kanban.git
synced 2026-10-09 13:17:52 +00:00
121 lines
3.3 KiB
JavaScript
121 lines
3.3 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
import { spawnSync } from 'node:child_process';
|
|
import { readFileSync } from 'node:fs';
|
|
import { fileURLToPath } from 'node:url';
|
|
import path from 'node:path';
|
|
|
|
const repositoryRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
const pnpmExecutable = process.platform === 'win32' ? 'pnpm.cmd' : 'pnpm';
|
|
|
|
export const UNIT_TEST_STAGES = Object.freeze([
|
|
{
|
|
id: 'shared-build',
|
|
label: 'shared prerequisite',
|
|
directory: 'shared',
|
|
packageName: '@veritas-kanban/shared',
|
|
requiredScript: 'build',
|
|
},
|
|
{
|
|
id: 'server',
|
|
label: 'server unit tests',
|
|
directory: 'server',
|
|
packageName: '@veritas-kanban/server',
|
|
requiredScript: 'test',
|
|
},
|
|
{
|
|
id: 'web',
|
|
label: 'web unit tests',
|
|
directory: 'web',
|
|
packageName: '@veritas-kanban/web',
|
|
requiredScript: 'test',
|
|
},
|
|
{
|
|
id: 'cli',
|
|
label: 'CLI unit tests',
|
|
directory: 'cli',
|
|
packageName: '@veritas-kanban/cli',
|
|
requiredScript: 'test',
|
|
},
|
|
{
|
|
id: 'mcp',
|
|
label: 'MCP unit tests',
|
|
directory: 'mcp',
|
|
packageName: '@veritas-kanban/mcp',
|
|
requiredScript: 'test',
|
|
},
|
|
]);
|
|
|
|
function readWorkspacePackage(stage) {
|
|
const packagePath = path.join(repositoryRoot, stage.directory, 'package.json');
|
|
return JSON.parse(readFileSync(packagePath, 'utf8'));
|
|
}
|
|
|
|
export function validateStage(stage, { readPackageJson = readWorkspacePackage } = {}) {
|
|
let packageJson;
|
|
try {
|
|
packageJson = readPackageJson(stage);
|
|
} catch (error) {
|
|
return `Cannot read ${stage.directory}/package.json: ${error.message}`;
|
|
}
|
|
if (packageJson.name !== stage.packageName) {
|
|
return `${stage.directory}/package.json must declare name ${stage.packageName}`;
|
|
}
|
|
if (
|
|
typeof packageJson.scripts?.[stage.requiredScript] !== 'string' ||
|
|
packageJson.scripts[stage.requiredScript].trim() === ''
|
|
) {
|
|
return `${stage.packageName} must define a non-empty ${stage.requiredScript} script`;
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
function executeStage(stage) {
|
|
const result = spawnSync(pnpmExecutable, ['--filter', stage.packageName, stage.requiredScript], {
|
|
cwd: repositoryRoot,
|
|
env: process.env,
|
|
stdio: 'inherit',
|
|
});
|
|
|
|
if (result.error) {
|
|
console.error(`Could not start ${stage.label}: ${result.error.message}`);
|
|
return 1;
|
|
}
|
|
return result.status ?? 1;
|
|
}
|
|
|
|
export function runWorkspaceUnitTests({
|
|
run = executeStage,
|
|
validate = validateStage,
|
|
log = console.log,
|
|
} = {}) {
|
|
const results = new Map(UNIT_TEST_STAGES.map((stage) => [stage.id, 'NOT RUN']));
|
|
let exitCode = 0;
|
|
|
|
for (const stage of UNIT_TEST_STAGES) {
|
|
log(`\n==> ${stage.label}`);
|
|
const validationError = validate(stage);
|
|
if (validationError) {
|
|
log(`Configuration error: ${validationError}`);
|
|
results.set(stage.id, 'FAIL');
|
|
exitCode = 1;
|
|
break;
|
|
}
|
|
const status = run(stage);
|
|
results.set(stage.id, status === 0 ? 'PASS' : 'FAIL');
|
|
if (status !== 0) {
|
|
exitCode = status > 0 ? status : 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
const workspaceSummary = UNIT_TEST_STAGES.filter((stage) => stage.id !== 'shared-build')
|
|
.map((stage) => `${stage.id}: ${results.get(stage.id)}`)
|
|
.join(' | ');
|
|
log(`\nWorkspace unit-test summary: ${workspaceSummary}`);
|
|
return exitCode;
|
|
}
|
|
|
|
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
process.exitCode = runWorkspaceUnitTests();
|
|
}
|