mirror of
https://github.com/dorny/test-reporter.git
synced 2025-12-17 23:07:08 +01:00
add support for karma-junit-reporter
This commit is contained in:
parent
aef3d726a6
commit
08646e4d97
17 changed files with 12441 additions and 1 deletions
|
|
@ -22,6 +22,7 @@ import {RspecJsonParser} from './parsers/rspec-json/rspec-json-parser'
|
|||
import {SwiftXunitParser} from './parsers/swift-xunit/swift-xunit-parser'
|
||||
import {normalizeDirPath, normalizeFilePath} from './utils/path-utils'
|
||||
import {getCheckRunContext} from './utils/github-utils'
|
||||
import {KarmaJunitParser} from './parsers/karma-junit/karma-junit-parser'
|
||||
|
||||
async function main(): Promise<void> {
|
||||
try {
|
||||
|
|
@ -269,6 +270,9 @@ class TestReporter {
|
|||
return new JavaJunitParser(options)
|
||||
case 'jest-junit':
|
||||
return new JestJunitParser(options)
|
||||
case 'karma-junit':
|
||||
return new KarmaJunitParser(options)
|
||||
|
||||
case 'mocha-json':
|
||||
return new MochaJsonParser(options)
|
||||
case 'python-xunit':
|
||||
|
|
|
|||
125
src/parsers/karma-junit/karma-junit-parser.ts
Normal file
125
src/parsers/karma-junit/karma-junit-parser.ts
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
import {ParseOptions, TestParser} from '../../test-parser'
|
||||
import {parseStringPromise} from 'xml2js'
|
||||
|
||||
import {KarmaReport, TestCase, TestSuite} from './karma-junit-types'
|
||||
import {getExceptionSource} from '../../utils/node-utils'
|
||||
import {getBasePath, normalizeFilePath} from '../../utils/path-utils'
|
||||
|
||||
import {
|
||||
TestExecutionResult,
|
||||
TestRunResult,
|
||||
TestSuiteResult,
|
||||
TestGroupResult,
|
||||
TestCaseResult,
|
||||
TestCaseError
|
||||
} from '../../test-results'
|
||||
|
||||
export class KarmaJunitParser implements TestParser {
|
||||
assumedWorkDir: string | undefined
|
||||
|
||||
constructor(readonly options: ParseOptions) {}
|
||||
|
||||
async parse(path: string, content: string): Promise<TestRunResult> {
|
||||
const ju = await this.getJunitReport(path, content)
|
||||
return this.getTestRunResult(path, ju)
|
||||
}
|
||||
|
||||
private async getJunitReport(path: string, content: string): Promise<KarmaReport> {
|
||||
try {
|
||||
return (await parseStringPromise(content)) as KarmaReport
|
||||
} catch (e) {
|
||||
throw new Error(`Invalid XML at ${path}\n\n${e}`)
|
||||
}
|
||||
}
|
||||
|
||||
private getTestRunResult(path: string, karma: KarmaReport): TestRunResult {
|
||||
const suites =
|
||||
karma.testsuite === undefined
|
||||
? []
|
||||
: [karma.testsuite].map(ts => {
|
||||
const name = this.escapeCharacters(ts.$.name.trim())
|
||||
const time = parseFloat(ts.$.time) * 1000
|
||||
const sr = new TestSuiteResult(name, this.getGroups(ts), time)
|
||||
return sr
|
||||
})
|
||||
|
||||
const time = karma.testsuite?.$ && parseFloat(karma.testsuite.$.time) * 1000
|
||||
return new TestRunResult(path, suites, time)
|
||||
}
|
||||
|
||||
protected getGroups(suite: TestSuite): TestGroupResult[] {
|
||||
if (!suite.testcase) {
|
||||
return []
|
||||
}
|
||||
|
||||
const groups: {describe: string; tests: TestCase[]}[] = []
|
||||
for (const tc of suite.testcase) {
|
||||
let grp = groups.find(g => g.describe === tc.$.classname)
|
||||
if (grp === undefined) {
|
||||
grp = {describe: tc.$.classname, tests: []}
|
||||
groups.push(grp)
|
||||
}
|
||||
grp.tests.push(tc)
|
||||
}
|
||||
|
||||
return groups.map(grp => {
|
||||
const tests = grp.tests.map(tc => {
|
||||
const name = tc.$.name.trim()
|
||||
const result = this.getTestCaseResult(tc)
|
||||
const time = parseFloat(tc.$.time) * 1000
|
||||
const error = this.getTestCaseError(tc)
|
||||
return new TestCaseResult(name, result, time, error)
|
||||
})
|
||||
return new TestGroupResult(grp.describe, tests)
|
||||
})
|
||||
}
|
||||
|
||||
private getTestCaseResult(test: TestCase): TestExecutionResult {
|
||||
if (test.failure) return 'failed'
|
||||
if (test.skipped) return 'skipped'
|
||||
return 'success'
|
||||
}
|
||||
|
||||
private getTestCaseError(tc: TestCase): TestCaseError | undefined {
|
||||
if (!this.options.parseErrors || !tc.failure) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const details = typeof tc.failure[0] === 'string' ? tc.failure[0] : tc.failure[0]['_']
|
||||
let path
|
||||
let line
|
||||
|
||||
const src = getExceptionSource(details, this.options.trackedFiles, file => this.getRelativePath(file))
|
||||
if (src) {
|
||||
path = src.path
|
||||
line = src.line
|
||||
}
|
||||
|
||||
return {
|
||||
path,
|
||||
line,
|
||||
details
|
||||
}
|
||||
}
|
||||
|
||||
private getRelativePath(path: string): string {
|
||||
path = normalizeFilePath(path)
|
||||
const workDir = this.getWorkDir(path)
|
||||
if (workDir !== undefined && path.startsWith(workDir)) {
|
||||
path = path.substr(workDir.length)
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
private getWorkDir(path: string): string | undefined {
|
||||
return (
|
||||
this.options.workDir ??
|
||||
this.assumedWorkDir ??
|
||||
(this.assumedWorkDir = getBasePath(path, this.options.trackedFiles))
|
||||
)
|
||||
}
|
||||
|
||||
protected escapeCharacters(s: string): string {
|
||||
return s.replace(/([<>])/g, '\\$1')
|
||||
}
|
||||
}
|
||||
34
src/parsers/karma-junit/karma-junit-types.ts
Normal file
34
src/parsers/karma-junit/karma-junit-types.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
export interface KarmaReport {
|
||||
testsuite: TestSuite
|
||||
}
|
||||
|
||||
export interface TestSuites {
|
||||
$: {
|
||||
time: string
|
||||
}
|
||||
testsuite?: TestSuite[]
|
||||
}
|
||||
|
||||
export interface TestSuite {
|
||||
$: {
|
||||
name: string
|
||||
tests: string
|
||||
errors: string
|
||||
failures: string
|
||||
skipped: string
|
||||
time: string
|
||||
timestamp?: Date
|
||||
}
|
||||
testcase?: TestCase[]
|
||||
}
|
||||
|
||||
export interface TestCase {
|
||||
$: {
|
||||
classname: string
|
||||
file?: string
|
||||
name: string
|
||||
time: string
|
||||
}
|
||||
failure?: string[]
|
||||
skipped?: string[]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue