From f5e6e235d8581db54c6c7f4ea1b0f0278186d051 Mon Sep 17 00:00:00 2001 From: Steven Lambert Date: Tue, 26 Jul 2022 11:10:49 -0600 Subject: [PATCH 01/14] fix(color-contrast): correctly determine color contrast for floating element that exactly overlaps midpoint of node --- lib/commons/dom/get-rect-stack.js | 4 ++-- test/checks/color/color-contrast.js | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/commons/dom/get-rect-stack.js b/lib/commons/dom/get-rect-stack.js index 5c0bc929a2..3782473c21 100644 --- a/lib/commons/dom/get-rect-stack.js +++ b/lib/commons/dom/get-rect-stack.js @@ -127,9 +127,9 @@ export function getRectStack(grid, rect, recursed = false) { // perform an AABB (axis-aligned bounding box) collision check for the // point inside the rect return ( - x <= rectX + clientRect.width && + x < rectX + clientRect.width && x >= rectX && - y <= rectY + clientRect.height && + y < rectY + clientRect.height && y >= rectY ); }); diff --git a/test/checks/color/color-contrast.js b/test/checks/color/color-contrast.js index c165796f57..422f1dd7aa 100644 --- a/test/checks/color/color-contrast.js +++ b/test/checks/color/color-contrast.js @@ -400,6 +400,18 @@ describe('color-contrast', function() { }); }); + it('should return true for floating element whose position exactly equals the midpoint of the container', function() { + var params = checkSetup( + '
' + + '
' + + '

Foo

' + + 'Bar' + + '
' + ); + + assert.isTrue(contrastEvaluate.apply(checkContext, params)); + }); + describe('with pseudo elements', function() { it('should return undefined if :before pseudo element has a background color', function() { var params = checkSetup( From 7b550dcf16295833c6938462d4f2625edefd0cc6 Mon Sep 17 00:00:00 2001 From: Steven Lambert Date: Wed, 27 Jul 2022 09:59:31 -0600 Subject: [PATCH 02/14] fix firefox --- lib/commons/dom/get-rect-stack.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/commons/dom/get-rect-stack.js b/lib/commons/dom/get-rect-stack.js index 3782473c21..3a3baa49f1 100644 --- a/lib/commons/dom/get-rect-stack.js +++ b/lib/commons/dom/get-rect-stack.js @@ -95,8 +95,8 @@ export function createGrid( export function getRectStack(grid, rect, recursed = false) { // use center point of rect - const x = rect.left + rect.width / 2; - const y = rect.top + rect.height / 2; + const x = toFixed(rect.left + rect.width / 2); + const y = toFixed(rect.top + rect.height / 2); // NOTE: there is a very rare edge case in Chrome vs Firefox that can // return different results of `document.elementsFromPoint`. If the center @@ -127,10 +127,10 @@ export function getRectStack(grid, rect, recursed = false) { // perform an AABB (axis-aligned bounding box) collision check for the // point inside the rect return ( - x < rectX + clientRect.width && - x >= rectX && - y < rectY + clientRect.height && - y >= rectY + x < toFixed(rectX + clientRect.width) && + x >= toFixed(rectX) && + y < toFixed(rectY + clientRect.height) && + y >= toFixed(rectY) ); }); }) ?? []; @@ -157,6 +157,13 @@ export function getRectStack(grid, rect, recursed = false) { return stack; } +/** + * Browsers handle floating point precision of bounding rects differently, so we need to normalize the size to account for this. + */ +function toFixed(float, digits = 2) { + return parseFloat(float.toFixed(digits)); +} + /** * Determine if node produces a stacking context. * References: From 947514c5a41bce090e47222be335117165b5cad1 Mon Sep 17 00:00:00 2001 From: Steven Lambert Date: Wed, 27 Jul 2022 10:26:22 -0600 Subject: [PATCH 03/14] test --- lib/commons/dom/get-rect-stack.js | 33 +++++++++++++++++-------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/lib/commons/dom/get-rect-stack.js b/lib/commons/dom/get-rect-stack.js index 3a3baa49f1..6febf1a404 100644 --- a/lib/commons/dom/get-rect-stack.js +++ b/lib/commons/dom/get-rect-stack.js @@ -95,8 +95,10 @@ export function createGrid( export function getRectStack(grid, rect, recursed = false) { // use center point of rect - const x = toFixed(rect.left + rect.width / 2); - const y = toFixed(rect.top + rect.height / 2); + const x = rect.left + rect.width / 2; + const y = rect.top + rect.height / 2; + const floorX = floor(x); + const floorY = floor(y); // NOTE: there is a very rare edge case in Chrome vs Firefox that can // return different results of `document.elementsFromPoint`. If the center @@ -104,8 +106,8 @@ export function getRectStack(grid, rect, recursed = false) { // Chrome appears to round the number up and return the element while Firefox // keeps the number as is and won't return the element. In this case, we // went with pixel perfect collision rather than rounding - const row = (y / gridSize) | 0; - const col = (x / gridSize) | 0; + const row = floor(y / gridSize); + const col = floor(x / gridSize); // we're making an assumption that there cannot be an element in the // grid which escapes the grid bounds. For example, if the grid is 4x4 there @@ -126,11 +128,13 @@ export function getRectStack(grid, rect, recursed = false) { // perform an AABB (axis-aligned bounding box) collision check for the // point inside the rect + // account for differences in how browsers handle floating point + // precision of bounding rects return ( - x < toFixed(rectX + clientRect.width) && - x >= toFixed(rectX) && - y < toFixed(rectY + clientRect.height) && - y >= toFixed(rectY) + floorX < floor(rectX + clientRect.width) && + floorX >= floor(rectX) && + floorY < floor(rectY + clientRect.height) && + floorY >= floor(rectY) ); }); }) ?? []; @@ -157,11 +161,9 @@ export function getRectStack(grid, rect, recursed = false) { return stack; } -/** - * Browsers handle floating point precision of bounding rects differently, so we need to normalize the size to account for this. - */ -function toFixed(float, digits = 2) { - return parseFloat(float.toFixed(digits)); +// equivalent to Math.floor(float) but is slightly faster +function floor(float) { + return float | 0; } /** @@ -410,8 +412,9 @@ function visuallySort(a, b) { // bNode is a node that shares a host with some part of the a parent // shadow tree, find the aNode that shares the same host as bNode - aNode = boundaries.find(boundary => boundary.root === bNode.getRootNode()) - .node; + aNode = boundaries.find( + boundary => boundary.root === bNode.getRootNode() + ).node; // sort child of shadow to it's host node by finding which element is // the child of the host and sorting it before the host From 413c6e410ae7ddec5950dd217762cefa4c527b05 Mon Sep 17 00:00:00 2001 From: Steven Lambert Date: Wed, 27 Jul 2022 10:56:12 -0600 Subject: [PATCH 04/14] debug --- lib/commons/dom/get-rect-stack.js | 10 ++++++++++ test/checks/color/color-contrast.js | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/commons/dom/get-rect-stack.js b/lib/commons/dom/get-rect-stack.js index 6febf1a404..0ab3d7af02 100644 --- a/lib/commons/dom/get-rect-stack.js +++ b/lib/commons/dom/get-rect-stack.js @@ -126,6 +126,16 @@ export function getRectStack(grid, rect, recursed = false) { const rectX = clientRect.left; const rectY = clientRect.top; + if (gridCellNode.attr('id') === 'debugNode') { + console.log(JSON.stringify({ + el: gridCellNode.actualNode.cloneNode(false).outerHTML, + y: y, + floorY: floorY, + 'rectY+height': rectY + clientRect.height, + 'floor(rectY+height)': floor(rectY + clientRect.height) + },null,2)); + } + // perform an AABB (axis-aligned bounding box) collision check for the // point inside the rect // account for differences in how browsers handle floating point diff --git a/test/checks/color/color-contrast.js b/test/checks/color/color-contrast.js index 422f1dd7aa..87d1bd4d2d 100644 --- a/test/checks/color/color-contrast.js +++ b/test/checks/color/color-contrast.js @@ -1,4 +1,4 @@ -describe('color-contrast', function() { +describe.only('color-contrast', function() { 'use strict'; var fixture = document.getElementById('fixture'); @@ -404,7 +404,7 @@ describe('color-contrast', function() { var params = checkSetup( '
' + '
' + - '

Foo

' + + '

Foo

' + 'Bar' + '
' ); From 431a8c82595559942d9d3de717b50b9f2fbc0a10 Mon Sep 17 00:00:00 2001 From: Steven Lambert Date: Wed, 27 Jul 2022 11:01:59 -0600 Subject: [PATCH 05/14] remove only --- test/checks/color/color-contrast.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/checks/color/color-contrast.js b/test/checks/color/color-contrast.js index 87d1bd4d2d..a7226bae6e 100644 --- a/test/checks/color/color-contrast.js +++ b/test/checks/color/color-contrast.js @@ -1,4 +1,4 @@ -describe.only('color-contrast', function() { +describe('color-contrast', function() { 'use strict'; var fixture = document.getElementById('fixture'); From 1126218b841efb0685d1a4e43a884fd3748e1448 Mon Sep 17 00:00:00 2001 From: Steven Lambert Date: Wed, 27 Jul 2022 11:40:13 -0600 Subject: [PATCH 06/14] increase logs --- lib/commons/dom/get-rect-stack.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/commons/dom/get-rect-stack.js b/lib/commons/dom/get-rect-stack.js index 0ab3d7af02..a347064286 100644 --- a/lib/commons/dom/get-rect-stack.js +++ b/lib/commons/dom/get-rect-stack.js @@ -131,6 +131,8 @@ export function getRectStack(grid, rect, recursed = false) { el: gridCellNode.actualNode.cloneNode(false).outerHTML, y: y, floorY: floorY, + 'rectY': rectY, + height: clientRect.height, 'rectY+height': rectY + clientRect.height, 'floor(rectY+height)': floor(rectY + clientRect.height) },null,2)); From 54f5165d675c9346310a2dc3a775831915f69028 Mon Sep 17 00:00:00 2001 From: Steven Lambert Date: Fri, 29 Jul 2022 08:41:47 -0600 Subject: [PATCH 07/14] change test to not use floats --- test/checks/color/color-contrast.js | 162 ++++++++++++++-------------- 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/test/checks/color/color-contrast.js b/test/checks/color/color-contrast.js index a7226bae6e..48d470f402 100644 --- a/test/checks/color/color-contrast.js +++ b/test/checks/color/color-contrast.js @@ -1,4 +1,4 @@ -describe('color-contrast', function() { +describe('color-contrast', function () { 'use strict'; var fixture = document.getElementById('fixture'); @@ -10,13 +10,13 @@ describe('color-contrast', function() { var checkContext = axe.testUtils.MockCheckContext(); var contrastEvaluate = axe.testUtils.getCheckEvaluate('color-contrast'); - afterEach(function() { + afterEach(function () { fixture.innerHTML = ''; checkContext.reset(); axe._tree = undefined; }); - it('should return true for hidden element', function() { + it('should return true for hidden element', function () { var params = checkSetup( '
' + 'My text
' @@ -26,7 +26,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should return true for child of hidden element', function() { + it('should return true for child of hidden element', function () { var params = checkSetup( '
' + 'My text
' @@ -36,7 +36,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should return the proper values stored in data', function() { + it('should return the proper values stored in data', function () { var params = checkSetup( '
' + 'My text
' @@ -53,7 +53,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should return true when there is sufficient contrast because of bold tag', function() { + it('should return true when there is sufficient contrast because of bold tag', function () { var params = checkSetup( '
' + 'My text
' @@ -63,7 +63,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should return true when there is sufficient contrast because of font weight', function() { + it('should return true when there is sufficient contrast because of font weight', function () { var params = checkSetup( '
' + 'My text
' @@ -73,7 +73,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should return false when there is not sufficient contrast because of font weight', function() { + it('should return false when there is not sufficient contrast because of font weight', function () { var params = checkSetup( '
' + 'My text
' @@ -83,7 +83,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, [params[0]]); }); - it('should return true when there is sufficient contrast because of font size', function() { + it('should return true when there is sufficient contrast because of font size', function () { var params = checkSetup( '
' + 'My text
' @@ -92,7 +92,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should return false when there is not sufficient contrast because of font size', function() { + it('should return false when there is not sufficient contrast because of font size', function () { var params = checkSetup( '
' + 'My text
' @@ -102,7 +102,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, [params[0]]); }); - it('should return true when there is sufficient contrast with explicit transparency', function() { + it('should return true when there is sufficient contrast with explicit transparency', function () { var params = checkSetup( '
' + 'My text
' @@ -112,7 +112,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should return true when there is sufficient contrast with implicit transparency', function() { + it('should return true when there is sufficient contrast with implicit transparency', function () { var params = checkSetup( '
' + 'My text
' @@ -122,7 +122,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should return true when there is sufficient contrast', function() { + it('should return true when there is sufficient contrast', function () { var params = checkSetup( '
' + 'My text
' @@ -132,7 +132,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should return true for inline elements with sufficient contrast spanning multiple lines', function() { + it('should return true for inline elements with sufficient contrast spanning multiple lines', function () { var params = checkSetup( '

Text oh heyyyy and here\'s
a link

' ); @@ -140,7 +140,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should return undefined for inline elements spanning multiple lines that are overlapped', function() { + it('should return undefined for inline elements spanning multiple lines that are overlapped', function () { var params = checkSetup( '
' + '

Text oh heyyyy and here\'s
a link

' @@ -149,7 +149,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should return true for truncated inline elements', function() { + it('should return true for truncated inline elements', function () { var params = checkSetup( '

Text oh heyyyy Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed et sollicitudin quam. Fusce mi odio, egestas pulvinar erat eget, vehicula tempus est. Proin vitae ullamcorper velit. Donec sagittis est justo, mattis iaculis arcu facilisis id. Proin pulvinar ornare arcu a fermentum. Quisque et dignissim nulla, sit amet consectetur ipsum. Donec in libero porttitor, dapibus neque imperdiet, aliquam est. Vivamus blandit volutpat fringilla. In mi magna, mollis sit amet imperdiet eu, rutrum ut tellus. Mauris vel condimentum nibh, quis ultricies nisi. Vivamus accumsan quam mauris, id iaculis quam fringilla ac. Curabitur pulvinar dolor ac magna vehicula, non auctor ligula dignissim. Nam ac nibh porttitor, malesuada tortor varius, feugiat turpis. Mauris dapibus, tellus ut viverra porta, ipsum turpis bibendum ligula, at tempor felis ante non libero. Donec dapibus, diam sit amet posuere commodo, magna orci hendrerit ipsum, eu egestas mauris nulla ut ipsum. Sed luctus, orci in fringilla finibus, odio leo porta dolor, eu dignissim risus eros eget erat

' ); @@ -157,7 +157,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should return true for inline elements with sufficient contrast', function() { + it('should return true for inline elements with sufficient contrast', function () { var params = checkSetup( '

Text oh heyyyy and here\'s bold text

' ); @@ -165,7 +165,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should return false when there is not sufficient contrast between foreground and background', function() { + it('should return false when there is not sufficient contrast between foreground and background', function () { var params = checkSetup( '
' + 'My text
' @@ -176,7 +176,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._data.messageKey, null); }); - it('should ignore position:fixed elements above the target', function() { + it('should ignore position:fixed elements above the target', function () { var params = checkSetup( '
' + '
header
' + @@ -190,7 +190,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, [expectedRelatedNodes]); }); - it('should ignore position:fixed elements directly above the target', function() { + it('should ignore position:fixed elements directly above the target', function () { var params = checkSetup( '
' + '
header
' + @@ -204,7 +204,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, [expectedRelatedNodes]); }); - it('should find contrast issues on position:fixed elements', function() { + it('should find contrast issues on position:fixed elements', function () { var params = checkSetup( '
' + '
header
' + @@ -217,7 +217,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, [params[0]]); }); - it('should return undefined for background-image elements', function() { + it('should return undefined for background-image elements', function () { var dataURI = 'data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/' + 'XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkA' + @@ -238,7 +238,7 @@ describe('color-contrast', function() { assert.equal(checkContext._data.messageKey, 'bgImage'); }); - it('should return undefined for background-gradient elements', function() { + it('should return undefined for background-gradient elements', function () { var params = checkSetup( '
' + '

Text 2

' + @@ -251,9 +251,9 @@ describe('color-contrast', function() { assert.equal(checkContext._data.contrastRatio, 0); }); - it('should return undefined when there are elements overlapping', function(done) { + it('should return undefined when there are elements overlapping', function (done) { // Give Edge time to scroll... :/ - setTimeout(function() { + setTimeout(function () { var params = checkSetup( '
' + 'My text
' @@ -267,14 +267,14 @@ describe('color-contrast', function() { }, 10); }); - it('should return true when a form wraps mixed content', function() { + it('should return true when a form wraps mixed content', function () { var params = checkSetup( '

Some text

' ); assert.isTrue(contrastEvaluate.apply(checkContext, params)); }); - it('should return true when a label wraps a text input', function() { + it('should return true when a label wraps a text input', function () { fixtureSetup(''); var target = fixture.querySelector('#target'); var virtualNode = axe.utils.getNodeFromTree(target); @@ -282,7 +282,7 @@ describe('color-contrast', function() { assert.isTrue(result); }); - it("should return true when a label wraps a text input but doesn't overlap", function() { + it("should return true when a label wraps a text input but doesn't overlap", function () { var params = checkSetup( '' @@ -291,7 +291,7 @@ describe('color-contrast', function() { assert.isTrue(result); }); - it('should return true when there is sufficient contrast based on thead', function() { + it('should return true when there is sufficient contrast based on thead', function () { var params = checkSetup( '
Col 1
' ); @@ -299,7 +299,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should return true when there is sufficient contrast based on tbody', function() { + it('should return true when there is sufficient contrast based on tbody', function () { var params = checkSetup( '
Col 1
' ); @@ -307,9 +307,9 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should return undefined if element overlaps text content', function(done) { + it('should return undefined if element overlaps text content', function (done) { // Give Edge time to scroll - setTimeout(function() { + setTimeout(function () { var params = checkSetup( '
' + '
Hi
' + @@ -324,7 +324,7 @@ describe('color-contrast', function() { }, 10); }); - it('should return undefined if element has same color as background', function() { + it('should return undefined if element has same color as background', function () { var params = checkSetup( '
' + '
Text
' + @@ -336,7 +336,7 @@ describe('color-contrast', function() { assert.equal(checkContext._data.contrastRatio, 1); }); - it('returns relatedNodes with undefined', function() { + it('returns relatedNodes with undefined', function () { var dataURI = 'data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/' + 'XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkA' + @@ -358,7 +358,7 @@ describe('color-contrast', function() { ); }); - it('should not error if client rects do not fill entire bounding rect', function() { + it('should not error if client rects do not fill entire bounding rect', function () { var params = checkSetup( '
' +
         '\nx x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x ' +
@@ -395,25 +395,25 @@ describe('color-contrast', function() {
         '\nx' +
         '\n
' ); - assert.doesNotThrow(function() { + assert.doesNotThrow(function () { contrastEvaluate.apply(checkContext, params); }); }); - it('should return true for floating element whose position exactly equals the midpoint of the container', function() { + it('should return true for element which exactly overlaps midpoint of another element', function () { var params = checkSetup( '
' + - '
' + + '
' + '

Foo

' + 'Bar' + - '
' + '
' ); assert.isTrue(contrastEvaluate.apply(checkContext, params)); }); - describe('with pseudo elements', function() { - it('should return undefined if :before pseudo element has a background color', function() { + describe('with pseudo elements', function () { + it('should return undefined if :before pseudo element has a background color', function () { var params = checkSetup( '' + '

Content

' @@ -432,7 +432,7 @@ describe('color-contrast', function() { ); }); - it('should return undefined if :after pseudo element has a background color', function() { + it('should return undefined if :after pseudo element has a background color', function () { var params = checkSetup( '' + '

Content

' @@ -451,7 +451,7 @@ describe('color-contrast', function() { ); }); - it('should return undefined if pseudo element has a background image', function() { + it('should return undefined if pseudo element has a background image', function () { var dataURI = 'data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/' + 'XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkA' + @@ -478,7 +478,7 @@ describe('color-contrast', function() { ); }); - it('should not return undefined if pseudo element has no content', function() { + it('should not return undefined if pseudo element has no content', function () { var params = checkSetup( '' + '

Content

' @@ -487,7 +487,7 @@ describe('color-contrast', function() { assert.isTrue(contrastEvaluate.apply(checkContext, params)); }); - it('should not return undefined if pseudo element is not absolutely positioned no content', function() { + it('should not return undefined if pseudo element is not absolutely positioned no content', function () { var params = checkSetup( '' + '

Content

' @@ -496,7 +496,7 @@ describe('color-contrast', function() { assert.isTrue(contrastEvaluate.apply(checkContext, params)); }); - it('should not return undefined if pseudo element is has zero dimension', function() { + it('should not return undefined if pseudo element is has zero dimension', function () { var params = checkSetup( '' + '

Content

' @@ -505,7 +505,7 @@ describe('color-contrast', function() { assert.isTrue(contrastEvaluate.apply(checkContext, params)); }); - it("should not return undefined if pseudo element doesn't have a background", function() { + it("should not return undefined if pseudo element doesn't have a background", function () { var params = checkSetup( '' + '

Content

' @@ -514,7 +514,7 @@ describe('color-contrast', function() { assert.isTrue(contrastEvaluate.apply(checkContext, params)); }); - it('should not return undefined if pseudo element has visibility: hidden', function() { + it('should not return undefined if pseudo element has visibility: hidden', function () { var params = checkSetup( '' + '

Content

' @@ -523,7 +523,7 @@ describe('color-contrast', function() { assert.isTrue(contrastEvaluate.apply(checkContext, params)); }); - it('should not return undefined if pseudo element has display: none', function() { + it('should not return undefined if pseudo element has display: none', function () { var params = checkSetup( '' + '

Content

' @@ -532,7 +532,7 @@ describe('color-contrast', function() { assert.isTrue(contrastEvaluate.apply(checkContext, params)); }); - it('should return undefined if pseudo element is more than 25% of the element', function() { + it('should return undefined if pseudo element is more than 25% of the element', function () { var params = checkSetup( '' + @@ -541,7 +541,7 @@ describe('color-contrast', function() { assert.isUndefined(contrastEvaluate.apply(checkContext, params)); }); - it('should not return undefined if pseudo element is 25% of the element', function() { + it('should not return undefined if pseudo element is 25% of the element', function () { var params = checkSetup( '' + @@ -552,7 +552,7 @@ describe('color-contrast', function() { (isIE11 ? it : xit)( 'should return undefined if the unit is not in px', - function() { + function () { var params = checkSetup( '' + @@ -563,8 +563,8 @@ describe('color-contrast', function() { ); }); - describe('with special texts', function() { - it('should return undefined for a single character text with insufficient contrast', function() { + describe('with special texts', function () { + it('should return undefined for a single character text with insufficient contrast', function () { var params = checkSetup( '
' + '
X
' + @@ -576,7 +576,7 @@ describe('color-contrast', function() { assert.equal(checkContext._data.messageKey, 'shortTextContent'); }); - it('should return true for a single character text with insufficient contrast', function() { + it('should return true for a single character text with insufficient contrast', function () { var params = checkSetup( '
' + '
X
' + @@ -588,7 +588,7 @@ describe('color-contrast', function() { assert.equal(checkContext._data.messageKey, 'shortTextContent'); }); - it('should return undefined when the text only contains nonBmp unicode when the ignoreUnicode option is true', function() { + it('should return undefined when the text only contains nonBmp unicode when the ignoreUnicode option is true', function () { var params = checkSetup( '
' + '
₠ ₡ ₢ ₣
' + @@ -603,7 +603,7 @@ describe('color-contrast', function() { assert.equal(checkContext._data.messageKey, 'nonBmp'); }); - it('should return true when the text only contains nonBmp unicode when the ignoreUnicode option is false, and there is sufficient contrast', function() { + it('should return true when the text only contains nonBmp unicode when the ignoreUnicode option is false, and there is sufficient contrast', function () { var params = checkSetup( '
' + '
' + @@ -617,7 +617,7 @@ describe('color-contrast', function() { assert.isTrue(actual); }); - it('should return undefined when the text only contains nonBmp unicode when the ignoreUnicode option is false and the ignoreLength option is default, and there is insufficient contrast', function() { + it('should return undefined when the text only contains nonBmp unicode when the ignoreUnicode option is false and the ignoreLength option is default, and there is insufficient contrast', function () { var params = checkSetup( '
' + '
' + @@ -632,7 +632,7 @@ describe('color-contrast', function() { assert.equal(checkContext._data.messageKey, 'shortTextContent'); }); - it('should return false when the text only contains nonBmp unicode when the ignoreUnicode option is false and the ignoreLength option is true, and there is insufficient contrast', function() { + it('should return false when the text only contains nonBmp unicode when the ignoreUnicode option is false and the ignoreLength option is true, and there is insufficient contrast', function () { var params = checkSetup( '
' + '
' + @@ -648,8 +648,8 @@ describe('color-contrast', function() { }); }); - describe('options', function() { - it('should support options.boldValue', function() { + describe('options', function () { + it('should support options.boldValue', function () { var params = checkSetup( '
' + 'My text
', @@ -662,7 +662,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should support options.boldTextPt', function() { + it('should support options.boldTextPt', function () { var params = checkSetup( '
' + 'My text
', @@ -675,7 +675,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should support options.largeTextPt', function() { + it('should support options.largeTextPt', function () { var params = checkSetup( '
' + 'My text
', @@ -688,7 +688,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should support options.contrastRatio.normal.expected', function() { + it('should support options.contrastRatio.normal.expected', function () { var params = checkSetup( '
' + 'My text
', @@ -705,7 +705,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should support options.contrastRatio.normal.minThreshold', function() { + it('should support options.contrastRatio.normal.minThreshold', function () { var params = checkSetup( '
' + 'My text
', @@ -722,7 +722,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should support options.contrastRatio.normal.maxThreshold', function() { + it('should support options.contrastRatio.normal.maxThreshold', function () { var params = checkSetup( '
' + 'My text
', @@ -739,7 +739,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should support options.contrastRatio.large.expected', function() { + it('should support options.contrastRatio.large.expected', function () { var params = checkSetup( '
' + 'My text
', @@ -756,7 +756,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should support options.contrastRatio.large.minThreshold', function() { + it('should support options.contrastRatio.large.minThreshold', function () { var params = checkSetup( '
' + 'My text
', @@ -773,7 +773,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should support options.contrastRatio.large.maxThreshold', function() { + it('should support options.contrastRatio.large.maxThreshold', function () { var params = checkSetup( '
' + 'My text
', @@ -790,7 +790,7 @@ describe('color-contrast', function() { assert.deepEqual(checkContext._relatedNodes, []); }); - it('should ignore pseudo element with options.ignorePseudo', function() { + it('should ignore pseudo element with options.ignorePseudo', function () { var params = checkSetup( '' + '

Content

', @@ -802,7 +802,7 @@ describe('color-contrast', function() { assert.isTrue(contrastEvaluate.apply(checkContext, params)); }); - it('should adjust the pseudo element minimum size with the options.pseudoSizeThreshold', function() { + it('should adjust the pseudo element minimum size with the options.pseudoSizeThreshold', function () { var params = checkSetup( '' + @@ -817,7 +817,7 @@ describe('color-contrast', function() { (shadowSupported ? it : xit)( 'returns colors across Shadow DOM boundaries', - function() { + function () { var params = shadowCheckSetup( '
', '

Text

' @@ -829,8 +829,8 @@ describe('color-contrast', function() { } ); - describe('with text-shadow', function() { - it('passes if thin text shadows have sufficient contrast with the text', function() { + describe('with text-shadow', function () { + it('passes if thin text shadows have sufficient contrast with the text', function () { var params = checkSetup( '
' + @@ -840,7 +840,7 @@ describe('color-contrast', function() { assert.isTrue(contrastEvaluate.apply(checkContext, params)); }); - it('does not count text shadows of offset 0, blur 0 as part of the background color', function() { + it('does not count text shadows of offset 0, blur 0 as part of the background color', function () { var params = checkSetup( '
' + @@ -856,7 +856,7 @@ describe('color-contrast', function() { assert.equal(checkContext._data.contrastRatio, '4.84'); }); - it('passes if thin text shadows have sufficient contrast with the background', function() { + it('passes if thin text shadows have sufficient contrast with the background', function () { var params = checkSetup( '
' + @@ -866,7 +866,7 @@ describe('color-contrast', function() { assert.isTrue(contrastEvaluate.apply(checkContext, params)); }); - it('fails if text shadows have sufficient contrast with the background if its width is thicker than `shadowOutlineEmMax`', function() { + it('fails if text shadows have sufficient contrast with the background if its width is thicker than `shadowOutlineEmMax`', function () { var checkOptions = { shadowOutlineEmMax: 0.05 }; var params = checkSetup( '
' + @@ -890,7 +890,7 @@ describe('color-contrast', function() { assert.isNull(checkContext._data.messageKey); }); - it('fails if text shadows do not have sufficient contrast with the background', function() { + it('fails if text shadows do not have sufficient contrast with the background', function () { var params = checkSetup( '
' + @@ -901,7 +901,7 @@ describe('color-contrast', function() { assert.equal(checkContext._data.messageKey, 'shadowOnBgColor'); }); - it("fails if thick text shadows don't have sufficient contrast", function() { + it("fails if thick text shadows don't have sufficient contrast", function () { var params = checkSetup( '
' + @@ -911,7 +911,7 @@ describe('color-contrast', function() { assert.isTrue(contrastEvaluate.apply(checkContext, params)); }); - it("passes if thin text shadows don't have sufficient contrast, but the text and background do", function() { + it("passes if thin text shadows don't have sufficient contrast, but the text and background do", function () { var params = checkSetup( '
' + From bca14b12c601398bb07d5209e2cd5e38f579d547 Mon Sep 17 00:00:00 2001 From: Steven Lambert <2433219+straker@users.noreply.github.com> Date: Tue, 9 Aug 2022 11:10:54 -0600 Subject: [PATCH 08/14] Update lib/commons/dom/get-rect-stack.js Co-authored-by: Wilco Fiers --- lib/commons/dom/get-rect-stack.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/lib/commons/dom/get-rect-stack.js b/lib/commons/dom/get-rect-stack.js index a347064286..6febf1a404 100644 --- a/lib/commons/dom/get-rect-stack.js +++ b/lib/commons/dom/get-rect-stack.js @@ -126,18 +126,6 @@ export function getRectStack(grid, rect, recursed = false) { const rectX = clientRect.left; const rectY = clientRect.top; - if (gridCellNode.attr('id') === 'debugNode') { - console.log(JSON.stringify({ - el: gridCellNode.actualNode.cloneNode(false).outerHTML, - y: y, - floorY: floorY, - 'rectY': rectY, - height: clientRect.height, - 'rectY+height': rectY + clientRect.height, - 'floor(rectY+height)': floor(rectY + clientRect.height) - },null,2)); - } - // perform an AABB (axis-aligned bounding box) collision check for the // point inside the rect // account for differences in how browsers handle floating point From dce77e92cb96160a31b92a15a1a12915d79462a8 Mon Sep 17 00:00:00 2001 From: Steven Lambert <2433219+straker@users.noreply.github.com> Date: Tue, 9 Aug 2022 11:12:40 -0600 Subject: [PATCH 09/14] Update test/checks/color/color-contrast.js Co-authored-by: Wilco Fiers --- test/checks/color/color-contrast.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/checks/color/color-contrast.js b/test/checks/color/color-contrast.js index 48d470f402..6f76338d22 100644 --- a/test/checks/color/color-contrast.js +++ b/test/checks/color/color-contrast.js @@ -404,7 +404,7 @@ describe('color-contrast', function () { var params = checkSetup( '
' + '
' + - '

Foo

' + + '

Foo

' + 'Bar' + '
' ); From 852486dd86c6a6f8209e11a599de8112395dd623 Mon Sep 17 00:00:00 2001 From: Steven Lambert Date: Tue, 9 Aug 2022 11:18:13 -0600 Subject: [PATCH 10/14] move test --- test/checks/color/color-contrast.js | 12 --- test/commons/dom/get-element-stack.js | 104 ++++++++++++++------------ 2 files changed, 57 insertions(+), 59 deletions(-) diff --git a/test/checks/color/color-contrast.js b/test/checks/color/color-contrast.js index 6f76338d22..41b1f2f595 100644 --- a/test/checks/color/color-contrast.js +++ b/test/checks/color/color-contrast.js @@ -400,18 +400,6 @@ describe('color-contrast', function () { }); }); - it('should return true for element which exactly overlaps midpoint of another element', function () { - var params = checkSetup( - '
' + - '
' + - '

Foo

' + - 'Bar' + - '
' - ); - - assert.isTrue(contrastEvaluate.apply(checkContext, params)); - }); - describe('with pseudo elements', function () { it('should return undefined if :before pseudo element has a background color', function () { var params = checkSetup( diff --git a/test/commons/dom/get-element-stack.js b/test/commons/dom/get-element-stack.js index 589d43d985..220f6db663 100644 --- a/test/commons/dom/get-element-stack.js +++ b/test/commons/dom/get-element-stack.js @@ -1,4 +1,4 @@ -describe('dom.getElementStack', function() { +describe('dom.getElementStack', function () { 'use strict'; var fixture = document.getElementById('fixture'); @@ -8,20 +8,20 @@ describe('dom.getElementStack', function() { function mapToIDs(stack) { return stack - .map(function(node) { + .map(function (node) { return node.id; }) - .filter(function(id) { + .filter(function (id) { return !!id; }); } - afterEach(function() { + afterEach(function () { fixture.innerHTML = ''; }); - describe('stack order', function() { - it('should return stack in DOM order of non-positioned elements', function() { + describe('stack order', function () { + it('should return stack in DOM order of non-positioned elements', function () { fixture.innerHTML = '
' + '
' + @@ -34,7 +34,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['target', '2', '1', 'fixture']); }); - it('should not return elements outside of the stack', function() { + it('should not return elements outside of the stack', function () { fixture.innerHTML = '
' + '
' + @@ -48,7 +48,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['target', '2', '1', 'fixture']); }); - it('should return stack in DOM order of non-positioned elements with z-index', function() { + it('should return stack in DOM order of non-positioned elements with z-index', function () { fixture.innerHTML = '
' + '
hello world
' + @@ -65,7 +65,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['3', '2', 'target', '1', 'fixture']); }); - it('should should handle positioned elements without z-index', function() { + it('should should handle positioned elements without z-index', function () { // see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/Stacking_without_z-index fixture.innerHTML = '
' + @@ -84,7 +84,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['4', '3', '2', '1', 'target', 'fixture']); }); - it('should handle floating and positioned elements without z-index', function() { + it('should handle floating and positioned elements without z-index', function () { // see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/Stacking_and_float fixture.innerHTML = '
' + @@ -101,7 +101,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['4', '1', '2', 'target', 'fixture']); }); - it('should handle floating parent elements', function() { + it('should handle floating parent elements', function () { fixture.innerHTML = '
' + '
whole picture
' + @@ -116,7 +116,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['target', '2', '1', '4', '3', 'fixture']); }); - it('should handle z-index positioned elements in the same stacking context', function() { + it('should handle z-index positioned elements in the same stacking context', function () { // see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/Stacking_context_example_1 fixture.innerHTML = '
' + @@ -144,7 +144,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['4', '2', '3', 'target', 'fixture']); }); - it('should handle z-index positioned elements in different stacking contexts', function() { + it('should handle z-index positioned elements in different stacking contexts', function () { // see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/Stacking_context_example_2 fixture.innerHTML = '
' + @@ -172,7 +172,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['2', '4', '3', 'target', 'fixture']); }); - it('should handle complex stacking context', function() { + it('should handle complex stacking context', function () { // see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context fixture.innerHTML = '
' + @@ -212,7 +212,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['1', '4', 'target', '5', '3', '2']); }); - it('should correctly order children of position elements without z-index', function() { + it('should correctly order children of position elements without z-index', function () { fixture.innerHTML = '
' + '
' + @@ -223,7 +223,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['target', '1', 'fixture']); }); - it('should correctly order children of position elements with z-index', function() { + it('should correctly order children of position elements with z-index', function () { fixture.innerHTML = '
' + '
' + @@ -234,7 +234,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['target', '1', 'fixture']); }); - it('should handle modals on top of the stack', function() { + it('should handle modals on top of the stack', function () { fixture.innerHTML = '
' + '
' + @@ -248,7 +248,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['3', 'target', '2', '1', 'fixture']); }); - it('should handle "pointer-events:none"', function() { + it('should handle "pointer-events:none"', function () { fixture.innerHTML = '
' + '
' + @@ -262,7 +262,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['3', 'target', '2', '1', 'fixture']); }); - it('should return elements left out by document.elementsFromPoint', function() { + it('should return elements left out by document.elementsFromPoint', function () { fixture.innerHTML = '
' + '
' + @@ -275,7 +275,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['target', '3', '2', '1', 'fixture']); }); - it('should not return elements that do not fully cover the target', function() { + it('should not return elements that do not fully cover the target', function () { fixture.innerHTML = '
' + '
' + @@ -287,7 +287,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['target', '1', 'fixture']); }); - it('should not return parent elements that do not fully cover the target', function() { + it('should not return parent elements that do not fully cover the target', function () { fixture.innerHTML = '
' + '
Text
' + @@ -298,7 +298,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['target']); }); - it('should return elements that partially cover the target', function() { + it('should return elements that partially cover the target', function () { fixture.innerHTML = '
' + '
' + @@ -310,7 +310,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['target', '2', '1', 'fixture']); }); - it('should handle negative z-index', function() { + it('should handle negative z-index', function () { fixture.innerHTML = '
' + '
' + @@ -323,7 +323,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['1', 'fixture', 'target', '2']); }); - it('should not add hidden elements', function() { + it('should not add hidden elements', function () { fixture.innerHTML = '
' + '' + @@ -337,7 +337,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['target', '1', 'fixture']); }); - it('should correctly position children of positioned parents', function() { + it('should correctly position children of positioned parents', function () { fixture.innerHTML = '
Some text
' + '
' + @@ -351,7 +351,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['target', '3', '1', 'fixture']); }); - it('should correctly position siblings with positioned children correctly', function() { + it('should correctly position siblings with positioned children correctly', function () { fixture.innerHTML = '
Some text
' + '
Some text
' + @@ -367,7 +367,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['4', 'target', '5', '3', '2', '1', 'fixture']); }); - it('should correctly position children of float elements with position elements', function() { + it('should correctly position children of float elements with position elements', function () { fixture.innerHTML = '
' + '
' + @@ -385,7 +385,7 @@ describe('dom.getElementStack', function() { assert.deepEqual(stack, ['5', 'target', '4', '3', '2', '1', 'fixture']); }); - it('should return empty array for hidden elements', function() { + it('should return empty array for hidden elements', function () { fixture.innerHTML = '
' + '