Merge pull request #672 from dorny/bugfix/671-allow_hyphens_in_badge_image_names
Some checks failed
Check dist/ / check-dist (push) Has been cancelled
CI / Build & Test (push) Has been cancelled

This commit is contained in:
Jozef Izso 2025-11-10 17:14:53 +01:00 committed by GitHub
commit 4a41472ca4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 137 additions and 5 deletions

View file

@ -0,0 +1,120 @@
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 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,
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)')
})
})
})

10
dist/index.js generated vendored
View file

@ -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, '__');
}
/***/ }),

View file

@ -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`)
@ -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, '--').replace(/_/g, '__')
}