From de77f76b7e05c7d618f81c52cefa9c1dc5c950b1 Mon Sep 17 00:00:00 2001 From: Jozef Izso Date: Wed, 5 Nov 2025 21:18:09 +0100 Subject: [PATCH 1/4] Fix badge image by correctly encoding the URI components --- src/report/get-report.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/report/get-report.ts b/src/report/get-report.ts index 5ea44fe..d2c2dfd 100644 --- a/src/report/get-report.ts +++ b/src/report/get-report.ts @@ -145,8 +145,10 @@ function getBadge(passed: number, failed: number, skipped: number, options: Repo color = 'yellow' } const hint = failed > 0 ? 'Tests failed' : 'Tests passed successfully' - const uri = encodeURIComponent(`${options.badgeTitle}-${message}-${color}`) - return `![${hint}](https://img.shields.io/badge/${uri})` + const encodedBadgeTitle = encodeImgShieldsURIComponent(options.badgeTitle) + const encodedMessage = encodeImgShieldsURIComponent(message) + const encodedColor = encodeImgShieldsURIComponent(color) + return `![${hint}](https://img.shields.io/badge/${encodedBadgeTitle}-${encodedMessage}-${encodedColor})` } function getTestRunsReport(testRuns: TestRunResult[], options: ReportOptions): string[] { @@ -305,3 +307,7 @@ function getResultIcon(result: TestExecutionResult): string { return '' } } + +function encodeImgShieldsURIComponent(component: string): string { + return encodeURIComponent(component).replace(/-/g, '--') +} From 6079ce3d17ccb1aef8e425af6b8c869fdefa646d Mon Sep 17 00:00:00 2001 From: Jozef Izso Date: Wed, 5 Nov 2025 21:19:18 +0100 Subject: [PATCH 2/4] Add unit tests for `getBadge()` function to ensure values are encoded for img.shields.io service --- __tests__/report/get-report.test.ts | 110 ++++++++++++++++++++++++++++ src/report/get-report.ts | 2 +- 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 __tests__/report/get-report.test.ts diff --git a/__tests__/report/get-report.test.ts b/__tests__/report/get-report.test.ts new file mode 100644 index 0000000..1925110 --- /dev/null +++ b/__tests__/report/get-report.test.ts @@ -0,0 +1,110 @@ +import {getBadge, DEFAULT_OPTIONS, ReportOptions} from '../../src/report/get-report' + +describe('getBadge', () => { + describe('URI encoding with special characters', () => { + it('generates correct URI with simple badge title', () => { + const options: ReportOptions = { + ...DEFAULT_OPTIONS, + badgeTitle: 'tests' + } + const badge = getBadge(5, 0, 1, options) + expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/tests-5%20passed%2C%201%20skipped-success)') + }) + + it('handles badge title with single hyphen', () => { + const options: ReportOptions = { + ...DEFAULT_OPTIONS, + badgeTitle: 'unit-tests' + } + const badge = getBadge(3, 0, 0, options) + // The hyphen in the badge title should be encoded as -- + expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/unit--tests-3%20passed-success)') + }) + + it('handles badge title with multiple hyphens', () => { + const options: ReportOptions = { + ...DEFAULT_OPTIONS, + badgeTitle: 'integration-api-tests' + } + const badge = getBadge(10, 0, 0, options) + // All hyphens in the title should be encoded as -- + expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/integration--api--tests-10%20passed-success)') + }) + + it('handles badge title with version format containing hyphen', () => { + const options: ReportOptions = { + ...DEFAULT_OPTIONS, + badgeTitle: 'MariaDb 12.0-ubi database tests' + } + const badge = getBadge(1, 0, 0, options) + // The hyphen in "12.0-ubi" should be encoded as -- + expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/MariaDb%2012.0--ubi%20database%20tests-1%20passed-success)') + }) + + it('handles badge title with dots and hyphens', () => { + const options: ReportOptions = { + ...DEFAULT_OPTIONS, + badgeTitle: 'v1.2.3-beta-test' + } + const badge = getBadge(4, 1, 0, options) + expect(badge).toBe('![Tests failed](https://img.shields.io/badge/v1.2.3--beta--test-4%20passed%2C%201%20failed-critical)') + }) + + it('preserves structural hyphens between label and message', () => { + const options: ReportOptions = { + ...DEFAULT_OPTIONS, + badgeTitle: 'test-suite' + } + const badge = getBadge(2, 3, 1, options) + // The URI should have literal hyphens separating title-message-color + expect(badge).toBe('![Tests failed](https://img.shields.io/badge/test--suite-2%20passed%2C%203%20failed%2C%201%20skipped-critical)') + }) + }) + + describe('generates test outcome as color name for imgshields', () => { + it('uses success color when all tests pass', () => { + const options: ReportOptions = {...DEFAULT_OPTIONS} + const badge = getBadge(5, 0, 0, options) + expect(badge).toContain('-success)') + }) + + it('uses critical color when tests fail', () => { + const options: ReportOptions = {...DEFAULT_OPTIONS} + const badge = getBadge(5, 2, 0, options) + expect(badge).toContain('-critical)') + }) + + it('uses yellow color when no tests found', () => { + const options: ReportOptions = {...DEFAULT_OPTIONS} + const badge = getBadge(0, 0, 0, options) + expect(badge).toContain('-yellow)') + }) + }) + + describe('badge message composition', () => { + it('includes only passed count when no failures or skips', () => { + const options: ReportOptions = {...DEFAULT_OPTIONS} + const badge = getBadge(5, 0, 0, options) + expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/tests-5%20passed-success)') + }) + + it('includes passed and failed counts', () => { + const options: ReportOptions = {...DEFAULT_OPTIONS} + const badge = getBadge(5, 2, 0, options) + expect(badge).toBe('![Tests failed](https://img.shields.io/badge/tests-5%20passed%2C%202%20failed-critical)') + }) + + it('includes passed, failed and skipped counts', () => { + const options: ReportOptions = {...DEFAULT_OPTIONS} + const badge = getBadge(5, 2, 1, options) + expect(badge).toBe('![Tests failed](https://img.shields.io/badge/tests-5%20passed%2C%202%20failed%2C%201%20skipped-critical)') + }) + + it('uses "none" message when no tests', () => { + const options: ReportOptions = {...DEFAULT_OPTIONS} + const badge = getBadge(0, 0, 0, options) + expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/tests-none-yellow)') + }) + }) +}) + diff --git a/src/report/get-report.ts b/src/report/get-report.ts index d2c2dfd..bbf8aca 100644 --- a/src/report/get-report.ts +++ b/src/report/get-report.ts @@ -125,7 +125,7 @@ function getReportBadge(results: TestRunResult[], options: ReportOptions): strin return getBadge(passed, failed, skipped, options) } -function getBadge(passed: number, failed: number, skipped: number, options: ReportOptions): string { +export function getBadge(passed: number, failed: number, skipped: number, options: ReportOptions): string { const text = [] if (passed > 0) { text.push(`${passed} passed`) From bed521d765c89ebb463b878b41ac697ad833491f Mon Sep 17 00:00:00 2001 From: Jozef Izso Date: Wed, 5 Nov 2025 21:20:23 +0100 Subject: [PATCH 3/4] Fix badge encoding for values including the `_` underscore character --- __tests__/report/get-report.test.ts | 10 ++++++++++ src/report/get-report.ts | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/__tests__/report/get-report.test.ts b/__tests__/report/get-report.test.ts index 1925110..670b0ad 100644 --- a/__tests__/report/get-report.test.ts +++ b/__tests__/report/get-report.test.ts @@ -31,6 +31,16 @@ describe('getBadge', () => { expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/integration--api--tests-10%20passed-success)') }) + it('handles badge title with multiple underscores', () => { + const options: ReportOptions = { + ...DEFAULT_OPTIONS, + badgeTitle: 'my_integration_test' + } + const badge = getBadge(10, 0, 0, options) + // All underscores in the title should be encoded as __ + expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/my__integration__test-10%20passed-success)') + }) + it('handles badge title with version format containing hyphen', () => { const options: ReportOptions = { ...DEFAULT_OPTIONS, diff --git a/src/report/get-report.ts b/src/report/get-report.ts index bbf8aca..5168b7a 100644 --- a/src/report/get-report.ts +++ b/src/report/get-report.ts @@ -309,5 +309,5 @@ function getResultIcon(result: TestExecutionResult): string { } function encodeImgShieldsURIComponent(component: string): string { - return encodeURIComponent(component).replace(/-/g, '--') + return encodeURIComponent(component).replace(/-/g, '--').replace(/_/g, '__') } From 22dc7b52f476dd68d1290212d31ef5748d278b85 Mon Sep 17 00:00:00 2001 From: Jozef Izso Date: Wed, 5 Nov 2025 21:25:14 +0100 Subject: [PATCH 4/4] Rebuild `dist/` code --- dist/index.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index 10200e5..d5914fe 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1909,6 +1909,7 @@ var __importStar = (this && this.__importStar) || (function () { Object.defineProperty(exports, "__esModule", ({ value: true })); exports.DEFAULT_OPTIONS = void 0; exports.getReport = getReport; +exports.getBadge = getBadge; const core = __importStar(__nccwpck_require__(7484)); const markdown_utils_1 = __nccwpck_require__(5129); const node_utils_1 = __nccwpck_require__(5384); @@ -2022,8 +2023,10 @@ function getBadge(passed, failed, skipped, options) { color = 'yellow'; } const hint = failed > 0 ? 'Tests failed' : 'Tests passed successfully'; - const uri = encodeURIComponent(`${options.badgeTitle}-${message}-${color}`); - return `![${hint}](https://img.shields.io/badge/${uri})`; + const encodedBadgeTitle = encodeImgShieldsURIComponent(options.badgeTitle); + const encodedMessage = encodeImgShieldsURIComponent(message); + const encodedColor = encodeImgShieldsURIComponent(color); + return `![${hint}](https://img.shields.io/badge/${encodedBadgeTitle}-${encodedMessage}-${encodedColor})`; } function getTestRunsReport(testRuns, options) { const sections = []; @@ -2153,6 +2156,9 @@ function getResultIcon(result) { return ''; } } +function encodeImgShieldsURIComponent(component) { + return encodeURIComponent(component).replace(/-/g, '--').replace(/_/g, '__'); +} /***/ }),