github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/ui/tests/integration/components/topo-viz/datacenter-test.js (about) 1 import { find, render } from '@ember/test-helpers'; 2 import { module, test } from 'qunit'; 3 import { setupRenderingTest } from 'ember-qunit'; 4 import hbs from 'htmlbars-inline-precompile'; 5 import { setupMirage } from 'ember-cli-mirage/test-support'; 6 import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit'; 7 import { create } from 'ember-cli-page-object'; 8 import sinon from 'sinon'; 9 import faker from 'nomad-ui/mirage/faker'; 10 import topoVizDatacenterPageObject from 'nomad-ui/tests/pages/components/topo-viz/datacenter'; 11 import { formatBytes, formatHertz } from 'nomad-ui/utils/units'; 12 13 const TopoVizDatacenter = create(topoVizDatacenterPageObject()); 14 15 const nodeGen = (name, datacenter, memory, cpu, allocations = []) => ({ 16 datacenter, 17 memory, 18 cpu, 19 node: { name }, 20 allocations: allocations.map((alloc) => ({ 21 memory: alloc.memory, 22 cpu: alloc.cpu, 23 memoryPercent: alloc.memory / memory, 24 cpuPercent: alloc.cpu / cpu, 25 allocation: { 26 id: faker.random.uuid(), 27 isScheduled: true, 28 }, 29 })), 30 }); 31 32 // Used in Array#reduce to sum by a property common to an array of objects 33 const sumBy = (prop) => (sum, obj) => (sum += obj[prop]); 34 35 module('Integration | Component | TopoViz::Datacenter', function (hooks) { 36 setupRenderingTest(hooks); 37 setupMirage(hooks); 38 39 const commonProps = (props) => ({ 40 isSingleColumn: true, 41 isDense: false, 42 heightScale: () => 50, 43 onAllocationSelect: sinon.spy(), 44 onNodeSelect: sinon.spy(), 45 ...props, 46 }); 47 48 const commonTemplate = hbs` 49 <TopoViz::Datacenter 50 @datacenter={{this.datacenter}} 51 @isSingleColumn={{this.isSingleColumn}} 52 @isDense={{this.isDense}} 53 @heightScale={{this.heightScale}} 54 @onAllocationSelect={{this.onAllocationSelect}} 55 @onNodeSelect={{this.onNodeSelect}} /> 56 `; 57 58 test('presents as a div with a label and a FlexMasonry with a collection of nodes', async function (assert) { 59 assert.expect(3); 60 61 this.setProperties( 62 commonProps({ 63 datacenter: { 64 name: 'dc1', 65 nodes: [nodeGen('node-1', 'dc1', 1000, 500)], 66 }, 67 }) 68 ); 69 70 await render(commonTemplate); 71 72 assert.ok(TopoVizDatacenter.isPresent); 73 assert.equal(TopoVizDatacenter.nodes.length, this.datacenter.nodes.length); 74 75 await componentA11yAudit(this.element, assert); 76 }); 77 78 test('datacenter stats are an aggregate of node stats', async function (assert) { 79 this.setProperties( 80 commonProps({ 81 datacenter: { 82 name: 'dc1', 83 nodes: [ 84 nodeGen('node-1', 'dc1', 1000, 500, [ 85 { memory: 100, cpu: 300 }, 86 { memory: 200, cpu: 50 }, 87 ]), 88 nodeGen('node-2', 'dc1', 1500, 100, [ 89 { memory: 50, cpu: 80 }, 90 { memory: 100, cpu: 20 }, 91 ]), 92 nodeGen('node-3', 'dc1', 2000, 300), 93 nodeGen('node-4', 'dc1', 3000, 200), 94 ], 95 }, 96 }) 97 ); 98 99 await render(commonTemplate); 100 101 const allocs = this.datacenter.nodes.reduce( 102 (allocs, node) => allocs.concat(node.allocations), 103 [] 104 ); 105 const memoryReserved = allocs.reduce(sumBy('memory'), 0); 106 const cpuReserved = allocs.reduce(sumBy('cpu'), 0); 107 const memoryTotal = this.datacenter.nodes.reduce(sumBy('memory'), 0); 108 const cpuTotal = this.datacenter.nodes.reduce(sumBy('cpu'), 0); 109 110 assert.ok(TopoVizDatacenter.label.includes(this.datacenter.name)); 111 assert.ok( 112 TopoVizDatacenter.label.includes(`${this.datacenter.nodes.length} Nodes`) 113 ); 114 assert.ok(TopoVizDatacenter.label.includes(`${allocs.length} Allocs`)); 115 assert.ok( 116 TopoVizDatacenter.label.includes( 117 `${formatBytes(memoryReserved, 'MiB')}/${formatBytes( 118 memoryTotal, 119 'MiB' 120 )}` 121 ) 122 ); 123 assert.ok( 124 TopoVizDatacenter.label.includes( 125 `${formatHertz(cpuReserved, 'MHz')}/${formatHertz(cpuTotal, 'MHz')}` 126 ) 127 ); 128 }); 129 130 test('when @isSingleColumn is true, the FlexMasonry layout gets one column, otherwise it gets two', async function (assert) { 131 this.setProperties( 132 commonProps({ 133 isSingleColumn: true, 134 datacenter: { 135 name: 'dc1', 136 nodes: [ 137 nodeGen('node-1', 'dc1', 1000, 500), 138 nodeGen('node-2', 'dc1', 1000, 500), 139 ], 140 }, 141 }) 142 ); 143 144 await render(commonTemplate); 145 146 assert.ok(find('[data-test-flex-masonry].flex-masonry-columns-1')); 147 148 this.set('isSingleColumn', false); 149 assert.ok(find('[data-test-flex-masonry].flex-masonry-columns-2')); 150 }); 151 152 test('args get passed down to the TopViz::Node children', async function (assert) { 153 assert.expect(4); 154 155 const heightSpy = sinon.spy(); 156 this.setProperties( 157 commonProps({ 158 isDense: true, 159 heightScale: (...args) => { 160 heightSpy(...args); 161 return 50; 162 }, 163 datacenter: { 164 name: 'dc1', 165 nodes: [ 166 nodeGen('node-1', 'dc1', 1000, 500, [{ memory: 100, cpu: 300 }]), 167 ], 168 }, 169 }) 170 ); 171 172 await render(commonTemplate); 173 174 TopoVizDatacenter.nodes[0].as(async (TopoVizNode) => { 175 assert.notOk(TopoVizNode.labelIsPresent); 176 assert.ok(heightSpy.calledWith(this.datacenter.nodes[0].memory)); 177 178 await TopoVizNode.selectNode(); 179 assert.ok(this.onNodeSelect.calledWith(this.datacenter.nodes[0])); 180 181 await TopoVizNode.memoryRects[0].select(); 182 assert.ok( 183 this.onAllocationSelect.calledWith( 184 this.datacenter.nodes[0].allocations[0] 185 ) 186 ); 187 }); 188 }); 189 });