Skip to content

Commit 7ea08dc

Browse files
author
ghosh-abhinaba
committed
fixed: cci junit report format
1 parent 8bd78dc commit 7ea08dc

File tree

6 files changed

+194
-8
lines changed

6 files changed

+194
-8
lines changed

package-lock.json

Lines changed: 40 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"test": "npm run test:unit && npm run test:integration",
2323
"test:unit": "jest test/unit --testEnvironment=node",
2424
"test:integration": "jest test/integration",
25+
"test:e2e": "jest test/e2e",
2526
"format": "npx prettier --write .",
2627
"prerelease": "npm run build",
2728
"release": "standard-version",
@@ -39,14 +40,16 @@
3940
"devDependencies": {
4041
"@types/jest": "^29.5.13",
4142
"@types/node": "^22.7.8",
43+
"@types/xml2js": "^0.4.14",
4244
"jest": "^29.7.0",
4345
"jest-each": "^29.7.0",
4446
"jest-playwright-preset": "^4.0.0",
4547
"playwright": "^1.48.1",
4648
"prettier": "^3.3.3",
4749
"standard-version": "^9.5.0",
4850
"ts-jest": "^29.2.5",
49-
"typescript": "^5.6.3"
51+
"typescript": "^5.6.3",
52+
"xml2js": "^0.6.2"
5053
},
5154
"dependencies": {
5255
"@types/junit-report-builder": "^3.0.2",

src/reporter/junitReporter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export default class JUnitReporter implements Reporter {
5858
const pass = violations.length === 0
5959

6060
if (pass) {
61-
builder.testCase().name('Accesibility testing - A11Y')
61+
suite.testCase().name('Accesibility testing - A11Y')
6262
this.verbose && console.log(`No accessibility violations detected!`)
6363
}
6464
let location = this.outputFilename || 'a11y-tests.xml'

test/e2e/a11y.spec.ts renamed to test/e2e/e2e.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { Browser, chromium, Page } from 'playwright'
22
import { injectAxe, checkA11y, getViolations } from '../../src'
3+
import * as fs from 'fs'
4+
import * as path from 'path'
35

46
let browser: Browser
57
let page: Page
@@ -37,7 +39,7 @@ describe('axe-playwright', () => {
3739
const labelViolations = violations.filter(v => v.id === 'label')
3840

3941
expect(labelViolations.length).toBe(1)
40-
expect(labelViolations[0].nodes.length).toBe(2) // username and password inputs
42+
expect(labelViolations[0].nodes.length).toBe(2)
4143
})
4244

4345
it('passes clean pages', async () => {

test/e2e/site.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
<!doctype html>
1+
<!DOCTYPE html>
22
<html>
33
<head>
44
<title>Login page</title>
55
</head>
66
<body>
77
<h1>Simple Login Page</h1>
88
<form name="login">
9-
<label>Username<input type="text" name="userid" /></label>
10-
<label>Password<input type="password" name="pswrd" /></label>
9+
Username<input type="text" name="userid" />
10+
Password<input type="password" name="pswrd" />
1111
<input type="button" onclick="check(this.form)" value="Login" />
1212
<input type="reset" value="Cancel" />
1313
</form>
1414
</body>
15-
</html>
15+
</html>

test/unit/junit.test.ts

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import JUnitReporter from '../../src/reporter/junitReporter'
2+
import { Result } from 'axe-core'
3+
import * as fs from 'fs'
4+
import * as path from 'path'
5+
6+
describe('JUnit Reporter XML Generation', () => {
7+
const testOutputDir = path.join(process.cwd(), 'test-output')
8+
const testXmlFile = path.join(testOutputDir, 'test-results.xml')
9+
10+
beforeEach(() => {
11+
// Clean up before each test
12+
if (fs.existsSync(testXmlFile)) {
13+
fs.unlinkSync(testXmlFile)
14+
}
15+
if (fs.existsSync(testOutputDir)) {
16+
fs.rmSync(testOutputDir, { recursive: true })
17+
}
18+
})
19+
20+
afterEach(() => {
21+
// Clean up after each test
22+
if (fs.existsSync(testXmlFile)) {
23+
fs.unlinkSync(testXmlFile)
24+
}
25+
if (fs.existsSync(testOutputDir)) {
26+
fs.rmSync(testOutputDir, { recursive: true })
27+
}
28+
})
29+
30+
it('generates valid XML when violations exist', async () => {
31+
const violations: Result[] = [
32+
{
33+
id: 'label',
34+
description: 'Form elements must have labels',
35+
help: 'Form elements must have labels',
36+
helpUrl: 'https://dequeuniversity.com/rules/axe/4.4/label',
37+
impact: 'critical',
38+
nodes: [
39+
{
40+
target: ['#username'],
41+
html: '<input type="text" name="username">',
42+
failureSummary: 'Fix any of the following:\n Element does not have a label'
43+
}
44+
]
45+
} as Result
46+
]
47+
48+
const reporter = new JUnitReporter(false, undefined, testXmlFile)
49+
50+
try {
51+
await reporter.report(violations)
52+
} catch (e) {
53+
// Expected to throw, but XML should still be generated
54+
}
55+
56+
// Check that XML file was created
57+
expect(fs.existsSync(testXmlFile)).toBe(true)
58+
59+
// Read and validate XML content
60+
const xmlContent = fs.readFileSync(testXmlFile, 'utf8')
61+
62+
// Basic XML structure checks
63+
expect(xmlContent).toContain('<?xml version="1.0" encoding="UTF-8"?>')
64+
expect(xmlContent).toContain('<testsuite')
65+
expect(xmlContent).toContain('<testcase')
66+
expect(xmlContent).toContain('</testsuite>')
67+
68+
// Violation-specific checks
69+
expect(xmlContent).toContain('label')
70+
expect(xmlContent).toContain('Form elements must have labels')
71+
expect(xmlContent).toContain('<failure')
72+
})
73+
74+
it('generates valid XML when no violations exist', async () => {
75+
const reporter = new JUnitReporter(false, undefined, testXmlFile)
76+
77+
await reporter.report([])
78+
79+
// Check that XML file was created
80+
expect(fs.existsSync(testXmlFile)).toBe(true)
81+
82+
// Read and validate XML content
83+
const xmlContent = fs.readFileSync(testXmlFile, 'utf8')
84+
85+
// Basic XML structure checks
86+
expect(xmlContent).toContain('<?xml version="1.0" encoding="UTF-8"?>')
87+
expect(xmlContent).toContain('<testsuite')
88+
expect(xmlContent).toContain('<testcase')
89+
expect(xmlContent).toContain('</testsuite>')
90+
91+
// Should contain the success test case
92+
expect(xmlContent).toContain('Accesibility testing - A11Y')
93+
94+
// Should NOT contain failure tags
95+
expect(xmlContent).not.toContain('<failure>')
96+
})
97+
98+
it('creates directory structure if missing', async () => {
99+
const deepPath = path.join(testOutputDir, 'nested', 'deeper', 'results.xml')
100+
const reporter = new JUnitReporter(false, undefined, deepPath)
101+
102+
await reporter.report([])
103+
104+
expect(fs.existsSync(deepPath)).toBe(true)
105+
})
106+
107+
it('validates XML structure with real XML parser', async () => {
108+
const violations: Result[] = [
109+
{
110+
id: 'color-contrast',
111+
description: 'Elements must have sufficient color contrast',
112+
help: 'Elements must have sufficient color contrast',
113+
nodes: [
114+
{
115+
target: ['.text'],
116+
html: '<span class="text">Low contrast text</span>',
117+
failureSummary: 'Element has insufficient color contrast'
118+
}
119+
]
120+
} as Result
121+
]
122+
123+
const reporter = new JUnitReporter(false, undefined, testXmlFile)
124+
125+
try {
126+
await reporter.report(violations)
127+
} catch (e) {
128+
// Expected to throw
129+
}
130+
131+
const xmlContent = fs.readFileSync(testXmlFile, 'utf8')
132+
133+
// Try to parse as XML (will throw if invalid)
134+
const parseXML = require('xml2js').parseString
135+
expect(() => {
136+
parseXML(xmlContent, (err: any, result: any) => {
137+
if (err) throw err
138+
expect(result).toBeDefined()
139+
})
140+
}).not.toThrow()
141+
})
142+
})

0 commit comments

Comments
 (0)