github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/ui/tests/acceptance/plugin-detail-test.js (about) 1 import { module, test } from 'qunit'; 2 import { currentURL } from '@ember/test-helpers'; 3 import { setupApplicationTest } from 'ember-qunit'; 4 import { setupMirage } from 'ember-cli-mirage/test-support'; 5 import a11yAudit from 'nomad-ui/tests/helpers/a11y-audit'; 6 import moment from 'moment'; 7 import { formatBytes } from 'nomad-ui/helpers/format-bytes'; 8 import PluginDetail from 'nomad-ui/tests/pages/storage/plugins/detail'; 9 import Layout from 'nomad-ui/tests/pages/layout'; 10 11 module('Acceptance | plugin detail', function(hooks) { 12 setupApplicationTest(hooks); 13 setupMirage(hooks); 14 15 let plugin; 16 17 hooks.beforeEach(function() { 18 server.create('node'); 19 plugin = server.create('csi-plugin', { controllerRequired: true }); 20 }); 21 22 test('it passes an accessibility audit', async function(assert) { 23 await PluginDetail.visit({ id: plugin.id }); 24 await a11yAudit(assert); 25 }); 26 27 test('/csi/plugins/:id should have a breadcrumb trail linking back to Plugins and Storage', async function(assert) { 28 await PluginDetail.visit({ id: plugin.id }); 29 30 assert.equal(Layout.breadcrumbFor('csi.index').text, 'Storage'); 31 assert.equal(Layout.breadcrumbFor('csi.plugins').text, 'Plugins'); 32 assert.equal(Layout.breadcrumbFor('csi.plugins.plugin').text, plugin.id); 33 }); 34 35 test('/csi/plugins/:id should show the plugin name in the title', async function(assert) { 36 await PluginDetail.visit({ id: plugin.id }); 37 38 assert.equal(document.title, `CSI Plugin ${plugin.id} - Nomad`); 39 assert.equal(PluginDetail.title, plugin.id); 40 }); 41 42 test('/csi/plugins/:id should list additional details for the plugin below the title', async function(assert) { 43 await PluginDetail.visit({ id: plugin.id }); 44 45 assert.ok( 46 PluginDetail.controllerHealth.includes( 47 `${Math.round((plugin.controllersHealthy / plugin.controllersExpected) * 100)}%` 48 ) 49 ); 50 assert.ok( 51 PluginDetail.controllerHealth.includes( 52 `${plugin.controllersHealthy}/${plugin.controllersExpected}` 53 ) 54 ); 55 assert.ok( 56 PluginDetail.nodeHealth.includes( 57 `${Math.round((plugin.nodesHealthy / plugin.nodesExpected) * 100)}%` 58 ) 59 ); 60 assert.ok(PluginDetail.nodeHealth.includes(`${plugin.nodesHealthy}/${plugin.nodesExpected}`)); 61 assert.ok(PluginDetail.provider.includes(plugin.provider)); 62 }); 63 64 test('/csi/plugins/:id should list all the controller plugin allocations for the plugin', async function(assert) { 65 await PluginDetail.visit({ id: plugin.id }); 66 67 assert.equal(PluginDetail.controllerAllocations.length, plugin.controllers.length); 68 plugin.controllers.models 69 .sortBy('updateTime') 70 .reverse() 71 .forEach((allocation, idx) => { 72 assert.equal(PluginDetail.controllerAllocations.objectAt(idx).id, allocation.allocID); 73 }); 74 }); 75 76 test('/csi/plugins/:id should list all the node plugin allocations for the plugin', async function(assert) { 77 await PluginDetail.visit({ id: plugin.id }); 78 79 assert.equal(PluginDetail.nodeAllocations.length, plugin.nodes.length); 80 plugin.nodes.models 81 .sortBy('updateTime') 82 .reverse() 83 .forEach((allocation, idx) => { 84 assert.equal(PluginDetail.nodeAllocations.objectAt(idx).id, allocation.allocID); 85 }); 86 }); 87 88 test('each allocation should have high-level details for the allocation', async function(assert) { 89 const controller = plugin.controllers.models.sortBy('updateTime').reverse()[0]; 90 const allocation = server.db.allocations.find(controller.allocID); 91 const allocStats = server.db.clientAllocationStats.find(allocation.id); 92 const taskGroup = server.db.taskGroups.findBy({ 93 name: allocation.taskGroup, 94 jobId: allocation.jobId, 95 }); 96 97 const tasks = taskGroup.taskIds.map(id => server.db.tasks.find(id)); 98 const cpuUsed = tasks.reduce((sum, task) => sum + task.resources.CPU, 0); 99 const memoryUsed = tasks.reduce((sum, task) => sum + task.resources.MemoryMB, 0); 100 101 await PluginDetail.visit({ id: plugin.id }); 102 103 PluginDetail.controllerAllocations.objectAt(0).as(allocationRow => { 104 assert.equal(allocationRow.shortId, allocation.id.split('-')[0], 'Allocation short ID'); 105 assert.equal( 106 allocationRow.createTime, 107 moment(allocation.createTime / 1000000).format('MMM D') 108 ); 109 assert.equal( 110 allocationRow.createTooltip, 111 moment(allocation.createTime / 1000000).format('MMM DD HH:mm:ss ZZ') 112 ); 113 assert.equal(allocationRow.modifyTime, moment(allocation.modifyTime / 1000000).fromNow()); 114 assert.equal(allocationRow.health, controller.healthy ? 'Healthy' : 'Unhealthy'); 115 assert.equal( 116 allocationRow.client, 117 server.db.nodes.find(allocation.nodeId).id.split('-')[0], 118 'Node ID' 119 ); 120 assert.equal(allocationRow.job, server.db.jobs.find(allocation.jobId).name, 'Job name'); 121 assert.ok(allocationRow.taskGroup, 'Task group name'); 122 assert.ok(allocationRow.jobVersion, 'Job Version'); 123 assert.equal( 124 allocationRow.cpu, 125 Math.floor(allocStats.resourceUsage.CpuStats.TotalTicks) / cpuUsed, 126 'CPU %' 127 ); 128 assert.equal( 129 allocationRow.cpuTooltip, 130 `${Math.floor(allocStats.resourceUsage.CpuStats.TotalTicks)} / ${cpuUsed} MHz`, 131 'Detailed CPU information is in a tooltip' 132 ); 133 assert.equal( 134 allocationRow.mem, 135 allocStats.resourceUsage.MemoryStats.RSS / 1024 / 1024 / memoryUsed, 136 'Memory used' 137 ); 138 assert.equal( 139 allocationRow.memTooltip, 140 `${formatBytes([allocStats.resourceUsage.MemoryStats.RSS])} / ${memoryUsed} MiB`, 141 'Detailed memory information is in a tooltip' 142 ); 143 }); 144 }); 145 146 test('each allocation should link to the allocation detail page', async function(assert) { 147 const controller = plugin.controllers.models.sortBy('updateTime').reverse()[0]; 148 149 await PluginDetail.visit({ id: plugin.id }); 150 await PluginDetail.controllerAllocations.objectAt(0).visit(); 151 152 assert.equal(currentURL(), `/allocations/${controller.allocID}`); 153 }); 154 155 test('when there are no plugin allocations, the tables present empty states', async function(assert) { 156 const emptyPlugin = server.create('csi-plugin', { 157 controllerRequired: true, 158 controllersHealthy: 0, 159 controllersExpected: 0, 160 nodesHealthy: 0, 161 nodesExpected: 0, 162 }); 163 164 await PluginDetail.visit({ id: emptyPlugin.id }); 165 166 assert.ok(PluginDetail.controllerTableIsEmpty); 167 assert.equal(PluginDetail.controllerEmptyState.headline, 'No Controller Plugin Allocations'); 168 169 assert.ok(PluginDetail.nodeTableIsEmpty); 170 assert.equal(PluginDetail.nodeEmptyState.headline, 'No Node Plugin Allocations'); 171 }); 172 173 test('when the plugin is node-only, the controller information is omitted', async function(assert) { 174 const nodeOnlyPlugin = server.create('csi-plugin', { controllerRequired: false }); 175 176 await PluginDetail.visit({ id: nodeOnlyPlugin.id }); 177 178 assert.notOk(PluginDetail.controllerAvailabilityIsPresent); 179 assert.ok(PluginDetail.nodeAvailabilityIsPresent); 180 181 assert.notOk(PluginDetail.controllerHealthIsPresent); 182 assert.notOk(PluginDetail.controllerTableIsPresent); 183 }); 184 185 test('when there are more than 10 controller or node allocations, only 10 are shown', async function(assert) { 186 const manyAllocationsPlugin = server.create('csi-plugin', { 187 shallow: true, 188 controllerRequired: false, 189 nodesExpected: 15, 190 }); 191 192 await PluginDetail.visit({ id: manyAllocationsPlugin.id }); 193 194 assert.equal(PluginDetail.nodeAllocations.length, 10); 195 }); 196 197 test('the View All links under each allocation table link to a filtered view of the plugins allocation list', async function(assert) { 198 const serialize = arr => window.encodeURIComponent(JSON.stringify(arr)); 199 200 await PluginDetail.visit({ id: plugin.id }); 201 assert.ok( 202 PluginDetail.goToControllerAllocationsText.includes(plugin.controllers.models.length) 203 ); 204 await PluginDetail.goToControllerAllocations(); 205 assert.equal( 206 currentURL(), 207 `/csi/plugins/${plugin.id}/allocations?type=${serialize(['controller'])}` 208 ); 209 210 await PluginDetail.visit({ id: plugin.id }); 211 assert.ok(PluginDetail.goToNodeAllocationsText.includes(plugin.nodes.models.length)); 212 await PluginDetail.goToNodeAllocations(); 213 assert.equal(currentURL(), `/csi/plugins/${plugin.id}/allocations?type=${serialize(['node'])}`); 214 }); 215 });