Skip to content

Commit

Permalink
tests: ensure after and reporter methods can run in isolated context (d…
Browse files Browse the repository at this point in the history
…equelabs#3136)

* tests: ensure after and reporter methods can run in isolated context

* Update test/integration/full/isolated-env/isolated-env.js

Co-authored-by: Wilco Fiers <WilcoFiers@users.noreply.github.com>

* cleanup

Co-authored-by: Wilco Fiers <WilcoFiers@users.noreply.github.com>
  • Loading branch information
straker and WilcoFiers committed Aug 26, 2021
1 parent e3e3c6b commit 7215dc4
Show file tree
Hide file tree
Showing 6 changed files with 312 additions and 2 deletions.
10 changes: 9 additions & 1 deletion lib/core/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ import frameMessenger from './public/frame-messenger';
import getRules from './public/get-rules';
import load from './public/load';
import registerPlugin from './public/plugins';
import { hasReporter, getReporter, addReporter } from './public/reporter';
import {
reporters,
hasReporter,
getReporter,
addReporter
} from './public/reporter';
import reset from './public/reset';
import runRules from './public/run-rules';
import runVirtualRule from './public/run-virtual-rule';
Expand Down Expand Up @@ -62,6 +67,9 @@ axe._thisWillBeDeletedDoNotUse.base = {
Rule,
metadataFunctionMap
};
axe._thisWillBeDeletedDoNotUse.public = {
reporters
};

axe.imports = imports;

Expand Down
2 changes: 1 addition & 1 deletion lib/core/public/reporter.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const reporters = {};
export const reporters = {};
let defaultReporter;

export function hasReporter(reporterName) {
Expand Down
11 changes: 11 additions & 0 deletions test/integration/full/isolated-env/frames/focusable.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html id="focusable">
<head>
<title>Hello</title>
<meta charset="utf8" />
<script src="/axe.js"></script>
</head>
<body>
<button>Click</button>
</body>
</html>
34 changes: 34 additions & 0 deletions test/integration/full/isolated-env/frames/isolated.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html>
<body>
<script>
window
.fetch('/axe.js')
.then(function(response) {
return response.text();
})
.then(function(axeSource) {
// add axe to the "this" object instead of
// window so we can ensure window and document
// do not exist for after and reporter
// functions
window.eval(`
var win = window;
(function() {
var window = undefined;
var document = undefined;
${axeSource}
win.axeConfigure = this.axe.configure;
win.axeFinishRun = this.axe.finishRun;
}).call({
document: document,
getComputedStyle: function () {}
});
`);
window.parent.postMessage('axe-loaded');
});
</script>
</body>
</html>
124 changes: 124 additions & 0 deletions test/integration/full/isolated-env/isolated-env.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
<!DOCTYPE html>
<html lang="en" xml:lang="en">
<head>
<title>all rules test</title>
<meta charset="utf8" />
<meta http-equiv="refresh" content="foo" />
<meta name="viewport" content="maximum-scale=2;" />
<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>
</head>
<body>
<div id="fixture">
<a href="#fail1-tgt" style="position: absolute; margin: -10000px"
>bad link 1</a
>
<banner></banner>
<main>
<div accesskey="B"></div>
<map>
<area href="#" id="pass1" alt="monkeys" />
</map>
<div aria-label="foo">Foo</div>
<div role="contentinfo"></div>
<div role="link">Home</div>
<div role="dialog" aria-label="Cookies"></div>
<p aria-hidden="true">Some text</p>
<div role="spinbutton" aria-label="foo"></div>
<div role="meter" title="foo"></div>
<div role="progressbar" title="foo"></div>
<div role="list">
<div role="listitem">Item 1</div>
</div>
<button aria-roledescription="my button">button</button>
<div role="text">Some text<span> and some more text</span></div>
<div role="checkbox">Newspaper</div>
<div role="tooltip">Copy this content</div>
<div role="tree">
<div role="treeitem">Item</div>
</div>
<audio id="caption"><track kind="captions" /></audio>
<input autocomplete="username" />
<p id="fail1" style="line-height: 1.5 !important;">Banana error</p>
<p><blink>text</blink></p>
<button id="text">Name</button>
<dl>
<dt>foo</dt>
<dd>bar</dd>
</dl>
<div id="foo"></div>
<h1>Ok</h1>
<h2>Ok</h2>
<table>
<tr>
<th scope="col">Ok</th>
</tr>
</table>

<img src="img.jpg" alt="" />
<video><track kind="captions" /></video>
<svg
xmlns="http://www.w3.org/2000/svg"
role="img"
width="100"
height="100"
>
<title>I am a circle</title>
<circle cx="50" cy="50" r="40" fill="yellow"></circle>
</svg>
<div lang="en"></div>
<object title="This object has text"></object>
<li role="presentation" aria-label="My Heading">Hello</li>
<div role="img" aria-label="blah"></div>
<div style="overflow-y: scroll; height: 5px;">
<input type="text" />
</div>
<select aria-label="foo"></select>
<img ismap src="image.jpg" />
<p tabindex="-1">Paragraph.</p>
<input type="button" />
<input type="image" src="img.jpg" />
<marquee>This content is inside a marquee.</marquee>
<div role="navigation">
<div role="banner"></div>
<div role="complementary"></div>
</div>
<span id="fail1" class="fail1"></span>
<button id="fail1"></button>
<span id="pass1"></span>
<button id="pass2"></button>
<div aria-labelledby="fail1 pass1 pass2"></div>
</main>
<footer></footer>

<iframe
id="isolated-frame"
title="foo"
src="frames/isolated.html"
></iframe>
<iframe
id="focusable-iframe"
title="bar"
src="frames/focusable.html"
tabindex="-1"
></iframe>
</div>
<div id="mocha"></div>
<script src="/test/testutils.js"></script>
<script src="isolated-env.js"></script>
<script src="/test/integration/adapter.js"></script>
</body>
</html>
133 changes: 133 additions & 0 deletions test/integration/full/isolated-env/isolated-env.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/* global chai */

describe('isolated-env test', function() {
'use strict';
var fixture = document.querySelector('#fixture');
var isIE11 = axe.testUtils.isIE11;
var origPartialResults;
var partialResults;
var win;

// just a nicer assertion error rather than just doing
// done(err)
function doesNotThrow(err, done) {
if (err instanceof chai.AssertionError) {
return done(err);
}

var error = new chai.AssertionError(
"expected [Function] to not throw an error but '" +
err.toString() +
"' was thrown"
);
done(error);
}

function setEmptyReporter() {
win.axeConfigure({
reporter: function(results, options, callback) {
if (typeof options === 'function') {
callback = options;
options = {};
}
callback(results);
}
});
}

before(function(done) {
if (isIE11) {
return this.skip();
}

axe.testUtils.awaitNestedLoad(function() {
win = fixture.querySelector('#isolated-frame').contentWindow;
var focusableFrame = fixture.querySelector('#focusable-iframe');

// trigger frame-focusable-content rule
var iframePromise = focusableFrame.contentWindow.axe.runPartial({
include: [],
exclude: [],
initiator: false,
focusable: false,
size: { width: 10, height: 10 }
});

var promises = [axe.runPartial(), iframePromise];
Promise.all(promises)
.then(function(r) {
origPartialResults = r;
done();
})
.catch(done);
});
});

beforeEach(function() {
// calling axe.finishRun mutates the partial results
// object and prevents calling finishRun again with
// the same object
partialResults = axe.utils.clone(origPartialResults);

if (win.axeConfigure) {
win.axeConfigure({ reporter: 'v1' });
}
});

it('successfully isolates axe object in iframe', function() {
assert.isUndefined(win.axe);
assert.isDefined(win.axeFinishRun);
assert.isDefined(win.axeConfigure);
});

it('after methods do not error by calling window or DOM methods', function(done) {
setEmptyReporter();

win
.axeFinishRun(partialResults)
.then(function(results) {
assert.isDefined(results);
done();
})
.catch(function(err) {
doesNotThrow(err, done);
});
});

it('runs all rules and after methods', function(done) {
win
.axeFinishRun(partialResults)
.then(function(results) {
assert.lengthOf(results.inapplicable, 0);
done();
})
.catch(function(err) {
doesNotThrow(err, done);
});
});

describe('reporters', function() {
var reporters = axe._thisWillBeDeletedDoNotUse.public.reporters;
Object.keys(reporters).forEach(function(reporterName) {
it(
reporterName +
' reporter does not error by calling window or DOM methods',
function(done) {
win.axeConfigure({
reporter: reporterName
});

win
.axeFinishRun(partialResults)
.then(function(results) {
assert.isDefined(results);
done();
})
.catch(function(err) {
doesNotThrow(err, done);
});
}
);
});
});
});

0 comments on commit 7215dc4

Please sign in to comment.