bdd.describe('for options.filter', function() { var handle; var events = []; bdd.before(function() { skipSyntheticEnterFailure(this); handle = whenKey({ filter: '#inner', enter: function() { events.push('enter'); }, }); }); bdd.after(function() { handle && handle.disengage({ force: true }); }); bdd.beforeEach(function() { events = []; }); bdd.it('should not react to enter key within filter', function() { var target = document.getElementById('target'); simulateKeyDown('enter', target); expect(events).to.deep.equal([]); }); bdd.it('should react to enter key outside of filter', function() { simulateKeyDown('enter', fixture.root); expect(events).to.deep.equal(['enter']); }); });
bdd.describe('for defaultPrevented events', function() { var handle; var events = []; function preventDefaultKeydown(event) { dispatchEvent.preventDefault(event); } bdd.before(function() { skipSyntheticEnterFailure(this); document.documentElement.addEventListener('keydown', preventDefaultKeydown, true); handle = whenKey({ escape: function() { events.push('escape'); }, }); }); bdd.after(function() { handle && handle.disengage({ force: true }); document.documentElement.removeEventListener('keydown', preventDefaultKeydown, true); }); bdd.beforeEach(function() { events = []; }); bdd.it('should not react to escape key', function() { simulateKeyDown('escape'); expect(events).to.deep.equal([]); }); });
bdd.describe('Actions', function () { var stub; bdd.beforeEach(function () { stub = sinon.stub(jQuery, 'ajax'); }); bdd.afterEach(function () { jQuery.ajax.restore(); }); bdd.it('should assign', function () { new Issue({ key: 'issue-key' }).assign('admin'); assert.isTrue(stub.calledOnce); assert.equal(stub.firstCall.args[0].url, '/api/issues/assign'); assert.deepEqual(stub.firstCall.args[0].data, { issue: 'issue-key', assignee: 'admin' }); }); bdd.it('should unassign', function () { new Issue({ key: 'issue-key' }).assign(); assert.isTrue(stub.calledOnce); assert.equal(stub.firstCall.args[0].url, '/api/issues/assign'); assert.deepEqual(stub.firstCall.args[0].data, { issue: 'issue-key', assignee: undefined }); }); bdd.it('should plan', function () { new Issue({ key: 'issue-key' }).plan('plan'); assert.isTrue(stub.calledOnce); assert.equal(stub.firstCall.args[0].url, '/api/issues/plan'); assert.deepEqual(stub.firstCall.args[0].data, { issue: 'issue-key', plan: 'plan' }); }); bdd.it('should unplan', function () { new Issue({ key: 'issue-key' }).plan(); assert.isTrue(stub.calledOnce); assert.equal(stub.firstCall.args[0].url, '/api/issues/plan'); assert.deepEqual(stub.firstCall.args[0].data, { issue: 'issue-key', plan: undefined }); }); bdd.it('should set severity', function () { new Issue({ key: 'issue-key' }).setSeverity('BLOCKER'); assert.isTrue(stub.calledOnce); assert.equal(stub.firstCall.args[0].url, '/api/issues/set_severity'); assert.deepEqual(stub.firstCall.args[0].data, { issue: 'issue-key', severity: 'BLOCKER' }); }); bdd.it('should do a transition', function () { new Issue({ key: 'issue-key' }).transition('RESOLVED'); assert.isTrue(stub.calledOnce); assert.equal(stub.firstCall.args[0].url, '/api/issues/do_transition'); assert.deepEqual(stub.firstCall.args[0].data, { issue: 'issue-key', transition: 'RESOLVED' }); }); });
bdd.describe('for disengaging handlers', function() { var handle; var events = []; bdd.before(function() { skipSyntheticEnterFailure(this); handle = whenKey({ enter: function() { events.push('enter'); }, escape: function(event, disengage) { events.push('escape'); disengage(); }, }); }); bdd.after(function() { handle && handle.disengage({ force: true }); }); bdd.beforeEach(function() { events = []; }); bdd.it('should react to enter key', function() { simulateKeyDown('enter'); expect(events).to.deep.equal(['enter']); }); bdd.it('should react to escape key', function() { simulateKeyDown('escape'); expect(events).to.deep.equal(['escape']); }); bdd.it('should not react to escape key again', function() { simulateKeyDown('enter'); expect(events).to.deep.equal([]); }); bdd.it('should not react to escape key again', function() { simulateKeyDown('escape'); expect(events).to.deep.equal([]); }); });
bdd.describe('fix/pointer-focus-children', function() { var fixture; var handle; bdd.beforeEach(function() { fixture = customFixture([ '<div></div>', ]); }); bdd.afterEach(function() { // make sure a failed test cannot leave listeners behind handle && handle.disengage({ force: true }); fixture.remove(); fixture = null; }); bdd.it('should be a global service API', function() { expect(fixPointerFocusChildren).to.be.a('function'); handle = fixPointerFocusChildren(); expect(handle.disengage).to.be.a('function'); handle.disengage(); }); });
bdd.describe('query/shadow-hosts', function() { var fixture; bdd.beforeEach(function() { fixture = shadowInputFixture(); }); bdd.afterEach(function() { fixture.remove(); fixture = null; }); bdd.it('should handle invalid input', function() { expect(function() { queryShadowHosts({ context: [true], }); }).to.throw(TypeError, 'query/shadow-hosts requires options.context to be an Element'); }); bdd.it('should not fail if ShadowDOM is not supported', function() { if (document.body.createShadowRoot !== undefined) { this.skip('ShadowDOM is supported'); } var result = queryShadowHosts(); expect(result).to.deep.equal([]); }); bdd.describe('for ShadowDOM', function() { bdd.before(function() { if (document.body.createShadowRoot === undefined) { this.skip('ShadowDOM is not supported'); } }); bdd.it('should find all ShadowHost elements', function() { var expected = [ '#first-shadow-host', '#second-shadow-host', '#third-shadow-host', ]; var elements = queryShadowHosts().map(fixture.nodeToString).filter(function(name) { // in Chrome the <html> node has a shadowRoot return name !== 'html'; }); expect(elements).to.deep.equal(expected); }); bdd.it('should find all ShadowHost elements with ShadowHost as context', function() { var expected = [ '#first-shadow-host', '#second-shadow-host', '#third-shadow-host', ]; var elements = queryShadowHosts({ context: fixture.shadow.first, }).map(fixture.nodeToString); expect(elements).to.deep.equal(expected); }); }); });
bdd.describe('util/visible-area', function() { var fixture; var reset = 'box-sizing: border-box; margin:0; padding:0; border:0;'; function fixFloat(num) { // expected 0.2500000190734878 to equal 0.25 return parseFloat(num.toFixed(5)); } function transform(element, value) { element.style.transform = element.style.WebkitTransform = element.style.msTransform = value; } bdd.before(function() { if (platform.is.IOS) { // works fine when run manually in iOS simulator on BrowserStack, // but fails via WebDriver on BrowserStack. This modules is also // tested by when.visible-area.test, so just skip it. this.skip('Test does not run in iOS simulator'); } }); bdd.beforeEach(function() { fixture = customFixture([ /* eslint-disable indent */ '<div id="outer">', '<div id="inner">', '<input type="text" id="target">', '</div>', '</div>', /*eslint-enable indent */ ]); fixture.outer = document.getElementById('outer'); fixture.inner = document.getElementById('inner'); fixture.target = document.getElementById('target'); // move target out of view by making the parent scrollable fixture.outer.setAttribute('style', reset + ' width: 200px; height: 50px; overflow: hidden;'); fixture.inner.setAttribute('style', reset + ' width: 1000px; height: 50px; padding-left: 200px;'); fixture.target.setAttribute('style', reset + ' width: 200px; height: 50px;'); fixture.outer.scrollLeft = 0; }); bdd.afterEach(function() { fixture.remove(); fixture = null; }); bdd.describe('for non-scrolled element', function() { bdd.it('should be visible 100%', function() { var dimensions = ' width: 300px; height: 50px;'; fixture.add('<div id="natural">test</div>'); var element = document.getElementById('natural'); element.parentElement.setAttribute('style', reset + dimensions); element.setAttribute('style', reset + dimensions); element.scrollIntoView(); expect(fixFloat(visibleArea(element))).to.equal(1); }); }); bdd.describe('for nested scrolled element', function() { bdd.it('should be visible 0%', function() { fixture.add([ /* eslint-disable indent */ '<div id="container" style="width: 20px; height: 20px; overflow: hidden">', '<div id="nested-container" style="width: 20px; height: 20px; margin-left: 30px; overflow: hidden;">', '<div id="nested-target">target</div>', '</div>', '</div>', /*eslint-enable indent */ ]); var element = document.getElementById('nested-target'); expect(fixFloat(visibleArea(element))).to.equal(0); }); }); bdd.describe('for scrolled element', function() { bdd.it('should be visible 0% when parent ist scrolled 0%', function() { expect(fixFloat(visibleArea(fixture.target))).to.equal(0); }); bdd.it('should be visible 25% when parent ist scrolled 25%', function() { fixture.outer.scrollLeft = 50; expect(fixFloat(visibleArea(fixture.target))).to.equal(0.25); }); bdd.it('should be visible 50% when parent ist scrolled 50%', function() { fixture.outer.scrollLeft = 100; expect(fixFloat(visibleArea(fixture.target))).to.equal(0.5); }); bdd.it('should be visible 75% when parent ist scrolled 75%', function() { fixture.outer.scrollLeft = 150; expect(fixFloat(visibleArea(fixture.target))).to.equal(0.75); }); bdd.it('should be visible 100% when parent ist scrolled 100%', function() { fixture.outer.scrollLeft = 200; expect(fixFloat(visibleArea(fixture.target))).to.equal(1); }); bdd.it('should be visible 75% when parent ist scrolled 125%', function() { if (document.body.getBoundingClientRect().top < 0) { // works fine when run manually in iOS simulator on BrowserStack, // but fails via WebDriver on BrowserStack. This modules is also // tested by when.visible-area.test, so just skip it. this.skip('scrolled body prevents this test from succeeding'); } fixture.outer.scrollLeft = 250; expect(fixFloat(visibleArea(fixture.target))).to.equal(0.75); }); }); bdd.describe('for translated element', function() { bdd.it('should be visible 0% when element ist translated 0%', function() { fixture.outer.scrollLeft = 0; transform(fixture.inner, 'translate(0px, 0px)'); expect(fixFloat(visibleArea(fixture.target))).to.equal(0); }); bdd.it('should be visible 25% when element ist translated 25%', function() { fixture.outer.scrollLeft = 0; transform(fixture.inner, 'translate(-50px, 0px)'); expect(fixFloat(visibleArea(fixture.target))).to.equal(0.25); }); bdd.it('should be visible 50% when element ist translated 50%', function() { fixture.outer.scrollLeft = 0; transform(fixture.inner, 'translate(-100px, 0px)'); expect(fixFloat(visibleArea(fixture.target))).to.equal(0.5); }); bdd.it('should be visible 75% when element ist translated 75%', function() { fixture.outer.scrollLeft = 0; transform(fixture.inner, 'translate(-150px, 0px)'); expect(fixFloat(visibleArea(fixture.target))).to.equal(0.75); }); bdd.it('should be visible 100% when element ist translated 100%', function() { fixture.outer.scrollLeft = 0; transform(fixture.inner, 'translate(-200px, 0px)'); expect(fixFloat(visibleArea(fixture.target))).to.equal(1); }); bdd.it('should be visible 75% when element ist translated 125%', function() { fixture.outer.scrollLeft = 0; transform(fixture.inner, 'translate(-250px, 0px)'); expect(fixFloat(visibleArea(fixture.target))).to.equal(0.75); }); }); });
bdd.describe('query/first-tabbable', function() { var fixture; bdd.beforeEach(function() { fixture = focusableFixture(); }); bdd.afterEach(function() { fixture.remove(); fixture = null; }); bdd.it('should default to using document as context', function() { var expected = !platform.is.IOS ? document.getElementById('tabindex-0') : document.getElementById('input'); var result = queryFirstTabbable(); expect(result).to.equal(expected); }); bdd.it('should search within context', function() { var expected = !platform.is.IOS ? document.getElementById('link') : null; var result = queryFirstTabbable({ context: '.context', }); expect(result).to.equal(expected); }); bdd.it('should return null as empty result', function() { var context = fixture.root.querySelector('.context'); context.setAttribute('tabindex', '-1'); [].forEach.call(context.children, function(element) { element.setAttribute('tabindex', '-1'); }); var expected = null; var result = queryFirstTabbable({ context: '.context', }); expect(result).to.equal(expected); }); bdd.describe('with option.defaultToContext', function() { bdd.it('should return context if it contains no tabbable element', function() { var context = fixture.root.querySelector('.context'); context.setAttribute('tabindex', '-1'); [].forEach.call(context.children, function(element) { element.setAttribute('tabindex', '-1'); }); var expected = context; var result = queryFirstTabbable({ context: '.context', defaultToContext: true, }); expect(result).to.equal(expected); }); }); bdd.describe('for option.defaultToContext', function() { bdd.it('should return context if it contains no tabbable element', function() { var context = fixture.root.querySelector('.context'); context.setAttribute('tabindex', '-1'); [].forEach.call(context.children, function(element) { element.setAttribute('tabindex', '-1'); }); var expected = context; var result = queryFirstTabbable({ context: '.context', defaultToContext: true, }); expect(result).to.equal(expected); }); }); bdd.describe('for option.ignoreAutofocus', function() { bdd.it('should return [autofocus] element when flag not supplied', function() { var context = fixture.root.querySelector('.context'); var input = document.createElement('input'); // add element to DOM before setting autofocus attribute // to prevent the element getting focus in Trident and WebKit context.appendChild(input); input.setAttribute('autofocus', ''); var expected = input; var result = queryFirstTabbable({ context: '.context', }); expect(result).to.equal(expected); }); bdd.it('should not return [autofocus] element when flag is supplied', function() { var context = fixture.root.querySelector('.context'); // otherwise iOS would simply show the autofocus input var _input = document.createElement('input'); context.appendChild(_input); var input = document.createElement('input'); // add before autofocus, to prevent the element getting // focus in Trident and WebKit context.appendChild(input); input.setAttribute('autofocus', ''); var expected = !platform.is.IOS ? document.getElementById('link') : _input; var result = queryFirstTabbable({ context: '.context', ignoreAutofocus: true, }); expect(result).to.equal(expected); }); }); });
bdd.describe('digger module', () => { // clean and quit database after each test bdd.beforeEach(() => digger.setClient(5)); bdd.afterEach(() => digger.setClient(5) .then((client) => flushQuitDB(client))); bdd.describe('getStatus', () => { bdd.it('should return null if no status in db', () => digger.getStatus(5) .then(status => { assert.notOk(status); assert.isNull(status); }) ); bdd.it('should return an object saved as JSON in status key', () => digger.setClient(5) .then(client => redis.set(client, 'status', '{ "test": "data" }')) .then(() => digger.getStatus()) .then(status => { assert.ok(status); assert.deepEqual({ test: 'data' }, status); }) ); }); bdd.describe('getFeatureStatus', () => { bdd.it('should throw if no status in db', () => digger.getFeatureStatus('not-existing', 5) .catch(err => { assert.equal(err.message, 'Not Found'); }) ); bdd.it('should throw if no feature in status', () => digger.setClient(5) .then(client => redis.set(client, 'status', '{ "test": "data" }')) .then(() => digger.getFeatureStatus('not-existing', 5)) .catch(err => { assert.equal(err.message, 'Not Found'); }) ); bdd.it('should return the value stored under key defined by slug', () => { const testData = { slug: 'feature', a: 'value A', b: 'value B', updated: {} }; return digger.setClient(5) .then(() => engine.saveData([testData], 5)) .then(() => digger.getFeatureStatus('feature', 5)) .then(featureStatus => { assert.ok(featureStatus); assert.deepEqual(featureStatus, testData); }); }); }); });
bdd.describe('api route', () => { const portfinder = require('intern/dojo/node!portfinder'); const platatus = require('intern/dojo/node!../app'); var port; var server; function api() { return chai.request(`http://localhost:${port}`); } // set database channel bdd.beforeEach(() => digger.setClient(5)); // find port and spin the server bdd.before(() => new Promise((resolve) => { portfinder.getPort((err, receivedPort) => { port = receivedPort; server = platatus.listen(port, () => { console.log('server is running on port %j', port); resolve(); }); }); })); bdd.after(() => server.close()); // clean and quit database after each test bdd.afterEach(() => digger.setClient(5) .then((client) => flushQuitDB(client))); bdd.describe('/api/status', () => { bdd.it('returns null if no status', () => api() .get('/api/status') .send() .then(response => { assert.strictEqual(response.body, null); }) ); bdd.it('should return the value stored under key defined by slug', () => { const testData = { slug: 'feature', a: 'value A', b: 'value B', updated: {} }; return digger.setClient(5) .then(() => engine.saveData([testData], 5)) .then(() => api() .get('/api/status') .send() ) .then(response => { assert.property(response.body, 'feature'); assert.deepEqual(response.body.feature, testData); }); }); }); bdd.describe('/api/feature/{slug}', () => { bdd.it('returns 404 if getFeatureStatus throws', () => api() .get('/api/feature/some-status') .send() .catch(err => { assert.equal(err.response.status, 404); }) ); bdd.it('returns savedData', () => { const testData1 = { slug: 'feature', a: 'value A', b: 'value B', updated: {} }; const testData2 = { slug: 'another-feature', a: 'another A', b: 'another B', updated: {} }; return digger.setClient(5) .then(() => engine.saveData([testData1, testData2], 5)) .then(() => api() .get('/api/feature/feature') .send() ) .then(response => { assert.deepEqual(response.body, testData1); }) .then(() => api() .get('/api/feature/another-feature') .send() ) .then(response => { assert.deepEqual(response.body, testData2); }); }); }); });
bdd.describe('Cache', function() { const cache = require('intern/dojo/node!../../../../engine/cache').default; const cacheDir = 'tests/support/var/engineCache'; const fetchMock = require('intern/dojo/node!fetch-mock'); bdd.before(function() { // Create the tests var dir if it doesn't already exist const dir = path.dirname(cacheDir); var stats; try { stats = fs.statSync(dir); if (!stats.isDirectory()) { throw new Error('tests var dir exists but is not a directory'); } } catch (statErr) { if (statErr.code !== 'ENOENT') { throw statErr; } fs.mkdirSync(dir); } // The test cache dir shouldn't exist, but delete it if it does return del([cacheDir]); }); bdd.afterEach(function() { // Remove the test cache dir return del([cacheDir]); }); bdd.beforeEach(function() { // Don't let tests interfere with each other's calls to `fetch` fetchMock.reset(); // Make dir to cache files to during tests fs.mkdirSync(cacheDir); }); bdd.it('should cache files', function() { const testURL = 'https://raw.githubusercontent.com/mozilla/platatus/master/package.json'; // Cache our package.json file return cache.readJson(testURL, cacheDir).then(function(originalText) { // Cause the next fetch to fail fetchMock.mock(testURL, 404); // Get our package.json (should succeed from cache) return cache.readJson(testURL, cacheDir).then(function(cachedText) { // Compare the original text with the cached text assert.equal(JSON.stringify(cachedText), JSON.stringify(originalText)); }); }); }); bdd.it('should reject on 404s', function() { const testURL = 'https://raw.githubusercontent.com/mozilla/platatus/master/package.json'; // Cause the fetch to 404 fetchMock.mock(testURL, 404); return cache.readJson(testURL, cacheDir).then(function() { assert.fail('`cache.readJson` should have rejected on a 404'); }).catch(function(err) { assert(err instanceof Error); return true; }); }); });
bdd.describe('lifecycle', function() { var handle; var events = []; bdd.before(function() { skipSyntheticEnterFailure(this); handle = whenKey({ enter: function() { events.push('enter'); }, escape: function() { events.push('escape'); }, 'shift+enter': function() { events.push('shift enter'); }, 'shift+ctrl+enter': function() { events.push('shift ctrl enter'); }, 'ctrl+enter': function() { events.push('ctrl enter'); }, }); }); bdd.after(function() { handle && handle.disengage({ force: true }); }); bdd.beforeEach(function() { events = []; }); bdd.it('should react to enter key', function() { simulateKeyDown('enter'); expect(events).to.deep.equal(['enter']); }); bdd.it('should react to escape key', function() { simulateKeyDown('escape'); expect(events).to.deep.equal(['escape']); }); bdd.it('should react to enter key again', function() { simulateKeyDown('enter'); expect(events).to.deep.equal(['enter']); }); bdd.it('should not react to space key', function() { simulateKeyDown('space'); expect(events).to.deep.equal([]); }); bdd.it('should react to enter with shift pressed', function() { simulateKeyDown('enter', document.documentElement, { shiftKey: true, }); expect(events).to.deep.equal(['shift enter']); }); bdd.it('should react to enter with control pressed', function() { simulateKeyDown('enter', document.documentElement, { ctrlKey: true, }); expect(events).to.deep.equal(['ctrl enter']); }); bdd.it('should react to enter with shift and control pressed', function() { simulateKeyDown('enter', document.documentElement, { ctrlKey: true, shiftKey: true, }); expect(events).to.deep.equal(['shift ctrl enter']); }); bdd.it('should not react to enter with shift and metaKey pressed', function() { simulateKeyDown('enter', document.documentElement, { metaKey: true, shiftKey: true, }); expect(events).to.deep.equal([]); }); bdd.it('should not react to any key after disengage', function() { handle.disengage(); simulateKeyDown('enter'); expect(events).to.deep.equal([]); }); });
bdd.describe('query/focusable.all', function() { var fixture; bdd.beforeEach(function() { var deferred = this.async(10000); fixture = focusableFixture(); // NOTE: Firefox decodes DataURIs asynchronously setTimeout(deferred.resolve, 200); }); bdd.afterEach(function() { fixture.remove(); fixture = null; }); bdd.it('should search within given context', function() { var expected = [ '#link', '#link-tabindex--1', ]; var result = queryFocusable({ strategy: 'all', context: '.context', }).map(fixture.nodeToString); expect(result).to.deep.equal(expected); }); bdd.describe('for option includeContext', function() { bdd.it('should find elements within context and the context element itself', function() { fixture.root.querySelector('.context').setAttribute('tabindex', '-1'); var expected = [ 'div', '#link', '#link-tabindex--1', ]; var result = queryFocusable({ strategy: 'all', context: '.context', includeContext: true, }).map(fixture.nodeToString); expect(result).to.deep.equal(expected); }); }); bdd.it('should find all focusable elements', function() { var result = queryFocusable({ strategy: 'all', }).map(fixture.nodeToString); var expected = [ '#tabindex--1', '#tabindex-0', '#tabindex-1', supports.focusInvalidTabindex && '#tabindex-bad', '#link', '#link-tabindex--1', '#image-map-area', '#image-map-area-nolink', supports.focusRedirectImgUsemap && '#img-usemap', supports.focusObjectSvg && '#object-svg', (supports.focusingSvgElements && supports.focusSvg) && '#svg', supports.focusObjectSvg && '#object-tabindex-svg', '#svg-link', !supports.AVOID_QUICKTIME && '#embed', !supports.AVOID_QUICKTIME && '#embed-tabindex-0', '#embed-svg', '#embed-tabindex-svg', !supports.AVOID_MEDIA && supports.focusAudioWithoutControls && '#audio', !supports.AVOID_MEDIA && '#audio-controls', '#label', '#input', '#input-tabindex--1', '#input-disabled', supports.focusFieldset && 'fieldset', '#fieldset-disabled-input', '#span-contenteditable', document.body.style.webkitUserModify !== undefined && '#span-user-modify', '#img-ismap-link', supports.focusImgIsmap && '#img-ismap', supports.focusScrollContainer && '#scroll-container', supports.focusScrollBody && '#scroll-body', supports.focusScrollContainerWithoutOverflow && '#scroll-container-without-overflow', supports.focusScrollContainerWithoutOverflow && '#scroll-body-without-overflow', supports.focusScrollContainer && '#div-section-overflow-scroll', supports.focusScrollContainer && !supports.focusScrollBody && '#section-div-overflow-scroll', supports.focusScrollBody && '#section-div-overflow-scroll-body', supports.focusFlexboxContainer && '#flexbox-container', supports.focusFlexboxContainer && '#flexbox-container-child', '#focusable-flexbox', supports.focusChildrenOfFocusableFlexbox && '#focusable-flexbox-child', ].filter(Boolean); expect(result).to.deep.equal(expected); }); bdd.describe('for children of <canvas>', function() { bdd.it('should find all focusable elements', function() { var container = fixture.add([ /* eslint-disable indent */ '<canvas>', '<input type="text" id="canvas-input">', '<input type="text" id="canvas-input-tabindex--1" tabindex="-1">', '<a href="#void" id="canvas-a">hello</a>', '<a href="#void" id="canvas-a-tabindex--1" tabindex="-1">hello</a>', '<span tabindex="0" id="canvas-span-tabindex-0">hello</span>', '<span tabindex="-1" id="canvas-span-tabindex--1">hello</span>', '</canvas>', /*eslint-enable indent */ ], 'canvas-container'); var expected = [ '#canvas-input', '#canvas-input-tabindex--1', '#canvas-a', '#canvas-a-tabindex--1', '#canvas-span-tabindex-0', '#canvas-span-tabindex--1', ]; var result = queryFocusable({ strategy: 'all', context: container, includeContext: true, }).map(fixture.nodeToString); expect(result).to.deep.equal(expected); }); }); bdd.describe('for ShadowDOM', function() { bdd.before(function() { if (document.body.createShadowRoot === undefined) { this.skip('ShadowDOM is not supported'); } }); bdd.it('should find elements nested in ShadowRoot', function() { var host = document.createElement('div'); host.id = 'first-shadow-host'; fixture.root.appendChild(host); shadowInputFixture.createShadowRoot(fixture); var result = queryFocusable({ strategy: 'all', }).map(fixture.nodeToString); var expected = [ '#tabindex--1', '#tabindex-0', '#tabindex-1', supports.focusInvalidTabindex && '#tabindex-bad', '#link', '#link-tabindex--1', '#image-map-area', '#image-map-area-nolink', supports.focusRedirectImgUsemap && '#img-usemap', supports.focusObjectSvg && '#object-svg', supports.focusObjectSvg && '#object-tabindex-svg', '#svg-link', !supports.AVOID_QUICKTIME && '#embed', !supports.AVOID_QUICKTIME && '#embed-tabindex-0', '#embed-svg', '#embed-tabindex-svg', !supports.AVOID_MEDIA && supports.focusAudioWithoutControls && '#audio', !supports.AVOID_MEDIA && '#audio-controls', '#label', '#input', '#input-tabindex--1', '#input-disabled', '#fieldset-disabled-input', '#span-contenteditable', document.body.style.webkitUserModify !== undefined && '#span-user-modify', '#img-ismap-link', supports.focusScrollContainer && '#scroll-container', supports.focusScrollContainer && '#div-section-overflow-scroll', supports.focusScrollContainer && !supports.focusScrollBody && '#section-div-overflow-scroll', supports.focusScrollBody && '#section-div-overflow-scroll-body', supports.focusFlexboxContainer && '#flexbox-container', supports.focusFlexboxContainer && '#flexbox-container-child', '#focusable-flexbox', supports.focusChildrenOfFocusableFlexbox && '#focusable-flexbox-child', '#first-input', '#second-input', '#third-input', ].filter(Boolean); expect(result).to.deep.equal(expected); }); }); });