diff --git a/README.md b/README.md index bdced5c..bc28d53 100644 --- a/README.md +++ b/README.md @@ -162,6 +162,10 @@ jobs: # Allows you to generate reports for Actions Summary # https://github.blog/2022-05-09-supercharging-github-actions-with-job-summaries/ use-actions-summary: 'true' + + # Prefix used when generating report anchor slugs. + # Useful to avoid collisions when multiple reports are rendered together. + slug-prefix: '' # Optionally specify a title (Heading level 1) for the report. Leading and trailing whitespace are ignored. # This is useful for separating your test report from other sections in the build summary. diff --git a/__tests__/utils/slugger.test.ts b/__tests__/utils/slugger.test.ts new file mode 100644 index 0000000..e2ad534 --- /dev/null +++ b/__tests__/utils/slugger.test.ts @@ -0,0 +1,28 @@ +import {DEFAULT_OPTIONS} from '../../src/report/get-report.js' +import {slug} from '../../src/utils/slugger.js' + +describe('slugger', () => { + it('adds prefix from report options to generated slug', () => { + const result = slug('r0s1', { + ...DEFAULT_OPTIONS, + slugPrefix: 'prefix-' + }) + + expect(result).toEqual({ + id: 'user-content-prefix-r0s1', + link: '#user-content-prefix-r0s1' + }) + }) + + it('sanitizes custom prefix using existing slug normalization', () => { + const result = slug('r0', { + ...DEFAULT_OPTIONS, + slugPrefix: ' my /custom_prefix?.' + }) + + expect(result).toEqual({ + id: 'user-content-my-customprefix-r0', + link: '#user-content-my-customprefix-r0' + }) + }) +}) diff --git a/action.yml b/action.yml index 8dbc85c..f66ac45 100644 --- a/action.yml +++ b/action.yml @@ -88,6 +88,10 @@ inputs: https://github.com/orgs/github/teams/engineering/discussions/871 default: 'true' required: false + slug-prefix: + description: Prefix used when generating report anchor slugs + required: false + default: '' badge-title: description: Customize badge title required: false diff --git a/dist/index.js b/dist/index.js index 171caa3..f49930a 100644 --- a/dist/index.js +++ b/dist/index.js @@ -55869,7 +55869,7 @@ function getExceptionSource(stackTrace, trackedFiles, getRelativePath) { ;// CONCATENATED MODULE: ./lib/utils/slugger.js function slug(name, options) { - const slugId = name + const slugId = `${options.slugPrefix}${name}` .trim() .replace(/_/g, '') .replace(/[./\\]/g, '-') @@ -55891,6 +55891,7 @@ const MAX_ACTIONS_SUMMARY_LENGTH = 1048576; const DEFAULT_OPTIONS = { listSuites: 'all', listTests: 'all', + slugPrefix: '', baseUrl: '', onlySummary: false, useActionsSummary: true, @@ -57890,6 +57891,7 @@ class TestReporter { workDirInput = getInput('working-directory', { required: false }); onlySummary = getInput('only-summary', { required: false }) === 'true'; useActionsSummary = getInput('use-actions-summary', { required: false }) === 'true'; + slugPrefix = getInput('slug-prefix', { required: false }); badgeTitle = getInput('badge-title', { required: false }); reportTitle = getInput('report-title', { required: false }); collapsed = getInput('collapsed', { required: false }); @@ -57989,7 +57991,7 @@ class TestReporter { throw error; } } - const { listSuites, listTests, onlySummary, useActionsSummary, badgeTitle, reportTitle, collapsed } = this; + const { listSuites, listTests, slugPrefix, onlySummary, useActionsSummary, badgeTitle, reportTitle, collapsed } = this; 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); @@ -57999,6 +58001,7 @@ class TestReporter { const summary = getReport(results, { listSuites, listTests, + slugPrefix, baseUrl, onlySummary, useActionsSummary, @@ -58027,6 +58030,7 @@ class TestReporter { const summary = getReport(results, { listSuites, listTests, + slugPrefix, baseUrl, onlySummary, useActionsSummary, diff --git a/src/main.ts b/src/main.ts index 888fd73..ead81b3 100644 --- a/src/main.ts +++ b/src/main.ts @@ -49,6 +49,7 @@ class TestReporter { readonly workDirInput = core.getInput('working-directory', {required: false}) readonly onlySummary = core.getInput('only-summary', {required: false}) === 'true' readonly useActionsSummary = core.getInput('use-actions-summary', {required: false}) === 'true' + readonly slugPrefix = core.getInput('slug-prefix', {required: false}) readonly badgeTitle = core.getInput('badge-title', {required: false}) readonly reportTitle = core.getInput('report-title', {required: false}) readonly collapsed = core.getInput('collapsed', {required: false}) as 'auto' | 'always' | 'never' @@ -174,7 +175,7 @@ class TestReporter { } } - const {listSuites, listTests, onlySummary, useActionsSummary, badgeTitle, reportTitle, collapsed} = this + const {listSuites, listTests, slugPrefix, onlySummary, useActionsSummary, badgeTitle, reportTitle, collapsed} = this const passed = results.reduce((sum, tr) => sum + tr.passed, 0) const failed = results.reduce((sum, tr) => sum + tr.failed, 0) @@ -188,6 +189,7 @@ class TestReporter { { listSuites, listTests, + slugPrefix, baseUrl, onlySummary, useActionsSummary, @@ -219,6 +221,7 @@ class TestReporter { const summary = getReport(results, { listSuites, listTests, + slugPrefix, baseUrl, onlySummary, useActionsSummary, diff --git a/src/report/get-report.ts b/src/report/get-report.ts index 63617b0..325e28c 100644 --- a/src/report/get-report.ts +++ b/src/report/get-report.ts @@ -11,6 +11,7 @@ const MAX_ACTIONS_SUMMARY_LENGTH = 1048576 export interface ReportOptions { listSuites: 'all' | 'failed' | 'none' listTests: 'all' | 'failed' | 'none' + slugPrefix: string baseUrl: string onlySummary: boolean useActionsSummary: boolean @@ -22,6 +23,7 @@ export interface ReportOptions { export const DEFAULT_OPTIONS: ReportOptions = { listSuites: 'all', listTests: 'all', + slugPrefix: '', baseUrl: '', onlySummary: false, useActionsSummary: true, diff --git a/src/utils/slugger.ts b/src/utils/slugger.ts index 656a81b..f12b49e 100644 --- a/src/utils/slugger.ts +++ b/src/utils/slugger.ts @@ -4,7 +4,7 @@ import {ReportOptions} from '../report/get-report.js' export function slug(name: string, options: ReportOptions): {id: string; link: string} { - const slugId = name + const slugId = `${options.slugPrefix}${name}` .trim() .replace(/_/g, '') .replace(/[./\\]/g, '-')