Skip to content

Commit

Permalink
Merge pull request #1836 from dequelabs/axe-pro-api
Browse files Browse the repository at this point in the history
chore: ensures axe Pro api
  • Loading branch information
AutoSponge authored Oct 9, 2019
2 parents b634c34 + 65f4a5c commit 5c7370a
Show file tree
Hide file tree
Showing 3 changed files with 248 additions and 1 deletion.
5 changes: 4 additions & 1 deletion build/test/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ exports = module.exports = function(grunt, options) {
'http://' + host + ':<%= connect.test.options.port %>/test/commons/',
'http://' +
host +
':<%= connect.test.options.port %>/test/integration/rules/'
':<%= connect.test.options.port %>/test/integration/rules/',
'http://' +
host +
':<%= connect.test.options.port %>/test/integration/api/external/'
],
run: true,
growlOnSuccess: false,
Expand Down
28 changes: 28 additions & 0 deletions test/integration/api/external/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>External API Test</title>

<link
rel="stylesheet"
type="text/css"
href="/node_modules/mocha/mocha.css"
/>
<script src="/node_modules/mocha/mocha.js"></script>
<script src="/node_modules/chai/chai.js"></script>
<script src="/axe.js"></script>
<script>
mocha.setup({
timeout: 10000,
ui: 'bdd'
});
var assert = chai.assert;
</script>
<script src="/test/integration/no-ui-reporter.js"></script>
</head>
<body>
<div id="mocha"></div>
<script src="index.js"></script>
<script src="/test/integration/adapter.js"></script>
</body>
</html>
216 changes: 216 additions & 0 deletions test/integration/api/external/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
// describes the API used by axe Pro
describe('external API', function() {
'use strict';

afterEach(function() {
// setup _tree as needed, always reset
axe._tree = null;
});

describe('axe.commons.text.sanitize', function() {
it('must be a function with the signature String -> String', function() {
assert.isString(axe.commons.text.sanitize(''));
assert.isString(axe.commons.text.sanitize('not empty'));
});
});

describe('axe.utils.getBaseLang', function() {
it('must be a function with the signature String -> String', function() {
assert.isString(axe.utils.getBaseLang(''));
assert.isString(axe.utils.getBaseLang('not empty'));
});
});

describe('axe.utils.validLangs', function() {
it('be a function with the signature * -> [String]', function() {
assert.isArray(axe.utils.validLangs());
axe.utils.validLangs().forEach(assert.isString);
assert.isArray(axe.utils.validLangs(document));
assert.isArray(axe.utils.validLangs({}));
});
});

describe('axe.commons.dom.isVisible', function() {
it('must be a function with the signature Element -> Boolean', function() {
var el = randomNodeInTree(isElement);
assert.isBoolean(axe.commons.dom.isVisible(el));
assert.isBoolean(axe.commons.dom.isVisible(randomNodeInTree(isElement)));
});
});

describe('axe.commons.aria.implicitRole', function() {
it('must be a function with the signature Element -> String|null', function() {
var implicitRolesOrNull = getEntries(
axe.commons.aria.lookupTable.role
).reduce(
function(roles, entry) {
var role = entry[0];
var val = entry[1];
if (val.implicit) {
roles.push(role);
}
return roles;
},
[null]
);
var role = axe.commons.aria.implicitRole(randomNodeInTree());
assert.oneOf(role, implicitRolesOrNull);
});
});

describe('axe.commons.aria.lookupTable.role', function() {
it('must be an object (dict)', function() {
assert.isObject(axe.commons.aria.lookupTable.role);
});
it('must have the signature String -> String {role.type}', function() {
var keys = getKeys(axe.commons.aria.lookupTable.role);
var types = getValues(axe.commons.aria.lookupTable.role).map(function(
role
) {
return role.type;
});
keys.forEach(assert.isString);
types.forEach(assert.isString);
});
});

describe('axe.utils.getFlattenedTree', function() {
it('must be a function with the signature Element -> [vnode]', function() {
assert.isArray(axe.utils.getFlattenedTree(document.body));
assert.lengthOf(
axe.utils.getFlattenedTree(randomNodeInTree(isElement)),
1
);
});
});

describe('axe.utils.getNodeFromTree', function() {
it('must be a function with the signature Node -> vnode', function() {
axe._tree = axe.utils.getFlattenedTree(document.body);
assert.oneOf(
axe.utils.getNodeFromTree(randomNodeInTree()),
flat(axe._tree[0])
);
});
it('must return undefined for nodes not in the axe._tree', function() {
assert.isUndefined(axe.utils.getNodeFromTree(randomElement()));
});
});

describe('axe.commons.dom.isOpaque', function() {
it('must be a function with the signature Element -> Boolean', function() {
assert.isBoolean(axe.commons.dom.isOpaque(randomNodeInTree(isElement)));
});
it('must return true for disconnected elements', function() {
assert.isTrue(axe.commons.dom.isOpaque(randomElement()));
});
});

describe('axe.commons.text.accessibleTextVirtual', function() {
it('must be a function with the signature Element vnode -> String', function() {
axe._tree = axe.utils.getFlattenedTree(document.body);
var vnode = axe.utils.getNodeFromTree(randomNodeInTree(isElement));
assert.isString(axe.commons.text.accessibleTextVirtual(vnode));
});
});
});

var elements = [
document.createElement('div'),
document.createElement('button'),
document.createElement('article')
];

var inTree = [];
var walker = collectNodes();
var next = walker.iterate().next();
while (!next.done) {
inTree.push(next.value);
next = walker.iterate().next();
}

function isElement(el) {
return el.nodeType === Node.ELEMENT_NODE;
}

function random(fromArr) {
return function(filter) {
filter = filter || isTrue;
var arr = fromArr.filter(filter);
var seed = Math.random();
return arr[Math.floor(seed * arr.length)];
};
}

function randomNodeInTree(filter) {
return random(inTree)(filter);
}

function randomElement(filter) {
return random(elements)(filter);
}

// mimic tree: body and all element and text children
function collectNodes() {
var walker = document.createTreeWalker(
document,
NodeFilter.SHOW_ALL,
function(node) {
if (!document.body.contains(node)) {
return NodeFilter.FILTER_SKIP;
}
return NodeFilter.FILTER_ACCEPT;
},
false
);
var next = function() {
var value = walker.nextNode();
return {
value: value,
done: !value
};
};
walker.iterate = function() {
return { next: next };
};
return walker;
}

function flat(tree) {
var result = [];
var insert = function(node) {
result.push(node);
(node.children || []).forEach(insert);
};
if (tree) {
insert(tree);
}
return result;
}

function isTrue() {
return true;
}

function getEntries(obj) {
var results = [];
var key;
for (key in obj) {
if (obj.hasOwnProperty(key)) {
results.push([key, obj[key]]);
}
}
return results;
}

function getValues(obj) {
return getEntries(obj).map(function(entry) {
return entry[1];
});
}

function getKeys(obj) {
return getEntries(obj).map(function(entry) {
return entry[0];
});
}

0 comments on commit 5c7370a

Please sign in to comment.