github.com/iqoqo/nomad@v0.11.3-0.20200911112621-d7021c74d101/ui/tests/acceptance/job-detail-test.js (about) 1 import { currentURL } from '@ember/test-helpers'; 2 import { module, test } from 'qunit'; 3 import { setupApplicationTest } from 'ember-qunit'; 4 import { selectChoose } from 'ember-power-select/test-support'; 5 import { setupMirage } from 'ember-cli-mirage/test-support'; 6 import moduleForJob from 'nomad-ui/tests/helpers/module-for-job'; 7 import JobDetail from 'nomad-ui/tests/pages/jobs/detail'; 8 import JobsList from 'nomad-ui/tests/pages/jobs/list'; 9 10 moduleForJob('Acceptance | job detail (batch)', 'allocations', () => 11 server.create('job', { type: 'batch', shallow: true }) 12 ); 13 moduleForJob('Acceptance | job detail (system)', 'allocations', () => 14 server.create('job', { type: 'system', shallow: true }) 15 ); 16 moduleForJob('Acceptance | job detail (periodic)', 'children', () => 17 server.create('job', 'periodic', { shallow: true }) 18 ); 19 20 moduleForJob('Acceptance | job detail (parameterized)', 'children', () => 21 server.create('job', 'parameterized', { shallow: true }) 22 ); 23 24 moduleForJob('Acceptance | job detail (periodic child)', 'allocations', () => { 25 const parent = server.create('job', 'periodic', { childrenCount: 1, shallow: true }); 26 return server.db.jobs.where({ parentId: parent.id })[0]; 27 }); 28 29 moduleForJob('Acceptance | job detail (parameterized child)', 'allocations', () => { 30 const parent = server.create('job', 'parameterized', { childrenCount: 1, shallow: true }); 31 return server.db.jobs.where({ parentId: parent.id })[0]; 32 }); 33 34 moduleForJob( 35 'Acceptance | job detail (service)', 36 'allocations', 37 () => server.create('job', { type: 'service' }), 38 { 39 'the subnav links to deployment': async (job, assert) => { 40 await JobDetail.tabFor('deployments').visit(); 41 assert.equal(currentURL(), `/jobs/${job.id}/deployments`); 42 }, 43 'when the job is not found, an error message is shown, but the URL persists': async ( 44 job, 45 assert 46 ) => { 47 await JobDetail.visit({ id: 'not-a-real-job' }); 48 49 assert.equal( 50 server.pretender.handledRequests 51 .filter(request => !request.url.includes('policy')) 52 .findBy('status', 404).url, 53 '/v1/job/not-a-real-job', 54 'A request to the nonexistent job is made' 55 ); 56 assert.equal(currentURL(), '/jobs/not-a-real-job', 'The URL persists'); 57 assert.ok(JobDetail.error.isPresent, 'Error message is shown'); 58 assert.equal(JobDetail.error.title, 'Not Found', 'Error message is for 404'); 59 }, 60 } 61 ); 62 63 module('Acceptance | job detail (with namespaces)', function(hooks) { 64 setupApplicationTest(hooks); 65 setupMirage(hooks); 66 67 let job, clientToken; 68 69 hooks.beforeEach(function() { 70 server.createList('namespace', 2); 71 server.create('node'); 72 job = server.create('job', { type: 'service', status: 'running', namespaceId: server.db.namespaces[1].name }); 73 server.createList('job', 3, { namespaceId: server.db.namespaces[0].name }); 74 75 server.create('token'); 76 clientToken = server.create('token'); 77 }); 78 79 test('when there are namespaces, the job detail page states the namespace for the job', async function(assert) { 80 const namespace = server.db.namespaces.find(job.namespaceId); 81 await JobDetail.visit({ id: job.id, namespace: namespace.name }); 82 83 assert.ok(JobDetail.statFor('namespace').text, 'Namespace included in stats'); 84 }); 85 86 test('when switching namespaces, the app redirects to /jobs with the new namespace', async function(assert) { 87 const namespace = server.db.namespaces.find(job.namespaceId); 88 const otherNamespace = server.db.namespaces.toArray().find(ns => ns !== namespace).name; 89 const label = otherNamespace === 'default' ? 'Default Namespace' : otherNamespace; 90 91 await JobDetail.visit({ id: job.id, namespace: namespace.name }); 92 93 // TODO: Migrate to Page Objects 94 await selectChoose('[data-test-namespace-switcher]', label); 95 assert.equal(currentURL().split('?')[0], '/jobs', 'Navigated to /jobs'); 96 97 const jobs = server.db.jobs 98 .where({ namespace: otherNamespace }) 99 .sortBy('modifyIndex') 100 .reverse(); 101 102 assert.equal(JobsList.jobs.length, jobs.length, 'Shows the right number of jobs'); 103 JobsList.jobs.forEach((jobRow, index) => { 104 assert.equal(jobRow.name, jobs[index].name, `Job ${index} is right`); 105 }); 106 }); 107 108 test('the exec button state can change between namespaces', async function(assert) { 109 const job1 = server.create('job', { status: 'running', namespaceId: server.db.namespaces[0].id }); 110 const job2 = server.create('job', { status: 'running', namespaceId: server.db.namespaces[1].id }); 111 112 window.localStorage.nomadTokenSecret = clientToken.secretId; 113 114 const policy = server.create('policy', { 115 id: 'something', 116 name: 'something', 117 rulesJSON: { 118 Namespaces: [ 119 { 120 Name: job1.namespaceId, 121 Capabilities: ['list-jobs', 'alloc-exec'], 122 }, 123 { 124 Name: job2.namespaceId, 125 Capabilities: ['list-jobs'], 126 }, 127 ], 128 }, 129 }); 130 131 clientToken.policyIds = [policy.id]; 132 clientToken.save(); 133 134 await JobDetail.visit({ id: job1.id }); 135 assert.notOk(JobDetail.execButton.isDisabled); 136 137 const secondNamespace = server.db.namespaces[1]; 138 await JobDetail.visit({ id: job2.id, namespace: secondNamespace.name }); 139 assert.ok(JobDetail.execButton.isDisabled); 140 }); 141 142 test('the anonymous policy is fetched to check whether to show the exec button', async function(assert) { 143 window.localStorage.removeItem('nomadTokenSecret'); 144 145 server.create('policy', { 146 id: 'anonymous', 147 name: 'anonymous', 148 rulesJSON: { 149 Namespaces: [ 150 { 151 Name: 'default', 152 Capabilities: ['list-jobs', 'alloc-exec'], 153 }, 154 ], 155 }, 156 }); 157 158 await JobDetail.visit({ id: job.id, namespace: server.db.namespaces[1].name }); 159 assert.notOk(JobDetail.execButton.isDisabled); 160 }); 161 });