github.com/hernad/nomad@v1.6.112/ui/tests/integration/components/allocation-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 hbs from 'htmlbars-inline-precompile'; 9 import generateResources from '../../../mirage/data/generate-resources'; 10 import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage'; 11 import { find, render } from '@ember/test-helpers'; 12 import Response from 'ember-cli-mirage/response'; 13 import { initialize as fragmentSerializerInitializer } from 'nomad-ui/initializers/fragment-serializer'; 14 import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit'; 15 16 module('Integration | Component | allocation row', function (hooks) { 17 setupRenderingTest(hooks); 18 19 hooks.beforeEach(function () { 20 fragmentSerializerInitializer(this.owner); 21 this.store = this.owner.lookup('service:store'); 22 this.server = startMirage(); 23 this.server.create('namespace'); 24 this.server.create('node-pool'); 25 this.server.create('node'); 26 this.server.create('job', { createAllocations: false }); 27 }); 28 29 hooks.afterEach(function () { 30 this.server.shutdown(); 31 }); 32 33 test('Allocation row polls for stats, even when it errors or has an invalid response', async function (assert) { 34 const component = this; 35 36 let currentFrame = 0; 37 let frames = [ 38 JSON.stringify({ ResourceUsage: generateResources() }), 39 JSON.stringify({ ResourceUsage: generateResources() }), 40 null, 41 '<Not>Valid JSON</Not>', 42 JSON.stringify({ ResourceUsage: generateResources() }), 43 ]; 44 45 this.server.get('/client/allocation/:id/stats', function () { 46 const response = frames[++currentFrame]; 47 48 // Disable polling to stop the EC task in the component 49 if (currentFrame >= frames.length) { 50 component.set('enablePolling', false); 51 } 52 53 if (response) { 54 return response; 55 } 56 return new Response(500, {}, ''); 57 }); 58 59 this.server.create('allocation', { clientStatus: 'running' }); 60 await this.store.findAll('allocation'); 61 62 const allocation = this.store.peekAll('allocation').get('firstObject'); 63 64 this.setProperties({ 65 allocation, 66 context: 'job', 67 enablePolling: true, 68 }); 69 70 await render(hbs` 71 <AllocationRow 72 @allocation={{allocation}} 73 @context={{context}} 74 @enablePolling={{enablePolling}} /> 75 `); 76 77 assert.equal( 78 this.server.pretender.handledRequests.filterBy( 79 'url', 80 `/v1/client/allocation/${allocation.get('id')}/stats` 81 ).length, 82 frames.length, 83 'Requests continue to be made after malformed responses and server errors' 84 ); 85 }); 86 87 test('Allocation row shows warning when it requires drivers that are unhealthy on the node it is running on', async function (assert) { 88 assert.expect(2); 89 90 const node = this.server.schema.nodes.first(); 91 const drivers = node.drivers; 92 Object.values(drivers).forEach((driver) => { 93 driver.Healthy = false; 94 driver.Detected = true; 95 }); 96 node.update({ drivers }); 97 98 this.server.create('allocation', { clientStatus: 'running' }); 99 await this.store.findAll('job'); 100 await this.store.findAll('node'); 101 await this.store.findAll('allocation'); 102 103 const allocation = this.store.peekAll('allocation').get('firstObject'); 104 105 this.setProperties({ 106 allocation, 107 context: 'job', 108 }); 109 110 await render(hbs` 111 <AllocationRow 112 @allocation={{allocation}} 113 @context={{context}} /> 114 `); 115 116 assert.ok( 117 find('[data-test-icon="unhealthy-driver"]'), 118 'Unhealthy driver icon is shown' 119 ); 120 await componentA11yAudit(this.element, assert); 121 }); 122 123 test('Allocation row shows an icon indicator when it was preempted', async function (assert) { 124 assert.expect(2); 125 126 const allocId = this.server.create('allocation', 'preempted').id; 127 const allocation = await this.store.findRecord('allocation', allocId); 128 129 this.setProperties({ allocation, context: 'job' }); 130 await render(hbs` 131 <AllocationRow 132 @allocation={{allocation}} 133 @context={{context}} /> 134 `); 135 136 assert.ok(find('[data-test-icon="preemption"]'), 'Preempted icon is shown'); 137 await componentA11yAudit(this.element, assert); 138 }); 139 140 test('when an allocation is not running, the utilization graphs are omitted', async function (assert) { 141 assert.expect(8); 142 143 this.setProperties({ 144 context: 'job', 145 enablePolling: false, 146 }); 147 148 // All non-running statuses need to be tested 149 ['pending', 'complete', 'failed', 'lost'].forEach((clientStatus) => 150 this.server.create('allocation', { clientStatus }) 151 ); 152 153 await this.store.findAll('allocation'); 154 155 const allocations = this.store.peekAll('allocation'); 156 157 for (const allocation of allocations.toArray()) { 158 this.set('allocation', allocation); 159 await render(hbs` 160 <AllocationRow 161 @allocation={{allocation}} 162 @context={{context}} 163 @enablePolling={{enablePolling}} /> 164 `); 165 166 const status = allocation.get('clientStatus'); 167 assert.notOk( 168 find('[data-test-cpu] .inline-chart'), 169 `No CPU chart for ${status}` 170 ); 171 assert.notOk( 172 find('[data-test-mem] .inline-chart'), 173 `No Mem chart for ${status}` 174 ); 175 } 176 }); 177 });