Merge remote-tracking branch 'upstream/main'

This commit is contained in:
Connor 2024-03-01 10:18:01 -06:00
parent 258d3a0780
commit dd2ae7c835
No known key found for this signature in database
GPG key ID: 455C6C81CB2BD091
38 changed files with 40986 additions and 17818 deletions

View file

@ -4,7 +4,10 @@ import {FileContent, InputProvider, ReportInput} from './input-provider'
import {listFiles} from '../utils/git'
export class LocalFileProvider implements InputProvider {
constructor(readonly name: string, readonly pattern: string[]) {}
constructor(
readonly name: string,
readonly pattern: string[]
) {}
async load(): Promise<ReportInput> {
const result: FileContent[] = []

View file

@ -17,10 +17,10 @@ import {DotnetTrxParser} from './parsers/dotnet-trx/dotnet-trx-parser'
import {JavaJunitParser} from './parsers/java-junit/java-junit-parser'
import {JestJunitParser} from './parsers/jest-junit/jest-junit-parser'
import {MochaJsonParser} from './parsers/mocha-json/mocha-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 {Icon} from './utils/markdown-utils'
async function main(): Promise<void> {
try {
@ -43,6 +43,7 @@ class TestReporter {
readonly listTests = core.getInput('list-tests', {required: true}) as 'all' | 'failed' | 'none' | 'non-skipped'
readonly maxAnnotations = parseInt(core.getInput('max-annotations', {required: true}))
readonly failOnError = core.getInput('fail-on-error', {required: true}) === 'true'
readonly failOnEmpty = core.getInput('fail-on-empty', {required: true}) === 'true'
readonly workDirInput = core.getInput('working-directory', {required: false})
readonly onlySummary = core.getInput('only-summary', {required: false}) === 'true'
readonly showHTMLNotice = core.getInput('show-html-notice', {required: false}) === 'true'
@ -150,7 +151,7 @@ class TestReporter {
return
}
if (results.length === 0) {
if (results.length === 0 && this.failOnEmpty) {
core.setFailed(`No test report files were found`)
return
}
@ -200,7 +201,11 @@ class TestReporter {
const isFailed = this.failOnError && results.some(tr => tr.result === 'failed')
const conclusion = isFailed ? 'failure' : 'success'
const icon = isFailed ? Icon.fail : Icon.success
const passed = results.reduce((sum, tr) => sum + tr.passed, 0)
const failed = results.reduce((sum, tr) => sum + tr.failed, 0)
const skipped = results.reduce((sum, tr) => sum + tr.skipped, 0)
const shortSummary = `${passed} passed, ${failed} failed and ${skipped} skipped `
core.info(`Updating check run conclusion (${conclusion}) and output`)
const resp = await this.handleAnnotations(annotations, {
@ -208,7 +213,7 @@ class TestReporter {
conclusion,
status: 'completed',
output: {
title: `${name} ${icon}`,
title: shortSummary,
summary,
annotations
},
@ -223,6 +228,8 @@ class TestReporter {
core.info(`Set env var to: ${process.env.TEST_RESULTS_URL}`)
core.info(`::notice title=Test Results::${resp.data.html_url}`)
}
core.setOutput('url', resp.data.url)
core.setOutput('url_html', resp.data.html_url)
return [results, resp.data.html_url]
}
@ -241,6 +248,8 @@ class TestReporter {
return new JestJunitParser(options)
case 'mocha-json':
return new MochaJsonParser(options)
case 'swift-xunit':
return new SwiftXunitParser(options)
default:
throw new Error(`Input variable 'reporter' is set to invalid value '${reporter}'`)
}

View file

@ -29,7 +29,12 @@ import {
} from '../../test-results'
class TestRun {
constructor(readonly path: string, readonly suites: TestSuite[], readonly success: boolean, readonly time: number) {}
constructor(
readonly path: string,
readonly suites: TestSuite[],
readonly success: boolean,
readonly time: number
) {}
}
class TestSuite {
@ -74,7 +79,10 @@ class TestCase {
export class DartJsonParser implements TestParser {
assumedWorkDir: string | undefined
constructor(readonly options: ParseOptions, readonly sdk: 'dart' | 'flutter') {}
constructor(
readonly options: ParseOptions,
readonly sdk: 'dart' | 'flutter'
) {}
async parse(path: string, content: string): Promise<TestRunResult> {
const tr = this.getTestRun(path, content)

View file

@ -37,7 +37,7 @@ export class JestJunitParser implements TestParser {
junit.testsuites.testsuite === undefined
? []
: junit.testsuites.testsuite.map(ts => {
const name = ts.$.name.trim()
const name = this.escapeCharacters(ts.$.name.trim())
const time = parseFloat(ts.$.time) * 1000
const sr = new TestSuiteResult(name, this.getGroups(ts), time)
return sr
@ -118,4 +118,8 @@ export class JestJunitParser implements TestParser {
(this.assumedWorkDir = getBasePath(path, this.options.trackedFiles))
)
}
private escapeCharacters(s: string): string {
return s.replace(/([<>])/g, '\\$1')
}
}

View file

@ -0,0 +1,8 @@
import {ParseOptions} from '../../test-parser'
import {JavaJunitParser} from '../java-junit/java-junit-parser'
export class SwiftXunitParser extends JavaJunitParser {
constructor(readonly options: ParseOptions) {
super(options)
}
}

View file

@ -1,7 +1,11 @@
import {DEFAULT_LOCALE} from './utils/node-utils'
export class TestRunResult {
constructor(readonly path: string, readonly suites: TestSuiteResult[], private totalTime?: number) {}
constructor(
readonly path: string,
readonly suites: TestSuiteResult[],
private totalTime?: number
) {}
get tests(): number {
return this.suites.reduce((sum, g) => sum + g.tests, 0)
@ -40,7 +44,11 @@ export class TestRunResult {
}
export class TestSuiteResult {
constructor(readonly name: string, readonly groups: TestGroupResult[], private totalTime?: number) {}
constructor(
readonly name: string,
readonly groups: TestGroupResult[],
private totalTime?: number
) {}
get tests(): number {
return this.groups.reduce((sum, g) => sum + g.tests.length, 0)
@ -78,7 +86,10 @@ export class TestSuiteResult {
}
export class TestGroupResult {
constructor(readonly name: string | undefined | null, readonly tests: TestCaseResult[]) {}
constructor(
readonly name: string | undefined | null,
readonly tests: TestCaseResult[]
) {}
get passed(): number {
return this.tests.reduce((sum, t) => (t.result === 'success' ? sum + 1 : sum), 0)

View file

@ -19,6 +19,6 @@ export function parseIsoDate(str: string): Date {
}
export function getFirstNonEmptyLine(stackTrace: string): string | undefined {
const lines = stackTrace.split(/\r?\n/g)
return lines.find(str => !/^\s*$/.test(str))
const lines = stackTrace?.split(/\r?\n/g)
return lines?.find(str => !/^\s*$/.test(str))
}