Files
hash-map/scripts/test-teamcity.ts

113 lines
3.0 KiB
TypeScript
Executable File

#!/usr/bin/env bun
import { TeamcityReporter } from "../tests/TeamcityReporter.ts";
const isTeamCity = process.env.TEAMCITY_VERSION !== undefined;
// Strip ANSI color codes
function stripAnsi(str: string): string {
// eslint-disable-next-line no-control-regex
return str.replace(/\x1b\[[0-9;]*m/g, "");
}
async function runTests() {
if (!isTeamCity) {
// Just pass through if not in TeamCity
const proc = Bun.spawn(["bun", "test", ...process.argv.slice(2)], {
stdout: "inherit",
stderr: "inherit",
env: { ...process.env },
});
const exitCode = await proc.exited;
process.exit(exitCode);
return;
}
console.error("TeamCity reporter enabled");
// Run tests and capture output
const proc = Bun.spawn(["bun", "test", ...process.argv.slice(2)], {
stdout: "pipe",
stderr: "pipe",
env: { ...process.env },
});
const suiteStack: string[] = [];
// Read stdout as text
const output = await new Response(proc.stdout).text();
const lines = output.split("\n");
for (const rawLine of lines) {
// Pass through original output (with colors)
console.log(rawLine);
// Parse without colors
const line = stripAnsi(rawLine).trim();
// Check for test suite/describe blocks (files ending with .test.ts)
if (line.match(/tests\/.+\.test\.ts:$/)) {
const fileName = line
.replace(":", "")
.replace("tests/", "")
.replace(".test.ts", "");
// End previous suite if exists
while (suiteStack.length > 0) {
const oldSuite = suiteStack.pop();
if (oldSuite) {
TeamcityReporter.reportSuiteEnd(oldSuite);
}
}
suiteStack.push(fileName);
TeamcityReporter.reportSuiteStart(fileName);
}
// Check for test pass: (pass) HashMap > constructor > should create an empty map...
const passMatch = line.match(/^\(pass\)\s+(.+?)(?:\s+\[[\d.]+m?s\])?$/);
if (passMatch) {
const testName = passMatch[1].trim();
TeamcityReporter.reportTestStart(testName);
TeamcityReporter.reportTestEnd(testName);
}
// Check for test fail: (fail) HashMap > constructor > should...
const failMatch = line.match(/^\(fail\)\s+(.+?)(?:\s+\[[\d.]+m?s\])?$/);
if (failMatch) {
const testName = failMatch[1].trim();
TeamcityReporter.reportTestStart(testName);
TeamcityReporter.reportTestFailed(testName, "Test failed", line, {
comparisonFailure: false,
expected: "",
actual: "",
});
TeamcityReporter.reportTestEnd(testName);
}
}
// Capture stderr
const errorOutput = await new Response(proc.stderr).text();
if (errorOutput) {
console.error(errorOutput);
}
const exitCode = await proc.exited;
// Close all open suites
while (suiteStack.length > 0) {
const suite = suiteStack.pop();
if (suite) {
TeamcityReporter.reportSuiteEnd(suite);
}
}
console.error("TeamCity reporter finished");
process.exit(exitCode);
}
runTests().catch((error) => {
console.error("Error running tests:", error);
process.exit(1);
});