Manually create anchors for headings

This commit is contained in:
Michal Dorner 2020-11-18 23:31:33 +01:00
parent 3e8db1a67b
commit 95d3d1fb85
No known key found for this signature in database
GPG key ID: 9EEE04B48DA36786
8 changed files with 82 additions and 156 deletions

View file

@ -1,9 +1,9 @@
import {TestResult} from '../test-parser'
import {parseStringPromise} from 'xml2js'
import GithubSlugger from 'github-slugger'
import {JunitReport, TestCase, TestSuite, TestSuites} from './jest-junit-types'
import {Align, Icon, link, table, exceptionCell} from '../../utils/markdown-utils'
import {slug} from '../../utils/slugger'
import {parseAttribute} from '../../utils/xml-utils'
export async function parseJestJunit(content: string): Promise<TestResult> {
@ -11,20 +11,18 @@ export async function parseJestJunit(content: string): Promise<TestResult> {
attrValueProcessors: [parseAttribute]
})) as JunitReport
const testsuites = junit.testsuites
const slugger = new GithubSlugger()
const success = !(testsuites.$?.failures > 0 || testsuites.$?.errors > 0)
return {
success,
output: {
title: junit.testsuites.$.name,
summary: getSummary(success, junit, slugger)
summary: getSummary(success, junit)
}
}
}
function getSummary(success: boolean, junit: JunitReport, slugger: GithubSlugger): string {
function getSummary(success: boolean, junit: JunitReport): string {
const stats = junit.testsuites.$
const icon = success ? Icon.success : Icon.fail
@ -37,16 +35,16 @@ function getSummary(success: boolean, junit: JunitReport, slugger: GithubSlugger
const heading = `# ${stats.name} ${icon}`
const headingLine = `**${stats.tests}** tests were completed in **${time}** with **${passed}** passed, **${skipped}** skipped and **${failed}** failed.`
const suitesSummary = junit.testsuites.testsuite.map(ts => {
const suitesSummary = junit.testsuites.testsuite.map((ts, i) => {
const skip = ts.$.skipped
const fail = ts.$.errors + ts.$.failures
const pass = ts.$.tests - fail - skip
const tm = `${ts.$.time.toFixed(3)}s`
const result = success ? Icon.success : Icon.fail
const slug = slugger.slug(`${ts.$.name} ${result}`).replace(/_/g, '')
const tsAddr = `#${slug}`
const name = link(ts.$.name, tsAddr)
return [result, name, ts.$.tests, tm, pass, fail, skip]
const tsName = ts.$.name
const tsAddr = makeSuiteSlug(i, tsName).link
const tsNameLink = link(tsName, tsAddr)
return [result, tsNameLink, ts.$.tests, tm, pass, fail, skip]
})
const summary = table(
@ -55,7 +53,7 @@ function getSummary(success: boolean, junit: JunitReport, slugger: GithubSlugger
...suitesSummary
)
const suites = junit.testsuites?.testsuite?.map(ts => getSuiteSummary(ts)).join('\n')
const suites = junit.testsuites?.testsuite?.map((ts, i) => getSuiteSummary(ts, i)).join('\n')
const suitesSection = `## Test Suites\n\n${suites}`
return `${heading}\n${headingLine}\n${summary}\n${suitesSection}`
@ -65,7 +63,7 @@ function getSkippedCount(suites: TestSuites): number {
return suites.testsuite.reduce((sum, suite) => sum + suite.$.skipped, 0)
}
function getSuiteSummary(suite: TestSuite): string {
function getSuiteSummary(suite: TestSuite, index: number): string {
const success = !(suite.$?.failures > 0 || suite.$?.errors > 0)
const icon = success ? Icon.success : Icon.fail
@ -98,7 +96,10 @@ function getSuiteSummary(suite: TestSuite): string {
})
.join('\n')
return `### ${suite.$.name} ${icon}\n\n${content}`
const tsName = suite.$.name
const tsSlug = makeSuiteSlug(index, tsName)
const tsNameLink = `<a id="${tsSlug.id}" href="${tsSlug.link}">${tsName}</a>`
return `### ${tsNameLink} ${icon}\n\n${content}`
}
function getTestCaseIcon(test: TestCase): string {
@ -119,3 +120,8 @@ function getTestCaseDetails(test: TestCase): string {
return ''
}
function makeSuiteSlug(index: number, name: string): {id: string; link: string} {
// use "ts-$index-" as prefix to avoid slug conflicts after escaping the paths
return slug(`ts-${index}-${name}`)
}

14
src/utils/slugger.ts Normal file
View file

@ -0,0 +1,14 @@
// Returns HTML element id and href link usable as manual anchor links
// This is needed because Github in check run summary doesn't automatically
// create links out of headings as it normally does for other markdown content
export function slug(name: string): {id: string; link: string} {
const slugId = name
.trim()
.replace(/_/g, '')
.replace(/[./\\]/g, '-')
.replace(/[^\w-]/g, '')
const id = `user-content-${slugId}`
const link = `#${slugId}`
return {id, link}
}