-
Notifications
You must be signed in to change notification settings - Fork 6.8k
chore: run a11y audits on protractor #2010
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
19536c1
3c30766
6af517b
f3e70f7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,20 @@ | ||
<a md-list-item [routerLink]="['button']">Button</a> | ||
<a md-list-item [routerLink]="['checkbox']">Checkbox</a> | ||
<a md-list-item [routerLink]="['dialog']">Dialog</a> | ||
<a md-list-item [routerLink]="['grid-list']">Grid list</a> | ||
<a md-list-item [routerLink]="['icon']">Icon</a> | ||
<a md-list-item [routerLink]="['list']">List</a> | ||
<a md-list-item [routerLink]="['menu']">Menu</a> | ||
<a md-list-item [routerLink]="['progress-bar']">Progress bar</a> | ||
<a md-list-item [routerLink]="['progress-circle']">Progress circle</a> | ||
<a md-list-item [routerLink]="['radio']">Radios</a> | ||
<a md-list-item [routerLink]="['slide-toggle']">Slide Toggle</a> | ||
<a md-list-item [routerLink]="['tabs']">Tabs</a> | ||
<button (click)="showLinks = !showLinks">Toggle Navigation Links</button> | ||
|
||
<router-outlet></router-outlet> | ||
<md-nav-list *ngIf="showLinks"> | ||
<a md-list-item [routerLink]="['button']">Button</a> | ||
<a md-list-item [routerLink]="['checkbox']">Checkbox</a> | ||
<a md-list-item [routerLink]="['dialog']">Dialog</a> | ||
<a md-list-item [routerLink]="['grid-list']">Grid list</a> | ||
<a md-list-item [routerLink]="['icon']">Icon</a> | ||
<a md-list-item [routerLink]="['list']">List</a> | ||
<a md-list-item [routerLink]="['menu']">Menu</a> | ||
<a md-list-item [routerLink]="['progress-bar']">Progress bar</a> | ||
<a md-list-item [routerLink]="['progress-circle']">Progress circle</a> | ||
<a md-list-item [routerLink]="['radio']">Radios</a> | ||
<a md-list-item [routerLink]="['slide-toggle']">Slide Toggle</a> | ||
<a md-list-item [routerLink]="['tabs']">Tabs</a> | ||
</md-nav-list> | ||
|
||
<main> | ||
<router-outlet role="main"></router-outlet> | ||
</main> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,12 @@ | ||
<section> | ||
<md-radio-group [disabled]="isGroupDisabled" | ||
[(value)]="groupValue" | ||
id="test-group"> | ||
id="test-group" aria-label="Select a Pokemon"> | ||
|
||
<md-radio-button value="fire" id="fire">Charmander</md-radio-button> | ||
<md-radio-button value="water" id="water">Squirtle</md-radio-button> | ||
<md-radio-button value="leaf" id="leaf">Bulbasaur</md-radio-button> | ||
|
||
</md-radio-group> | ||
<button (click)="isGroupDisabled=!isGroupDisabled" id="toggle-disable">Disable/enable group</button> | ||
</section> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
'use strict'; | ||
|
||
/** | ||
* Protractor Plugin to run axe-core accessibility audits after Angular bootstrapped. | ||
*/ | ||
|
||
const AxeBuilder = require('axe-webdriverjs'); | ||
const {buildMessage} = require('./build-message'); | ||
|
||
/* List of pages which were already checked by axe-core and shouldn't run again */ | ||
const checkedPages = []; | ||
|
||
/** | ||
* Protractor plugin hook which always runs when Angular successfully bootstrapped. | ||
*/ | ||
function onPageStable() { | ||
AxeBuilder(browser.driver) | ||
.configure(this.config || {}) | ||
.analyze(results => handleResults(this, results)); | ||
} | ||
|
||
/** | ||
* Processes the axe-core results by reporting recognized violations | ||
* to Protractor and printing them out. | ||
* @param {!protractor.ProtractorPlugin} context | ||
* @param {!axe.AxeResults} results | ||
*/ | ||
function handleResults(context, results) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
if (checkedPages.indexOf(results.url) === -1) { | ||
|
||
checkedPages.push(results.url); | ||
|
||
results.violations.forEach(violation => { | ||
|
||
let specName = `${violation.help} (${results.url})`; | ||
let message = '\n' + buildMessage(violation); | ||
|
||
context.addFailure(message, {specName}); | ||
|
||
}); | ||
|
||
} | ||
|
||
} | ||
|
||
exports.name = 'protractor-axe'; | ||
exports.onPageStable = onPageStable; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/** | ||
* Builds a simple message of the violation results of axe-core by listing | ||
* each violation and the associated element selector in a new line. | ||
* @param {!axe.Violation} violation | ||
*/ | ||
exports.buildMessage = violation => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add description for what this does. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
|
||
let selectors = violation.nodes.map(node => { | ||
return node.target.join(' '); | ||
}); | ||
|
||
return selectors.reduce((content, selector) => { | ||
return content + '- ' + selector + '\n'; | ||
}, ''); | ||
|
||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At which point in the e2e test does axe run?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a short comment for it.
It basically means that the A11y check runs each time the e2e app changes its page.
Unfortunately we are not that flexible here, because the Protractor API does not provide much hooks (See https://github.com/angular/protractor/blob/master/docs/plugins.md)