github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/ui/tests/integration/components/topo-viz-test.js (about) 1 import { module, test } from 'qunit'; 2 import { render, triggerEvent } from '@ember/test-helpers'; 3 import { setupRenderingTest } from 'ember-qunit'; 4 import hbs from 'htmlbars-inline-precompile'; 5 import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit'; 6 import { create } from 'ember-cli-page-object'; 7 import { setupMirage } from 'ember-cli-mirage/test-support'; 8 import sinon from 'sinon'; 9 import faker from 'nomad-ui/mirage/faker'; 10 import topoVizPageObject from 'nomad-ui/tests/pages/components/topo-viz'; 11 12 const TopoViz = create(topoVizPageObject()); 13 14 const alloc = (nodeId, jobId, taskGroupName, memory, cpu, props = {}) => ({ 15 id: faker.random.uuid(), 16 taskGroupName, 17 isScheduled: true, 18 allocatedResources: { 19 cpu, 20 memory, 21 }, 22 belongsTo: (type) => ({ 23 id: () => (type === 'job' ? jobId : nodeId), 24 }), 25 ...props, 26 }); 27 28 const node = (datacenter, id, memory, cpu) => ({ 29 datacenter, 30 id, 31 resources: { memory, cpu }, 32 }); 33 34 module('Integration | Component | TopoViz', function (hooks) { 35 setupRenderingTest(hooks); 36 setupMirage(hooks); 37 38 const commonTemplate = hbs` 39 <TopoViz 40 @nodes={{this.nodes}} 41 @allocations={{this.allocations}} 42 @onAllocationSelect={{this.onAllocationSelect}} 43 @onNodeSelect={{this.onNodeSelect}} 44 @onDataError={{this.onDataError}} /> 45 `; 46 47 test('presents as a FlexMasonry of datacenters', async function (assert) { 48 assert.expect(6); 49 50 this.setProperties({ 51 nodes: [node('dc1', 'node0', 1000, 500), node('dc2', 'node1', 1000, 500)], 52 53 allocations: [ 54 alloc('node0', 'job1', 'group', 100, 100), 55 alloc('node0', 'job1', 'group', 100, 100), 56 alloc('node1', 'job1', 'group', 100, 100), 57 ], 58 }); 59 60 await render(commonTemplate); 61 62 assert.equal(TopoViz.datacenters.length, 2); 63 assert.equal(TopoViz.datacenters[0].nodes.length, 1); 64 assert.equal(TopoViz.datacenters[1].nodes.length, 1); 65 assert.equal(TopoViz.datacenters[0].nodes[0].memoryRects.length, 2); 66 assert.equal(TopoViz.datacenters[1].nodes[0].memoryRects.length, 1); 67 68 await componentA11yAudit(this.element, assert); 69 }); 70 71 test('clicking on a node in a deeply nested TopoViz::Node will toggle node selection and call @onNodeSelect', async function (assert) { 72 this.setProperties({ 73 // TopoViz must be dense for node selection to be a feature 74 nodes: Array(55) 75 .fill(null) 76 .map((_, index) => node('dc1', `node${index}`, 1000, 500)), 77 allocations: [], 78 onNodeSelect: sinon.spy(), 79 }); 80 81 await render(commonTemplate); 82 83 await TopoViz.datacenters[0].nodes[0].selectNode(); 84 assert.ok(this.onNodeSelect.calledOnce); 85 assert.equal(this.onNodeSelect.getCall(0).args[0].node, this.nodes[0]); 86 87 await TopoViz.datacenters[0].nodes[0].selectNode(); 88 assert.ok(this.onNodeSelect.calledTwice); 89 assert.equal(this.onNodeSelect.getCall(1).args[0], null); 90 }); 91 92 test('clicking on an allocation in a deeply nested TopoViz::Node will update the topology object with selections and call @onAllocationSelect and @onNodeSelect', async function (assert) { 93 this.setProperties({ 94 nodes: [node('dc1', 'node0', 1000, 500)], 95 allocations: [alloc('node0', 'job1', 'group', 100, 100)], 96 onNodeSelect: sinon.spy(), 97 onAllocationSelect: sinon.spy(), 98 }); 99 100 await render(commonTemplate); 101 102 await TopoViz.datacenters[0].nodes[0].memoryRects[0].select(); 103 assert.ok(this.onAllocationSelect.calledOnce); 104 assert.equal( 105 this.onAllocationSelect.getCall(0).args[0], 106 this.allocations[0] 107 ); 108 assert.ok(this.onNodeSelect.calledOnce); 109 110 await TopoViz.datacenters[0].nodes[0].memoryRects[0].select(); 111 assert.ok(this.onAllocationSelect.calledTwice); 112 assert.equal(this.onAllocationSelect.getCall(1).args[0], null); 113 assert.ok(this.onNodeSelect.calledTwice); 114 assert.ok(this.onNodeSelect.alwaysCalledWith(null)); 115 }); 116 117 test('clicking on an allocation in a deeply nested TopoViz::Node will associate sibling allocations with curves', async function (assert) { 118 this.setProperties({ 119 nodes: [ 120 node('dc1', 'node0', 1000, 500), 121 node('dc1', 'node1', 1000, 500), 122 node('dc1', 'node2', 1000, 500), 123 node('dc2', 'node3', 1000, 500), 124 node('dc2', 'node4', 1000, 500), 125 node('dc2', 'node5', 1000, 500), 126 ], 127 allocations: [ 128 alloc('node0', 'job1', 'group', 100, 100), 129 alloc('node0', 'job1', 'group', 100, 100), 130 alloc('node1', 'job1', 'group', 100, 100), 131 alloc('node2', 'job1', 'group', 100, 100), 132 alloc('node0', 'job1', 'groupTwo', 100, 100), 133 alloc('node1', 'job2', 'group', 100, 100), 134 alloc('node2', 'job2', 'groupTwo', 100, 100), 135 ], 136 onNodeSelect: sinon.spy(), 137 onAllocationSelect: sinon.spy(), 138 }); 139 140 const selectedAllocations = this.allocations.filter( 141 (alloc) => 142 alloc.belongsTo('job').id() === 'job1' && 143 alloc.taskGroupName === 'group' 144 ); 145 146 await render(commonTemplate); 147 148 assert.notOk(TopoViz.allocationAssociationsArePresent); 149 150 await TopoViz.datacenters[0].nodes[0].memoryRects[0].select(); 151 152 assert.ok(TopoViz.allocationAssociationsArePresent); 153 assert.equal( 154 TopoViz.allocationAssociations.length, 155 selectedAllocations.length * 2 156 ); 157 158 // Lines get redrawn when the window resizes; make sure the lines persist. 159 await triggerEvent(window, 'resize'); 160 assert.equal( 161 TopoViz.allocationAssociations.length, 162 selectedAllocations.length * 2 163 ); 164 165 await TopoViz.datacenters[0].nodes[0].memoryRects[0].select(); 166 assert.notOk(TopoViz.allocationAssociationsArePresent); 167 }); 168 169 test('when the count of sibling allocations is high enough relative to the node count, curves are not rendered', async function (assert) { 170 this.setProperties({ 171 nodes: [node('dc1', 'node0', 1000, 500), node('dc1', 'node1', 1000, 500)], 172 allocations: [ 173 // There need to be at least 10 sibling allocations to trigger this behavior 174 alloc('node0', 'job1', 'group', 100, 100), 175 alloc('node0', 'job1', 'group', 100, 100), 176 alloc('node0', 'job1', 'group', 100, 100), 177 alloc('node0', 'job1', 'group', 100, 100), 178 alloc('node0', 'job1', 'group', 100, 100), 179 alloc('node0', 'job1', 'group', 100, 100), 180 alloc('node1', 'job1', 'group', 100, 100), 181 alloc('node1', 'job1', 'group', 100, 100), 182 alloc('node1', 'job1', 'group', 100, 100), 183 alloc('node1', 'job1', 'group', 100, 100), 184 alloc('node1', 'job1', 'group', 100, 100), 185 alloc('node1', 'job1', 'group', 100, 100), 186 alloc('node0', 'job1', 'groupTwo', 100, 100), 187 ], 188 onNodeSelect: sinon.spy(), 189 onAllocationSelect: sinon.spy(), 190 }); 191 192 await render(commonTemplate); 193 assert.notOk(TopoViz.allocationAssociationsArePresent); 194 195 await TopoViz.datacenters[0].nodes[0].memoryRects[0].select(); 196 assert.equal(TopoViz.allocationAssociations.length, 0); 197 198 // Lines get redrawn when the window resizes; make sure that doesn't make the lines show up again 199 await triggerEvent(window, 'resize'); 200 assert.equal(TopoViz.allocationAssociations.length, 0); 201 }); 202 203 test('when one or more nodes are missing the resources property, those nodes are filtered out of the topology view and onDataError is called', async function (assert) { 204 const badNode = node('dc1', 'node0', 1000, 500); 205 delete badNode.resources; 206 207 this.setProperties({ 208 nodes: [badNode, node('dc1', 'node1', 1000, 500)], 209 allocations: [ 210 alloc('node0', 'job1', 'group', 100, 100), 211 alloc('node0', 'job1', 'group', 100, 100), 212 alloc('node1', 'job1', 'group', 100, 100), 213 alloc('node1', 'job1', 'group', 100, 100), 214 alloc('node0', 'job1', 'groupTwo', 100, 100), 215 ], 216 onNodeSelect: sinon.spy(), 217 onAllocationSelect: sinon.spy(), 218 onDataError: sinon.spy(), 219 }); 220 221 await render(commonTemplate); 222 223 assert.ok(this.onDataError.calledOnce); 224 assert.deepEqual(this.onDataError.getCall(0).args[0], [ 225 { 226 type: 'filtered-nodes', 227 context: [this.nodes[0]], 228 }, 229 ]); 230 231 assert.equal(TopoViz.datacenters[0].nodes.length, 1); 232 }); 233 });