Skip to main content
Glama
ooples

MCP Console Automation Server

JUnitReporter.ts3.5 kB
/** * JUnit Reporter * * Generates JUnit XML test reports for CI/CD integration. */ import { TestReport, TestSuiteResult, TestResult, } from '../../types/test-framework.js'; import { TestReporter } from '../TestReporter.js'; export class JUnitReporter extends TestReporter { constructor() { super('junit'); } protected getFileExtension(): string { return '.xml'; } protected async formatReport(report: TestReport): Promise<string> { const { summary, suiteResults, generatedAt } = report; const testsuites: string[] = []; for (const suiteResult of suiteResults) { const testsuite = this.generateTestSuiteXml(suiteResult); testsuites.push(testsuite); } const xml = `<?xml version="1.0" encoding="UTF-8"?> <testsuites name="Console Automation Test Report" tests="${summary.totalTests}" failures="${summary.failed}" skipped="${summary.skipped}" time="${(summary.duration / 1000).toFixed(3)}" timestamp="${generatedAt}"> ${testsuites.join('\n')} </testsuites>`; return xml; } private generateTestSuiteXml(suiteResult: TestSuiteResult): string { const { suite, totalTests, passed, failed, skipped, duration, startTime } = suiteResult; const testcases = suiteResult.tests .map((testResult) => this.generateTestCaseXml(testResult)) .join('\n '); return ` <testsuite name="${this.escapeXml(suite.name)}" tests="${totalTests}" failures="${failed}" skipped="${skipped}" time="${(duration / 1000).toFixed(3)}" timestamp="${new Date(startTime).toISOString()}"> ${testcases} </testsuite>`; } private generateTestCaseXml(testResult: TestResult): string { const { test, status, duration, error, assertions, output } = testResult; let body = ''; // Add failure information if (status === 'fail' && error) { const failedAssertions = assertions.filter((a) => !a.passed); const message = failedAssertions.length > 0 ? failedAssertions.map((a) => a.message).join('; ') : error.message; body += `\n <failure message="${this.escapeXml(message)}" type="${this.escapeXml(error.name || 'AssertionError')}">`; if (error.stack) { body += `\n${this.escapeXml(error.stack)}`; } body += `\n </failure>`; } // Add timeout information if (status === 'timeout') { body += `\n <failure message="Test timeout after ${test.timeout}ms" type="TimeoutError"/>`; } // Add skip information if (status === 'skip') { body += `\n <skipped/>`; } // Add system-out with test output if (output) { body += `\n <system-out><![CDATA[${output}]]></system-out>`; } // Add system-err with assertion details const failedAssertions = assertions.filter((a) => !a.passed); if (failedAssertions.length > 0) { const assertionDetails = failedAssertions .map((a) => `${a.message}${a.stack ? '\n' + a.stack : ''}`) .join('\n---\n'); body += `\n <system-err><![CDATA[${assertionDetails}]]></system-err>`; } const testName = this.escapeXml(test.name); const className = this.escapeXml(test.tags?.join('.') || 'default'); const time = (duration / 1000).toFixed(3); if (body) { return `<testcase name="${testName}" classname="${className}" time="${time}">${body}\n </testcase>`; } else { return `<testcase name="${testName}" classname="${className}" time="${time}"/>`; } } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ooples/mcp-console-automation'

If you have feedback or need assistance with the MCP directory API, please join our Discord server