Skip to content

Commit

Permalink
feat(setup/teardown): add functions to setup and teardown axe-core in…
Browse files Browse the repository at this point in the history
…ternal data, deprecate axe._tree (#2738)

* feat(setup/teardown): add functions to setup and teardown axe-core internal data

* return tree
  • Loading branch information
straker authored Jan 12, 2021
1 parent 0c7967e commit 9d19f24
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 22 deletions.
4 changes: 4 additions & 0 deletions lib/core/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import reset from './public/reset';
import runRules from './public/run-rules';
import runVirtualRule from './public/run-virtual-rule';
import run from './public/run';
import setup from './public/setup';
import teardown from './public/teardown';

import naReporter from './reporters/na';
import noPassesReporter from './reporters/no-passes';
Expand Down Expand Up @@ -73,6 +75,8 @@ axe.reset = reset;
axe._runRules = runRules;
axe.runVirtualRule = runVirtualRule;
axe.run = run;
axe.setup = setup;
axe.teardown = teardown;

axe.commons = commons;
axe.utils = utils;
Expand Down
29 changes: 7 additions & 22 deletions lib/core/public/run-rules.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Context from '../base/context';
import cache from '../base/cache';
import teardown from './teardown';
import {
getSelectorData,
queue,
Expand All @@ -11,27 +11,12 @@ import {
} from '../utils';
import log from '../log';

// Clean up after resolve / reject
function cleanup() {
if (cache.get('globalDocumentSet')) {
document = null;
}
if (cache.get('globalWindowSet')) {
window = null;
}

axe._memoizedFns.forEach(fn => fn.clear());
cache.clear();
axe._tree = undefined;
axe._selectorData = undefined;
}

/**
* Starts analysis on the current document and its subframes
* @private
* @param {Object} context The `Context` specification object @see Context
* @param {Array} options Optional RuleOptions
* @param {Function} resolve Called when done running rules, receives ([results : Object], cleanup : Function)
* @param {Function} resolve Called when done running rules, receives ([results : Object], teardown : Function)
* @param {Function} reject Called when execution failed, receives (err : Error)
*/
function runRules(context, options, resolve, reject) {
Expand All @@ -40,7 +25,7 @@ function runRules(context, options, resolve, reject) {
axe._tree = context.flatTree;
axe._selectorData = getSelectorData(context.flatTree);
} catch (e) {
cleanup();
teardown();
return reject(e);
}

Expand Down Expand Up @@ -80,17 +65,17 @@ function runRules(context, options, resolve, reject) {
results = results.map(finalizeRuleResult);
}
try {
resolve(results, cleanup);
resolve(results, teardown);
} catch (e) {
cleanup();
teardown();
log(e);
}
} catch (e) {
cleanup();
teardown();
reject(e);
}
}).catch(e => {
cleanup();
teardown();
reject(e);
});
}
Expand Down
20 changes: 20 additions & 0 deletions lib/core/public/setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { getFlattenedTree, getSelectorData } from '../utils';

/**
* Setup axe-core so axe.common functions can work properly.
* @param {Node} [node=document.documentElement] optional node. NOTE: passing in anything other than body or the documentElement may result in incomplete results.
*/
function setup(node) {
if (axe._tree) {
throw new Error(
'Axe is already setup. Call `axe.teardown()` before calling `axe.setup` again.'
);
}

axe._tree = getFlattenedTree(node);
axe._selectorData = getSelectorData(axe._tree);

return axe._tree[0];
}

export default setup;
20 changes: 20 additions & 0 deletions lib/core/public/teardown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import cache from '../base/cache';

/**
* Clean up axe-core tree and caches. `axe.run` will call this function at the end of the run so there's no need to call it yourself afterwards.
*/
function teardown() {
if (cache.get('globalDocumentSet')) {
document = null;
}
if (cache.get('globalWindowSet')) {
window = null;
}

axe._memoizedFns.forEach(fn => fn.clear());
cache.clear();
axe._tree = undefined;
axe._selectorData = undefined;
}

export default teardown;
43 changes: 43 additions & 0 deletions test/core/public/setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
describe('axe.setup', function() {
'use strict';

afterEach(function() {
axe.teardown();
});

it('should setup the tree', function() {
axe._tree = undefined;
axe.setup();
assert.exists(axe._tree);
});

it('should default the tree to use html element', function() {
axe.setup();
assert.equal(axe._tree[0].actualNode, document.documentElement);
});

it('should use the passed in node as the root of the tree', function() {
axe.setup(document.body);
assert.equal(axe._tree[0].actualNode, document.body);
});

it('should return the root node', function() {
var vNode = axe.setup(document.body);
assert.equal(vNode.actualNode, document.body);
});

it('should setup selector data', function() {
axe._selectorData = undefined;
axe.setup();
assert.exists(axe._selectorData);
});

it('should throw if called twice in a row', function() {
function fn() {
axe.setup();
axe.setup();
}

assert.throws(fn);
});
});
39 changes: 39 additions & 0 deletions test/core/public/teardown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
describe('axe.teardown', function() {
'use strict';

it('should reset the tree', function() {
axe._tree = 'foo';
axe.teardown();
assert.isUndefined(axe._tree);
});

it('should reset selector data', function() {
axe._selectorData = 'foo';
axe.teardown();
assert.isUndefined(axe._selectorData);
});

it('should reset memozied functions', function() {
var orgFn = axe._memoizedFns[0];
var called = false;
axe._memoizedFns[0] = {
clear: function() {
called = true;
}
};
axe.teardown();
assert.isTrue(called);
axe._memoizedFns[0] = orgFn;
});

it('should reset the cache', function() {
var orgFn = axe._cache.clear;
var called = false;
axe._cache.clear = function() {
called = true;
};
axe.teardown();
assert.isTrue(called);
axe._cache.clear = orgFn;
});
});

0 comments on commit 9d19f24

Please sign in to comment.