Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/cdk-experimental/radio/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ ts_project(
":radio",
"//:node_modules/@angular/core",
"//:node_modules/@angular/platform-browser",
"//:node_modules/axe-core",
"//src/cdk/testing/private",
],
)
Expand Down
75 changes: 1 addition & 74 deletions src/cdk-experimental/radio/radio.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,80 +3,7 @@ import {CdkRadioButton, CdkRadioGroup} from './radio';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {By} from '@angular/platform-browser';
import {BidiModule, Direction} from '@angular/cdk/bidi';
import {provideFakeDirectionality} from '@angular/cdk/testing/private';
import axe from 'axe-core';

// Basic ANSI color functions because chalk has issues with unit tests.
const colors = {
red: (text: string) => `\x1b[31m${text}\x1b[0m`,
yellow: (text: string) => `\x1b[33m${text}\x1b[0m`,
blue: (text: string) => `\x1b[34m${text}\x1b[0m`,
magenta: (text: string) => `\x1b[35m${text}\x1b[0m`,
cyan: (text: string) => `\x1b[36m${text}\x1b[0m`,
gray: (text: string) => `\x1b[90m${text}\x1b[0m`,
underline: (text: string) => `\x1b[4m${text}\x1b[0m`,
default: (text: string) => `\x1b[0m${text}\x1b[0m`,
};

// TODO: Move this to a separate folder/file so it can be reused across components.
async function runAccessibilityChecks(root: HTMLElement): Promise<void> {
const results = await axe.run(root);

if (!results.violations.length) {
return;
}

const reportLines: string[] = [];
const append = (text: string) => reportLines.push(colors.default(text));
append(colors.red(`Found ${results.violations.length} accessibility violation(s):`));

results.violations.forEach((violation, index) => {
append('');
append(colors.red(`Violation ${index + 1}: ${violation.id}\n`));

let impactText = violation.impact || 'unknown';
switch (violation.impact) {
case 'critical':
impactText = colors.red(impactText);
break;
case 'serious':
impactText = colors.yellow(impactText);
break;
case 'moderate':
impactText = colors.blue(impactText);
break;
case 'minor':
impactText = colors.gray(impactText);
break;
default:
impactText = colors.default(impactText);
break;
}

append(` Impact: ${impactText}`);
append(` Description: ${violation.description}`);
append(` Help: ${violation.help}`);
append(` Help URL: ${colors.underline(colors.blue(violation.helpUrl))}\n`);

if (violation.nodes && violation.nodes.length > 0) {
append(' Failing Elements:');
violation.nodes.forEach((node, nodeIndex) => {
append(colors.cyan(` Node ${nodeIndex + 1}:`));
if (node.target && node.target.length > 0) {
append(` Selector: ${colors.magenta(node.target.join(', '))}`);
}
if (node.failureSummary) {
append(' Failure Summary:');
node.failureSummary
.split('\n')
.forEach(line => append(colors.yellow(` ${line.trim()}`)));
}
});
}
});

fail(reportLines.join('\n'));
}
import {provideFakeDirectionality, runAccessibilityChecks} from '@angular/cdk/testing/private';

describe('CdkRadioGroup', () => {
let fixture: ComponentFixture<RadioGroupExample>;
Expand Down
1 change: 1 addition & 0 deletions src/cdk/testing/private/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ ts_project(
deps = [
"//:node_modules/@angular/core",
"//:node_modules/@types/jasmine",
"//:node_modules/axe-core",
"//src/cdk/bidi",
"//src/cdk/testing/testbed",
],
Expand Down
1 change: 1 addition & 0 deletions src/cdk/testing/private/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
export * from './fake-directionality';
export * from './text-dedent';
export * from './wrapped-error-message';
export * from './run-accessibility-checks';

// Re-exported for convenience.
export * from '../testbed/fake-events';
84 changes: 84 additions & 0 deletions src/cdk/testing/private/run-accessibility-checks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/

import axe from 'axe-core';

// Basic ANSI color functions because chalk has issues with unit tests.
const colors = {
red: (text: string) => `\x1b[31m${text}\x1b[0m`,
yellow: (text: string) => `\x1b[33m${text}\x1b[0m`,
blue: (text: string) => `\x1b[34m${text}\x1b[0m`,
magenta: (text: string) => `\x1b[35m${text}\x1b[0m`,
cyan: (text: string) => `\x1b[36m${text}\x1b[0m`,
gray: (text: string) => `\x1b[90m${text}\x1b[0m`,
underline: (text: string) => `\x1b[4m${text}\x1b[0m`,
default: (text: string) => `\x1b[0m${text}\x1b[0m`,
};

/**
* Runs accessibility checks on a specified HTML element using the axe-core library.
* @param root The root HTML element to check for accessibility violations.
*/
export async function runAccessibilityChecks(root: HTMLElement): Promise<void> {
const results = await axe.run(root);

if (!results.violations.length) {
return;
}

const reportLines: string[] = [];
const append = (text: string) => reportLines.push(colors.default(text));
append(colors.red(`Found ${results.violations.length} accessibility violation(s):`));

results.violations.forEach((violation, index) => {
append('');
append(colors.red(`Violation ${index + 1}: ${violation.id}\n`));

let impactText = violation.impact || 'unknown';
switch (violation.impact) {
case 'critical':
impactText = colors.red(impactText);
break;
case 'serious':
impactText = colors.yellow(impactText);
break;
case 'moderate':
impactText = colors.blue(impactText);
break;
case 'minor':
impactText = colors.gray(impactText);
break;
default:
impactText = colors.default(impactText);
break;
}

append(` Impact: ${impactText}`);
append(` Description: ${violation.description}`);
append(` Help: ${violation.help}`);
append(` Help URL: ${colors.underline(colors.blue(violation.helpUrl))}\n`);

if (violation.nodes && violation.nodes.length > 0) {
append(' Failing Elements:');
violation.nodes.forEach((node, nodeIndex) => {
append(colors.cyan(` Node ${nodeIndex + 1}:`));
if (node.target && node.target.length > 0) {
append(` Selector: ${colors.magenta(node.target.join(', '))}`);
}
if (node.failureSummary) {
append(' Failure Summary:');
node.failureSummary
.split('\n')
.forEach(line => append(colors.yellow(` ${line.trim()}`)));
}
});
}
});

fail(reportLines.join('\n'));
}
Loading