Example #1
0
    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']);
      });
    });
Example #2
0
    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([]);
      });
    });
Example #3
0
    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' });
      });
    });
Example #4
0
    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);
      });
    });
  });
Example #9
0
  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);
        });
      });
    });
  });
Example #10
0
  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);
        });
      });
    });
  });
Example #11
0
    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;
        });
      });
    });
Example #12
0
    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);
      });
    });
  });