Skip to content

Commit d1b4ce0

Browse files
committed
fixup! feat(cdk-experimental/radio): create radio group and button directives
1 parent 39a8707 commit d1b4ce0

File tree

4 files changed

+107
-7
lines changed

4 files changed

+107
-7
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
"@types/shelljs": "^0.8.11",
105105
"@types/yargs": "^17.0.8",
106106
"autoprefixer": "^10.4.2",
107+
"axe-core": "^4.10.3",
107108
"chalk": "^4.1.0",
108109
"dgeni": "^0.4.14",
109110
"dgeni-packages": "^0.29.5",

pnpm-lock.yaml

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

src/cdk-experimental/radio/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ ts_project(
2727
":radio",
2828
"//:node_modules/@angular/core",
2929
"//:node_modules/@angular/platform-browser",
30+
"//:node_modules/axe-core",
3031
],
3132
)
3233

src/cdk-experimental/radio/radio.spec.ts

Lines changed: 96 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,79 @@ import {CdkRadioButton, CdkRadioGroup} from './radio';
33
import {ComponentFixture, TestBed} from '@angular/core/testing';
44
import {By} from '@angular/platform-browser';
55
import {BidiModule, Direction, Directionality} from '@angular/cdk/bidi';
6+
import axe from 'axe-core';
7+
8+
// Basic ANSI color functions because chalk has issues with unit tests.
9+
const colors = {
10+
red: (text: string) => `\x1b[31m${text}\x1b[0m`,
11+
yellow: (text: string) => `\x1b[33m${text}\x1b[0m`,
12+
blue: (text: string) => `\x1b[34m${text}\x1b[0m`,
13+
magenta: (text: string) => `\x1b[35m${text}\x1b[0m`,
14+
cyan: (text: string) => `\x1b[36m${text}\x1b[0m`,
15+
gray: (text: string) => `\x1b[90m${text}\x1b[0m`,
16+
underline: (text: string) => `\x1b[4m${text}\x1b[0m`,
17+
default: (text: string) => `\x1b[0m${text}\x1b[0m`,
18+
};
19+
20+
// TODO: Move this to a separate folder/file so it can be reused across components.
21+
async function getAccessibilityViolationsReport(root: HTMLElement): Promise<string | null> {
22+
const results = await axe.run(root);
23+
24+
if (!results.violations.length) {
25+
return null;
26+
}
27+
28+
const reportLines: string[] = [];
29+
const append = (text: string) => reportLines.push(colors.default(text));
30+
append(colors.red(`Found ${results.violations.length} accessibility violation(s):`));
31+
32+
results.violations.forEach((violation, index) => {
33+
append('');
34+
append(colors.red(`Violation ${index + 1}: ${violation.id}\n`));
35+
36+
let impactText = violation.impact || 'unknown';
37+
switch (violation.impact) {
38+
case 'critical':
39+
impactText = colors.red(impactText);
40+
break;
41+
case 'serious':
42+
impactText = colors.yellow(impactText);
43+
break;
44+
case 'moderate':
45+
impactText = colors.blue(impactText);
46+
break;
47+
case 'minor':
48+
impactText = colors.gray(impactText);
49+
break;
50+
default:
51+
impactText = colors.default(impactText);
52+
break;
53+
}
54+
55+
append(` Impact: ${impactText}`);
56+
append(` Description: ${violation.description}`);
57+
append(` Help: ${violation.help}`);
58+
append(` Help URL: ${colors.underline(colors.blue(violation.helpUrl))}\n`);
59+
60+
if (violation.nodes && violation.nodes.length > 0) {
61+
append(' Failing Elements:');
62+
violation.nodes.forEach((node, nodeIndex) => {
63+
append(colors.cyan(` Node ${nodeIndex + 1}:`));
64+
if (node.target && node.target.length > 0) {
65+
append(` Selector: ${colors.magenta(node.target.join(', '))}`);
66+
}
67+
if (node.failureSummary) {
68+
append(' Failure Summary:');
69+
node.failureSummary
70+
.split('\n')
71+
.forEach(line => append(colors.yellow(` ${line.trim()}`)));
72+
}
73+
});
74+
}
75+
});
76+
77+
return reportLines.join('\n');
78+
}
679

780
describe('CdkRadioGroup', () => {
881
let fixture: ComponentFixture<RadioGroupExample>;
@@ -46,14 +119,16 @@ describe('CdkRadioGroup', () => {
46119

47120
const fixture = TestBed.createComponent<T>(component);
48121
fixture.detectChanges();
122+
defineTestVariables(fixture);
123+
return fixture;
124+
}
49125

126+
function defineTestVariables(fixture: ComponentFixture<unknown>) {
50127
radioGroup = fixture.debugElement.query(By.directive(CdkRadioGroup));
51-
radioButtons = radioGroup.queryAll(By.directive(CdkRadioButton));
128+
radioButtons = fixture.debugElement.queryAll(By.directive(CdkRadioButton));
52129
radioGroupInstance = radioGroup.injector.get<CdkRadioGroup<number>>(CdkRadioGroup);
53130
radioGroupElement = radioGroup.nativeElement;
54131
radioButtonElements = radioButtons.map(radioButton => radioButton.nativeElement);
55-
56-
return fixture;
57132
}
58133

59134
function setupRadioGroup(opts?: {
@@ -99,8 +174,17 @@ describe('CdkRadioGroup', () => {
99174
textDirection.emit(opts.textDirection);
100175
}
101176
fixture.detectChanges();
177+
defineTestVariables(fixture); // Ensure env vars are up-to-date with the dom.
102178
}
103179

180+
afterEach(async () => {
181+
const report = await getAccessibilityViolationsReport(radioGroupElement);
182+
183+
if (report) {
184+
fail(report);
185+
}
186+
});
187+
104188
describe('ARIA attributes and roles', () => {
105189
describe('default configuration', () => {
106190
beforeEach(() => {
@@ -490,10 +574,15 @@ describe('CdkRadioGroup', () => {
490574
return radioGroupElement.getAttribute('aria-activedescendant') === radioButtonElements[i].id;
491575
});
492576

493-
it('should handle an empty set of radio buttons gracefully', () => {
494-
setupRadioGroup({options: []});
495-
radioButtons = fixture.debugElement.queryAll(By.directive(CdkRadioButton));
496-
expect(radioButtons.length).toBe(0);
577+
describe('failure cases', () => {
578+
beforeEach(() => {
579+
fixture = setupTestEnvironment(RadioGroupExample);
580+
});
581+
582+
it('should handle an empty set of radio buttons gracefully', () => {
583+
setupRadioGroup({options: []});
584+
expect(radioButtons.length).toBe(0);
585+
});
497586
});
498587
});
499588

0 commit comments

Comments
 (0)