Skip to content

Commit

Permalink
Merge branch 'develop' into async-perf-timer
Browse files Browse the repository at this point in the history
  • Loading branch information
WilcoFiers authored Oct 28, 2024
2 parents d769ba8 + 61dd5e3 commit f587dcc
Show file tree
Hide file tree
Showing 31 changed files with 444 additions and 142 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

### [4.10.1](https://github.com/dequelabs/axe-core/compare/v4.10.0...v4.10.1) (2024-10-16)

### Bug Fixes

- **aria-allowed-role:** add form to allowed roles of form element ([#4588](https://github.com/dequelabs/axe-core/issues/4588)) ([d462d67](https://github.com/dequelabs/axe-core/commit/d462d674bb7de0848ce2695f80b95d677c5016e0)), closes [/github.com/dequelabs/axe-core/blob/develop/lib/standards/html-elms.js#L264](https://github.com/dequelabs//github.com/dequelabs/axe-core/blob/develop/lib/standards/html-elms.js/issues/L264)
- **axe.d.ts:** add typings for preload options object ([#4543](https://github.com/dequelabs/axe-core/issues/4543)) ([72e269f](https://github.com/dequelabs/axe-core/commit/72e269f1e6d6039e70e614005f04ebfd3fe5aca5))
- **button-name,input-button-name,input-img-alt:** allow label to give accessible name ([#4607](https://github.com/dequelabs/axe-core/issues/4607)) ([364eb72](https://github.com/dequelabs/axe-core/commit/364eb72bb8f20b0ffc31be24cc96cbd349c301cb)), closes [#4472](https://github.com/dequelabs/axe-core/issues/4472) [#3696](https://github.com/dequelabs/axe-core/issues/3696) [#3696](https://github.com/dequelabs/axe-core/issues/3696)
- **get-ancestry:** add nth-child selector for multiple siblings of shadow root ([#4606](https://github.com/dequelabs/axe-core/issues/4606)) ([bdd94a2](https://github.com/dequelabs/axe-core/commit/bdd94a227a95cd5b9f8e2a1e0fd259ddd702810c)), closes [#4563](https://github.com/dequelabs/axe-core/issues/4563)
- **rules:** Change "alternate text" to "alternative text" ([#4582](https://github.com/dequelabs/axe-core/issues/4582)) ([31e0f61](https://github.com/dequelabs/axe-core/commit/31e0f61ca871b3df86468577c449a02c8ece12f0))

## [4.10.0](https://github.com/dequelabs/axe-core/compare/v4.9.1...v4.10.0) (2024-07-29)

### Features
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# axe-core

[![License](https://img.shields.io/npm/l/axe-core.svg)](LICENSE)
[![License](https://img.shields.io/npm/l/axe-core.svg?color=c41)](LICENSE)
[![Version](https://img.shields.io/npm/v/axe-core.svg)](https://www.npmjs.com/package/axe-core)
[![Total npm downloads](https://img.shields.io/npm/dt/axe-core.svg)](https://www.npmjs.com/package/axe-core)
[![NPM downloads](https://img.shields.io/npm/dw/axe-core.svg?color=080)![](https://img.shields.io/npm/dy/axe-core.svg?color=080&label=)](https://npm-stat.com/charts.html?package=axe-core&from=2017-01-01)
[![Commits](https://img.shields.io/github/commit-activity/y/dequelabs/axe-core.svg)](https://github.com/dequelabs/axe-core/commits/develop)
[![GitHub contributors](https://img.shields.io/github/contributors/dequelabs/axe-core.svg)](https://github.com/dequelabs/axe-core/graphs/contributors)
[![GitHub contributors](https://img.shields.io/github/contributors/dequelabs/axe-core.svg?color=080)](https://github.com/dequelabs/axe-core/graphs/contributors)
[![Join our Slack chat](https://img.shields.io/badge/slack-chat-purple.svg?logo=slack)](https://accessibility.deque.com/axe-community)
[![Package Quality](https://npm.packagequality.com/shield/axe-core.svg)](https://packagequality.com/#?package=axe-core)

Expand Down
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "axe-core",
"version": "4.10.0",
"version": "4.10.1",
"deprecated": true,
"contributors": [
{
Expand Down
2 changes: 1 addition & 1 deletion doc/accessibility-supported.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ In order to adhere to the manifesto and at the same time be useful to developers

Accessibility supported means that in order for a technique to pass, it must work in some predefined set of browsers and assistive technologies. For axe-core this means that for a screen reader, browser, or environment to be added to the list of supported combinations, the following two criteria must be met:

1. Be used by more than 1% of users (currently extrapolated from the [WebAims Screen Reader User Survey](https://webaim.org/projects/screenreadersurvey8/#browsercombos))
1. Be used by more than 1% of users (currently extrapolated from the [WebAims Screen Reader User Survey](https://webaim.org/projects/screenreadersurvey10/#browsercombos))
1. Introduce new coverage for a screen reader, browser, or environment not currently accessibility supported

We currently test the following AT combinations for support
Expand Down
4 changes: 2 additions & 2 deletions lib/checks/label/explicit.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"metadata": {
"impact": "critical",
"messages": {
"pass": "Form element has an explicit <label>",
"fail": "Form element does not have an explicit <label>",
"pass": "Element has an explicit <label>",
"fail": "Element does not have an explicit <label>",
"incomplete": "Unable to determine if form element has an explicit <label>"
}
}
Expand Down
4 changes: 2 additions & 2 deletions lib/checks/label/implicit.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"metadata": {
"impact": "critical",
"messages": {
"pass": "Form element has an implicit (wrapped) <label>",
"fail": "Form element does not have an implicit (wrapped) <label>",
"pass": "Element has an implicit (wrapped) <label>",
"fail": "Element does not have an implicit (wrapped) <label>",
"incomplete": "Unable to determine if form element has an implicit (wrapped) <label>"
}
}
Expand Down
5 changes: 2 additions & 3 deletions lib/commons/text/native-text-methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@ const nativeTextMethods = {
* @param {VirtualNode} element
* @return {String} value text
*/
valueText: ({ actualNode }) => actualNode.value || '',
valueText: vNode => vNode.props.value || '',

/**
* Return default value of a button
* @param {VirtualNode} element
* @return {String} default button text
*/
buttonDefaultText: ({ actualNode }) =>
defaultButtonValues[actualNode.type] || '',
buttonDefaultText: vNode => defaultButtonValues[vNode.props.type] || '',

/**
* Return caption text of an HTML table element
Expand Down
4 changes: 4 additions & 0 deletions lib/core/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ const definitions = [

const constants = {
helpUrlBase: 'https://dequeuniversity.com/rules/',
// Size of a grid square in pixels
gridSize: 200,
// At a certain point, looping over an array of elements and using .match on them
// is slower than just running querySelectorAll again.
selectorSimilarFilterLimit: 700,
results: [],
resultGroups: [],
resultGroupMap: {},
Expand Down
13 changes: 12 additions & 1 deletion lib/core/public/run-rules.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,19 @@ export default function runRules(context, options, resolve, reject) {

// after should only run once, so ensure we are in the top level window
if (context.initiator) {
if (options.performanceTimer) {
performanceTimer.mark('auditAfterStart');
}
results = audit.after(results, options);

if (options.performanceTimer) {
performanceTimer.mark('auditAfterEnd');
performanceTimer.measure(
'audit.after',
'auditAfterStart',
'auditAfterEnd'
);
performanceTimer.logMeasures('audit.after');
}
results.forEach(publishMetaData);
results = results.map(finalizeRuleResult);
}
Expand Down
18 changes: 12 additions & 6 deletions lib/core/public/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { getReporter } from './reporter';
import normalizeRunParams from './run/normalize-run-params';
import { setupGlobals } from './run/globals-setup';
import { assert } from '../utils';
import performanceTimer from '../utils/performance-timer';

const noop = () => {};

Expand Down Expand Up @@ -33,11 +34,17 @@ export default function run(...args) {

axe._running = true;
if (options.performanceTimer) {
axe.utils.performanceTimer.start();
performanceTimer.start();
}

function handleRunRules(rawResults, teardown) {
const respond = results => {
if (options.performanceTimer) {
performanceTimer.mark('reporterEnd');
performanceTimer.measure('reporter', 'reporterStart', 'reporterEnd');
performanceTimer.logMeasures('reporter');
performanceTimer.end();
}
axe._running = false;
teardown();
try {
Expand All @@ -56,11 +63,10 @@ export default function run(...args) {
}
};

if (options.performanceTimer) {
axe.utils.performanceTimer.end();
}

try {
if (options.performanceTimer) {
performanceTimer.mark('reporterStart');
}
createReport(rawResults, options, respond, wrappedReject);
} catch (err) {
wrappedReject(err);
Expand All @@ -69,7 +75,7 @@ export default function run(...args) {

function errorRunRules(err) {
if (options.performanceTimer) {
axe.utils.performanceTimer.end();
performanceTimer.end();
}
axe._running = false;
callback(err);
Expand Down
16 changes: 9 additions & 7 deletions lib/core/utils/get-ancestry.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,24 @@ import getShadowSelector from './get-shadow-selector';

function generateAncestry(node) {
const nodeName = node.nodeName.toLowerCase();
const parent = node.parentElement;
if (!parent) {
return nodeName;
}
const parentElement = node.parentElement;
const parentNode = node.parentNode;

let nthChild = '';
if (
nodeName !== 'head' &&
nodeName !== 'body' &&
parent.children.length > 1
parentNode?.children.length > 1
) {
const index = Array.prototype.indexOf.call(parent.children, node) + 1;
const index = Array.prototype.indexOf.call(parentNode.children, node) + 1;
nthChild = `:nth-child(${index})`;
}

return generateAncestry(parent) + ' > ' + nodeName + nthChild;
if (!parentElement) {
return nodeName + nthChild;
}

return generateAncestry(parentElement) + ' > ' + nodeName + nthChild;
}

/**
Expand Down
21 changes: 17 additions & 4 deletions lib/core/utils/get-selector.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import getNodeAttributes from './get-node-attributes';
import matchesSelector from './element-matches';
import isXHTML from './is-xhtml';
import getShadowSelector from './get-shadow-selector';
import memoize from './memoize';
import constants from '../../core/constants';

const ignoredAttributes = [
'class',
Expand All @@ -25,6 +27,7 @@ const ignoredAttributes = [
'aria-valuenow',
'xmlns'
];

const MAXATTRIBUTELENGTH = 31;
const attrCharsRegex = /([\\"])/g;
const newlineChars = /(\r\n|\r|\n)/g;
Expand Down Expand Up @@ -346,7 +349,6 @@ function getThreeLeastCommonFeatures(elm, selectorData) {
* @param {RootNode} doc The root node of the document or document fragment
* @returns {String} The selector
*/

function generateSelector(elm, options, doc) {
/*eslint no-loop-func:0*/
// TODO: es-modules_selectorData
Expand All @@ -373,8 +375,9 @@ function generateSelector(elm, options, doc) {
} else {
selector = features;
}
if (!similar) {
similar = Array.from(doc.querySelectorAll(selector));
// If there are too many similar element running QSA again is faster
if (!similar || similar.length > constants.selectorSimilarFilterLimit) {
similar = findSimilar(doc, selector);
} else {
similar = similar.filter(item => {
return matchesSelector(item, selector);
Expand All @@ -398,6 +401,16 @@ function generateSelector(elm, options, doc) {
* @param {Object} optional options
* @returns {String|Array<String>} Unique CSS selector for the node
*/
export default function getSelector(elm, options) {
function getSelector(elm, options) {
return getShadowSelector(generateSelector, elm, options);
}

// Axe can call getSelector more than once for the same element because
// the same element can end up on multiple DqElements.
export default memoize(getSelector);

// Similar elements create similar selectors. If there are lots of similar elements on the page,
// axe ends up needing to run that same selector many times. We can memoize for a huge perf boost.
const findSimilar = memoize((doc, selector) =>
Array.from(doc.querySelectorAll(selector))
);
2 changes: 2 additions & 0 deletions lib/rules/button-name.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
"aria-label",
"aria-labelledby",
"non-empty-title",
"implicit-label",
"explicit-label",
"presentational-role"
],
"none": []
Expand Down
2 changes: 2 additions & 0 deletions lib/rules/input-button-name.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
"aria-label",
"aria-labelledby",
"non-empty-title",
"implicit-label",
"explicit-label",
"presentational-role"
],
"none": []
Expand Down
9 changes: 8 additions & 1 deletion lib/rules/input-image-alt.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@
"help": "Image buttons must have alternative text"
},
"all": [],
"any": ["non-empty-alt", "aria-label", "aria-labelledby", "non-empty-title"],
"any": [
"non-empty-alt",
"aria-label",
"aria-labelledby",
"non-empty-title",
"implicit-label",
"explicit-label"
],
"none": []
}
8 changes: 4 additions & 4 deletions locales/_template.json
Original file line number Diff line number Diff line change
Expand Up @@ -771,8 +771,8 @@
"fail": "Element contains <img> element with alt text that duplicates existing text"
},
"explicit-label": {
"pass": "Form element has an explicit <label>",
"fail": "Form element does not have an explicit <label>",
"pass": "Element has an explicit <label>",
"fail": "Element does not have an explicit <label>",
"incomplete": "Unable to determine if form element has an explicit <label>"
},
"help-same-as-label": {
Expand All @@ -785,8 +785,8 @@
"incomplete": "Unable to determine if form element has explicit <label> that is hidden"
},
"implicit-label": {
"pass": "Form element has an implicit (wrapped) <label>",
"fail": "Form element does not have an implicit (wrapped) <label>",
"pass": "Element has an implicit (wrapped) <label>",
"fail": "Element does not have an implicit (wrapped) <label>",
"incomplete": "Unable to determine if form element has an implicit (wrapped) <label>"
},
"label-content-name-mismatch": {
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "axe-core",
"description": "Accessibility engine for automated Web UI testing",
"version": "4.10.0",
"version": "4.10.1",
"license": "MPL-2.0",
"engines": {
"node": ">=4"
Expand Down
4 changes: 4 additions & 0 deletions sri-history.json
Original file line number Diff line number Diff line change
Expand Up @@ -382,5 +382,9 @@
"4.10.0": {
"axe.js": "sha256-n/KN+TQhojZXnh49uUEY3/Df5WszWcCEothu0P58qDY=",
"axe.min.js": "sha256-SDpP7Usv5Wz9lKWFZQIMhjmD+EFeKCfzSB3ONecO/7U="
},
"4.10.1": {
"axe.js": "sha256-KQDnBck/AyiC+OE3x0AJ/EQYykYTnH+1z7punr4Xc0c=",
"axe.min.js": "sha256-OBXf33U9n+qCj0mI9MLkiVyC1nCzabDnmopjyuv1gZ4="
}
}
14 changes: 14 additions & 0 deletions test/commons/text/native-text-methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,20 @@ describe('text.nativeTextMethods', () => {
const input = axe.utils.querySelectorAll(axe._tree[0], 'input')[0];
assert.equal(buttonDefaultText(input), '');
});

it('returns the default button text with mixed-case types', () => {
fixtureSetup(
'<input type="SUBMIT" />' +
'<input type="ImAGE" />' +
'<input type="ResET" />' +
'<input type="buTTON" />'
);
const inputs = axe.utils.querySelectorAll(axe._tree[0], 'input');
assert.equal(buttonDefaultText(inputs[0]), 'Submit');
assert.equal(buttonDefaultText(inputs[1]), 'Submit');
assert.equal(buttonDefaultText(inputs[2]), 'Reset');
assert.equal(buttonDefaultText(inputs[3]), '');
});
});

describe('altText', () => {
Expand Down
8 changes: 8 additions & 0 deletions test/core/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,12 @@ describe('axe.constants', function () {
it('should have groups for results', function () {
assert.equal(axe.constants.FAIL_GROUP, 'violations');
});

it('should have a gridSize', function () {
assert.equal(axe.constants.gridSize, 200);
});

it('should have a selectorSimilarFilterLimit', function () {
assert.equal(axe.constants.selectorSimilarFilterLimit, 700);
});
});
Loading

0 comments on commit f587dcc

Please sign in to comment.