github.com/zoomfoo/nomad@v0.8.5-0.20180907175415-f28fd3a1a056/ui/tests/acceptance/task-group-detail-test.js (about) 1 import { currentURL } from 'ember-native-dom-helpers'; 2 import { test } from 'qunit'; 3 import moduleForAcceptance from 'nomad-ui/tests/helpers/module-for-acceptance'; 4 import { formatBytes } from 'nomad-ui/helpers/format-bytes'; 5 import TaskGroup from 'nomad-ui/tests/pages/jobs/job/task-group'; 6 import JobsList from 'nomad-ui/tests/pages/jobs/list'; 7 import moment from 'moment'; 8 9 let job; 10 let taskGroup; 11 let tasks; 12 let allocations; 13 14 const sum = (total, n) => total + n; 15 16 moduleForAcceptance('Acceptance | task group detail', { 17 beforeEach() { 18 server.create('agent'); 19 server.create('node', 'forceIPv4'); 20 21 job = server.create('job', { 22 groupsCount: 2, 23 createAllocations: false, 24 }); 25 26 const taskGroups = server.db.taskGroups.where({ jobId: job.id }); 27 taskGroup = taskGroups[0]; 28 29 tasks = taskGroup.taskIds.map(id => server.db.tasks.find(id)); 30 31 server.create('node', 'forceIPv4'); 32 33 allocations = server.createList('allocation', 2, { 34 jobId: job.id, 35 taskGroup: taskGroup.name, 36 }); 37 38 // Allocations associated to a different task group on the job to 39 // assert that they aren't showing up in on this page in error. 40 server.createList('allocation', 3, { 41 jobId: job.id, 42 taskGroup: taskGroups[1].name, 43 }); 44 45 // Set a static name to make the search test deterministic 46 server.db.allocations.forEach(alloc => { 47 alloc.name = 'aaaaa'; 48 }); 49 50 // Mark the first alloc as rescheduled 51 allocations[0].update({ 52 nextAllocation: allocations[1].id, 53 }); 54 allocations[1].update({ 55 previousAllocation: allocations[0].id, 56 }); 57 58 TaskGroup.visit({ id: job.id, name: taskGroup.name }); 59 }, 60 }); 61 62 test('/jobs/:id/:task-group should list high-level metrics for the allocation', function(assert) { 63 const totalCPU = tasks.mapBy('Resources.CPU').reduce(sum, 0); 64 const totalMemory = tasks.mapBy('Resources.MemoryMB').reduce(sum, 0); 65 const totalDisk = taskGroup.ephemeralDisk.SizeMB; 66 67 assert.equal(TaskGroup.tasksCount, `# Tasks ${tasks.length}`, '# Tasks'); 68 assert.equal( 69 TaskGroup.cpu, 70 `Reserved CPU ${totalCPU} MHz`, 71 'Aggregated CPU reservation for all tasks' 72 ); 73 assert.equal( 74 TaskGroup.mem, 75 `Reserved Memory ${totalMemory} MiB`, 76 'Aggregated Memory reservation for all tasks' 77 ); 78 assert.equal( 79 TaskGroup.disk, 80 `Reserved Disk ${totalDisk} MiB`, 81 'Aggregated Disk reservation for all tasks' 82 ); 83 }); 84 85 test('/jobs/:id/:task-group should have breadcrumbs for job and jobs', function(assert) { 86 assert.equal(TaskGroup.breadcrumbFor('jobs.index').text, 'Jobs', 'First breadcrumb says jobs'); 87 assert.equal( 88 TaskGroup.breadcrumbFor('jobs.job.index').text, 89 job.name, 90 'Second breadcrumb says the job name' 91 ); 92 assert.equal( 93 TaskGroup.breadcrumbFor('jobs.job.task-group').text, 94 taskGroup.name, 95 'Third breadcrumb says the job name' 96 ); 97 }); 98 99 test('/jobs/:id/:task-group first breadcrumb should link to jobs', function(assert) { 100 TaskGroup.breadcrumbFor('jobs.index').visit(); 101 andThen(() => { 102 assert.equal(currentURL(), '/jobs', 'First breadcrumb links back to jobs'); 103 }); 104 }); 105 106 test('/jobs/:id/:task-group second breadcrumb should link to the job for the task group', function(assert) { 107 TaskGroup.breadcrumbFor('jobs.job.index').visit(); 108 andThen(() => { 109 assert.equal( 110 currentURL(), 111 `/jobs/${job.id}`, 112 'Second breadcrumb links back to the job for the task group' 113 ); 114 }); 115 }); 116 117 test('/jobs/:id/:task-group should list one page of allocations for the task group', function(assert) { 118 server.createList('allocation', TaskGroup.pageSize, { 119 jobId: job.id, 120 taskGroup: taskGroup.name, 121 }); 122 123 JobsList.visit(); 124 TaskGroup.visit({ id: job.id, name: taskGroup.name }); 125 126 andThen(() => { 127 assert.ok( 128 server.db.allocations.where({ jobId: job.id }).length > TaskGroup.pageSize, 129 'There are enough allocations to invoke pagination' 130 ); 131 132 assert.equal( 133 TaskGroup.allocations.length, 134 TaskGroup.pageSize, 135 'All allocations for the task group' 136 ); 137 }); 138 }); 139 140 test('each allocation should show basic information about the allocation', function(assert) { 141 const allocation = allocations.sortBy('modifyIndex').reverse()[0]; 142 const allocationRow = TaskGroup.allocations.objectAt(0); 143 144 andThen(() => { 145 assert.equal(allocationRow.shortId, allocation.id.split('-')[0], 'Allocation short id'); 146 assert.equal( 147 allocationRow.createTime, 148 moment(allocation.createTime / 1000000).format('MM/DD HH:mm:ss'), 149 'Allocation create time' 150 ); 151 assert.equal( 152 allocationRow.modifyTime, 153 moment(allocation.modifyTime / 1000000).fromNow(), 154 'Allocation modify time' 155 ); 156 assert.equal(allocationRow.status, allocation.clientStatus, 'Client status'); 157 assert.equal(allocationRow.jobVersion, allocation.jobVersion, 'Job Version'); 158 assert.equal( 159 allocationRow.client, 160 server.db.nodes.find(allocation.nodeId).id.split('-')[0], 161 'Node ID' 162 ); 163 }); 164 165 allocationRow.visitClient(); 166 167 andThen(() => { 168 assert.equal(currentURL(), `/clients/${allocation.nodeId}`, 'Node links to node page'); 169 }); 170 }); 171 172 test('each allocation should show stats about the allocation', function(assert) { 173 const allocation = allocations.sortBy('name')[0]; 174 const allocationRow = TaskGroup.allocations.objectAt(0); 175 176 const allocStats = server.db.clientAllocationStats.find(allocation.id); 177 const tasks = taskGroup.taskIds.map(id => server.db.tasks.find(id)); 178 179 const cpuUsed = tasks.reduce((sum, task) => sum + task.Resources.CPU, 0); 180 const memoryUsed = tasks.reduce((sum, task) => sum + task.Resources.MemoryMB, 0); 181 182 assert.equal( 183 allocationRow.cpu, 184 Math.floor(allocStats.resourceUsage.CpuStats.TotalTicks) / cpuUsed, 185 'CPU %' 186 ); 187 188 assert.equal( 189 allocationRow.cpuTooltip, 190 `${Math.floor(allocStats.resourceUsage.CpuStats.TotalTicks)} / ${cpuUsed} MHz`, 191 'Detailed CPU information is in a tooltip' 192 ); 193 194 assert.equal( 195 allocationRow.mem, 196 allocStats.resourceUsage.MemoryStats.RSS / 1024 / 1024 / memoryUsed, 197 'Memory used' 198 ); 199 200 assert.equal( 201 allocationRow.memTooltip, 202 `${formatBytes([allocStats.resourceUsage.MemoryStats.RSS])} / ${memoryUsed} MiB`, 203 'Detailed memory information is in a tooltip' 204 ); 205 }); 206 207 test('when the allocation search has no matches, there is an empty message', function(assert) { 208 TaskGroup.search('zzzzzz'); 209 210 andThen(() => { 211 assert.ok(TaskGroup.isEmpty, 'Empty state is shown'); 212 assert.equal( 213 TaskGroup.emptyState.headline, 214 'No Matches', 215 'Empty state has an appropriate message' 216 ); 217 }); 218 }); 219 220 test('when the allocation has reschedule events, the allocation row is denoted with an icon', function(assert) { 221 const rescheduleRow = TaskGroup.allocationFor(allocations[0].id); 222 const normalRow = TaskGroup.allocationFor(allocations[1].id); 223 224 assert.ok(rescheduleRow.rescheduled, 'Reschedule row has a reschedule icon'); 225 assert.notOk(normalRow.rescheduled, 'Normal row has no reschedule icon'); 226 });