github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/ui/tests/acceptance/search-test.js (about) 1 /* eslint-disable ember-a11y-testing/a11y-audit-called */ // TODO 2 import { module, test } from 'qunit'; 3 import { currentURL, triggerEvent, visit } from '@ember/test-helpers'; 4 import { setupApplicationTest } from 'ember-qunit'; 5 import { setupMirage } from 'ember-cli-mirage/test-support'; 6 import Layout from 'nomad-ui/tests/pages/layout'; 7 import JobsList from 'nomad-ui/tests/pages/jobs/list'; 8 import { selectSearch } from 'ember-power-select/test-support'; 9 import sinon from 'sinon'; 10 11 import { COLLECTION_CACHE_DURATION } from 'nomad-ui/services/data-caches'; 12 13 function getRequestCount(server, url) { 14 return server.pretender.handledRequests.filterBy('url', url).length; 15 } 16 17 module('Acceptance | search', function(hooks) { 18 setupApplicationTest(hooks); 19 setupMirage(hooks); 20 21 test('search searches jobs and nodes with route- and time-based caching and navigates to chosen items', async function(assert) { 22 server.create('node', { name: 'xyz' }); 23 const otherNode = server.create('node', { name: 'ghi' }); 24 25 server.create('job', { id: 'vwxyz', namespaceId: 'default' }); 26 server.create('job', { id: 'xyz', name: 'xyz job', namespace: 'default' }); 27 server.create('job', { id: 'abc', namespace: 'default' }); 28 29 await visit('/'); 30 31 const clock = sinon.useFakeTimers({ 32 now: new Date(), 33 shouldAdvanceTime: true, 34 }); 35 36 let presearchJobsRequestCount = getRequestCount(server, '/v1/jobs'); 37 let presearchNodesRequestCount = getRequestCount(server, '/v1/nodes'); 38 39 await selectSearch(Layout.navbar.search.scope, 'xy'); 40 41 Layout.navbar.search.as(search => { 42 assert.equal(search.groups.length, 2); 43 44 search.groups[0].as(jobs => { 45 assert.equal(jobs.name, 'Jobs (2)'); 46 assert.equal(jobs.options.length, 2); 47 assert.equal(jobs.options[0].text, 'xyz job'); 48 assert.equal(jobs.options[1].text, 'vwxyz'); 49 }); 50 51 search.groups[1].as(clients => { 52 assert.equal(clients.name, 'Clients (1)'); 53 assert.equal(clients.options.length, 1); 54 assert.equal(clients.options[0].text, 'xyz'); 55 }); 56 }); 57 58 assert.equal( 59 getRequestCount(server, '/v1/jobs'), 60 presearchJobsRequestCount, 61 'no new jobs request should be sent when in the jobs hierarchy' 62 ); 63 assert.equal( 64 getRequestCount(server, '/v1/nodes'), 65 presearchNodesRequestCount + 1, 66 'a nodes request should happen when not in the clients hierarchy' 67 ); 68 69 await Layout.navbar.search.groups[0].options[0].click(); 70 assert.equal(currentURL(), '/jobs/xyz'); 71 72 await selectSearch(Layout.navbar.search.scope, otherNode.id.substr(0, 3)); 73 74 await Layout.navbar.search.groups[1].options[0].click(); 75 assert.equal(currentURL(), `/clients/${otherNode.id}`); 76 77 presearchJobsRequestCount = getRequestCount(server, '/v1/jobs'); 78 presearchNodesRequestCount = getRequestCount(server, '/v1/nodes'); 79 80 await selectSearch(Layout.navbar.search.scope, 'zzzzzzzzzzz'); 81 82 assert.equal( 83 getRequestCount(server, '/v1/jobs'), 84 presearchJobsRequestCount, 85 'a jobs request should not happen because the cache hasn’t expired' 86 ); 87 assert.equal( 88 presearchNodesRequestCount, 89 getRequestCount(server, '/v1/nodes'), 90 'no new nodes request should happen when in the clients hierarchy' 91 ); 92 93 clock.tick(COLLECTION_CACHE_DURATION * 2); 94 95 await selectSearch(Layout.navbar.search.scope, otherNode.id.substr(0, 3)); 96 97 assert.equal( 98 getRequestCount(server, '/v1/jobs'), 99 presearchJobsRequestCount + 1, 100 'a jobs request should happen because the cache has expired' 101 ); 102 103 clock.restore(); 104 }); 105 106 test('search highlights matching substrings', async function(assert) { 107 server.create('node', { name: 'xyz' }); 108 109 server.create('job', { id: 'traefik', namespaceId: 'default' }); 110 server.create('job', { id: 'tracking', namespace: 'default' }); 111 server.create('job', { id: 'smtp-sensor', namespaceId: 'default' }); 112 113 await visit('/'); 114 115 await selectSearch(Layout.navbar.search.scope, 'trae'); 116 117 Layout.navbar.search.as(search => { 118 search.groups[0].as(jobs => { 119 assert.equal(jobs.options[0].text, 'traefik'); 120 assert.equal(jobs.options[0].formattedText, '*trae*fik'); 121 122 assert.equal(jobs.options[1].text, 'tracking'); 123 assert.equal(jobs.options[1].formattedText, '*tra*cking'); 124 }); 125 }); 126 127 await selectSearch(Layout.navbar.search.scope, 'ra'); 128 129 Layout.navbar.search.as(search => { 130 search.groups[0].as(jobs => { 131 assert.equal(jobs.options[0].formattedText, 't*ra*efik'); 132 assert.equal(jobs.options[1].formattedText, 't*ra*cking'); 133 }); 134 }); 135 136 await selectSearch(Layout.navbar.search.scope, 'sensor'); 137 138 Layout.navbar.search.as(search => { 139 search.groups[0].as(jobs => { 140 assert.equal(jobs.options[0].formattedText, '*s*mtp-*sensor*'); 141 }); 142 }); 143 }); 144 145 test('results are truncated at 10 per group', async function(assert) { 146 server.create('node', { name: 'xyz' }); 147 148 for (let i = 0; i < 15; i++) { 149 server.create('job', { id: `job-${i}`, namespaceId: 'default' }); 150 } 151 152 await visit('/'); 153 154 await selectSearch(Layout.navbar.search.scope, 'job'); 155 156 Layout.navbar.search.as(search => { 157 search.groups[0].as(jobs => { 158 assert.equal(jobs.name, 'Jobs (showing 10 of 15)'); 159 assert.equal(jobs.options.length, 10); 160 }); 161 }); 162 }); 163 164 test('node id prefix matches take priority over node name matches', async function(assert) { 165 const nodeToMatchById = server.create('node', { name: 'xyz' }); 166 167 const idPrefix = nodeToMatchById.id.substr(0, 5); 168 169 const nodeToMatchByName = server.create('node', { 170 name: `node-name-with-id-piece-${idPrefix}`, 171 }); 172 173 await visit('/'); 174 175 await selectSearch(Layout.navbar.search.scope, idPrefix); 176 177 Layout.navbar.search.as(search => { 178 search.groups[1].as(clients => { 179 assert.equal(clients.options[0].text, nodeToMatchById.name); 180 assert.equal(clients.options[1].text, nodeToMatchByName.name); 181 }); 182 }); 183 }); 184 185 test('clicking the search field starts search immediately', async function(assert) { 186 await visit('/'); 187 188 assert.notOk(Layout.navbar.search.field.isPresent); 189 190 await Layout.navbar.search.click(); 191 192 assert.ok(Layout.navbar.search.field.isPresent); 193 }); 194 195 test('pressing slash starts a search', async function(assert) { 196 await visit('/'); 197 198 assert.notOk(Layout.navbar.search.field.isPresent); 199 200 await triggerEvent('.page-layout', 'keydown', { 201 keyCode: 191, // slash 202 }); 203 204 assert.ok(Layout.navbar.search.field.isPresent); 205 }); 206 207 test('pressing slash when an input element is focused does not start a search', async function(assert) { 208 server.create('node'); 209 server.create('job'); 210 211 await visit('/'); 212 213 assert.notOk(Layout.navbar.search.field.isPresent); 214 215 await JobsList.search.click(); 216 await JobsList.search.keydown({ keyCode: 191 }); 217 218 assert.notOk(Layout.navbar.search.field.isPresent); 219 }); 220 });