From 6ddc4e532926688c3d624683403d3fbd2cd983cc Mon Sep 17 00:00:00 2001 From: Marcy Sutton Date: Fri, 9 Feb 2018 11:40:51 -0800 Subject: [PATCH 1/4] fix: use virtual methods where applicable Until we have bi-directional node/vNode APIs it didn't make sense to use virtual methods everywhere --- lib/checks/keyboard/focusable-no-name.js | 2 +- lib/checks/label/implicit.js | 2 +- lib/checks/shared/button-has-visible-text.js | 2 +- lib/checks/shared/has-visible-text.js | 2 +- lib/checks/tables/same-caption-summary.js | 1 + test/checks/keyboard/focusable-no-name.js | 51 ++++++++-------- test/checks/shared/button-has-visible-text.js | 4 +- test/checks/shared/has-visible-text.js | 26 ++++---- test/checks/tables/same-caption-summary.js | 59 ++++++++++--------- 9 files changed, 80 insertions(+), 69 deletions(-) diff --git a/lib/checks/keyboard/focusable-no-name.js b/lib/checks/keyboard/focusable-no-name.js index 2edb257d4a..d1586d50d8 100644 --- a/lib/checks/keyboard/focusable-no-name.js +++ b/lib/checks/keyboard/focusable-no-name.js @@ -3,4 +3,4 @@ var tabIndex = node.getAttribute('tabindex'), if (!inFocusOrder) { return false; } -return !axe.commons.text.accessibleText(node); +return !axe.commons.text.accessibleTextVirtual(virtualNode); diff --git a/lib/checks/label/implicit.js b/lib/checks/label/implicit.js index f57f653d35..e813768e13 100644 --- a/lib/checks/label/implicit.js +++ b/lib/checks/label/implicit.js @@ -1,6 +1,6 @@ var label = axe.commons.dom.findUpVirtual(virtualNode, 'label'); if (label) { - return !!axe.commons.text.accessibleText(label); + return !!axe.commons.text.accessibleTextVirtual(label); } return false; diff --git a/lib/checks/shared/button-has-visible-text.js b/lib/checks/shared/button-has-visible-text.js index 64eea0e629..daa9a745fa 100644 --- a/lib/checks/shared/button-has-visible-text.js +++ b/lib/checks/shared/button-has-visible-text.js @@ -3,7 +3,7 @@ let role = node.getAttribute('role'); let label; if (nodeName === 'BUTTON' || (role === 'button' && nodeName !== 'INPUT')) { - label = axe.commons.text.accessibleText(node); + label = axe.commons.text.accessibleTextVirtual(virtualNode); this.data(label); return !!label; diff --git a/lib/checks/shared/has-visible-text.js b/lib/checks/shared/has-visible-text.js index f985e913a5..29eda782a3 100644 --- a/lib/checks/shared/has-visible-text.js +++ b/lib/checks/shared/has-visible-text.js @@ -1 +1 @@ -return axe.commons.text.accessibleText(node).length > 0; \ No newline at end of file +return axe.commons.text.accessibleTextVirtual(virtualNode).length > 0; \ No newline at end of file diff --git a/lib/checks/tables/same-caption-summary.js b/lib/checks/tables/same-caption-summary.js index 3f58cf3521..d8bdd9772f 100644 --- a/lib/checks/tables/same-caption-summary.js +++ b/lib/checks/tables/same-caption-summary.js @@ -1 +1,2 @@ +// passing node.caption to accessibleText instead of using the logic in accessibleTextVirtual on virtualNode return !!(node.summary && node.caption) && node.summary === axe.commons.text.accessibleText(node.caption); diff --git a/test/checks/keyboard/focusable-no-name.js b/test/checks/keyboard/focusable-no-name.js index 70191cc18b..470740f843 100644 --- a/test/checks/keyboard/focusable-no-name.js +++ b/test/checks/keyboard/focusable-no-name.js @@ -2,52 +2,51 @@ describe('focusable-no-name', function () { 'use strict'; var fixture = document.getElementById('fixture'); - var fixtureSetup = axe.testUtils.fixtureSetup; + var checkSetup = axe.testUtils.checkSetup; + var shadowCheckSetup = axe.testUtils.shadowCheckSetup; var shadowSupport = axe.testUtils.shadowSupport; + var checkContext = { + _data: null, + data: function (d) { + this._data = d; + } + }; + afterEach(function () { fixture.innerHTML = ''; + axe._tree = undefined; }); it('should pass if tabindex < 0', function () { - fixtureSetup(''); - var node = fixture.querySelector('a'); - assert.isFalse(checks['focusable-no-name'].evaluate(node)); + var params = checkSetup(''); + assert.isFalse(checks['focusable-no-name'].evaluate.apply(checkContext, params)); }); it('should pass element is not natively focusable', function () { - fixtureSetup(''); - var node = fixture.querySelector('span'); - assert.isFalse(checks['focusable-no-name'].evaluate(node)); + var params = checkSetup(''); + assert.isFalse(checks['focusable-no-name'].evaluate.apply(checkContext, params)); }); it('should fail if element is tabbable with no name - native', function () { - fixtureSetup(''); - var node = fixture.querySelector('a'); - assert.isTrue(checks['focusable-no-name'].evaluate(node)); + var params = checkSetup(''); + assert.isTrue(checks['focusable-no-name'].evaluate.apply(checkContext, params)); }); - it('should fail if element is tabable with no name - ARIA', function () { - fixtureSetup(''); - var node = fixture.querySelector('span'); - assert.isTrue(checks['focusable-no-name'].evaluate(node)); + it('should fail if element is tabbable with no name - ARIA', function () { + var params = checkSetup(''); + assert.isTrue(checks['focusable-no-name'].evaluate.apply(checkContext, params)); }); - it('should pass if the element is tabable but has an accessible name', function () { - fixtureSetup(''); - var node = fixture.querySelector('a'); - assert.isFalse(checks['focusable-no-name'].evaluate(node)); + it('should pass if the element is tabbable but has an accessible name', function () { + var params = checkSetup(''); + assert.isFalse(checks['focusable-no-name'].evaluate.apply(checkContext, params)); }); (shadowSupport.v1 ? it : xit)('should pass if the content is passed in with shadow DOM', function () { - var node = document.createElement('div'); - node.innerText = 'Content!'; - var shadow = node.attachShadow({ mode: 'open' }); - shadow.innerHTML = ''; - fixtureSetup(node); - - var link = shadow.querySelector('a'); - assert.isFalse(checks['focusable-no-name'].evaluate(link)); + var params = shadowCheckSetup('
Content!
', ''); + + assert.isFalse(checks['focusable-no-name'].evaluate.apply(checkContext, params)); }); }); diff --git a/test/checks/shared/button-has-visible-text.js b/test/checks/shared/button-has-visible-text.js index 3526aea46b..ce8c09eb3a 100644 --- a/test/checks/shared/button-has-visible-text.js +++ b/test/checks/shared/button-has-visible-text.js @@ -29,14 +29,14 @@ describe('button-has-visible-text', function () { }); it('should return true if ARIA button has text', function () { - var checkArgs = checkSetup('
Text
>', '[role=button]'); + var checkArgs = checkSetup('
Text
', '[role=button]'); assert.isTrue(checks['button-has-visible-text'].evaluate.apply(checkContext, checkArgs)); assert.deepEqual(checkContext._data, 'Text'); }); it('should return false if ARIA button has no text', function () { - var checkArgs = checkSetup('
>', '[role=button]'); + var checkArgs = checkSetup('
', '[role=button]'); assert.isFalse(checks['button-has-visible-text'].evaluate.apply(checkContext, checkArgs)); }); diff --git a/test/checks/shared/has-visible-text.js b/test/checks/shared/has-visible-text.js index f62e080bd6..4e51656943 100644 --- a/test/checks/shared/has-visible-text.js +++ b/test/checks/shared/has-visible-text.js @@ -2,28 +2,34 @@ describe('has-visible-text', function () { 'use strict'; var fixture = document.getElementById('fixture'); - var fixtureSetup = axe.testUtils.fixtureSetup; + var checkSetup = axe.testUtils.checkSetup; + + var checkContext = { + _data: null, + data: function (d) { + this._data = d; + } + }; afterEach(function () { fixture.innerHTML = ''; + axe._tree = undefined; + checkContext._data = null; }); it('should return false if there is no visible text', function () { - fixtureSetup(''); - var node = document.querySelector('object'); - assert.isFalse(checks['has-visible-text'].evaluate(node)); + var params = checkSetup(''); + assert.isFalse(checks['has-visible-text'].evaluate.apply(checkContext, params)); }); it('should return false if there is text, but its hidden', function () { - fixtureSetup('hello!'); - var node = document.querySelector('object'); - assert.isFalse(checks['has-visible-text'].evaluate(node)); + var params = checkSetup('hello!'); + assert.isFalse(checks['has-visible-text'].evaluate.apply(checkContext, params)); }); it('should return true if there is visible text', function () { - fixtureSetup('hello!'); - var node = document.querySelector('object'); - assert.isTrue(checks['has-visible-text'].evaluate(node)); + var params = checkSetup('hello!'); + assert.isTrue(checks['has-visible-text'].evaluate.apply(checkContext, params)); }); }); diff --git a/test/checks/tables/same-caption-summary.js b/test/checks/tables/same-caption-summary.js index f56dfedd2c..0cf5ddaed9 100644 --- a/test/checks/tables/same-caption-summary.js +++ b/test/checks/tables/same-caption-summary.js @@ -2,59 +2,64 @@ describe('same-caption-summary', function () { 'use strict'; var fixture = document.getElementById('fixture'); - var fixtureSetup = axe.testUtils.fixtureSetup; + var checkSetup = axe.testUtils.checkSetup; + var shadowCheckSetup = axe.testUtils.shadowCheckSetup; var shadowSupport = axe.testUtils.shadowSupport; + var checkContext = { + _data: null, + data: function (d) { + this._data = d; + } + }; + + afterEach(function () { fixture.innerHTML = ''; + axe._tree = undefined; }); it('should return false there is no caption', function () { - fixtureSetup('
'); - var node = fixture.querySelector('table'); + var params = checkSetup('
'); - assert.isFalse(checks['same-caption-summary'].evaluate(node)); + assert.isFalse(checks['same-caption-summary'].evaluate.apply(checkContext, params)); }); it('should return false there is no summary', function () { - fixtureSetup('
Hi
'); - var node = fixture.querySelector('table'); + var params = checkSetup('
Hi
'); - assert.isFalse(checks['same-caption-summary'].evaluate(node)); + assert.isFalse(checks['same-caption-summary'].evaluate.apply(checkContext, params)); }); it('should return false if summary and caption are different', function () { - fixtureSetup('
Hi
'); - var node = fixture.querySelector('table'); + var params = checkSetup('
Hi
'); - assert.isFalse(checks['same-caption-summary'].evaluate(node)); + assert.isFalse(checks['same-caption-summary'].evaluate.apply(checkContext, params)); }); it('should return true if summary and caption are the same', function () { - fixtureSetup('
Hi
'); - var node = fixture.querySelector('table'); + var params = checkSetup('
Hi
'); - assert.isTrue(checks['same-caption-summary'].evaluate(node)); + assert.isTrue(checks['same-caption-summary'].evaluate.apply(checkContext, params)); }); (shadowSupport.v1 ? it : xit)('should match slotted caption elements', function () { - var node = document.createElement('div'); - node.innerHTML = 'Caption' + - 'Data element 1' + - 'Data element 2'; - - var root = node.attachShadow({ mode: 'open' }); - var table = document.createElement('table'); - table.innerHTML = '' + - ''; - table.setAttribute('summary', 'Caption'); - root.appendChild(table); - fixtureSetup(node); - - assert.isTrue(checks['same-caption-summary'].evaluate(table)); + var params = shadowCheckSetup( + '
' + + 'Caption' + + 'Data element 1' + + 'Data element 2' + + '
', + '' + + '' + + '' + + '
' + ); + + assert.isTrue(checks['same-caption-summary'].evaluate.apply(checkContext, params)); }); }); \ No newline at end of file From 64b9cc2e6804447f3929926227ed86a69ebc74ba Mon Sep 17 00:00:00 2001 From: Marcy Sutton Date: Fri, 9 Feb 2018 17:07:07 -0800 Subject: [PATCH 2/4] test: use MockCheckContext for all checks --- test/checks/aria/allowed-attr.js | 10 +- test/checks/aria/aria-hidden-body.js | 10 +- test/checks/aria/errormessage.js | 2 +- test/checks/aria/required-attr.js | 10 +- test/checks/aria/required-children.js | 11 +- test/checks/aria/required-parent.js | 11 +- test/checks/aria/valid-attr-value.js | 10 +- test/checks/aria/valid-attr.js | 10 +- test/checks/color/color-contrast.js | 15 +- test/checks/color/link-in-text-block.js | 14 +- test/checks/forms/fieldset.js | 12 +- test/checks/forms/group-labelledby.js | 9 +- test/checks/keyboard/accesskeys.js | 15 +- test/checks/keyboard/focusable-no-name.js | 10 +- test/checks/keyboard/has-at-least-one-main.js | 6 +- test/checks/label/multiple-label.js | 14 +- test/checks/language/valid-lang.js | 9 +- test/checks/lists/only-dlitems.js | 9 +- test/checks/lists/only-listitems.js | 9 +- test/checks/navigation/header-present.js | 38 +++-- test/checks/navigation/heading-order.js | 10 +- .../navigation/internal-link-present.js | 12 +- test/checks/navigation/p-as-heading.js | 156 ++++++++---------- .../navigation/unique-frame-title-after.js | 9 +- test/checks/navigation/unique-frame-title.js | 9 +- test/checks/shared/button-has-visible-text.js | 9 +- test/checks/shared/duplicate-id.js | 14 +- test/checks/shared/has-visible-text.js | 9 +- test/checks/shared/non-empty-if-present.js | 9 +- test/checks/tables/has-th.js | 14 +- test/checks/tables/same-caption-summary.js | 8 +- test/checks/tables/td-has-header.js | 14 +- test/checks/tables/td-headers-attr.js | 14 +- test/checks/tables/th-has-data-cells.js | 14 +- test/checks/visibility/hidden-content.js | 9 +- test/testutils.js | 6 +- 36 files changed, 168 insertions(+), 382 deletions(-) diff --git a/test/checks/aria/allowed-attr.js b/test/checks/aria/allowed-attr.js index 5ce187f9f9..98473880c3 100644 --- a/test/checks/aria/allowed-attr.js +++ b/test/checks/aria/allowed-attr.js @@ -2,17 +2,11 @@ describe('aria-allowed-attr', function () { 'use strict'; var fixture = document.getElementById('fixture'); - - var checkContext = { - _data: null, - data: function (d) { - this._data = d; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; - checkContext._data = null; + checkContext.reset(); }); it('should detect incorrectly used attributes', function () { diff --git a/test/checks/aria/aria-hidden-body.js b/test/checks/aria/aria-hidden-body.js index dd074eb77d..453300a12b 100644 --- a/test/checks/aria/aria-hidden-body.js +++ b/test/checks/aria/aria-hidden-body.js @@ -2,16 +2,10 @@ describe('aria-hidden', function () { 'use strict'; var node = document.getElementsByTagName('body')[0]; - - var checkContext = { - _data: null, - data: function (d) { - this._data = d; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { - checkContext._data = null; + checkContext.reset(); node.removeAttribute('aria-hidden'); }); diff --git a/test/checks/aria/errormessage.js b/test/checks/aria/errormessage.js index 819cd875b8..4605f10dba 100644 --- a/test/checks/aria/errormessage.js +++ b/test/checks/aria/errormessage.js @@ -7,7 +7,7 @@ describe('aria-errormessage', function () { afterEach(function () { fixture.innerHTML = ''; - checkContext._data = null; + checkContext.reset(); }); it('should return false if aria-errormessage value is invalid', function () { diff --git a/test/checks/aria/required-attr.js b/test/checks/aria/required-attr.js index 79ec2890e2..1592bdc4a5 100644 --- a/test/checks/aria/required-attr.js +++ b/test/checks/aria/required-attr.js @@ -2,17 +2,11 @@ describe('aria-required-attr', function () { 'use strict'; var fixture = document.getElementById('fixture'); - - var checkContext = { - _data: null, - data: function (d) { - this._data = d; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; - checkContext._data = null; + checkContext.reset(); }); it('should detect missing attributes', function () { diff --git a/test/checks/aria/required-children.js b/test/checks/aria/required-children.js index de489077ae..5d5d4c09da 100644 --- a/test/checks/aria/required-children.js +++ b/test/checks/aria/required-children.js @@ -3,20 +3,13 @@ describe('aria-required-children', function () { var fixture = document.getElementById('fixture'); var shadowSupported = axe.testUtils.shadowSupport.v1; - - var checkContext = { - _data: null, - data: function (d) { - this._data = d; - } - }; - + var checkContext = axe.testUtils.MockCheckContext(); var checkSetup = axe.testUtils.checkSetup; afterEach(function () { fixture.innerHTML = ''; axe._tree = undefined; - checkContext._data = null; + checkContext.reset(); }); it('should detect missing sole required child', function () { diff --git a/test/checks/aria/required-parent.js b/test/checks/aria/required-parent.js index c6c4c8cfd8..12565d14ea 100644 --- a/test/checks/aria/required-parent.js +++ b/test/checks/aria/required-parent.js @@ -3,19 +3,12 @@ describe('aria-required-parent', function () { var fixture = document.getElementById('fixture'); var shadowSupported = axe.testUtils.shadowSupport.v1; - - var checkContext = { - _data: null, - data: function (d) { - this._data = d; - } - }; - + var checkContext = axe.testUtils.MockCheckContext(); var checkSetup = axe.testUtils.checkSetup; afterEach(function () { fixture.innerHTML = ''; - checkContext._data = null; + checkContext.reset(); axe._tree = undefined; }); diff --git a/test/checks/aria/valid-attr-value.js b/test/checks/aria/valid-attr-value.js index a375600de4..a975e16b25 100644 --- a/test/checks/aria/valid-attr-value.js +++ b/test/checks/aria/valid-attr-value.js @@ -2,17 +2,11 @@ describe('aria-valid-attr-value', function () { 'use strict'; var fixture = document.getElementById('fixture'); - - var checkContext = { - _data: null, - data: function (d) { - this._data = d; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; - checkContext._data = null; + checkContext.reset(); }); it('should not check the validity of attribute names', function () { diff --git a/test/checks/aria/valid-attr.js b/test/checks/aria/valid-attr.js index 63e36b7de8..638f60d641 100644 --- a/test/checks/aria/valid-attr.js +++ b/test/checks/aria/valid-attr.js @@ -2,17 +2,11 @@ describe('aria-valid-attr', function () { 'use strict'; var fixture = document.getElementById('fixture'); - - var checkContext = { - _data: null, - data: function (d) { - this._data = d; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; - checkContext._data = null; + checkContext.reset(); }); it('should return false if any invalid ARIA attributes are found', function () { diff --git a/test/checks/color/color-contrast.js b/test/checks/color/color-contrast.js index eab3f2fd11..a44d657852 100644 --- a/test/checks/color/color-contrast.js +++ b/test/checks/color/color-contrast.js @@ -5,22 +5,11 @@ describe('color-contrast', function () { var fixtureSetup = axe.testUtils.fixtureSetup; var shadowSupported = axe.testUtils.shadowSupport.v1; var shadowCheckSetup = axe.testUtils.shadowCheckSetup; - - var checkContext = { - _relatedNodes: [], - _data: null, - data: function (d) { - this._data = d; - }, - relatedNodes: function (rn) { - this._relatedNodes = rn; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; - checkContext._relatedNodes = []; - checkContext._data = null; + checkContext.reset(); axe._tree = undefined; }); diff --git a/test/checks/color/link-in-text-block.js b/test/checks/color/link-in-text-block.js index f557602af4..4b5e478046 100644 --- a/test/checks/color/link-in-text-block.js +++ b/test/checks/color/link-in-text-block.js @@ -5,16 +5,7 @@ describe('link-in-text-block', function () { var shadowSupport = axe.testUtils.shadowSupport; var styleElm; - var checkContext = { - _relatedNodes: [], - _data: null, - data: function (d) { - this._data = d; - }, - relatedNodes: function (rn) { - this._relatedNodes = rn; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); before(function () { styleElm = document.createElement('style'); @@ -33,8 +24,7 @@ describe('link-in-text-block', function () { afterEach(function () { fixture.innerHTML = ''; styleElm.innerHTML = ''; - checkContext._relatedNodes = []; - checkContext._data = null; + checkContext.reset(); }); after(function () { diff --git a/test/checks/forms/fieldset.js b/test/checks/forms/fieldset.js index b63169ca55..b452d313fb 100644 --- a/test/checks/forms/fieldset.js +++ b/test/checks/forms/fieldset.js @@ -4,19 +4,11 @@ describe('fieldset', function () { var shadowSupport = axe.testUtils.shadowSupport.v1; var fixtureSetup = axe.testUtils.fixtureSetup; - var checkContext = { - _data: null, - data: function (d) { - this._data = d; - }, - relatedNodes: function (nodes) { - this._relatedNodes = Array.isArray(nodes) ? nodes : [nodes]; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; - checkContext._data = null; + checkContext.reset(); }); function tests(type) { diff --git a/test/checks/forms/group-labelledby.js b/test/checks/forms/group-labelledby.js index 37184b0cff..70b93b732a 100644 --- a/test/checks/forms/group-labelledby.js +++ b/test/checks/forms/group-labelledby.js @@ -5,12 +5,7 @@ describe('group-labelledby', function () { var fixtureSetup = axe.testUtils.fixtureSetup; var shadowSupport = axe.testUtils.shadowSupport.v1; - var checkContext = { - _data: null, - data: function (d) { - this._data = d; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); beforeEach(function () { axe._tree = undefined; @@ -18,7 +13,7 @@ describe('group-labelledby', function () { afterEach(function () { fixture.innerHTML = ''; - checkContext._data = null; + checkContext.reset(); }); function tests(type) { diff --git a/test/checks/keyboard/accesskeys.js b/test/checks/keyboard/accesskeys.js index 851c53e771..05008287e4 100644 --- a/test/checks/keyboard/accesskeys.js +++ b/test/checks/keyboard/accesskeys.js @@ -3,22 +3,11 @@ describe('accesskeys', function () { var fixture = document.getElementById('fixture'); - - var checkContext = { - _relatedNodes: [], - _data: null, - data: function (d) { - this._data = d; - }, - relatedNodes: function (rn) { - this._relatedNodes = rn; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; - checkContext._relatedNodes = []; - checkContext._data = null; + checkContext.reset(); }); it('should return true and record accesskey', function () { diff --git a/test/checks/keyboard/focusable-no-name.js b/test/checks/keyboard/focusable-no-name.js index 470740f843..7909710345 100644 --- a/test/checks/keyboard/focusable-no-name.js +++ b/test/checks/keyboard/focusable-no-name.js @@ -5,17 +5,13 @@ describe('focusable-no-name', function () { var checkSetup = axe.testUtils.checkSetup; var shadowCheckSetup = axe.testUtils.shadowCheckSetup; var shadowSupport = axe.testUtils.shadowSupport; - - var checkContext = { - _data: null, - data: function (d) { - this._data = d; - } - }; + + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; axe._tree = undefined; + checkContext.reset(); }); it('should pass if tabindex < 0', function () { diff --git a/test/checks/keyboard/has-at-least-one-main.js b/test/checks/keyboard/has-at-least-one-main.js index 6df5b93111..02ba609051 100644 --- a/test/checks/keyboard/has-at-least-one-main.js +++ b/test/checks/keyboard/has-at-least-one-main.js @@ -39,7 +39,11 @@ describe('has-at-least-one-main', function () { }); it('should return true if one div has role equal to main', function() { - var params = checkSetup('
Div with role main
'); + var params = checkSetup('
Div with role main
'); + var mainIsFound = checks['has-at-least-one-main'].evaluate.apply(checkContext, params); + assert.isTrue(mainIsFound); + assert.equal(checkContext._data, mainIsFound); + }); var mainIsFound = checks['has-at-least-one-main'].evaluate.apply(checkContext, params); assert.isTrue(mainIsFound); assert.equal(checkContext._data, mainIsFound); diff --git a/test/checks/label/multiple-label.js b/test/checks/label/multiple-label.js index 8af003d732..921a7059ef 100644 --- a/test/checks/label/multiple-label.js +++ b/test/checks/label/multiple-label.js @@ -3,21 +3,11 @@ describe('multiple-label', function () { var fixture = document.getElementById('fixture'); - var checkContext = { - _relatedNodes: [], - _data: null, - data: function (d) { - this._data = d; - }, - relatedNodes: function (rn) { - this._relatedNodes = rn; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; - checkContext._relatedNodes = []; - checkContext._data = null; + checkContext.reset(); }); it('should return true if there are multiple implicit labels', function () { diff --git a/test/checks/language/valid-lang.js b/test/checks/language/valid-lang.js index 54c15a8c74..60762ba1d2 100644 --- a/test/checks/language/valid-lang.js +++ b/test/checks/language/valid-lang.js @@ -3,16 +3,11 @@ describe('valid-lang', function () { var fixture = document.getElementById('fixture'); - var checkContext = { - _data: null, - data: function (data) { - this._data = data; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; - checkContext._data = null; + checkContext.reset(); }); describe('lang', function () { diff --git a/test/checks/lists/only-dlitems.js b/test/checks/lists/only-dlitems.js index e0b890f514..71fa350dd2 100644 --- a/test/checks/lists/only-dlitems.js +++ b/test/checks/lists/only-dlitems.js @@ -5,16 +5,11 @@ describe('only-dlitems', function () { var checkSetup = axe.testUtils.checkSetup; var shadowSupport = axe.testUtils.shadowSupport; - var checkContext = { - _relatedNodes: [], - relatedNodes: function (rn) { - this._relatedNodes = rn; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; - checkContext._relatedNodes = []; + checkContext.reset(); }); it('should return false if the list has no contents', function () { diff --git a/test/checks/lists/only-listitems.js b/test/checks/lists/only-listitems.js index 9150cad922..5ff9108829 100644 --- a/test/checks/lists/only-listitems.js +++ b/test/checks/lists/only-listitems.js @@ -5,16 +5,11 @@ describe('only-listitems', function () { var checkSetup = axe.testUtils.checkSetup; var shadowSupport = axe.testUtils.shadowSupport; - var checkContext = { - _relatedNodes: [], - relatedNodes: function (rn) { - this._relatedNodes = rn; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; - checkContext._relatedNodes = []; + checkContext.reset(); }); it('should return false if the list has no contents', function () { diff --git a/test/checks/navigation/header-present.js b/test/checks/navigation/header-present.js index 5ac8261464..d1b535db28 100644 --- a/test/checks/navigation/header-present.js +++ b/test/checks/navigation/header-present.js @@ -2,41 +2,43 @@ describe('header-present', function () { 'use strict'; var fixture = document.getElementById('fixture'); + var checkSetup = axe.testUtils.checkSetup; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; + axe._tree = undefined; + checkContext.reset(); }); it('should return true if h1-h6 is found', function () { - fixture.innerHTML = '

Hi

'; - assert.isTrue(checks['header-present'].evaluate(fixture)); + var params = checkSetup('

Hi

'); + assert.isTrue(checks['header-present'].evaluate.apply(checkContext, params)); - fixture.innerHTML = '

Hi

'; - assert.isTrue(checks['header-present'].evaluate(fixture)); + params = checkSetup('

Hi

'); + assert.isTrue(checks['header-present'].evaluate.apply(checkContext, params)); - fixture.innerHTML = '

Hi

'; - assert.isTrue(checks['header-present'].evaluate(fixture)); + params = checkSetup('

Hi

'); + assert.isTrue(checks['header-present'].evaluate.apply(checkContext, params)); - fixture.innerHTML = '

Hi

'; - assert.isTrue(checks['header-present'].evaluate(fixture)); + params = checkSetup('

Hi

'); + assert.isTrue(checks['header-present'].evaluate.apply(checkContext, params)); - fixture.innerHTML = '
Hi
'; - assert.isTrue(checks['header-present'].evaluate(fixture)); + params = checkSetup('
Hi
'); + assert.isTrue(checks['header-present'].evaluate.apply(checkContext, params)); - fixture.innerHTML = '
Hi
'; - assert.isTrue(checks['header-present'].evaluate(fixture)); + params = checkSetup('
Hi
'); + assert.isTrue(checks['header-present'].evaluate.apply(checkContext, params)); }); it('should return true if role=heading is found', function () { - - fixture.innerHTML = '
Hi
'; - assert.isTrue(checks['header-present'].evaluate(fixture)); - + var params = checkSetup('
Hi
'); + assert.isTrue(checks['header-present'].evaluate.apply(checkContext, params)); }); it('should otherwise return false', function () { - fixture.innerHTML = '

Some stuff and stuff

'; - assert.isFalse(checks['header-present'].evaluate(fixture)); + var params = checkSetup('

Some stuff and stuff

'); + assert.isFalse(checks['header-present'].evaluate.apply(checkContext, params)); }); }); diff --git a/test/checks/navigation/heading-order.js b/test/checks/navigation/heading-order.js index 82332bbab2..5a916c7f79 100644 --- a/test/checks/navigation/heading-order.js +++ b/test/checks/navigation/heading-order.js @@ -2,16 +2,12 @@ describe('heading-order', function () { 'use strict'; var fixture = document.getElementById('fixture'); - var checkContext = { - _data: null, - data: function (d) { - this._data = d; - } - }; + + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; - checkContext._data = null; + checkContext.reset(); }); it('should store the correct header level for aria-level and return true', function () { diff --git a/test/checks/navigation/internal-link-present.js b/test/checks/navigation/internal-link-present.js index dd76b34084..964af66069 100644 --- a/test/checks/navigation/internal-link-present.js +++ b/test/checks/navigation/internal-link-present.js @@ -2,19 +2,23 @@ describe('internal-link-present', function () { 'use strict'; var fixture = document.getElementById('fixture'); + var checkContext = axe.testUtils.MockCheckContext(); + var checkSetup = axe.testUtils.checkSetup; afterEach(function () { fixture.innerHTML = ''; + axe._tree = undefined; + checkContext.reset(); }); it('should return true when an internal link is found', function () { - fixture.innerHTML = 'hi'; - assert.isTrue(checks['internal-link-present'].evaluate(fixture)); + var params = checkSetup(''); + assert.isTrue(checks['internal-link-present'].evaluate.apply(checkContext, params)); }); it('should otherwise return false', function () { - fixture.innerHTML = 'hi'; - assert.isFalse(checks['internal-link-present'].evaluate(fixture)); + var params = checkSetup(''); + assert.isFalse(checks['internal-link-present'].evaluate.apply(checkContext, params)); }); }); diff --git a/test/checks/navigation/p-as-heading.js b/test/checks/navigation/p-as-heading.js index a485512a5e..08230dd216 100644 --- a/test/checks/navigation/p-as-heading.js +++ b/test/checks/navigation/p-as-heading.js @@ -1,14 +1,11 @@ describe('p-as-heading', function () { 'use strict'; var fixture = document.getElementById('fixture'); - var fixtureSetup = axe.testUtils.fixtureSetup; + var checkSetup = axe.testUtils.checkSetup; - var checkContext = { - _data: null, - data: function (d) { - this._data = d; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); + var shadowSupported = axe.testUtils.shadowSupport.v1; + var shadowCheckSetup = axe.testUtils.shadowCheckSetup; var testOptions = { margins: [ @@ -20,99 +17,82 @@ describe('p-as-heading', function () { afterEach(function () { fixture.innerHTML = ''; - checkContext._data = null; + checkContext.reset(); axe._tree = undefined; }); it('returns true if the styles are identical', function () { - fixtureSetup('

elm 1

elm 2

'); - var node = fixture.querySelector('p'); - var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node); - assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode)); + var params = checkSetup('

elm 1

elm 2

', testOptions); + assert.isTrue(checks['p-as-heading'].evaluate.apply(checkContext, params)); }); it('returns true if there is no p element following it', function () { - fixtureSetup('

lone elm

'); - var node = fixture.querySelector('p'); - var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node); - assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode)); + var params = checkSetup('

lone elm

', testOptions); + assert.isTrue(checks['p-as-heading'].evaluate.apply(checkContext, params)); }); it('returns false if the font-weight is heavier', function () { - fixtureSetup('

elm 1

elm 2

'); - var node = fixture.querySelector('p'); - var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node); - assert.isFalse(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode)); + var params = checkSetup( + '

elm 1

' + + '

elm 2

', + testOptions + ); + assert.isFalse(checks['p-as-heading'].evaluate.apply(checkContext, params)); }); it('returns false if the font-size is bigger', function () { - fixtureSetup('

elm 1

elm 2

'); - var node = fixture.querySelector('p'); - var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node); - assert.isFalse(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode)); + var params = checkSetup('

elm 1

elm 2

', testOptions); + assert.isFalse(checks['p-as-heading'].evaluate.apply(checkContext, params)); }); it('returns false if the fake heading is italic and the text is not', function () { - fixtureSetup('

elm 1

elm 2

'); - var node = fixture.querySelector('p'); - var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node); - assert.isFalse(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode)); + var params = checkSetup('

elm 1

elm 2

', testOptions); + assert.isFalse(checks['p-as-heading'].evaluate.apply(checkContext, params)); }); it('returns true if both texts are bold, italic and larger', function () { - fixtureSetup('

elm 1

' + - '

elm 2

'); - var node = fixture.querySelector('p'); - var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node); - assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode)); + var params = checkSetup( + '

elm 1

' + + '

elm 2

', + testOptions + ); + assert.isTrue(checks['p-as-heading'].evaluate.apply(checkContext, params)); }); it('considers styles of elements inside the paragraph', function () { - fixtureSetup('

elm 1

elm 2

'); - var node = fixture.querySelector('p'); - var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node); - assert.isFalse(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode)); + var params = checkSetup('

elm 1

elm 2

', testOptions); + assert.isFalse(checks['p-as-heading'].evaluate.apply(checkContext, params)); }); it('ignores empty child element for style', function () { - fixtureSetup('

elm 1

elm 2

'); - var node = fixture.querySelector('p'); - var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node); - assert.isFalse(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode)); + var params = checkSetup('

elm 1

elm 2

', testOptions); + assert.isFalse(checks['p-as-heading'].evaluate.apply(checkContext, params)); }); it('considers styles of elements that do not contain all the text', function () { - fixtureSetup('

elm 1

elm 2

'); - var node = fixture.querySelector('p'); - var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node); - assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode)); + var params = checkSetup('

elm 1

elm 2

', testOptions); + assert.isTrue(checks['p-as-heading'].evaluate.apply(checkContext, params)); }); it('returns undefined instead of false if the element is inside a blockquote', function () { - fixtureSetup('
' + - '

elm 1

elm 2

' + - '
'); - var node = fixture.querySelector('p'); - var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node); - assert.isUndefined(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode)); + var params = checkSetup('
' + + '

elm 1

elm 2

' + + '
', testOptions); + assert.isUndefined(checks['p-as-heading'].evaluate.apply(checkContext, params)); }); it('returns true over undefined from within a blockquote', function () { - fixtureSetup('
' + - '

elm 1

elm 2

' + - '
'); - var node = fixture.querySelector('p'); - var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node); - assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode)); + var params = checkSetup('
' + + '

elm 1

elm 2

' + + '
', testOptions); + assert.isTrue(checks['p-as-heading'].evaluate.apply(checkContext, params)); }); it('returns undefined if a previous sibling has a similar font-weight', function () { - fixtureSetup('

elm 1

'+ + var params = checkSetup('

elm 1

'+ '

elm 2

'+ - '

elm 3

'); - var node = fixture.querySelector('#target'); - var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node); - assert.isUndefined(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode)); + '

elm 3

', testOptions); + assert.isUndefined(checks['p-as-heading'].evaluate.apply(checkContext, params)); }); describe('option.margin', function () { @@ -120,10 +100,8 @@ describe('p-as-heading', function () { it('passes if no margins are set', function () { var options = {}; - fixtureSetup('

elm 1

elm 2

'); - var node = fixture.querySelector('p'); - var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node); - assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, options, virtualNode)); + var params = checkSetup('

elm 1

elm 2

', options); + assert.isTrue(checks['p-as-heading'].evaluate.apply(checkContext, params)); }); it('takes an array of margins', function () { @@ -131,10 +109,8 @@ describe('p-as-heading', function () { margins: [{ size: 1.2 }] }; - fixtureSetup('

elm 1

elm 2

'); - var node = fixture.querySelector('p'); - var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node); - assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, options, virtualNode)); + var params = checkSetup('

elm 1

elm 2

', options); + assert.isTrue(checks['p-as-heading'].evaluate.apply(checkContext, params)); }); it('returns false if all values in the margin are passed', function () { @@ -142,10 +118,12 @@ describe('p-as-heading', function () { margins: [{ size: 1.2, weight: 100 }] }; - fixtureSetup('

elm 1

elm 2

'); - var node = fixture.querySelector('p'); - var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node); - assert.isFalse(checks['p-as-heading'].evaluate.call(checkContext, node, options, virtualNode)); + var params = checkSetup( + '

elm 1

' + + '

elm 2

', + options + ); + assert.isFalse(checks['p-as-heading'].evaluate.apply(checkContext, params)); }); it('returns true if any of the values is not passed', function () { @@ -153,10 +131,12 @@ describe('p-as-heading', function () { margins: [{ size: 1.2, weight: 100 }] }; - fixtureSetup('

elm 1

elm 2

'); - var node = fixture.querySelector('p'); - var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node); - assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, options, virtualNode)); + var params = checkSetup( + '

elm 1

' + + '

elm 2

', + options + ); + assert.isTrue(checks['p-as-heading'].evaluate.apply(checkContext, params)); }); it('returns false if any of the margins is passed', function () { @@ -168,10 +148,12 @@ describe('p-as-heading', function () { ], }; - fixtureSetup('

elm 1

elm 2

'); - var node = fixture.querySelector('p'); - var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node); - assert.isFalse(checks['p-as-heading'].evaluate.call(checkContext, node, options, virtualNode)); + var params = checkSetup( + '

elm 1

' + + '

elm 2

', + options + ); + assert.isFalse(checks['p-as-heading'].evaluate.apply(checkContext, params)); }); it('returns true if none of the set margins is passed', function () { @@ -183,11 +165,11 @@ describe('p-as-heading', function () { ] }; - fixtureSetup('

elm 1

elm 2

'); - var node = fixture.querySelector('p'); - var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node); - assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, options, virtualNode)); + var params = checkSetup('

elm 1

' + + '

elm 2

', + options + ); + assert.isTrue(checks['p-as-heading'].evaluate.apply(checkContext, params)); }); }); - }); \ No newline at end of file diff --git a/test/checks/navigation/unique-frame-title-after.js b/test/checks/navigation/unique-frame-title-after.js index d29987cde6..4337289bd1 100644 --- a/test/checks/navigation/unique-frame-title-after.js +++ b/test/checks/navigation/unique-frame-title-after.js @@ -1,15 +1,10 @@ describe('unique-frame-title-after', function () { 'use strict'; - var checkContext = { - _data: null, - data: function (d) { - this._data = d; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { - checkContext._data = null; + checkContext.reset(); }); diff --git a/test/checks/navigation/unique-frame-title.js b/test/checks/navigation/unique-frame-title.js index 50fa7e7309..7f5caa968d 100644 --- a/test/checks/navigation/unique-frame-title.js +++ b/test/checks/navigation/unique-frame-title.js @@ -1,15 +1,10 @@ describe('unique-frame-title', function () { 'use strict'; - var checkContext = { - _data: null, - data: function (d) { - this._data = d; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { - checkContext._data = null; + checkContext.reset(); }); diff --git a/test/checks/shared/button-has-visible-text.js b/test/checks/shared/button-has-visible-text.js index ce8c09eb3a..6ca87bd31b 100644 --- a/test/checks/shared/button-has-visible-text.js +++ b/test/checks/shared/button-has-visible-text.js @@ -3,16 +3,11 @@ describe('button-has-visible-text', function () { var fixture = document.getElementById('fixture'); var checkSetup = axe.testUtils.checkSetup; - var checkContext = { - _data: null, - data: function (d) { - this._data = d; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; - checkContext._data = null; + checkContext.reset(); }); it('should return false if button element is empty', function () { diff --git a/test/checks/shared/duplicate-id.js b/test/checks/shared/duplicate-id.js index 95e6627150..b7b9518e45 100644 --- a/test/checks/shared/duplicate-id.js +++ b/test/checks/shared/duplicate-id.js @@ -4,21 +4,11 @@ describe('duplicate-id', function () { var fixture = document.getElementById('fixture'); var shadowSupport = axe.testUtils.shadowSupport; - var checkContext = { - _relatedNodes: [], - _data: null, - data: function (d) { - this._data = d; - }, - relatedNodes: function (rn) { - this._relatedNodes = rn; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; - checkContext._relatedNodes = []; - checkContext._data = null; + checkContext.reset(); }); it('should return true if there is only one element with an ID', function () { diff --git a/test/checks/shared/has-visible-text.js b/test/checks/shared/has-visible-text.js index 4e51656943..6017448d51 100644 --- a/test/checks/shared/has-visible-text.js +++ b/test/checks/shared/has-visible-text.js @@ -4,17 +4,12 @@ describe('has-visible-text', function () { var fixture = document.getElementById('fixture'); var checkSetup = axe.testUtils.checkSetup; - var checkContext = { - _data: null, - data: function (d) { - this._data = d; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; axe._tree = undefined; - checkContext._data = null; + checkContext.reset(); }); it('should return false if there is no visible text', function () { diff --git a/test/checks/shared/non-empty-if-present.js b/test/checks/shared/non-empty-if-present.js index a2a89ebc85..0aafb3b4a0 100644 --- a/test/checks/shared/non-empty-if-present.js +++ b/test/checks/shared/non-empty-if-present.js @@ -8,16 +8,11 @@ describe('non-empty-if-present', function () { input.type = 'submit'; var isEdgeOrIe = typeof input.getAttribute('value') === 'string'; - var checkContext = { - _data: null, - data: function (d) { - this._data = d; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; - checkContext._data = null; + checkContext.reset(); }); it('should return false if a value is present', function () { diff --git a/test/checks/tables/has-th.js b/test/checks/tables/has-th.js index c31c47e588..d4163086d7 100644 --- a/test/checks/tables/has-th.js +++ b/test/checks/tables/has-th.js @@ -2,21 +2,11 @@ describe('has-th', function () { 'use strict'; var fixture = document.getElementById('fixture'); - var checkContext = { - _relatedNodes: [], - _data: null, - data: function (d) { - this._data = d; - }, - relatedNodes: function (rn) { - this._relatedNodes = rn; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; - checkContext._relatedNodes = []; - checkContext._data = null; + checkContext.reset(); }); it('should return false when the table has no th', function () { diff --git a/test/checks/tables/same-caption-summary.js b/test/checks/tables/same-caption-summary.js index 0cf5ddaed9..3756d7381e 100644 --- a/test/checks/tables/same-caption-summary.js +++ b/test/checks/tables/same-caption-summary.js @@ -6,16 +6,12 @@ describe('same-caption-summary', function () { var shadowCheckSetup = axe.testUtils.shadowCheckSetup; var shadowSupport = axe.testUtils.shadowSupport; - var checkContext = { - _data: null, - data: function (d) { - this._data = d; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; + checkContext.reset(); axe._tree = undefined; }); diff --git a/test/checks/tables/td-has-header.js b/test/checks/tables/td-has-header.js index 92accbdaff..5db716bd91 100644 --- a/test/checks/tables/td-has-header.js +++ b/test/checks/tables/td-has-header.js @@ -3,21 +3,11 @@ describe('td-has-header', function () { var fixture = document.getElementById('fixture'); var shadowSupport = axe.testUtils.shadowSupport.v1; - var checkContext = { - _relatedNodes: [], - _data: null, - data: function (d) { - this._data = d; - }, - relatedNodes: function (rn) { - this._relatedNodes = rn; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; - checkContext._relatedNodes = []; - checkContext._data = null; + checkContext.reset(); axe._tree = null; }); diff --git a/test/checks/tables/td-headers-attr.js b/test/checks/tables/td-headers-attr.js index 89e3e4844d..5ec33cbf97 100644 --- a/test/checks/tables/td-headers-attr.js +++ b/test/checks/tables/td-headers-attr.js @@ -2,21 +2,11 @@ describe('td-headers-attr', function () { 'use strict'; var fixture = document.getElementById('fixture'); - var checkContext = { - _relatedNodes: [], - _data: null, - data: function (d) { - this._data = d; - }, - relatedNodes: function (rn) { - this._relatedNodes = rn; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; - checkContext._relatedNodes = []; - checkContext._data = null; + checkContext.reset(); }); it('returns true no headers attribute is present', function () { diff --git a/test/checks/tables/th-has-data-cells.js b/test/checks/tables/th-has-data-cells.js index 8f0703cfaf..9a5b9e08fa 100644 --- a/test/checks/tables/th-has-data-cells.js +++ b/test/checks/tables/th-has-data-cells.js @@ -3,21 +3,11 @@ describe('th-has-data-cells', function () { var fixture = document.getElementById('fixture'); var shadowSupport = axe.testUtils.shadowSupport.v1; - var checkContext = { - _relatedNodes: [], - _data: null, - data: function (d) { - this._data = d; - }, - relatedNodes: function (rn) { - this._relatedNodes = rn; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; - checkContext._relatedNodes = []; - checkContext._data = null; + checkContext.reset(); }); it('should return true each row header has a non-empty cell', function (){ diff --git a/test/checks/visibility/hidden-content.js b/test/checks/visibility/hidden-content.js index 58ddc8ab29..ef84ee46af 100644 --- a/test/checks/visibility/hidden-content.js +++ b/test/checks/visibility/hidden-content.js @@ -5,16 +5,11 @@ describe('hidden content', function () { var fixture = document.getElementById('fixture'); var shadowSupport = axe.testUtils.shadowSupport.v1; var checkSetup = axe.testUtils.checkSetup; - var checkContext = { - _data: null, - data: function (d) { - this._data = d; - } - }; + var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { fixture.innerHTML = ''; - checkContext._data = null; + checkContext.reset(); axe._tree = undefined; }); diff --git a/test/testutils.js b/test/testutils.js index 940294d816..631003e41b 100644 --- a/test/testutils.js +++ b/test/testutils.js @@ -13,8 +13,8 @@ testUtils.MockCheckContext = function () { data: function (d) { this._data = d; }, - relatedNodes: function (rn) { - this._relatedNodes = rn; + relatedNodes: function (nodes) { + this._relatedNodes = Array.isArray(nodes) ? nodes : [nodes]; }, reset: function () { this._data = null; @@ -100,7 +100,7 @@ testUtils.checkSetup = function (content, options, target) { * Create check arguments with Shadow DOM. Target can be inside or outside of Shadow DOM, queried by * adding `id="target"` to a fragment. Or specify a custom selector as the `targetSelector` argument. * - * @param Node|String Stuff to go into the fixture (html or node) + * @param Node|String Stuff to go into the fixture (html string or DOM Node) * @param Node|String Stuff to go into the shadow boundary (html or node) * @param String Target selector for the check, can be inside or outside of Shadow DOM (default: '#target') * @param Object Options argument for the check (optional, default: {}) From 6145f7e3ea7f0a5103d1806c87498cc90b880772 Mon Sep 17 00:00:00 2001 From: Marcy Sutton Date: Tue, 13 Feb 2018 10:12:15 -0800 Subject: [PATCH 3/4] style: clean up a few tests --- test/checks/aria/allowed-attr.js | 10 ---------- test/checks/keyboard/has-at-least-one-main.js | 11 +++++------ test/checks/keyboard/tabindex.js | 5 +---- 3 files changed, 6 insertions(+), 20 deletions(-) diff --git a/test/checks/aria/allowed-attr.js b/test/checks/aria/allowed-attr.js index 98473880c3..34d602e27d 100644 --- a/test/checks/aria/allowed-attr.js +++ b/test/checks/aria/allowed-attr.js @@ -19,8 +19,6 @@ describe('aria-allowed-attr', function () { assert.isFalse(checks['aria-allowed-attr'].evaluate.call(checkContext, node)); assert.deepEqual(checkContext._data, ['aria-selected="true"']); - - }); it('should not report on required attributes', function () { @@ -32,8 +30,6 @@ describe('aria-allowed-attr', function () { fixture.appendChild(node); assert.isTrue(checks['aria-allowed-attr'].evaluate.call(checkContext, node)); - - }); it('should detect incorrectly used attributes - implicit role', function () { @@ -46,8 +42,6 @@ describe('aria-allowed-attr', function () { assert.isFalse(checks['aria-allowed-attr'].evaluate.call(checkContext, node)); assert.deepEqual(checkContext._data, ['aria-selected="true"']); - - }); it('should return true if there is no role', function () { @@ -60,8 +54,6 @@ describe('aria-allowed-attr', function () { assert.isTrue(checks['aria-allowed-attr'].evaluate.call(checkContext, node)); assert.isNull(checkContext._data); - - }); it('should determine attribute validity by calling axe.commons.aria.allowedAttr', function () { @@ -97,8 +89,6 @@ describe('aria-allowed-attr', function () { assert.isTrue(checks['aria-allowed-attr'].evaluate.call(checkContext, node)); assert.isNull(checkContext._data); - - }); it('should not report on allowed attributes', function () { diff --git a/test/checks/keyboard/has-at-least-one-main.js b/test/checks/keyboard/has-at-least-one-main.js index 02ba609051..eea12f126f 100644 --- a/test/checks/keyboard/has-at-least-one-main.js +++ b/test/checks/keyboard/has-at-least-one-main.js @@ -11,35 +11,35 @@ describe('has-at-least-one-main', function () { }); it('should return false if no div has role property', function() { - var params = checkSetup('
No role
'); + var params = checkSetup('
No role
'); var mainIsFound = checks['has-at-least-one-main'].evaluate.apply(checkContext, params); assert.isFalse(mainIsFound); assert.deepEqual(checkContext._data, mainIsFound); }); it('should return false if div has empty role', function() { - var params = checkSetup('
Empty role
'); + var params = checkSetup('
Empty role
'); var mainIsFound = checks['has-at-least-one-main'].evaluate.apply(checkContext, params); assert.isFalse(mainIsFound); assert.equal(checkContext._data, mainIsFound); }); it('should return false if div has role not equal to main', function() { - var params = checkSetup('
Wrong role
'); + var params = checkSetup('
Wrong role
'); var mainIsFound = checks['has-at-least-one-main'].evaluate.apply(checkContext, params); assert.isFalse(mainIsFound); assert.equal(checkContext._data, mainIsFound); }); it('should return true if main landmark exists', function(){ - var params = checkSetup('
main landmark
'); + var params = checkSetup('
main landmark
'); var mainIsFound = checks['has-at-least-one-main'].evaluate.apply(checkContext, params); assert.isTrue(mainIsFound); assert.equal(checkContext._data, mainIsFound); }); it('should return true if one div has role equal to main', function() { - var params = checkSetup('
Div with role main
'); + var params = checkSetup('
Div with role main
'); var mainIsFound = checks['has-at-least-one-main'].evaluate.apply(checkContext, params); assert.isTrue(mainIsFound); assert.equal(checkContext._data, mainIsFound); @@ -58,5 +58,4 @@ describe('has-at-least-one-main', function () { var results = [{data: false, result: false}, {data: false, result: false}]; assert.isFalse(checks['has-at-least-one-main'].after(results)[0].result && checks['has-at-least-one-main'].after(results)[1].result); }); - }); \ No newline at end of file diff --git a/test/checks/keyboard/tabindex.js b/test/checks/keyboard/tabindex.js index 4eb6f0bd4a..ce542c067c 100644 --- a/test/checks/keyboard/tabindex.js +++ b/test/checks/keyboard/tabindex.js @@ -13,17 +13,14 @@ describe('tabindex', function () { fixture.appendChild(node); assert.isFalse(checks.tabindex.evaluate(node)); - - }); + it('should pass if the tabindex is <= 0', function () { var node = document.createElement('div'); node.setAttribute('tabindex', '0'); fixture.appendChild(node); assert.isTrue(checks.tabindex.evaluate(node)); - - }); }); From 0e48413e158e998270ef801545bab02fd7d724d9 Mon Sep 17 00:00:00 2001 From: Marcy Sutton Date: Tue, 13 Feb 2018 10:12:51 -0800 Subject: [PATCH 4/4] fix: add shadow dom coverage to all checks Closes #690 --- lib/checks/navigation/header-present.js | 2 +- .../navigation/internal-link-present.js | 3 ++- test/checks/aria/errormessage.js | 22 ++++++++++++++++++- test/checks/keyboard/has-at-least-one-main.js | 7 ++++++ test/checks/navigation/header-present.js | 10 +++++++++ .../navigation/internal-link-present.js | 10 +++++++++ test/checks/navigation/p-as-heading.js | 16 ++++++++++++++ test/testutils.js | 19 +++++++++++----- 8 files changed, 80 insertions(+), 9 deletions(-) diff --git a/lib/checks/navigation/header-present.js b/lib/checks/navigation/header-present.js index aafe0e7c30..0140c85b6c 100644 --- a/lib/checks/navigation/header-present.js +++ b/lib/checks/navigation/header-present.js @@ -1 +1 @@ -return !!node.querySelector('h1, h2, h3, h4, h5, h6, [role="heading"]'); +return !!axe.utils.querySelectorAll(virtualNode, 'h1, h2, h3, h4, h5, h6, [role="heading"]')[0]; diff --git a/lib/checks/navigation/internal-link-present.js b/lib/checks/navigation/internal-link-present.js index 8f164ca3da..ad7fd17cb6 100644 --- a/lib/checks/navigation/internal-link-present.js +++ b/lib/checks/navigation/internal-link-present.js @@ -1 +1,2 @@ -return !!node.querySelector('a[href^="#"]'); +const links = axe.utils.querySelectorAll(virtualNode, 'a[href]'); +return links.some(vLink => vLink.actualNode.getAttribute('href')[0] === '#'); diff --git a/test/checks/aria/errormessage.js b/test/checks/aria/errormessage.js index 4605f10dba..bf1c8c193e 100644 --- a/test/checks/aria/errormessage.js +++ b/test/checks/aria/errormessage.js @@ -2,7 +2,8 @@ describe('aria-errormessage', function () { 'use strict'; var fixture = document.getElementById('fixture'); - + var shadowSupported = axe.testUtils.shadowSupport.v1; + var shadowCheckSetup = axe.testUtils.shadowCheckSetup; var checkContext = axe.testUtils.MockCheckContext(); afterEach(function () { @@ -46,4 +47,23 @@ describe('aria-errormessage', function () { target.setAttribute('aria-describedby', 'plain'); assert.isTrue(checks['aria-errormessage'].evaluate.call(checkContext, target)); }); + + (shadowSupported ? it : xit) + ('should return false if aria-errormessage value crosses shadow boundary', function () { + var params = shadowCheckSetup( + '
', + '
' + ); + assert.isFalse(checks['aria-errormessage'].evaluate.apply(checkContext, params)); + }); + + (shadowSupported ? it : xit) + ('should return true if aria-errormessage and value are inside shadow dom', function () { + var params = shadowCheckSetup( + '
', + '
' + + '
' + ); + assert.isTrue(checks['aria-errormessage'].evaluate.apply(checkContext, params)); + }); }); diff --git a/test/checks/keyboard/has-at-least-one-main.js b/test/checks/keyboard/has-at-least-one-main.js index eea12f126f..6dd7b2a59a 100644 --- a/test/checks/keyboard/has-at-least-one-main.js +++ b/test/checks/keyboard/has-at-least-one-main.js @@ -4,10 +4,13 @@ describe('has-at-least-one-main', function () { var fixture = document.getElementById('fixture'); var checkContext = new axe.testUtils.MockCheckContext(); var checkSetup = axe.testUtils.checkSetup; + var shadowSupported = axe.testUtils.shadowSupport.v1; + var shadowCheckSetup = axe.testUtils.shadowCheckSetup; afterEach(function () { fixture.innerHTML = ''; checkContext.reset(); + axe._tree = undefined; }); it('should return false if no div has role property', function() { @@ -44,6 +47,10 @@ describe('has-at-least-one-main', function () { assert.isTrue(mainIsFound); assert.equal(checkContext._data, mainIsFound); }); + + (shadowSupported ? it : xit) + ('should return true if main is inside of shadow dom', function() { + var params = shadowCheckSetup('
', '
main landmark
'); var mainIsFound = checks['has-at-least-one-main'].evaluate.apply(checkContext, params); assert.isTrue(mainIsFound); assert.equal(checkContext._data, mainIsFound); diff --git a/test/checks/navigation/header-present.js b/test/checks/navigation/header-present.js index d1b535db28..df45cac5f4 100644 --- a/test/checks/navigation/header-present.js +++ b/test/checks/navigation/header-present.js @@ -3,7 +3,9 @@ describe('header-present', function () { var fixture = document.getElementById('fixture'); var checkSetup = axe.testUtils.checkSetup; + var shadowSupported = axe.testUtils.shadowSupport.v1; var checkContext = axe.testUtils.MockCheckContext(); + var shadowCheckSetup = axe.testUtils.shadowCheckSetup; afterEach(function () { fixture.innerHTML = ''; @@ -41,4 +43,12 @@ describe('header-present', function () { assert.isFalse(checks['header-present'].evaluate.apply(checkContext, params)); }); + (shadowSupported ? it : xit) + ('should return true if heading is in shadow dom', function () { + var params = shadowCheckSetup( + '
', + '

' + ); + assert.isTrue(checks['header-present'].evaluate.apply(checkContext, params)); + }); }); diff --git a/test/checks/navigation/internal-link-present.js b/test/checks/navigation/internal-link-present.js index 964af66069..c6d372f09b 100644 --- a/test/checks/navigation/internal-link-present.js +++ b/test/checks/navigation/internal-link-present.js @@ -2,8 +2,10 @@ describe('internal-link-present', function () { 'use strict'; var fixture = document.getElementById('fixture'); + var shadowSupported = axe.testUtils.shadowSupport.v1; var checkContext = axe.testUtils.MockCheckContext(); var checkSetup = axe.testUtils.checkSetup; + var shadowCheckSetup = axe.testUtils.shadowCheckSetup; afterEach(function () { fixture.innerHTML = ''; @@ -21,4 +23,12 @@ describe('internal-link-present', function () { assert.isFalse(checks['internal-link-present'].evaluate.apply(checkContext, params)); }); + (shadowSupported ? it : xit) + ('should return true when internal link is found in shadow dom', function () { + var params = shadowCheckSetup( + '
', + 'hi' + ); + assert.isTrue(checks['internal-link-present'].evaluate.apply(checkContext, params)); + }); }); diff --git a/test/checks/navigation/p-as-heading.js b/test/checks/navigation/p-as-heading.js index 08230dd216..af3f1b7ef5 100644 --- a/test/checks/navigation/p-as-heading.js +++ b/test/checks/navigation/p-as-heading.js @@ -172,4 +172,20 @@ describe('p-as-heading', function () { assert.isTrue(checks['p-as-heading'].evaluate.apply(checkContext, params)); }); }); + + (shadowSupported ? it : xit) + ('returns undefined instead of false if the element is inside a blockquote in light dom', function () { + var params = shadowCheckSetup('
', + '

elm 1

elm 2

', + testOptions); + assert.isUndefined(checks['p-as-heading'].evaluate.apply(checkContext, params)); + }); + + (shadowSupported ? it : xit) + ('returns true over undefined from within a blockquote in light dom', function () { + var params = shadowCheckSetup('
', + '

elm 1

elm 2

', + testOptions); + assert.isTrue(checks['p-as-heading'].evaluate.apply(checkContext, params)); + }); }); \ No newline at end of file diff --git a/test/testutils.js b/test/testutils.js index 631003e41b..1a9e05c4d0 100644 --- a/test/testutils.js +++ b/test/testutils.js @@ -102,25 +102,32 @@ testUtils.checkSetup = function (content, options, target) { * * @param Node|String Stuff to go into the fixture (html string or DOM Node) * @param Node|String Stuff to go into the shadow boundary (html or node) - * @param String Target selector for the check, can be inside or outside of Shadow DOM (default: '#target') * @param Object Options argument for the check (optional, default: {}) + * @param String Target selector for the check, can be inside or outside of Shadow DOM (optional, default: '#target') * @return Array */ -testUtils.shadowCheckSetup = function (content, shadowContent, targetSelector, options) { +testUtils.shadowCheckSetup = function (content, shadowContent, options, targetSelector) { 'use strict'; - // Normalize the params + // Normalize target, allow it to be the provided string or use '#target' to query composed tree + if (typeof targetSelector !== 'string') { + targetSelector = '#target'; + } + + // Normalize the object params if (typeof options !== 'object') { options = {}; } - // Normalize target, allow it to be the provided string or use '#target' to query composed tree - targetSelector = targetSelector || '#target'; var fixture = testUtils.fixtureSetup(content); var targetCandidate = fixture.querySelector(targetSelector); var container = targetCandidate; if (!targetCandidate) { - container = fixture.firstChild; + // check if content specifies a shadow container + container = fixture.querySelector('#shadow'); + if (!container) { + container = fixture.firstChild; + } } // attach a shadowRoot with the content provided var shadowRoot = container.attachShadow({ mode: 'open' });