github.com/hernad/nomad@v1.6.112/ui/tests/integration/components/task-group-row-test.js (about) 1 /** 2 * Copyright (c) HashiCorp, Inc. 3 * SPDX-License-Identifier: MPL-2.0 4 */ 5 6 import { module, test } from 'qunit'; 7 import { setupRenderingTest } from 'ember-qunit'; 8 import { click, find, render, settled, waitUntil } from '@ember/test-helpers'; 9 import hbs from 'htmlbars-inline-precompile'; 10 import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage'; 11 import { initialize as fragmentSerializerInitializer } from 'nomad-ui/initializers/fragment-serializer'; 12 import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit'; 13 14 const jobName = 'test-job'; 15 const jobId = JSON.stringify([jobName, 'default']); 16 17 const countChange = () => { 18 const initial = find('[data-test-task-group-count]').textContent; 19 return () => find('[data-test-task-group-count]').textContent !== initial; 20 }; 21 22 let managementToken; 23 let clientToken; 24 25 const makeJob = (server, props = {}) => { 26 // These tests require a job with particular task groups. This requires 27 // mild Mirage surgery. 28 const job = server.create('job', { 29 id: jobName, 30 groupCount: 0, 31 createAllocations: false, 32 shallow: true, 33 ...props, 34 }); 35 const noScalingGroup = server.create('task-group', { 36 job, 37 name: 'no-scaling', 38 shallow: true, 39 withScaling: false, 40 }); 41 const scalingGroup = server.create('task-group', { 42 job, 43 count: 2, 44 name: 'scaling', 45 shallow: true, 46 withScaling: true, 47 }); 48 job.update({ 49 taskGroupIds: [noScalingGroup.id, scalingGroup.id], 50 }); 51 }; 52 53 module('Integration | Component | task group row', function (hooks) { 54 setupRenderingTest(hooks); 55 56 hooks.beforeEach(async function () { 57 fragmentSerializerInitializer(this.owner); 58 this.store = this.owner.lookup('service:store'); 59 this.token = this.owner.lookup('service:token'); 60 this.server = startMirage(); 61 this.server.create('node-pool'); 62 this.server.create('node'); 63 64 managementToken = this.server.create('token'); 65 clientToken = this.server.create('token'); 66 window.localStorage.nomadTokenSecret = managementToken.secretId; 67 }); 68 69 hooks.afterEach(function () { 70 this.server.shutdown(); 71 window.localStorage.clear(); 72 }); 73 74 const commonTemplate = hbs` 75 <TaskGroupRow @taskGroup={{group}} /> 76 `; 77 78 test('Task group row conditionally shows scaling buttons based on the presence of the scaling attr on the task group', async function (assert) { 79 assert.expect(3); 80 81 makeJob(this.server, { noActiveDeployment: true }); 82 this.token.fetchSelfTokenAndPolicies.perform(); 83 await settled(); 84 85 const job = await this.store.find('job', jobId); 86 this.set('group', job.taskGroups.findBy('name', 'no-scaling')); 87 88 await render(commonTemplate); 89 assert.notOk(find('[data-test-scale]')); 90 91 this.set('group', job.taskGroups.findBy('name', 'scaling')); 92 93 await settled(); 94 assert.ok(find('[data-test-scale]')); 95 96 await componentA11yAudit(this.element, assert); 97 }); 98 99 test('Clicking scaling buttons immediately updates the rendered count but debounces the scaling API request', async function (assert) { 100 makeJob(this.server, { noActiveDeployment: true }); 101 this.token.fetchSelfTokenAndPolicies.perform(); 102 await settled(); 103 104 const job = await this.store.find('job', jobId); 105 this.set('group', job.taskGroups.findBy('name', 'scaling')); 106 107 await render(commonTemplate); 108 assert.equal(find('[data-test-task-group-count]').textContent, 2); 109 110 click('[data-test-scale="increment"]'); 111 await waitUntil(countChange()); 112 assert.equal(find('[data-test-task-group-count]').textContent, 3); 113 114 click('[data-test-scale="increment"]'); 115 await waitUntil(countChange()); 116 assert.equal(find('[data-test-task-group-count]').textContent, 4); 117 118 assert.notOk( 119 server.pretender.handledRequests.find( 120 (req) => req.method === 'POST' && req.url.endsWith('/scale') 121 ) 122 ); 123 124 await settled(); 125 const scaleRequests = server.pretender.handledRequests.filter( 126 (req) => req.method === 'POST' && req.url.endsWith('/scale') 127 ); 128 assert.equal(scaleRequests.length, 1); 129 assert.equal(JSON.parse(scaleRequests[0].requestBody).Count, 4); 130 }); 131 132 test('When the current count is equal to the max count, the increment count button is disabled', async function (assert) { 133 assert.expect(2); 134 135 makeJob(this.server, { noActiveDeployment: true }); 136 this.token.fetchSelfTokenAndPolicies.perform(); 137 await settled(); 138 139 const job = await this.store.find('job', jobId); 140 const group = job.taskGroups.findBy('name', 'scaling'); 141 group.set('count', group.scaling.max); 142 this.set('group', group); 143 144 await render(commonTemplate); 145 assert.ok(find('[data-test-scale="increment"]:disabled')); 146 147 await componentA11yAudit(this.element, assert); 148 }); 149 150 test('When the current count is equal to the min count, the decrement count button is disabled', async function (assert) { 151 assert.expect(2); 152 153 makeJob(this.server, { noActiveDeployment: true }); 154 this.token.fetchSelfTokenAndPolicies.perform(); 155 await settled(); 156 157 const job = await this.store.find('job', jobId); 158 const group = job.taskGroups.findBy('name', 'scaling'); 159 group.set('count', group.scaling.min); 160 this.set('group', group); 161 162 await render(commonTemplate); 163 assert.ok(find('[data-test-scale="decrement"]:disabled')); 164 165 await componentA11yAudit(this.element, assert); 166 }); 167 168 test('When there is an active deployment, both scale buttons are disabled', async function (assert) { 169 assert.expect(3); 170 171 makeJob(this.server, { activeDeployment: true }); 172 this.token.fetchSelfTokenAndPolicies.perform(); 173 await settled(); 174 175 const job = await this.store.find('job', jobId); 176 this.set('group', job.taskGroups.findBy('name', 'scaling')); 177 178 await render(commonTemplate); 179 assert.ok(find('[data-test-scale="increment"]:disabled')); 180 assert.ok(find('[data-test-scale="decrement"]:disabled')); 181 182 await componentA11yAudit(this.element, assert); 183 }); 184 185 test('When the current ACL token does not have the namespace:scale-job or namespace:submit-job policy rule', async function (assert) { 186 makeJob(this.server, { noActiveDeployment: true }); 187 window.localStorage.nomadTokenSecret = clientToken.secretId; 188 this.token.fetchSelfTokenAndPolicies.perform(); 189 await settled(); 190 191 const job = await this.store.find('job', jobId); 192 this.set('group', job.taskGroups.findBy('name', 'scaling')); 193 194 await render(commonTemplate); 195 assert.ok(find('[data-test-scale="increment"]:disabled')); 196 assert.ok(find('[data-test-scale="decrement"]:disabled')); 197 assert.ok( 198 find('[data-test-scale-controls]') 199 .getAttribute('aria-label') 200 .includes("You aren't allowed") 201 ); 202 }); 203 });