Skip to content

Commit 4a41472

Browse files
authored
Merge pull request #672 from dorny/bugfix/671-allow_hyphens_in_badge_image_names
2 parents c883ae9 + 22dc7b5 commit 4a41472

3 files changed

Lines changed: 137 additions & 5 deletions

File tree

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import {getBadge, DEFAULT_OPTIONS, ReportOptions} from '../../src/report/get-report'
2+
3+
describe('getBadge', () => {
4+
describe('URI encoding with special characters', () => {
5+
it('generates correct URI with simple badge title', () => {
6+
const options: ReportOptions = {
7+
...DEFAULT_OPTIONS,
8+
badgeTitle: 'tests'
9+
}
10+
const badge = getBadge(5, 0, 1, options)
11+
expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/tests-5%20passed%2C%201%20skipped-success)')
12+
})
13+
14+
it('handles badge title with single hyphen', () => {
15+
const options: ReportOptions = {
16+
...DEFAULT_OPTIONS,
17+
badgeTitle: 'unit-tests'
18+
}
19+
const badge = getBadge(3, 0, 0, options)
20+
// The hyphen in the badge title should be encoded as --
21+
expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/unit--tests-3%20passed-success)')
22+
})
23+
24+
it('handles badge title with multiple hyphens', () => {
25+
const options: ReportOptions = {
26+
...DEFAULT_OPTIONS,
27+
badgeTitle: 'integration-api-tests'
28+
}
29+
const badge = getBadge(10, 0, 0, options)
30+
// All hyphens in the title should be encoded as --
31+
expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/integration--api--tests-10%20passed-success)')
32+
})
33+
34+
it('handles badge title with multiple underscores', () => {
35+
const options: ReportOptions = {
36+
...DEFAULT_OPTIONS,
37+
badgeTitle: 'my_integration_test'
38+
}
39+
const badge = getBadge(10, 0, 0, options)
40+
// All underscores in the title should be encoded as __
41+
expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/my__integration__test-10%20passed-success)')
42+
})
43+
44+
it('handles badge title with version format containing hyphen', () => {
45+
const options: ReportOptions = {
46+
...DEFAULT_OPTIONS,
47+
badgeTitle: 'MariaDb 12.0-ubi database tests'
48+
}
49+
const badge = getBadge(1, 0, 0, options)
50+
// The hyphen in "12.0-ubi" should be encoded as --
51+
expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/MariaDb%2012.0--ubi%20database%20tests-1%20passed-success)')
52+
})
53+
54+
it('handles badge title with dots and hyphens', () => {
55+
const options: ReportOptions = {
56+
...DEFAULT_OPTIONS,
57+
badgeTitle: 'v1.2.3-beta-test'
58+
}
59+
const badge = getBadge(4, 1, 0, options)
60+
expect(badge).toBe('![Tests failed](https://img.shields.io/badge/v1.2.3--beta--test-4%20passed%2C%201%20failed-critical)')
61+
})
62+
63+
it('preserves structural hyphens between label and message', () => {
64+
const options: ReportOptions = {
65+
...DEFAULT_OPTIONS,
66+
badgeTitle: 'test-suite'
67+
}
68+
const badge = getBadge(2, 3, 1, options)
69+
// The URI should have literal hyphens separating title-message-color
70+
expect(badge).toBe('![Tests failed](https://img.shields.io/badge/test--suite-2%20passed%2C%203%20failed%2C%201%20skipped-critical)')
71+
})
72+
})
73+
74+
describe('generates test outcome as color name for imgshields', () => {
75+
it('uses success color when all tests pass', () => {
76+
const options: ReportOptions = {...DEFAULT_OPTIONS}
77+
const badge = getBadge(5, 0, 0, options)
78+
expect(badge).toContain('-success)')
79+
})
80+
81+
it('uses critical color when tests fail', () => {
82+
const options: ReportOptions = {...DEFAULT_OPTIONS}
83+
const badge = getBadge(5, 2, 0, options)
84+
expect(badge).toContain('-critical)')
85+
})
86+
87+
it('uses yellow color when no tests found', () => {
88+
const options: ReportOptions = {...DEFAULT_OPTIONS}
89+
const badge = getBadge(0, 0, 0, options)
90+
expect(badge).toContain('-yellow)')
91+
})
92+
})
93+
94+
describe('badge message composition', () => {
95+
it('includes only passed count when no failures or skips', () => {
96+
const options: ReportOptions = {...DEFAULT_OPTIONS}
97+
const badge = getBadge(5, 0, 0, options)
98+
expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/tests-5%20passed-success)')
99+
})
100+
101+
it('includes passed and failed counts', () => {
102+
const options: ReportOptions = {...DEFAULT_OPTIONS}
103+
const badge = getBadge(5, 2, 0, options)
104+
expect(badge).toBe('![Tests failed](https://img.shields.io/badge/tests-5%20passed%2C%202%20failed-critical)')
105+
})
106+
107+
it('includes passed, failed and skipped counts', () => {
108+
const options: ReportOptions = {...DEFAULT_OPTIONS}
109+
const badge = getBadge(5, 2, 1, options)
110+
expect(badge).toBe('![Tests failed](https://img.shields.io/badge/tests-5%20passed%2C%202%20failed%2C%201%20skipped-critical)')
111+
})
112+
113+
it('uses "none" message when no tests', () => {
114+
const options: ReportOptions = {...DEFAULT_OPTIONS}
115+
const badge = getBadge(0, 0, 0, options)
116+
expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/tests-none-yellow)')
117+
})
118+
})
119+
})
120+

dist/index.js

Lines changed: 8 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/report/get-report.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ function getReportBadge(results: TestRunResult[], options: ReportOptions): strin
125125
return getBadge(passed, failed, skipped, options)
126126
}
127127

128-
function getBadge(passed: number, failed: number, skipped: number, options: ReportOptions): string {
128+
export function getBadge(passed: number, failed: number, skipped: number, options: ReportOptions): string {
129129
const text = []
130130
if (passed > 0) {
131131
text.push(`${passed} passed`)
@@ -145,8 +145,10 @@ function getBadge(passed: number, failed: number, skipped: number, options: Repo
145145
color = 'yellow'
146146
}
147147
const hint = failed > 0 ? 'Tests failed' : 'Tests passed successfully'
148-
const uri = encodeURIComponent(`${options.badgeTitle}-${message}-${color}`)
149-
return `![${hint}](https://img.shields.io/badge/${uri})`
148+
const encodedBadgeTitle = encodeImgShieldsURIComponent(options.badgeTitle)
149+
const encodedMessage = encodeImgShieldsURIComponent(message)
150+
const encodedColor = encodeImgShieldsURIComponent(color)
151+
return `![${hint}](https://img.shields.io/badge/${encodedBadgeTitle}-${encodedMessage}-${encodedColor})`
150152
}
151153

152154
function getTestRunsReport(testRuns: TestRunResult[], options: ReportOptions): string[] {
@@ -305,3 +307,7 @@ function getResultIcon(result: TestExecutionResult): string {
305307
return ''
306308
}
307309
}
310+
311+
function encodeImgShieldsURIComponent(component: string): string {
312+
return encodeURIComponent(component).replace(/-/g, '--').replace(/_/g, '__')
313+
}

0 commit comments

Comments
 (0)