diff --git a/lib/commons/dom/find-nearby-elms.js b/lib/commons/dom/find-nearby-elms.js index 8bfbfa8a64..fc77a315de 100644 --- a/lib/commons/dom/find-nearby-elms.js +++ b/lib/commons/dom/find-nearby-elms.js @@ -1,8 +1,10 @@ import createGrid from './create-grid'; +import { memoize } from '../../core/utils'; export default function findNearbyElms(vNode, margin = 0) { /*eslint no-bitwise: 0*/ const gridSize = createGrid(); + const selfIsFixed = hasFixedPosition(vNode); if (!vNode._grid?.cells?.length) { return []; // Elements not in the grid don't have ._grid } @@ -18,10 +20,16 @@ export default function findNearbyElms(vNode, margin = 0) { const neighbors = []; loopGridCells(gridCells, boundaries, vNeighbor => { - if (vNeighbor && vNeighbor !== vNode && !neighbors.includes(vNeighbor)) { + if ( + vNeighbor && + vNeighbor !== vNode && + !neighbors.includes(vNeighbor) && + selfIsFixed === hasFixedPosition(vNeighbor) + ) { neighbors.push(vNeighbor); } }); + return neighbors; } @@ -37,3 +45,13 @@ function loopGridCells(gridCells, boundaries, cb) { } } } + +const hasFixedPosition = memoize(vNode => { + if (!vNode) { + return false; + } + if (vNode.getComputedStylePropertyValue('position') === 'fixed') { + return true; + } + return hasFixedPosition(vNode.parent); +}); diff --git a/test/commons/dom/find-nearby-elms.js b/test/commons/dom/find-nearby-elms.js index 548ba3fc64..ceef24d37c 100644 --- a/test/commons/dom/find-nearby-elms.js +++ b/test/commons/dom/find-nearby-elms.js @@ -1,11 +1,10 @@ -describe('findNearbyElms', function () { - 'use strict'; - var fixtureSetup = axe.testUtils.fixtureSetup; - var findNearbyElms = axe.commons.dom.findNearbyElms; - var fixture; +describe('findNearbyElms', () => { + let fixture; + const fixtureSetup = axe.testUtils.fixtureSetup; + const findNearbyElms = axe.commons.dom.findNearbyElms; function getIds(vNodeList) { - var ids = []; + const ids = []; vNodeList.forEach(function (vNode) { if (vNode.props.id && vNode.props.id !== 'fixture') { ids.push(vNode.props.id); @@ -14,8 +13,8 @@ describe('findNearbyElms', function () { return ids; } - describe('in the viewport', function () { - beforeEach(function () { + describe('in the viewport', () => { + beforeEach(() => { fixture = fixtureSetup( '
0
' + '
1
' + @@ -30,19 +29,19 @@ describe('findNearbyElms', function () { ); }); - it('returns node from the same grid cell', function () { - var nearbyElms = findNearbyElms(fixture.children[1]); + it('returns node from the same grid cell', () => { + const nearbyElms = findNearbyElms(fixture.children[1]); assert.deepEqual(getIds(nearbyElms), ['n0', 'n2', 'n3']); }); - it('returns node from multiple grid cells when crossing a boundary', function () { - var nearbyElms = findNearbyElms(fixture.children[5]); + it('returns node from multiple grid cells when crossing a boundary', () => { + const nearbyElms = findNearbyElms(fixture.children[5]); assert.deepEqual(getIds(nearbyElms), ['n3', 'n4', 'n6']); }); }); - describe('on the edge', function () { - beforeEach(function () { + describe('on the edge', () => { + beforeEach(() => { fixture = fixtureSetup( '
0
' + '
1
' + @@ -50,19 +49,44 @@ describe('findNearbyElms', function () { ); }); - it('ignores cells outside the document boundary', function () { - var nearbyElms = findNearbyElms(fixture.children[0]); + it('ignores cells outside the document boundary', () => { + const nearbyElms = findNearbyElms(fixture.children[0]); assert.deepEqual(getIds(nearbyElms), ['n2']); }); - it('returns no neighbors for off-screen elements', function () { - var nearbyElms = findNearbyElms(fixture.children[1]); + it('returns no neighbors for off-screen elements', () => { + const nearbyElms = findNearbyElms(fixture.children[1]); assert.deepEqual(getIds(nearbyElms), []); }); - it('returns element partially on screen as neighbors', function () { - var nearbyElms = findNearbyElms(fixture.children[2]); + it('returns element partially on screen as neighbors', () => { + const nearbyElms = findNearbyElms(fixture.children[2]); assert.deepEqual(getIds(nearbyElms), ['n0']); }); }); + + describe('when some nodes are fixed', () => { + beforeEach(() => { + fixture = fixtureSetup( + '
' + + '
1
' + + '
2
' + + '
' + + '
3
' + + '
4
' + ); + }); + + it('skips fixed position neighbors when not fixed', () => { + const n3 = axe.utils.querySelectorAll(fixture, '#n3')[0]; + const nearbyElms = findNearbyElms(n3); + assert.deepEqual(getIds(nearbyElms), ['n4']); + }); + + it('includes only fixed position neighbors when fixed', () => { + const n1 = axe.utils.querySelectorAll(fixture, '#n1')[0]; + const nearbyElms = findNearbyElms(n1); + assert.deepEqual(getIds(nearbyElms), ['n0', 'n2']); + }); + }); }); diff --git a/test/integration/rules/target-size/target-size.html b/test/integration/rules/target-size/target-size.html index 794f00a0b7..05e714c2df 100644 --- a/test/integration/rules/target-size/target-size.html +++ b/test/integration/rules/target-size/target-size.html @@ -5,6 +5,13 @@ } + +

+ Wide link + x +

+