github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/ui/tests/unit/adapters/node-test.js (about) 1 import { run } from '@ember/runloop'; 2 import { module, test } from 'qunit'; 3 import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage'; 4 import { setupTest } from 'ember-qunit'; 5 import { settled } from '@ember/test-helpers'; 6 7 module('Unit | Adapter | Node', function (hooks) { 8 setupTest(hooks); 9 10 hooks.beforeEach(function () { 11 this.store = this.owner.lookup('service:store'); 12 this.subject = () => this.store.adapterFor('node'); 13 14 window.localStorage.clear(); 15 16 this.server = startMirage(); 17 18 this.server.create('region', { id: 'region-1' }); 19 this.server.create('region', { id: 'region-2' }); 20 21 this.server.create('node', { id: 'node-1' }); 22 this.server.create('node', { id: 'node-2' }); 23 this.server.create('job', { id: 'job-1', createAllocations: false }); 24 25 this.server.create('allocation', { id: 'node-1-1', nodeId: 'node-1' }); 26 this.server.create('allocation', { id: 'node-1-2', nodeId: 'node-1' }); 27 this.server.create('allocation', { id: 'node-2-1', nodeId: 'node-2' }); 28 this.server.create('allocation', { id: 'node-2-2', nodeId: 'node-2' }); 29 }); 30 31 hooks.afterEach(function () { 32 this.server.shutdown(); 33 }); 34 35 test('findHasMany removes old related models from the store', async function (assert) { 36 // Fetch the model and related allocations 37 let node = await run(() => this.store.findRecord('node', 'node-1')); 38 let allocations = await run(() => findHasMany(node, 'allocations')); 39 assert.equal( 40 allocations.get('length'), 41 this.server.db.allocations.where({ nodeId: node.get('id') }).length, 42 'Allocations returned from the findHasMany matches the db state' 43 ); 44 45 await settled(); 46 server.db.allocations.remove('node-1-1'); 47 48 allocations = await run(() => findHasMany(node, 'allocations')); 49 const dbAllocations = this.server.db.allocations.where({ 50 nodeId: node.get('id'), 51 }); 52 assert.equal( 53 allocations.get('length'), 54 dbAllocations.length, 55 'Allocations returned from the findHasMany matches the db state' 56 ); 57 assert.equal( 58 this.store.peekAll('allocation').get('length'), 59 dbAllocations.length, 60 'Server-side deleted allocation was removed from the store' 61 ); 62 }); 63 64 test('findHasMany does not remove old unrelated models from the store', async function (assert) { 65 // Fetch the first node and related allocations 66 const node = await run(() => this.store.findRecord('node', 'node-1')); 67 await run(() => findHasMany(node, 'allocations')); 68 69 // Also fetch the second node and related allocations; 70 const node2 = await run(() => this.store.findRecord('node', 'node-2')); 71 await run(() => findHasMany(node2, 'allocations')); 72 73 await settled(); 74 assert.deepEqual( 75 this.store.peekAll('allocation').mapBy('id').sort(), 76 ['node-1-1', 'node-1-2', 'node-2-1', 'node-2-2'], 77 'All allocations for the first and second node are in the store' 78 ); 79 80 server.db.allocations.remove('node-1-1'); 81 82 // Reload the related allocations now that one was removed server-side 83 await run(() => findHasMany(node, 'allocations')); 84 assert.deepEqual( 85 this.store.peekAll('allocation').mapBy('id').sort(), 86 ['node-1-2', 'node-2-1', 'node-2-2'], 87 'The deleted allocation is removed from the store and the allocations associated with the other node are untouched' 88 ); 89 }); 90 91 const testCases = [ 92 { 93 variation: '', 94 id: 'node-1', 95 region: null, 96 eligibility: 'POST /v1/node/node-1/eligibility', 97 drain: 'POST /v1/node/node-1/drain', 98 }, 99 { 100 variation: 'with non-default region', 101 id: 'node-1', 102 region: 'region-2', 103 eligibility: 'POST /v1/node/node-1/eligibility?region=region-2', 104 drain: 'POST /v1/node/node-1/drain?region=region-2', 105 }, 106 ]; 107 108 testCases.forEach((testCase) => { 109 test(`setEligible makes the correct POST request to /:node_id/eligibility ${testCase.variation}`, async function (assert) { 110 const { pretender } = this.server; 111 if (testCase.region) 112 window.localStorage.nomadActiveRegion = testCase.region; 113 114 const node = await run(() => this.store.findRecord('node', testCase.id)); 115 await this.subject().setEligible(node); 116 117 const request = pretender.handledRequests.lastObject; 118 assert.equal(`${request.method} ${request.url}`, testCase.eligibility); 119 assert.deepEqual(JSON.parse(request.requestBody), { 120 NodeID: node.id, 121 Eligibility: 'eligible', 122 }); 123 }); 124 125 test(`setIneligible makes the correct POST request to /:node_id/eligibility ${testCase.variation}`, async function (assert) { 126 const { pretender } = this.server; 127 if (testCase.region) 128 window.localStorage.nomadActiveRegion = testCase.region; 129 130 const node = await run(() => this.store.findRecord('node', testCase.id)); 131 await this.subject().setIneligible(node); 132 133 const request = pretender.handledRequests.lastObject; 134 assert.equal(`${request.method} ${request.url}`, testCase.eligibility); 135 assert.deepEqual(JSON.parse(request.requestBody), { 136 NodeID: node.id, 137 Eligibility: 'ineligible', 138 }); 139 }); 140 141 test(`drain makes the correct POST request to /:node_id/drain with appropriate defaults ${testCase.variation}`, async function (assert) { 142 const { pretender } = this.server; 143 if (testCase.region) 144 window.localStorage.nomadActiveRegion = testCase.region; 145 146 const node = await run(() => this.store.findRecord('node', testCase.id)); 147 await this.subject().drain(node); 148 149 const request = pretender.handledRequests.lastObject; 150 assert.equal(`${request.method} ${request.url}`, testCase.drain); 151 assert.deepEqual(JSON.parse(request.requestBody), { 152 NodeID: node.id, 153 DrainSpec: { 154 Deadline: 0, 155 IgnoreSystemJobs: true, 156 }, 157 }); 158 }); 159 160 test(`drain makes the correct POST request to /:node_id/drain with the provided drain spec ${testCase.variation}`, async function (assert) { 161 const { pretender } = this.server; 162 if (testCase.region) 163 window.localStorage.nomadActiveRegion = testCase.region; 164 165 const node = await run(() => this.store.findRecord('node', testCase.id)); 166 167 const spec = { Deadline: 123456789, IgnoreSystemJobs: false }; 168 await this.subject().drain(node, spec); 169 170 const request = pretender.handledRequests.lastObject; 171 assert.equal(`${request.method} ${request.url}`, testCase.drain); 172 assert.deepEqual(JSON.parse(request.requestBody), { 173 NodeID: node.id, 174 DrainSpec: { 175 Deadline: spec.Deadline, 176 IgnoreSystemJobs: spec.IgnoreSystemJobs, 177 }, 178 }); 179 }); 180 181 test(`forceDrain makes the correct POST request to /:node_id/drain with appropriate defaults ${testCase.variation}`, async function (assert) { 182 const { pretender } = this.server; 183 if (testCase.region) 184 window.localStorage.nomadActiveRegion = testCase.region; 185 186 const node = await run(() => this.store.findRecord('node', testCase.id)); 187 188 await this.subject().forceDrain(node); 189 190 const request = pretender.handledRequests.lastObject; 191 assert.equal(`${request.method} ${request.url}`, testCase.drain); 192 assert.deepEqual(JSON.parse(request.requestBody), { 193 NodeID: node.id, 194 DrainSpec: { 195 Deadline: -1, 196 IgnoreSystemJobs: true, 197 }, 198 }); 199 }); 200 201 test(`forceDrain makes the correct POST request to /:node_id/drain with the provided drain spec ${testCase.variation}`, async function (assert) { 202 const { pretender } = this.server; 203 if (testCase.region) 204 window.localStorage.nomadActiveRegion = testCase.region; 205 206 const node = await run(() => this.store.findRecord('node', testCase.id)); 207 208 const spec = { Deadline: 123456789, IgnoreSystemJobs: false }; 209 await this.subject().forceDrain(node, spec); 210 211 const request = pretender.handledRequests.lastObject; 212 assert.equal(`${request.method} ${request.url}`, testCase.drain); 213 assert.deepEqual(JSON.parse(request.requestBody), { 214 NodeID: node.id, 215 DrainSpec: { 216 Deadline: -1, 217 IgnoreSystemJobs: spec.IgnoreSystemJobs, 218 }, 219 }); 220 }); 221 222 test(`cancelDrain makes the correct POST request to /:node_id/drain ${testCase.variation}`, async function (assert) { 223 const { pretender } = this.server; 224 if (testCase.region) 225 window.localStorage.nomadActiveRegion = testCase.region; 226 227 const node = await run(() => this.store.findRecord('node', testCase.id)); 228 229 await this.subject().cancelDrain(node); 230 231 const request = pretender.handledRequests.lastObject; 232 assert.equal(`${request.method} ${request.url}`, testCase.drain); 233 assert.deepEqual(JSON.parse(request.requestBody), { 234 NodeID: node.id, 235 DrainSpec: null, 236 }); 237 }); 238 }); 239 }); 240 241 // Using fetchLink on a model's hasMany relationship exercises the adapter's 242 // findHasMany method as well normalizing the response and pushing it to the store 243 function findHasMany(model, relationshipName) { 244 const relationship = model.relationshipFor(relationshipName); 245 return model.hasMany(relationship.key).reload(); 246 }