handleEvent = deferred.rejectOnError(function(event) { expect(event.type).to.equal('focus'); expect(event.target).to.equal(fixture.input.outer); expect(events.length).to.equal(0); waitForFirst(); });
return function() { // static result state var element = data.elements[label] || {}; var focusable = Boolean(element.focusable); var tabbable = focusable && Boolean(element.tabbable); var onlyTabbable = !focusable && Boolean(element.tabbable); var focusRelevant = Boolean(focusable || onlyTabbable || element.scriptFocus && element.scriptFocus.redirected); // evaluated state var _element = framed.getElement(label); if (!_element) { this.skip('element not found'); } var _focusRelevant = isFocusRelevant(_element); var _focusable = isFocusable(_element); var _tabbable = _focusable && isTabbable(_element); var _onlyTabbable = isOnlyTabbable(_element); // focus-relevant is allowed to produce false-positives // as it is only used as a pre-filter var okFocusRelevant = _focusRelevant === focusRelevant || _focusRelevant && !focusRelevant; expect(okFocusRelevant).to.equal(true, 'is/focus-relevant'); expect(_focusable).to.equal(focusable, 'is/focusable'); expect(_tabbable).to.equal(tabbable, 'is/tabbable'); expect(_onlyTabbable).to.equal(onlyTabbable, 'is/only-tabbable'); var redirectTarget = element.scriptFocus && element.scriptFocus.redirected || null; var _redirectTarget = getFocusRedirectTarget({context: _element}); var _redirectTargetLabel = _redirectTarget && _redirectTarget.getAttribute('data-label') || null; expect(_redirectTargetLabel).to.equal(redirectTarget, 'get/focus-redirect-target'); };
bdd.it('should show interaction after mousedown', function() { dispatchEvent.mouse(document.documentElement, 'mousedown', {}); var type = handle.get(); expect(type.pointer).to.equal(true, 'pointer'); expect(type.key).to.equal(false, 'key'); });
'.rules() and .except()': function() { var element = document.getElementById('inert-div'); expect(isFocusable.rules({ context: element, })).to.equal(false, '.rules()'); expect(isFocusable.rules.except({})(element)).to.equal(false, '.rules.except()'); },
handleEvent = deferred.rejectOnError(function(event) { expect(event.detail.blur).to.equal(document.body, 'document lost focus'); expect(event.detail.focus).to.equal(first, 'first got focus'); expect(events.length).to.equal(1, 'first event buffer'); waitForSecond(); });
handleEvent = deferred.rejectOnError(function(event) { expect(event.detail.blur).to.equal(first, 'first lost focus'); expect(event.detail.focus).to.equal(second, 'second got focus'); expect(events.length).to.equal(2, 'second event buffer'); waitForDone(); });
bdd.it('should identify <body> after blur()', function() { input.blur(); expect(isActiveElement(link)).to.equal(false, 'link'); expect(isActiveElement(input)).to.equal(false, 'input'); expect(isActiveElement(document.body)).to.equal(true, 'body'); expect(isActiveElement(document)).to.equal(false, 'document'); });
bdd.it('should engage a service', function() { handle = styleFocusSource(); expect(handle.disengage).to.be.a('function', 'handle.disengage'); expect(handle.lock).to.be.a('function', 'handle.lock'); expect(handle.current).to.be.a('function', 'handle.current'); expect(handle.used).to.be.a('function', 'handle.used'); });
bdd.it('should identify <a>', function() { link.focus(); expect(isActiveElement(link)).to.equal(true, 'link'); expect(isActiveElement(input)).to.equal(false, 'input'); expect(isActiveElement(document.body)).to.equal(false, 'body'); expect(isActiveElement(document)).to.equal(false, 'document'); });
bdd.it('should return ancestor ShadowHosts for ShadowRoots', function() { var shadowParents = getShadowHostParents({ context: fixture.shadow.first.shadowRoot, }); expect(shadowParents.length).to.equal(1); expect(shadowParents[0]).to.equal(fixture.shadow.first); });
bdd.it('should retain "pointer" on lock("pointer")', function() { handle.lock('pointer'); fixture.input.after.focus(); expect(handle.current()).to.equal('pointer', 'handle.current()'); fixture.input.outer.focus(); expect(handle.current()).to.equal('pointer', 'handle.current() repeat'); });
setTimeout(deferred.callback(function() { var context = document.getElementById('img-container'); var tabbable = queryTabbable({context: context}); var result = sortArea(tabbable, context).map(fixture.nodeToString); expect(tabbable.length).to.equal(0); expect(result).to.deep.equal(expected); }), 200);
invalid: function() { expect(function() { isFocusable(null); }).to.throw(TypeError, 'is/focusable requires valid options.context'); expect(function() { isFocusable([true]); }).to.throw(TypeError, 'is/focusable requires options.context to be an Element'); },
setTimeout(deferred.callback(function() { // clean events that may have been caught by IE10 before we even got started events.length = 0; handle = eventActiveElement(); expect(handle.disengage).to.be.a('function', 'initialized disengage'); expect(events.length).to.equal(0, 'initialized event buffer'); }), 20);
bdd.it('should return ancestor ShadowHosts for shadowed elements', function() { var shadowParents = getShadowHostParents({ context: fixture.input.second, }); expect(shadowParents.length).to.equal(2); expect(shadowParents[0]).to.equal(fixture.shadow.second); expect(shadowParents[1]).to.equal(fixture.shadow.first); });
bdd.it('should show interaction after keydown', function() { dispatchEvent.key(document.documentElement, 'keydown', { key: 'Tab', keyCode: 9, }); var type = handle.get(); expect(type.pointer).to.equal(false, 'pointer'); expect(type.key).to.equal(true, 'key'); });
'inactive document': function() { var active = getActiveElements(); expect(active.length).to.equal(1); // Internet Explorer 10 may think it's <html> rather than <body> if (active[0] === document.documentElement) { expect(active[0]).to.equal(document.documentElement); } else { expect(active[0]).to.equal(document.body); } },
'active in ShadowHost': function() { if (!fixture.shadow.first) { this.skip('Shadow DOM not supported'); } fixture.input.first.focus(); var active = getActiveElements(); expect(active.length).to.equal(2); expect(active[0]).to.equal(fixture.input.first); expect(active[1]).to.equal(fixture.shadow.first); },
bdd.it('should return a service handle', function() { var handle = observeInteractionType(); expect(handle.disengage).to.be.a('function'); expect(handle.get).to.be.a('function'); var type = handle.get(); expect(type.pointer).to.equal(false, 'pointer'); expect(type.key).to.equal(false, 'key'); handle.disengage({force: true}); });
it('should remove a subscriber', function() { var o = new Signal(), r = false, f = function() { r = !r; }; o.subscribe(f); o.propagate(); expect(r).to.equal(true); o.unsubscribe(f); expect(r).to.equal(true); });
handleEvent = deferred.rejectOnError(function(event) { if (event.type === 'focus') { return; } expect(event.type).to.equal('shadow-focus'); expect(event.detail.active).to.equal(fixture.input.first); expect(event.detail.hosts.length).to.equal(1); expect(event.detail.hosts[0]).to.equal(fixture.shadow.first); expect(events.length).to.equal(1); waitForSecond(); });
invalid: function() { expect(function() { queryFocusable({ context: [true], }); }).to.throw(TypeError, 'query/focusable requires options.context to be an Element', 'non-element context'); expect(function() { queryFocusable({ strategy: 'random', }); }).to.throw(TypeError, 'query/focusable requires option.strategy to be one of ["quick", "strict", "all"]', 'bad strategy'); },
bdd.it('should register focus shift by script', function() { fixture.input.outer.focus(); expect(document.activeElement).to.equal(fixture.input.outer, 'activeElement'); expect(document.documentElement.getAttribute('data-focus-source')).to.equal('script', 'attribute'); expect(document.documentElement.className.indexOf('focus-source-script') !== -1).to.equal(true, 'script class'); expect(document.documentElement.className.indexOf('focus-source-key') !== -1).to.equal(false, 'key class'); expect(document.documentElement.className.indexOf('focus-source-pointer') !== -1).to.equal(false, 'pointer class'); expect(handle.current()).to.equal('script', 'handle.current()'); expect(handle.used('initial')).to.equal(true, 'handle.used(initial)'); expect(handle.used('script')).to.equal(true, 'handle.used(script)'); expect(handle.used('key')).to.equal(false, 'handle.used(key)'); expect(handle.used('pointer')).to.equal(false, 'handle.used(pointer)'); });
lifecycle: function() { var uncle1 = document.getElementById('uncle-1'); expect(uncle1.hasAttribute('aria-hidden')).to.equal(false, 'uncle-1 before engaged'); handle = maintainHidden({ filter: '#target', }); expect(handle.disengage).to.be.a('function'); expect(fixture.root.hasAttribute('aria-hidden')).to.equal(false, 'root after engaged'); expect(uncle1.getAttribute('aria-hidden')).to.equal('true', 'uncle-1 after engaged'); handle.disengage(); expect(uncle1.hasAttribute('aria-hidden')).to.equal(false, 'uncle-1 after disengaged'); },
it('should not add a subscriber more than once', function() { var o = new Signal(), r = false, f = function() { r = !r; }; o.subscribe(f); o.propagate(); expect(r).to.equal(true); o.propagate(); expect(r).to.equal(false); o.subscribe(f); o.propagate(); expect(r).to.equal(true); });
bdd.it('should revert interactions after mouseup event', function() { var deferred = this.async(10000); dispatchEvent.mouse(document.documentElement, 'mouseup', {}); var type = handle.get(); expect(type.pointer).to.equal(true, 'pointer immediately'); expect(type.key).to.equal(false, 'key immediately'); setTimeout(deferred.callback(function() { type = handle.get(); expect(type.pointer).to.equal(false, 'pointer delayed'); expect(type.key).to.equal(false, 'key delayed'); }), 20); });
'default context': function() { var engaged = []; var decorated = decorateContext({ engage: function(element) { engaged.push(element); }, disengage: function() {}, }); expect(decorated).to.be.a('function'); decorated(); expect(engaged.length).to.equal(1); expect(engaged[0]).to.equal(document); },
bdd.it('should ignore shift on keydown', function() { var spaceKey = { key: 'Space', keyCode: 16, }; if (dispatchEvent.key(null, 'keydown', spaceKey).keyCode !== 16) { this.skip('Synthetic shift event not detectable'); } dispatchEvent.key(document.documentElement, 'keydown', spaceKey); var type = handle.get(); expect(type.pointer).to.equal(false, 'key-down pointer'); expect(type.key).to.equal(false, 'key-down key'); });
lifecycle: function() { var deferred = this.async(10000); expect(document.documentElement.hasAttribute('data-focus-source')).to.equal(false, 'before engage'); // initiate with delay because of IE10's async focus event from previous test setTimeout(deferred.callback(function() { handle = styleFocusSource(); expect(handle.disengage).to.be.a('function'); expect(handle.lock).to.be.a('function'); expect(handle.current).to.be.a('function'); expect(handle.used).to.be.a('function'); expect(document.documentElement.getAttribute('data-focus-source')).to.equal('initial', 'attribute after engage'); expect(handle.current()).to.equal('initial', 'current after engage'); fixture.input.outer.focus(); expect(document.activeElement).to.equal(fixture.input.outer, 'focus shift'); expect(document.documentElement.getAttribute('data-focus-source')).to.equal('script', 'attribute focus shift'); expect(handle.current()).to.equal('script', 'current focus shift'); expect(handle.used('initial')).to.equal(true, 'used(initial) focus shift'); expect(handle.used('script')).to.equal(true, 'used(script) focus shift'); expect(handle.used('key')).to.equal(false, 'used(key) focus shift'); expect(handle.used('pointer')).to.equal(false, 'used(pointer) focus shift'); handle.disengage(); handle = null; expect(document.documentElement.hasAttribute('data-focus-source')).to.equal(false, 'after disengage'); }), 100); },
'lock()': function() { handle = styleFocusSource(); dispatchEvent.mouse(document.documentElement, 'mousedown', {}); fixture.input.outer.focus(); dispatchEvent.mouse(document.documentElement, 'mouseup', {}); expect(handle.current()).to.equal('pointer', 'current() after focus shift'); handle.lock('key'); fixture.input.after.focus(); expect(handle.current()).to.equal('key', 'current() after second focus shift'); fixture.input.outer.focus(); expect(handle.current()).to.equal('key', 'current() after third focus shift'); },