-
Notifications
You must be signed in to change notification settings - Fork 795
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(utils): add getFrameContexts method (#2995)
* feat(utils): add getFrameContexts method * updates * finish tests * better * revert playground * fix ie11 * Update lib/core/base/context.js Co-authored-by: Wilco Fiers <WilcoFiers@users.noreply.github.com> * Update lib/core/public/load.js Co-authored-by: Wilco Fiers <WilcoFiers@users.noreply.github.com> * tests Co-authored-by: Steven Lambert <steven.lambert@deque.com> Co-authored-by: Steven Lambert <2433219+straker@users.noreply.github.com>
- Loading branch information
1 parent
70c683c
commit f478bab
Showing
4 changed files
with
307 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import Context from '../base/context'; | ||
import getAncestry from './get-ancestry'; | ||
|
||
export default function getFrameContexts(context) { | ||
const { frames } = new Context(context); | ||
return frames.map(({ node, include, exclude }) => { | ||
const frameContext = { include, exclude }; | ||
frameContext.initiator = false; | ||
const frameSelector = getAncestry(node); | ||
return { frameSelector, frameContext }; | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,274 @@ | ||
describe('utils.getFrameContexts', function() { | ||
var getFrameContexts = axe.utils.getFrameContexts; | ||
var shadowSupported = axe.testUtils.shadowSupport.v1; | ||
var fixture = document.querySelector('#fixture'); | ||
|
||
it('returns an empty array if the page has no frames', function() { | ||
var frameContext = getFrameContexts(); | ||
assert.isArray(frameContext); | ||
assert.lengthOf(frameContext, 0); | ||
}); | ||
|
||
it('sets context.initiator to false for each included frame', function() { | ||
fixture.innerHTML = | ||
'<iframe></iframe>' + '<iframe></iframe>' + '<iframe></iframe>'; | ||
|
||
var contexts = getFrameContexts().map(function(frameData) { | ||
return frameData.frameContext; | ||
}); | ||
|
||
assert.lengthOf(contexts, 3); | ||
assert.isFalse(contexts[0].initiator); | ||
assert.isFalse(contexts[1].initiator); | ||
assert.isFalse(contexts[2].initiator); | ||
}); | ||
|
||
it('returns a `frameSelector` for each included frame', function() { | ||
fixture.innerHTML = | ||
'<iframe></iframe>' + '<iframe></iframe>' + '<iframe></iframe>'; | ||
|
||
var selectors = getFrameContexts().map(function(frameData) { | ||
return frameData.frameSelector; | ||
}); | ||
assert.lengthOf(selectors, 3); | ||
assert.include(selectors[0], 'iframe:nth-child(1)'); | ||
assert.include(selectors[1], 'iframe:nth-child(2)'); | ||
assert.include(selectors[2], 'iframe:nth-child(3)'); | ||
}); | ||
|
||
it('returns a `frameContext` for each included frame', function() { | ||
fixture.innerHTML = | ||
'<iframe id="f1"></iframe>' + | ||
'<iframe id="f2"></iframe>' + | ||
'<iframe id="f3"></iframe>'; | ||
var context = { | ||
include: [ | ||
['#f1', 'header'], | ||
['#f2', 'main'] | ||
], | ||
exclude: [['#f3', 'footer']] | ||
}; | ||
var contexts = getFrameContexts(context).map(function(frameData) { | ||
return frameData.frameContext; | ||
}); | ||
|
||
assert.lengthOf(contexts, 3); | ||
assert.deepEqual(contexts[0], { | ||
initiator: false, | ||
include: [['header']], | ||
exclude: [] | ||
}); | ||
assert.deepEqual(contexts[1], { | ||
initiator: false, | ||
include: [['main']], | ||
exclude: [] | ||
}); | ||
assert.deepEqual(contexts[2], { | ||
initiator: false, | ||
include: [], | ||
exclude: [['footer']] | ||
}); | ||
}); | ||
|
||
it('excludes non-frame contexts', function() { | ||
fixture.innerHTML = '<iframe id="f1"></iframe>'; | ||
var context = { | ||
include: [['#header'], ['a'], ['#f1', 'header']] | ||
}; | ||
var contexts = getFrameContexts(context).map(function(frameData) { | ||
return frameData.frameContext; | ||
}); | ||
|
||
assert.lengthOf(contexts, 1); | ||
assert.deepEqual(contexts[0], { | ||
initiator: false, | ||
include: [['header']], | ||
exclude: [] | ||
}); | ||
}); | ||
|
||
it('mixes contexts if the frame is selected twice', function() { | ||
fixture.innerHTML = | ||
'<iframe id="f1"></iframe>' + '<iframe id="f2"></iframe>'; | ||
var context = { | ||
include: [ | ||
['#f1', 'header'], | ||
['#f2', 'footer'] | ||
], | ||
exclude: [['iframe', 'main']] | ||
}; | ||
var contexts = getFrameContexts(context).map(function(frameData) { | ||
return frameData.frameContext; | ||
}); | ||
assert.lengthOf(contexts, 2); | ||
assert.deepEqual(contexts[0], { | ||
initiator: false, | ||
include: [['header']], | ||
exclude: [['main']] | ||
}); | ||
assert.deepEqual(contexts[1], { | ||
initiator: false, | ||
include: [['footer']], | ||
exclude: [['main']] | ||
}); | ||
}); | ||
|
||
it('combines include/exclude arrays of frames selected twice', function() { | ||
fixture.innerHTML = '<iframe></iframe>'; | ||
var context = { | ||
include: [ | ||
['iframe', 'header'], | ||
['iframe', 'main'] | ||
], | ||
exclude: [ | ||
['iframe', 'aside'], | ||
['iframe', 'footer'] | ||
] | ||
}; | ||
var contexts = getFrameContexts(context).map(function(frameData) { | ||
return frameData.frameContext; | ||
}); | ||
|
||
assert.lengthOf(contexts, 1); | ||
assert.deepEqual(contexts[0], { | ||
initiator: false, | ||
include: [['header'], ['main']], | ||
exclude: [['aside'], ['footer']] | ||
}); | ||
}); | ||
|
||
it('skips excluded frames', function() { | ||
fixture.innerHTML = | ||
'<iframe id="f1"></iframe>' + | ||
'<iframe id="f2"></iframe>' + | ||
'<iframe id="f3"></iframe>'; | ||
var context = { | ||
exclude: [[['#f2']]] | ||
}; | ||
var selectors = getFrameContexts(context).map(function(frameData) { | ||
return frameData.frameSelector; | ||
}); | ||
assert.lengthOf(selectors, 2); | ||
assert.include(selectors[0], 'iframe:nth-child(1)'); | ||
assert.include(selectors[1], 'iframe:nth-child(3)'); | ||
}); | ||
|
||
it('skips frames excluded by a parent', function() { | ||
fixture.innerHTML = '<iframe></iframe>'; | ||
var frameContexts = getFrameContexts({ | ||
exclude: [['#fixture']] | ||
}); | ||
assert.lengthOf(frameContexts, 0); | ||
}); | ||
|
||
it('normalizes the context', function() { | ||
var frameContexts; | ||
fixture.innerHTML = | ||
'<iframe id="f1"></iframe>' + '<iframe id="f2"></iframe>'; | ||
frameContexts = getFrameContexts('#f1'); | ||
assert.lengthOf(frameContexts, 1); | ||
assert.include(frameContexts[0].frameSelector, 'iframe:nth-child(1)'); | ||
assert.deepEqual(frameContexts[0].frameContext, { | ||
initiator: false, | ||
include: [], | ||
exclude: [] | ||
}); | ||
|
||
frameContexts = getFrameContexts({ include: ['#f1'] }); | ||
assert.lengthOf(frameContexts, 1); | ||
assert.include(frameContexts[0].frameSelector, 'iframe:nth-child(1)'); | ||
assert.deepEqual(frameContexts[0].frameContext, { | ||
initiator: false, | ||
include: [], | ||
exclude: [] | ||
}); | ||
|
||
frameContexts = getFrameContexts({ exclude: ['#f2'] }); | ||
assert.include(frameContexts[0].frameSelector, 'iframe:nth-child(1)'); | ||
assert.lengthOf(frameContexts, 1); | ||
assert.deepEqual(frameContexts[0].frameContext, { | ||
initiator: false, | ||
include: [], | ||
exclude: [] | ||
}); | ||
}); | ||
|
||
it('accepts elements', function() { | ||
var frameContexts; | ||
fixture.innerHTML = | ||
'<iframe id="f1"></iframe>' + '<iframe id="f2"></iframe>'; | ||
var f1 = fixture.querySelector('#f1'); | ||
var f2 = fixture.querySelector('#f2'); | ||
frameContexts = getFrameContexts(f1); | ||
assert.lengthOf(frameContexts, 1); | ||
assert.include(frameContexts[0].frameSelector, 'iframe:nth-child(1)'); | ||
assert.deepEqual(frameContexts[0].frameContext, { | ||
initiator: false, | ||
include: [], | ||
exclude: [] | ||
}); | ||
|
||
frameContexts = getFrameContexts({ include: [f1] }); | ||
assert.lengthOf(frameContexts, 1); | ||
assert.include(frameContexts[0].frameSelector, 'iframe:nth-child(1)'); | ||
assert.deepEqual(frameContexts[0].frameContext, { | ||
initiator: false, | ||
include: [], | ||
exclude: [] | ||
}); | ||
|
||
frameContexts = getFrameContexts({ exclude: [f2] }); | ||
assert.include(frameContexts[0].frameSelector, 'iframe:nth-child(1)'); | ||
assert.lengthOf(frameContexts, 1); | ||
assert.deepEqual(frameContexts[0].frameContext, { | ||
initiator: false, | ||
include: [], | ||
exclude: [] | ||
}); | ||
}); | ||
|
||
it('works with nested frames', function() { | ||
fixture.innerHTML = | ||
'<iframe id="f1"></iframe>' + '<iframe id="f2"></iframe>'; | ||
var context = { | ||
include: [ | ||
['#f1', '#f3', 'header'], | ||
['#f2', '#f4', '#f5', 'footer'] | ||
], | ||
exclude: [['#f2', '#f6', '#f7', '#f7', 'main']] | ||
}; | ||
var contexts = getFrameContexts(context).map(function(frameData) { | ||
return frameData.frameContext; | ||
}); | ||
|
||
assert.lengthOf(contexts, 2); | ||
assert.deepEqual(contexts[0], { | ||
initiator: false, | ||
include: [['#f3', 'header']], | ||
exclude: [] | ||
}); | ||
assert.deepEqual(contexts[1], { | ||
initiator: false, | ||
include: [['#f4', '#f5', 'footer']], | ||
exclude: [['#f6', '#f7', '#f7', 'main']] | ||
}); | ||
}); | ||
|
||
(shadowSupported ? it : xit)('works on iframes in shadow dom', function() { | ||
fixture.innerHTML = '<div id="shadow"></div>'; | ||
var div = fixture.querySelector('div'); | ||
var shadowRoot = div.attachShadow({ mode: 'open' }); | ||
shadowRoot.innerHTML = '<main><iframe id="f1"></iframe></main>'; | ||
|
||
var frameContext = getFrameContexts(); | ||
|
||
assert.lengthOf(frameContext, 1); | ||
assert.lengthOf(frameContext[0].frameSelector, 2); | ||
assert.equal(frameContext[0].frameSelector[1], 'main > iframe'); | ||
assert.deepEqual(frameContext[0].frameContext, { | ||
initiator: false, | ||
include: [], | ||
exclude: [] | ||
}); | ||
}); | ||
}); |