UNPKG

axe-core

Version:

Accessibility engine for automated Web UI testing

467 lines (353 loc) • 12.2 kB
/*global Context, axe */ /*eslint no-unused-vars:0*/ describe('Context', function() { 'use strict'; function iframeReady(src, context, id, cb) { var i = document.createElement('iframe'); i.addEventListener('load', function() { cb(); }); i.src = src; i.id = id; context.appendChild(i); } function $id(id) { return document.getElementById(id); } var fixture = document.getElementById('fixture'); afterEach(function() { fixture.innerHTML = ''; }); describe('include', function() { it('should accept a single selector', function() { fixture.innerHTML = '<div id="foo"></div>'; var result = new Context('#foo'); assert.deepEqual([result.include[0].actualNode], [$id('foo')]); }); it('should accept multiple selectors', function() { fixture.innerHTML = '<div id="foo"><div id="bar"></div></div>'; var result = new Context([ ['#foo'], ['#bar'] ]); assert.deepEqual([result.include[0].actualNode, result.include[1].actualNode], [$id('foo'), $id('bar')]); }); it('should accept a node reference', function() { var div = document.createElement('div'); fixture.appendChild(div); var result = new Context(div); assert.deepEqual([result.include[0].actualNode], [div]); }); it('should accept a node reference consisting of nested divs', function() { var div1 = document.createElement('div'); var div2 = document.createElement('div'); div1.appendChild(div2); fixture.appendChild(div1); var result = new Context(div1); assert.deepEqual([result.include[0].actualNode], [div1]); }); it('should accept a node reference consisting of a form with nested controls', function() { var form = document.createElement('form'); var input = document.createElement('input'); form.appendChild(input); fixture.appendChild(form); var result = new Context(form); assert.deepEqual([result.include[0].actualNode], [form]); }); it('should accept an array of node references', function() { fixture.innerHTML = '<div id="foo"><div id="bar"></div></div>'; var result = new Context([$id('foo'), $id('bar')]); assert.deepEqual([result.include[0].actualNode, result.include[1].actualNode], [$id('foo'), $id('bar')]); }); it('should remove any non-matched reference', function() { fixture.innerHTML = '<div id="foo"><div id="bar"></div></div>'; var result = new Context([ ['#foo'], ['#baz'], ['#bar'] ]); assert.deepEqual(result.include.map(function (n) { return n.actualNode; }), [$id('foo'), $id('bar')]); }); it('should sort the include nodes in document order', function() { fixture.innerHTML = '<div id="foo"><div id="bar"></div></div><div id="baz"></div>'; var result = new Context([ ['#foo'], ['#baz'], ['#bar'] ]); assert.deepEqual(result.include.map(function (n) { return n.actualNode; }), [$id('foo'), $id('bar'), $id('baz')]); }); it('should remove any null reference', function() { fixture.innerHTML = '<div id="foo"><div id="bar"></div></div>'; var result = new Context([$id('foo'), $id('bar'), null]); assert.deepEqual(result.include.map(function (n) { return n.actualNode; }), [$id('foo'), $id('bar')]); }); it('should accept mixed', function() { fixture.innerHTML = '<div id="foo"><div id="bar"></div></div>'; var div = document.createElement('div'); div.id = 'baz'; fixture.appendChild(div); var result = new Context([ ['#foo'], ['#bar'], div ]); assert.deepEqual(result.include.map(function (n) { return n.actualNode; }), [$id('foo'), $id('bar'), $id('baz')]); }); it('should support jQuery-like objects', function() { fixture.innerHTML = '<div id="foo"></div><div id="bar"></div><div id="baz"></div>'; var $test = { 0: $id('foo'), 1: $id('bar'), 2: $id('baz'), length: 3 }; var result = new Context($test); assert.deepEqual(result.include.map(function (n) { return n.actualNode; }), [$id('foo'), $id('bar'), $id('baz')]); }); it('should add frame references to frames - implicit', function(done) { fixture.innerHTML = '<div id="outer"></div>'; iframeReady('../mock/frames/context.html', $id('outer'), 'target', function() { var result = new Context('#outer'); assert.deepEqual(result.frames, [{ node: $id('target'), include: [], exclude: [] }]); done(); }); }); it('should add frame references to frames - explicit', function(done) { fixture.innerHTML = '<div id="outer"></div>'; iframeReady('../mock/frames/context.html', $id('outer'), 'target', function() { var result = new Context('#target'); assert.deepEqual(result.frames, [{ node: $id('target'), include: [], exclude: [] }]); done(); }); }); it('should add frame references to frames - frame selector', function(done) { fixture.innerHTML = '<div id="outer"></div>'; iframeReady('../mock/frames/context.html', $id('outer'), 'target', function() { var result = new Context([ ['#target', '#foo'] ]); assert.deepEqual(result.frames, [{ node: $id('target'), include: [ ['#foo'] ], exclude: [] }]); done(); }); }); it('should only push unique frame references - frame selector', function(done) { fixture.innerHTML = '<div id="outer"></div>'; iframeReady('../mock/frames/context.html', $id('outer'), 'target', function() { var result = new Context([ ['#target', '#foo'], ['#target', '#bar'] ]); assert.deepEqual(result.frames, [{ node: $id('target'), include: [ ['#foo'], ['#bar'] ], exclude: [] }]); done(); }); }); it('should only push unique frame references - node reference', function(done) { fixture.innerHTML = '<div id="outer"></div>'; iframeReady('../mock/frames/context.html', $id('outer'), 'target', function() { var result = new Context([$id('target'), $id('target')]); assert.deepEqual(result.frames, [{ node: $id('target'), include: [], exclude: [] }]); done(); }); }); it('should filter out invisible frames', function(done) { fixture.innerHTML = '<div id="outer"></div>'; iframeReady('../mock/frames/context.html', $id('outer'), 'target', function() { var frame = $id('target'); var orig = axe.utils.isHidden; var success = false; axe.utils.isHidden = function(actual) { assert.equal(actual, frame); success = true; return true; }; var result = new Context([$id('target')]); assert.deepEqual(result.frames, []); axe.utils.isHidden = orig; assert.isTrue(success, 'axe.utils.isHidden was called'); done(); }); }); it('should not filter out visible frames', function(done) { fixture.innerHTML = '<div id="outer"></div>'; iframeReady('../mock/frames/context.html', $id('outer'), 'target', function() { var frame = $id('target'); var orig = axe.utils.isHidden; var success = false; axe.utils.isHidden = function(actual) { assert.equal(actual, frame); success = true; return false; }; var result = new Context([$id('target')]); assert.deepEqual(result.frames, [{ include: [], exclude: [], node: $id('target') }]); axe.utils.isHidden = orig; assert.isTrue(success, 'axe.utils.isHidden was called'); done(); }); }); describe('throwing errors', function () { var isInFrame; beforeEach(function () { isInFrame = axe.utils.respondable.isInFrame; }); afterEach(function () { axe.utils.respondable.isInFrame = isInFrame; }); it('should throw when no elements match the context', function () { fixture.innerHTML = '<div id="foo"></div>'; assert.throws(function () { var ctxt = new Context('#notAnElement'); }, Error, 'No elements found for include in page Context'); }); it('should throw when no elements match the context inside a frame', function () { axe.utils.respondable.isInFrame = function () { return true; }; fixture.innerHTML = '<div id="foo"></div>'; assert.throws(function () { var ctxt = new Context('#notAnElement'); }, Error, 'No elements found for include in frame Context'); }); }); it('should create a flatTree property', function () { var context = new Context({ include: [document] }); // WARNING: This only works because there is now Shadow DOM on this page assert.deepEqual(context.flatTree, axe.utils.getFlattenedTree(document)); }); it('should throw when frame could not be found', function (done) { fixture.innerHTML = '<div id="outer"></div>'; iframeReady('../mock/frames/context.html', $id('outer'), 'target', function() { assert.throws(function () { var ctxt; ctxt = new Context(['#notAFrame', '#foo']); }); done(); }); }); }); describe('object definition', function() { it('should assign include/exclude', function() { var flatTree = axe.utils.getFlattenedTree(document); assert.deepEqual(new Context({ include: ['#fixture'], exclude: ['#mocha'] }), { include: axe.utils.querySelectorAll(flatTree, '#fixture'), exclude: axe.utils.querySelectorAll(flatTree, '#mocha'), flatTree: flatTree, initiator: true, page: false, frames: [] }); }); it('should disregard bad input, non-matching selectors', function() { var flatTree = axe.utils.getFlattenedTree(document); assert.deepEqual(new Context({ include: ['#fixture', '#monkeys'], exclude: ['#bananas'] }), { include: axe.utils.querySelectorAll(flatTree, '#fixture'), exclude: [], flatTree: flatTree, initiator: true, page: false, frames: [] }); }); it('should disregard bad input (null)', function() { var result = new Context(); assert.lengthOf(result.include, 1); assert.equal(result.include[0].actualNode, document.documentElement); assert.lengthOf(result.exclude, 0); assert.isTrue(result.initiator); assert.isTrue(result.page); assert.lengthOf(result.frames, 0); }); it('should default include to document', function () { var result = new Context({ exclude: ['#fixture'] }); assert.lengthOf(result.include, 1); assert.equal(result.include[0].actualNode, document.documentElement); assert.lengthOf(result.exclude, 1); assert.equal(result.exclude[0].actualNode, $id('fixture')); assert.isTrue(result.initiator); assert.isTrue(result.page); assert.lengthOf(result.frames, 0); }); it('should default empty include to document', function () { var result = new Context({ include: [], exclude: [] }); assert.lengthOf(result.include, 1); assert.equal(result.include[0].actualNode, document.documentElement); }); }); describe('initiator', function() { it('should not be clobbered', function() { var result = new Context({ initiator: false }); assert.lengthOf(result.include, 1); assert.equal(result.include[0].actualNode, document.documentElement); assert.lengthOf(result.exclude, 0); assert.isFalse(result.initiator); assert.isTrue(result.page); assert.lengthOf(result.frames, 0); }); // document.hasOwnProperty is undefined in Firefox content scripts it('should not throw given really weird circumstances when hasOwnProperty is deleted from a document node?', function() { var spec = document.implementation.createHTMLDocument('ie is dumb'); spec.hasOwnProperty = undefined; var result = new Context(spec); assert.lengthOf(result.include, 1); assert.equal(result.include[0].actualNode, spec.documentElement); assert.lengthOf(result.exclude, 0); assert.isTrue(result.initiator); assert.isFalse(result.page); assert.lengthOf(result.frames, 0); }); }); describe('page', function() { it('should be true if given an entire document', function() { assert.isTrue(new Context(document).page); }); it('should be true if given falsey parameter', function() { assert.isTrue(new Context(null).page); assert.isTrue(new Context().page); assert.isTrue(new Context(false).page); }); }); });