beadboard/tests/pr14-critical-bugs.test.ts

115 lines
3.7 KiB
JavaScript

#!/usr/bin/env node
import { describe, it } from 'node:test';
import assert from 'node:assert';
import { spawn } from 'node:child_process';
import path from 'node:path';
import fs from 'node:fs';
const repoRoot = path.resolve(process.cwd());
describe('PR 14 Critical Bugs', () => {
describe('Bug 1: CLI needs dev tsx', () => {
it('should have tsx in production dependencies if bin/beadboard.js uses tsx', async () => {
const binPath = path.join(repoRoot, 'bin', 'beadboard.js');
const packageJsonPath = path.join(repoRoot, 'package.json');
if (!fs.existsSync(binPath)) {
throw new Error('bin/beadboard.js not found');
}
const binContent = fs.readFileSync(binPath, 'utf8');
const usesTsx = binContent.includes('--import tsx') || binContent.includes('tsx');
if (!usesTsx) {
console.log('✓ Bug 1: bin/beadboard.js does not use tsx');
return;
}
if (!fs.existsSync(packageJsonPath)) {
throw new Error('package.json not found');
}
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
if (!packageJson.dependencies || !packageJson.dependencies.tsx) {
throw new Error('bin/beadboard.js uses tsx but tsx is not in production dependencies');
}
console.log('✓ Bug 1: tsx is in production dependencies for CLI use');
});
it('should have package.json configured correctly for CLI production use', async () => {
const packageJsonPath = path.join(repoRoot, 'package.json');
if (!fs.existsSync(packageJsonPath)) {
throw new Error('package.json not found');
}
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
if (!packageJson.bin) {
throw new Error('package.json missing bin field');
}
if (!packageJson.bin.beadboard && !packageJson.bin.bb) {
throw new Error('package.json bin field missing beadboard or bb');
}
console.log('✓ Bug 1: package.json has bin field configured');
});
});
describe('Bug 2: bb shim target exists', () => {
it('should have tools/bb.ts file that the bb shim points to', async () => {
const bbTsPath = path.join(repoRoot, 'tools', 'bb.ts');
if (!fs.existsSync(bbTsPath)) {
throw new Error('tools/bb.ts does not exist - bb shim will fail');
}
console.log('✓ Bug 2: tools/bb.ts exists');
});
});
describe('Bug 3: spawn() has error handlers', () => {
it('should have error handlers on spawn() calls in beadboard.mjs', async () => {
const beadboardMjsPath = path.join(repoRoot, 'install', 'beadboard.mjs');
if (!fs.existsSync(beadboardMjsPath)) {
throw new Error('install/beadboard.mjs not found');
}
const content = fs.readFileSync(beadboardMjsPath, 'utf8');
const spawnCalls = [];
const spawnPattern = /spawn\s*\(/g;
let match;
while ((match = spawnPattern.exec(content)) !== null) {
spawnCalls.push(match.index);
}
if (spawnCalls.length === 0) {
throw new Error('No spawn() calls found in beadboard.mjs');
}
const spawnWithErrors = [];
spawnCalls.forEach((index) => {
const context = content.substring(index, index + 500);
if (context.includes('.on(\'error\'') || context.includes('on("error"')) {
spawnWithErrors.push(index);
}
});
if (spawnWithErrors.length < spawnCalls.length) {
throw new Error(
`Found ${spawnCalls.length} spawn() calls but only ${spawnWithErrors.length} have error handlers. ` +
`All spawn() calls must have error event handlers to prevent crashes.`
);
}
console.log('✓ Bug 3: All spawn() calls have error handlers');
});
});
});