github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/ui/tests/acceptance/keyboard-test.js (about)

     1  /* eslint-disable qunit/require-expect */
     2  import { module, test } from 'qunit';
     3  import { setupApplicationTest } from 'ember-qunit';
     4  import {
     5    click,
     6    currentURL,
     7    visit,
     8    triggerEvent,
     9    triggerKeyEvent,
    10    findAll,
    11  } from '@ember/test-helpers';
    12  import { setupMirage } from 'ember-cli-mirage/test-support';
    13  import Layout from 'nomad-ui/tests/pages/layout';
    14  import percySnapshot from '@percy/ember';
    15  import a11yAudit from 'nomad-ui/tests/helpers/a11y-audit';
    16  import faker from 'nomad-ui/mirage/faker';
    17  
    18  module('Acceptance | keyboard', function (hooks) {
    19    setupApplicationTest(hooks);
    20    setupMirage(hooks);
    21  
    22    module('modal', function () {
    23      test('Opening and closing shortcuts modal with key commands', async function (assert) {
    24        faker.seed(1);
    25        assert.expect(4);
    26        await visit('/');
    27        assert.notOk(Layout.keyboard.modalShown);
    28        await triggerEvent('.page-layout', 'keydown', { key: '?' });
    29        assert.ok(Layout.keyboard.modalShown);
    30        await percySnapshot(assert);
    31        await a11yAudit(assert);
    32        await triggerEvent('.page-layout', 'keydown', { key: 'Escape' });
    33        assert.notOk(Layout.keyboard.modalShown);
    34      });
    35  
    36      test('closing shortcuts modal by clicking dismiss', async function (assert) {
    37        await visit('/');
    38        await triggerEvent('.page-layout', 'keydown', { key: '?' });
    39        assert.ok(Layout.keyboard.modalShown);
    40        assert.dom('button.dismiss').isFocused();
    41        await click('button.dismiss');
    42        assert.notOk(Layout.keyboard.modalShown);
    43      });
    44  
    45      test('closing shortcuts modal by clicking outside', async function (assert) {
    46        await visit('/');
    47        await triggerEvent('.page-layout', 'keydown', { key: '?' });
    48        assert.ok(Layout.keyboard.modalShown);
    49        await click('.page-layout');
    50        assert.notOk(Layout.keyboard.modalShown);
    51      });
    52    });
    53  
    54    module('Enable/Disable', function (enableDisableHooks) {
    55      enableDisableHooks.beforeEach(function () {
    56        window.localStorage.clear();
    57      });
    58  
    59      test('Shortcuts work by default and stops working when disabled', async function (assert) {
    60        await visit('/');
    61  
    62        triggerEvent('.page-layout', 'keydown', { key: 'g' });
    63        await triggerEvent('.page-layout', 'keydown', { key: 'c' });
    64        assert.equal(
    65          currentURL(),
    66          `/clients`,
    67          'end up on the clients page after typing g c'
    68        );
    69        assert.notOk(Layout.keyboard.modalShown);
    70        await triggerEvent('.page-layout', 'keydown', { key: '?' });
    71        assert.ok(Layout.keyboard.modalShown);
    72        assert.dom('[data-test-enable-shortcuts-toggle]').hasClass('is-active');
    73        await click('[data-test-enable-shortcuts-toggle]');
    74        assert
    75          .dom('[data-test-enable-shortcuts-toggle]')
    76          .doesNotHaveClass('is-active');
    77        await triggerEvent('.page-layout', 'keydown', { key: 'Escape' });
    78        assert.notOk(Layout.keyboard.modalShown);
    79        triggerEvent('.page-layout', 'keydown', { key: 'g' });
    80        await triggerEvent('.page-layout', 'keydown', { key: 'j' });
    81        assert.equal(
    82          currentURL(),
    83          `/clients`,
    84          'typing g j did not bring you back to the jobs page, since shortcuts are disabled'
    85        );
    86        await triggerEvent('.page-layout', 'keydown', { key: '?' });
    87        await click('[data-test-enable-shortcuts-toggle]');
    88        assert.dom('[data-test-enable-shortcuts-toggle]').hasClass('is-active');
    89        await triggerEvent('.page-layout', 'keydown', { key: 'Escape' });
    90        triggerEvent('.page-layout', 'keydown', { key: 'g' });
    91        await triggerEvent('.page-layout', 'keydown', { key: 'j' });
    92        assert.equal(
    93          currentURL(),
    94          `/jobs`,
    95          'typing g j brings me to the jobs page after re-enabling shortcuts'
    96        );
    97      });
    98    });
    99  
   100    module('Local storage bind/rebind', function (rebindHooks) {
   101      rebindHooks.beforeEach(function () {
   102        window.localStorage.clear();
   103      });
   104  
   105      test('You can rebind shortcuts', async function (assert) {
   106        await visit('/');
   107  
   108        triggerEvent('.page-layout', 'keydown', { key: 'g' });
   109        await triggerEvent('.page-layout', 'keydown', { key: 'c' });
   110        assert.equal(
   111          currentURL(),
   112          `/clients`,
   113          'end up on the clients page after typing g c'
   114        );
   115  
   116        triggerEvent('.page-layout', 'keydown', { key: 'g' });
   117        await triggerEvent('.page-layout', 'keydown', { key: 'j' });
   118        assert.equal(
   119          currentURL(),
   120          `/jobs`,
   121          'end up on the clients page after typing g j'
   122        );
   123  
   124        assert.notOk(Layout.keyboard.modalShown);
   125        await triggerEvent('.page-layout', 'keydown', { key: '?' });
   126        assert.ok(Layout.keyboard.modalShown);
   127  
   128        await click(
   129          '[data-test-command-label="Go to Clients"] button[data-test-rebinder]'
   130        );
   131  
   132        triggerEvent('.page-layout', 'keydown', { key: 'r' });
   133        triggerEvent('.page-layout', 'keydown', { key: 'o' });
   134        triggerEvent('.page-layout', 'keydown', { key: 'f' });
   135        triggerEvent('.page-layout', 'keydown', { key: 'l' });
   136        await triggerEvent('.page-layout', 'keydown', { key: 'Enter' });
   137        assert
   138          .dom(
   139            '[data-test-command-label="Go to Clients"] button[data-test-rebinder]'
   140          )
   141          .hasText('r o f l');
   142  
   143        assert.equal(
   144          currentURL(),
   145          `/jobs`,
   146          'typing g c does not do anything, since I re-bound the shortcut'
   147        );
   148  
   149        triggerEvent('.page-layout', 'keydown', { key: 'r' });
   150        triggerEvent('.page-layout', 'keydown', { key: 'o' });
   151        triggerEvent('.page-layout', 'keydown', { key: 'f' });
   152        await triggerEvent('.page-layout', 'keydown', { key: 'l' });
   153  
   154        assert.equal(
   155          currentURL(),
   156          `/clients`,
   157          'typing the newly bound shortcut brings me to clients'
   158        );
   159  
   160        await click(
   161          '[data-test-command-label="Go to Clients"] button[data-test-rebinder]'
   162        );
   163  
   164        triggerEvent('.page-layout', 'keydown', { key: 'n' });
   165        triggerEvent('.page-layout', 'keydown', { key: 'o' });
   166        triggerEvent('.page-layout', 'keydown', { key: 'p' });
   167        triggerEvent('.page-layout', 'keydown', { key: 'e' });
   168        await triggerEvent('.page-layout', 'keydown', { key: 'Escape' });
   169        assert
   170          .dom(
   171            '[data-test-command-label="Go to Clients"] button[data-test-rebinder]'
   172          )
   173          .hasText(
   174            'r o f l',
   175            'text unchanged when I hit escape during recording'
   176          );
   177  
   178        await click(
   179          '[data-test-command-label="Go to Clients"] button.reset-to-default'
   180        );
   181        assert
   182          .dom(
   183            '[data-test-command-label="Go to Clients"] button[data-test-rebinder]'
   184          )
   185          .hasText('g c', 'Resetting to default rebinds the shortcut');
   186      });
   187  
   188      test('Rebound shortcuts persist from localStorage', async function (assert) {
   189        window.localStorage.setItem(
   190          'keyboard.command.Go to Clients',
   191          JSON.stringify(['b', 'o', 'o', 'p'])
   192        );
   193        await visit('/');
   194  
   195        triggerEvent('.page-layout', 'keydown', { key: 'g' });
   196        await triggerEvent('.page-layout', 'keydown', { key: 'c' });
   197        assert.equal(
   198          currentURL(),
   199          `/jobs`,
   200          'After a refresh with a localStorage-found binding, a default key binding doesnt do anything'
   201        );
   202  
   203        triggerEvent('.page-layout', 'keydown', { key: 'b' });
   204        triggerEvent('.page-layout', 'keydown', { key: 'o' });
   205        triggerEvent('.page-layout', 'keydown', { key: 'o' });
   206        await triggerEvent('.page-layout', 'keydown', { key: 'p' });
   207        assert.equal(
   208          currentURL(),
   209          `/clients`,
   210          'end up on the clients page after typing the localstorage-bound shortcut'
   211        );
   212  
   213        assert.notOk(Layout.keyboard.modalShown);
   214        await triggerEvent('.page-layout', 'keydown', { key: '?' });
   215        assert.ok(Layout.keyboard.modalShown);
   216        assert
   217          .dom(
   218            '[data-test-command-label="Go to Clients"] button[data-test-rebinder]'
   219          )
   220          .hasText('b o o p');
   221      });
   222    });
   223  
   224    module('Hints', function () {
   225      test('Hints show up on shift', async function (assert) {
   226        await visit('/');
   227  
   228        await triggerEvent('.page-layout', 'keydown', { key: 'Shift' });
   229        assert.equal(
   230          document.querySelectorAll('[data-test-keyboard-hint]').length,
   231          7,
   232          'Shows 7 hints by default'
   233        );
   234        await triggerEvent('.page-layout', 'keyup', { key: 'Shift' });
   235  
   236        assert.equal(
   237          document.querySelectorAll('[data-test-keyboard-hint]').length,
   238          0,
   239          'Hints disappear when you release Shift'
   240        );
   241      });
   242    });
   243  
   244    module('Dynamic Nav', function (dynamicHooks) {
   245      dynamicHooks.beforeEach(async function () {
   246        server.create('node');
   247      });
   248      test('Dynamic Table Nav', async function (assert) {
   249        assert.expect(4);
   250        server.createList('job', 3, { createRecommendations: true });
   251        await visit('/jobs');
   252  
   253        await triggerEvent('.page-layout', 'keydown', { key: 'Shift' });
   254        assert.equal(
   255          document.querySelectorAll('[data-shortcut="Shift+01"]').length,
   256          1,
   257          'First job gets a shortcut hint'
   258        );
   259        assert.equal(
   260          document.querySelectorAll('[data-shortcut="Shift+02"]').length,
   261          1,
   262          'Second job gets a shortcut hint'
   263        );
   264        assert.equal(
   265          document.querySelectorAll('[data-shortcut="Shift+03"]').length,
   266          1,
   267          'Third job gets a shortcut hint'
   268        );
   269  
   270        triggerEvent('.page-layout', 'keydown', { key: 'Shift' });
   271        triggerEvent('.page-layout', 'keydown', { key: '0' });
   272        await triggerEvent('.page-layout', 'keydown', { key: '1' });
   273  
   274        const clickedJob = server.db.jobs.sortBy('modifyIndex').reverse()[0].id;
   275        assert.equal(
   276          currentURL(),
   277          `/jobs/${clickedJob}@default`,
   278          'Shift+01 takes you to the first job'
   279        );
   280      });
   281      test('Multi-Table Nav', async function (assert) {
   282        server.createList('job', 3, { createRecommendations: true });
   283        await visit(
   284          `/jobs/${server.db.jobs.sortBy('modifyIndex').reverse()[0].id}@default`
   285        );
   286        const numberOfGroups = findAll('.task-group-row').length;
   287        const numberOfAllocs = findAll('.allocation-row').length;
   288  
   289        await triggerEvent('.page-layout', 'keydown', { key: 'Shift' });
   290        [...Array(numberOfGroups + numberOfAllocs)].forEach((_, iter) => {
   291          assert.equal(
   292            document.querySelectorAll(`[data-shortcut="Shift+0${iter + 1}"]`)
   293              .length,
   294            1,
   295            `Dynamic item #${iter + 1} gets a shortcut hint`
   296          );
   297        });
   298        await triggerEvent('.page-layout', 'keyup', { key: 'Shift' });
   299      });
   300  
   301      test('Dynamic nav arrows and looping', async function (assert) {
   302        server.createList('job', 3, { createAllocations: true, type: 'system' });
   303        const jobID = server.db.jobs.sortBy('modifyIndex').reverse()[0].id;
   304        await visit(`/jobs/${jobID}@default`);
   305  
   306        await triggerKeyEvent('.page-layout', 'keydown', 'ArrowRight', {
   307          shiftKey: true,
   308        });
   309        assert.equal(
   310          currentURL(),
   311          `/jobs/${jobID}@default/definition`,
   312          'Shift+ArrowRight takes you to the next tab (Definition)'
   313        );
   314  
   315        await triggerKeyEvent('.page-layout', 'keydown', 'ArrowRight', {
   316          shiftKey: true,
   317        });
   318        assert.equal(
   319          currentURL(),
   320          `/jobs/${jobID}@default/versions`,
   321          'Shift+ArrowRight takes you to the next tab (Version)'
   322        );
   323  
   324        await triggerKeyEvent('.page-layout', 'keydown', 'ArrowRight', {
   325          shiftKey: true,
   326        });
   327        assert.equal(
   328          currentURL(),
   329          `/jobs/${jobID}@default/allocations`,
   330          'Shift+ArrowRight takes you to the next tab (Allocations)'
   331        );
   332  
   333        await triggerKeyEvent('.page-layout', 'keydown', 'ArrowRight', {
   334          shiftKey: true,
   335        });
   336        assert.equal(
   337          currentURL(),
   338          `/jobs/${jobID}@default/evaluations`,
   339          'Shift+ArrowRight takes you to the next tab (Evaluations)'
   340        );
   341  
   342        await triggerKeyEvent('.page-layout', 'keydown', 'ArrowRight', {
   343          shiftKey: true,
   344        });
   345        assert.equal(
   346          currentURL(),
   347          `/jobs/${jobID}@default/services`,
   348          'Shift+ArrowRight takes you to the next tab (Services)'
   349        );
   350  
   351        await triggerKeyEvent('.page-layout', 'keydown', 'ArrowRight', {
   352          shiftKey: true,
   353        });
   354        assert.equal(
   355          currentURL(),
   356          `/jobs/${jobID}@default`,
   357          'Shift+ArrowRight takes you to the first tab in the loop'
   358        );
   359      });
   360    });
   361  });