From 54c34c5d2211ad4fb9e393691aca58cf890071d2 Mon Sep 17 00:00:00 2001 From: Steven Lambert Date: Mon, 23 Jan 2023 15:36:09 -0700 Subject: [PATCH 1/7] fix(color-contrast): correctly calculate contrast of flex/grid items with z-index --- lib/commons/dom/create-grid.js | 42 ++- test/commons/dom/get-element-stack.js | 300 ++++++++++-------- .../rules/color-contrast/color-contrast.html | 10 + .../rules/color-contrast/color-contrast.json | 3 +- 4 files changed, 200 insertions(+), 155 deletions(-) diff --git a/lib/commons/dom/create-grid.js b/lib/commons/dom/create-grid.js index 509fbba5f9..5d368166c7 100644 --- a/lib/commons/dom/create-grid.js +++ b/lib/commons/dom/create-grid.js @@ -102,6 +102,24 @@ export default function createGrid( return constants.gridSize; } +/** + * Determine if element is a flex or grid container. + * @param {VirtualNode} vNode + * @return {Boolean} + */ +function isFlexOrGridContainer(vNode) { + const display = vNode.getComputedStylePropertyValue('display'); + + return [ + 'flex', + 'inline-flex', + 'inline flex', + 'grid', + 'inline-grid', + 'inline grid' + ].includes(display); +} + /** * Determine if node produces a stacking context. * References: @@ -221,20 +239,8 @@ function isStackingContext(vNode, parentVNode) { } // a flex item or gird item with a z-index value other than "auto", that is the parent element display: flex|inline-flex|grid|inline-grid, - if (zIndex !== 'auto' && parentVNode) { - const parentDsiplay = parentVNode.getComputedStylePropertyValue('display'); - if ( - [ - 'flex', - 'inline-flex', - 'inline flex', - 'grid', - 'inline-grid', - 'inline grid' - ].includes(parentDsiplay) - ) { - return true; - } + if (zIndex !== 'auto' && parentVNode && isFlexOrGridContainer(parentVNode)) { + return true; } return false; @@ -253,7 +259,13 @@ function getStackingOrder(vNode, parentVNode) { vNode.getComputedStylePropertyValue('position') !== 'static'; const floated = vNode.getComputedStylePropertyValue('float') !== 'none'; - if (positioned && !['auto', '0'].includes(zIndex)) { + // flex and grid items can use z-index even if position: static + // @see https://www.w3.org/TR/css-flexbox-1/#painting + // @see https://www.w3.org/TR/css-grid-1/#z-order + if ( + !['auto', '0'].includes(zIndex) && + (positioned || isFlexOrGridContainer(parentVNode)) + ) { // if a positioned element has a z-index > 0, find the first // true stack (not a "fake" stack created from positioned or // floated elements without a z-index) and create a new stack at diff --git a/test/commons/dom/get-element-stack.js b/test/commons/dom/get-element-stack.js index fb33e7f2da..14484cf127 100644 --- a/test/commons/dom/get-element-stack.js +++ b/test/commons/dom/get-element-stack.js @@ -1,9 +1,9 @@ -describe('dom.getElementStack', function () { +describe('dom.getElementStack', () => { 'use strict'; - var fixture = document.getElementById('fixture'); - var getElementStack = axe.commons.dom.getElementStack; - var shadowSupported = axe.testUtils.shadowSupport.v1; + const fixture = document.getElementById('fixture'); + const getElementStack = axe.commons.dom.getElementStack; + const shadowSupported = axe.testUtils.shadowSupport.v1; function mapToIDs(stack) { return stack @@ -15,12 +15,12 @@ describe('dom.getElementStack', function () { }); } - afterEach(function () { + afterEach(() => { fixture.innerHTML = ''; }); - describe('stack order', function () { - it('should return stack in DOM order of non-positioned elements', function () { + describe('stack order', () => { + it('should return stack in DOM order of non-positioned elements', () => { fixture.innerHTML = '
' + '
' + @@ -28,12 +28,12 @@ describe('dom.getElementStack', function () { '
' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); 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', () => { fixture.innerHTML = '
' + '
' + @@ -42,12 +42,12 @@ describe('dom.getElementStack', function () { '
' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); 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', () => { fixture.innerHTML = '
' + '
hello world
' + @@ -56,15 +56,15 @@ describe('dom.getElementStack', function () { '
Some text
' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); // Browsers seem to be buggy, which suggest [3, target, 2, 1, fixture] // We're following the spec in this. // @see https://codepen.io/straker/pen/gOxpJyE 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', () => { // see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/Stacking_without_z-index fixture.innerHTML = '
' + @@ -78,12 +78,12 @@ describe('dom.getElementStack', function () { '
' + 'DIV #5
position:static;
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); 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', () => { // see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/Stacking_and_float fixture.innerHTML = '
' + @@ -95,12 +95,12 @@ describe('dom.getElementStack', function () { '
' + 'DIV #4
position:absolute;
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); assert.deepEqual(stack, ['4', '1', '2', 'target', 'fixture']); }); - it('should handle floating parent elements', function () { + it('should handle floating parent elements', () => { fixture.innerHTML = '
' + '
whole picture
' + @@ -110,12 +110,12 @@ describe('dom.getElementStack', function () { '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); 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', () => { // see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/Stacking_context_example_1 fixture.innerHTML = '
' + @@ -138,12 +138,12 @@ describe('dom.getElementStack', function () { '
' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); 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', () => { // see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/Stacking_context_example_2 fixture.innerHTML = '
' + @@ -166,12 +166,12 @@ describe('dom.getElementStack', function () { '
' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); assert.deepEqual(stack, ['2', '4', '3', 'target', 'fixture']); }); - it('should handle complex stacking context', function () { + it('should handle complex stacking context', () => { // see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context fixture.innerHTML = '
' + @@ -206,34 +206,56 @@ describe('dom.getElementStack', function () { '
' + ''; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); 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', () => { fixture.innerHTML = '
' + '
' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); 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', () => { fixture.innerHTML = '
' + '
' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); assert.deepEqual(stack, ['target', '1', 'fixture']); }); - it('should handle modals on top of the stack', function () { + [ + 'flex', + 'inline-flex', + 'inline flex', + 'grid', + 'inline-grid', + 'inline grid' + ].forEach(type => { + it(`should correctly order "${type}" items with z-index`, () => { + fixture.innerHTML = ` +
+
+
+
+ `; + axe.testUtils.flatTreeSetup(fixture); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); + assert.deepEqual(stack, ['target', '1', '2', 'fixture']); + }); + }); + + it('should handle modals on top of the stack', () => { fixture.innerHTML = '
' + '
' + @@ -242,12 +264,12 @@ describe('dom.getElementStack', function () { '
' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); assert.deepEqual(stack, ['3', 'target', '2', '1', 'fixture']); }); - it('should handle "pointer-events:none"', function () { + it('should handle "pointer-events:none"', () => { fixture.innerHTML = '
' + '
' + @@ -256,12 +278,12 @@ describe('dom.getElementStack', function () { '
' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); 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', () => { fixture.innerHTML = '
' + '
' + @@ -269,47 +291,47 @@ describe('dom.getElementStack', function () { '
' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); 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', () => { fixture.innerHTML = '
' + '
' + '

Text oh heyyyy and here\'s
a link

' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); 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', () => { fixture.innerHTML = '
' + '
Text
' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); assert.deepEqual(stack, ['target']); }); - it('should return elements that partially cover the target', function () { + it('should return elements that partially cover the target', () => { fixture.innerHTML = '
' + '
' + '
Text
' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); assert.deepEqual(stack, ['target', '2', '1', 'fixture']); }); - it('should handle negative z-index', function () { + it('should handle negative z-index', () => { fixture.innerHTML = '
' + '
' + @@ -317,12 +339,12 @@ describe('dom.getElementStack', function () { '
' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); assert.deepEqual(stack, ['1', 'fixture', 'target', '2']); }); - it('should not add hidden elements', function () { + it('should not add hidden elements', () => { fixture.innerHTML = '
' + '' + @@ -331,12 +353,12 @@ describe('dom.getElementStack', function () { 'Hello World' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); assert.deepEqual(stack, ['target', '1', 'fixture']); }); - it('should correctly position children of positioned parents', function () { + it('should correctly position children of positioned parents', () => { fixture.innerHTML = '
Some text
' + '
' + @@ -345,12 +367,12 @@ describe('dom.getElementStack', function () { '' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); 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', () => { fixture.innerHTML = '
Some text
' + '
Some text
' + @@ -361,12 +383,12 @@ describe('dom.getElementStack', function () { '' + ''; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); 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', () => { fixture.innerHTML = '
' + '
' + @@ -379,12 +401,12 @@ describe('dom.getElementStack', function () { '
' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); 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', () => { fixture.innerHTML = '
' + '' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); assert.deepEqual(stack, []); }); - it('should return empty array for children of 0 height scrollable regions', function () { + it('should return empty array for children of 0 height scrollable regions', () => { fixture.innerHTML = '
' + '
' + @@ -407,18 +429,18 @@ describe('dom.getElementStack', function () { '
' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); assert.deepEqual(stack, []); }); - it('should throw error if element midpoint-x exceeds the grid', function () { + it('should throw error if element midpoint-x exceeds the grid', () => { fixture.innerHTML = '
Hello World
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var vNode = axe.utils.getNodeFromTree(target); + const target = fixture.querySelector('#target'); + const vNode = axe.utils.getNodeFromTree(target); Object.defineProperty(vNode, 'boundingClientRect', { - get: function () { + get: () => { return { left: 0, top: 10, @@ -427,18 +449,18 @@ describe('dom.getElementStack', function () { }; } }); - assert.throws(function () { + assert.throws(() => { getElementStack(target); }, 'Element midpoint exceeds the grid bounds'); }); - it('should throw error if element midpoint-y exceeds the grid', function () { + it('should throw error if element midpoint-y exceeds the grid', () => { fixture.innerHTML = '
Hello World
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var vNode = axe.utils.getNodeFromTree(target); + const target = fixture.querySelector('#target'); + const vNode = axe.utils.getNodeFromTree(target); Object.defineProperty(vNode, 'boundingClientRect', { - get: function () { + get: () => { return { left: 0, top: 10, @@ -447,12 +469,12 @@ describe('dom.getElementStack', function () { }; } }); - assert.throws(function () { + assert.throws(() => { getElementStack(target); }, 'Element midpoint exceeds the grid bounds'); }); - it('should ignore element which exactly overlaps midpoint of target element', function () { + it('should ignore element which exactly overlaps midpoint of target element', () => { fixture.innerHTML = '
' + '

Foo

' + @@ -460,56 +482,56 @@ describe('dom.getElementStack', function () { '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); assert.deepEqual(stack, ['target', 'fixture']); }); // IE11 either only supports clip paths defined by url() or not at all, // MDN and caniuse.com give different results... - it('should not add hidden elements using clip-path', function () { + it('should not add hidden elements using clip-path', () => { fixture.innerHTML = '
' + '
Some text
' + 'Hello World' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); assert.deepEqual(stack, ['target', '1', 'fixture']); }); (shadowSupported ? it : xit)( 'should sort shadow dom elements correctly', - function () { + () => { fixture.innerHTML = '
'; - var container = fixture.querySelector('#container'); - var shadow = container.attachShadow({ mode: 'open' }); + const container = fixture.querySelector('#container'); + const shadow = container.attachShadow({ mode: 'open' }); shadow.innerHTML = 'Text'; axe.testUtils.flatTreeSetup(fixture); - var target = shadow.querySelector('#shadowTarget'); - var stack = mapToIDs(getElementStack(target)); + const target = shadow.querySelector('#shadowTarget'); + const stack = mapToIDs(getElementStack(target)); assert.deepEqual(stack, ['shadowTarget', 'container', 'fixture']); } ); (shadowSupported ? it : xit)( 'should sort nested shadow dom elements correctly', - function () { + () => { fixture.innerHTML = '
'; - var container = fixture.querySelector('#container'); - var shadow = container.attachShadow({ mode: 'open' }); + const container = fixture.querySelector('#container'); + const shadow = container.attachShadow({ mode: 'open' }); shadow.innerHTML = '
'; - var nestedContainer = shadow.querySelector('#shadowContainer'); - var nestedShadow = nestedContainer.attachShadow({ mode: 'open' }); + const nestedContainer = shadow.querySelector('#shadowContainer'); + const nestedShadow = nestedContainer.attachShadow({ mode: 'open' }); nestedShadow.innerHTML = 'Text'; axe.testUtils.flatTreeSetup(fixture); - var target = nestedShadow.querySelector('#shadowTarget'); - var stack = mapToIDs(getElementStack(target)); + const target = nestedShadow.querySelector('#shadowTarget'); + const stack = mapToIDs(getElementStack(target)); assert.deepEqual(stack, [ 'shadowTarget', 'shadowContainer', @@ -521,21 +543,21 @@ describe('dom.getElementStack', function () { (shadowSupported ? it : xit)( 'should sort positioned shadow elements correctly', - function () { + () => { fixture.innerHTML = '
'; - var container = fixture.querySelector('#container'); - var shadow = container.attachShadow({ mode: 'open' }); + const container = fixture.querySelector('#container'); + const shadow = container.attachShadow({ mode: 'open' }); shadow.innerHTML = '
'; - var nestedContainer = shadow.querySelector('#shadowContainer'); - var nestedShadow = nestedContainer.attachShadow({ mode: 'open' }); + const nestedContainer = shadow.querySelector('#shadowContainer'); + const nestedShadow = nestedContainer.attachShadow({ mode: 'open' }); nestedShadow.innerHTML = 'Text'; axe.testUtils.flatTreeSetup(fixture); - var target = nestedShadow.querySelector('#shadowTarget'); - var stack = mapToIDs(getElementStack(target)); + const target = nestedShadow.querySelector('#shadowTarget'); + const stack = mapToIDs(getElementStack(target)); assert.deepEqual(stack, [ 'container', 'fixture', @@ -547,20 +569,20 @@ describe('dom.getElementStack', function () { (shadowSupported ? it : xit)( 'should sort shadow elements with different trees correctly', - function () { + () => { fixture.innerHTML = '
'; - var container1 = fixture.querySelector('#container1'); - var shadow1 = container1.attachShadow({ mode: 'open' }); + const container1 = fixture.querySelector('#container1'); + const shadow1 = container1.attachShadow({ mode: 'open' }); shadow1.innerHTML = 'Text'; - var container2 = fixture.querySelector('#container2'); - var shadow2 = container2.attachShadow({ mode: 'open' }); + const container2 = fixture.querySelector('#container2'); + const shadow2 = container2.attachShadow({ mode: 'open' }); shadow2.innerHTML = 'Container 2 text'; axe.testUtils.flatTreeSetup(fixture); - var target = shadow1.querySelector('#shadowTarget'); - var stack = mapToIDs(getElementStack(target)); + const target = shadow1.querySelector('#shadowTarget'); + const stack = mapToIDs(getElementStack(target)); assert.deepEqual(stack, [ '1', 'container2', @@ -592,16 +614,16 @@ describe('dom.getElementStack', function () { }); }); - describe('scroll regions', function () { - var origHeight = document.documentElement.style.height; - var origOverflow = document.documentElement.style.overflowY; + describe('scroll regions', () => { + const origHeight = document.documentElement.style.height; + const origOverflow = document.documentElement.style.overflowY; - afterEach(function () { + afterEach(() => { document.documentElement.style.height = origHeight; document.documentElement.style.overflowY = origOverflow; }); - it('should return stack of scroll regions', function () { + it('should return stack of scroll regions', () => { fixture.innerHTML = '
' + '
' + @@ -611,12 +633,12 @@ describe('dom.getElementStack', function () { '
' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); assert.deepEqual(stack, ['target', '3', '2', '1', 'fixture']); }); - it('should return stack when scroll region is larger than parent', function () { + it('should return stack when scroll region is larger than parent', () => { fixture.innerHTML = '
' + '
' + @@ -626,12 +648,12 @@ describe('dom.getElementStack', function () { '
' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); assert.deepEqual(stack, ['target', '3', '2', '1', 'fixture']); }); - it('should return stack of recursive scroll regions', function () { + it('should return stack of recursive scroll regions', () => { fixture.innerHTML = '
' + '
' + @@ -645,12 +667,12 @@ describe('dom.getElementStack', function () { '
' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); assert.deepEqual(stack, ['target', '5', '4', '3', '2', '1', 'fixture']); }); - it('should handle html as a scroll region', function () { + it('should handle html as a scroll region', () => { fixture.innerHTML = '
' + '
' + @@ -662,12 +684,12 @@ describe('dom.getElementStack', function () { document.documentElement.style.height = '5000px'; document.documentElement.style.overflowY = 'scroll'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); assert.deepEqual(stack, ['target', '3', '2', '1', 'fixture']); }); - it('should use correct scroll region parent', function () { + it('should use correct scroll region parent', () => { fixture.innerHTML = '
' + '
' + @@ -677,8 +699,8 @@ describe('dom.getElementStack', function () { '
' + '
'; axe.testUtils.flatTreeSetup(fixture); - var target = fixture.querySelector('#target'); - var stack = mapToIDs(getElementStack(target)); + const target = fixture.querySelector('#target'); + const stack = mapToIDs(getElementStack(target)); assert.deepEqual(stack, ['target', '3', '2', '1', 'fixture']); }); }); diff --git a/test/integration/rules/color-contrast/color-contrast.html b/test/integration/rules/color-contrast/color-contrast.html index d3c97e5a6f..f35d2b8cb3 100644 --- a/test/integration/rules/color-contrast/color-contrast.html +++ b/test/integration/rules/color-contrast/color-contrast.html @@ -424,3 +424,13 @@

Text-stroke 0.02em

+ +
+
+
+ This div will be on top of the stack +
+
diff --git a/test/integration/rules/color-contrast/color-contrast.json b/test/integration/rules/color-contrast/color-contrast.json index b3801df32d..0cd24e9ad7 100644 --- a/test/integration/rules/color-contrast/color-contrast.json +++ b/test/integration/rules/color-contrast/color-contrast.json @@ -35,7 +35,8 @@ ["#pass18"], ["#pass19"], ["#pass20"], - ["#pass21"] + ["#pass21"], + ["#pass22"] ], "incomplete": [ ["#canttell1"], From 00f658322727238aa8dc3ce5b3d5c4bdd7b5ba9e Mon Sep 17 00:00:00 2001 From: Steven Lambert <2433219+straker@users.noreply.github.com> Date: Wed, 25 Jan 2023 08:12:16 -0700 Subject: [PATCH 2/7] Update test/integration/rules/color-contrast/color-contrast.html Co-authored-by: Wilco Fiers --- test/integration/rules/color-contrast/color-contrast.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/rules/color-contrast/color-contrast.html b/test/integration/rules/color-contrast/color-contrast.html index f35d2b8cb3..9490398b3d 100644 --- a/test/integration/rules/color-contrast/color-contrast.html +++ b/test/integration/rules/color-contrast/color-contrast.html @@ -427,7 +427,7 @@
From 141b48f6919db5e14fb3dacd16045fc7d08d653f Mon Sep 17 00:00:00 2001 From: Steven Lambert <2433219+straker@users.noreply.github.com> Date: Wed, 25 Jan 2023 08:12:35 -0700 Subject: [PATCH 3/7] Update test/commons/dom/get-element-stack.js Co-authored-by: Wilco Fiers --- test/commons/dom/get-element-stack.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/commons/dom/get-element-stack.js b/test/commons/dom/get-element-stack.js index 14484cf127..f3325ceaf3 100644 --- a/test/commons/dom/get-element-stack.js +++ b/test/commons/dom/get-element-stack.js @@ -244,7 +244,7 @@ describe('dom.getElementStack', () => { it(`should correctly order "${type}" items with z-index`, () => { fixture.innerHTML = `
-
+
`; From c30266ca0c04ebb347f0e3acb9a379c906997118 Mon Sep 17 00:00:00 2001 From: straker Date: Wed, 25 Jan 2023 15:13:58 +0000 Subject: [PATCH 4/7] :robot: Automated formatting fixes --- test/integration/rules/color-contrast/color-contrast.html | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/integration/rules/color-contrast/color-contrast.html b/test/integration/rules/color-contrast/color-contrast.html index 9490398b3d..1231e9cf86 100644 --- a/test/integration/rules/color-contrast/color-contrast.html +++ b/test/integration/rules/color-contrast/color-contrast.html @@ -427,7 +427,13 @@
From 45e112f9e0d14706ce749d0218089b70cb4c9f3f Mon Sep 17 00:00:00 2001 From: Steven Lambert Date: Wed, 25 Jan 2023 08:14:21 -0700 Subject: [PATCH 5/7] suggestions --- lib/commons/dom/create-grid.js | 41 ++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/lib/commons/dom/create-grid.js b/lib/commons/dom/create-grid.js index 5d368166c7..3c43cece2f 100644 --- a/lib/commons/dom/create-grid.js +++ b/lib/commons/dom/create-grid.js @@ -102,24 +102,6 @@ export default function createGrid( return constants.gridSize; } -/** - * Determine if element is a flex or grid container. - * @param {VirtualNode} vNode - * @return {Boolean} - */ -function isFlexOrGridContainer(vNode) { - const display = vNode.getComputedStylePropertyValue('display'); - - return [ - 'flex', - 'inline-flex', - 'inline flex', - 'grid', - 'inline-grid', - 'inline grid' - ].includes(display); -} - /** * Determine if node produces a stacking context. * References: @@ -239,13 +221,34 @@ function isStackingContext(vNode, parentVNode) { } // a flex item or gird item with a z-index value other than "auto", that is the parent element display: flex|inline-flex|grid|inline-grid, - if (zIndex !== 'auto' && parentVNode && isFlexOrGridContainer(parentVNode)) { + if (zIndex !== 'auto' && isFlexOrGridContainer(parentVNode)) { return true; } return false; } +/** + * Determine if element is a flex or grid container. + * @param {VirtualNode} vNode + * @return {Boolean} + */ +function isFlexOrGridContainer(vNode) { + if (!vNode) { + return false; + } + + const display = vNode.getComputedStylePropertyValue('display'); + return [ + 'flex', + 'inline-flex', + 'inline flex', + 'grid', + 'inline-grid', + 'inline grid' + ].includes(display); +} + /** * Determine the stacking order of an element. The stacking order is an array of * zIndex values for each stacking context parent. From 0e0881c5c6fe5faf4a3414a3353f62e374cb93f0 Mon Sep 17 00:00:00 2001 From: Steven Lambert Date: Wed, 25 Jan 2023 09:31:10 -0700 Subject: [PATCH 6/7] no inline flex/grid (with space) --- lib/commons/dom/create-grid.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/lib/commons/dom/create-grid.js b/lib/commons/dom/create-grid.js index 3c43cece2f..f522ddd17e 100644 --- a/lib/commons/dom/create-grid.js +++ b/lib/commons/dom/create-grid.js @@ -239,14 +239,7 @@ function isFlexOrGridContainer(vNode) { } const display = vNode.getComputedStylePropertyValue('display'); - return [ - 'flex', - 'inline-flex', - 'inline flex', - 'grid', - 'inline-grid', - 'inline grid' - ].includes(display); + return ['flex', 'inline-flex', 'grid', 'inline-grid'].includes(display); } /** From db0e8b8fc5a574b97837cdb431b495d637f097f7 Mon Sep 17 00:00:00 2001 From: Steven Lambert Date: Wed, 25 Jan 2023 10:03:59 -0700 Subject: [PATCH 7/7] in test too --- test/commons/dom/get-element-stack.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/test/commons/dom/get-element-stack.js b/test/commons/dom/get-element-stack.js index f3325ceaf3..6f99c999d0 100644 --- a/test/commons/dom/get-element-stack.js +++ b/test/commons/dom/get-element-stack.js @@ -233,14 +233,7 @@ describe('dom.getElementStack', () => { assert.deepEqual(stack, ['target', '1', 'fixture']); }); - [ - 'flex', - 'inline-flex', - 'inline flex', - 'grid', - 'inline-grid', - 'inline grid' - ].forEach(type => { + ['flex', 'inline-flex', 'grid', 'inline-grid'].forEach(type => { it(`should correctly order "${type}" items with z-index`, () => { fixture.innerHTML = `