113 lines
3.0 KiB
TypeScript
Executable File
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);
|
|
});
|