github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/ui/tests/integration/components/topo-viz-test.js (about) 1 import { module, test } from 'qunit'; 2 import { 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 this.setProperties({ 49 nodes: [node('dc1', 'node0', 1000, 500), node('dc2', 'node1', 1000, 500)], 50 51 allocations: [ 52 alloc('node0', 'job1', 'group', 100, 100), 53 alloc('node0', 'job1', 'group', 100, 100), 54 alloc('node1', 'job1', 'group', 100, 100), 55 ], 56 }); 57 58 await this.render(commonTemplate); 59 60 assert.equal(TopoViz.datacenters.length, 2); 61 assert.equal(TopoViz.datacenters[0].nodes.length, 1); 62 assert.equal(TopoViz.datacenters[1].nodes.length, 1); 63 assert.equal(TopoViz.datacenters[0].nodes[0].memoryRects.length, 2); 64 assert.equal(TopoViz.datacenters[1].nodes[0].memoryRects.length, 1); 65 66 await componentA11yAudit(this.element, assert); 67 }); 68 69 test('clicking on a node in a deeply nested TopoViz::Node will toggle node selection and call @onNodeSelect', async function(assert) { 70 this.setProperties({ 71 // TopoViz must be dense for node selection to be a feature 72 nodes: Array(55) 73 .fill(null) 74 .map((_, index) => node('dc1', `node${index}`, 1000, 500)), 75 allocations: [], 76 onNodeSelect: sinon.spy(), 77 }); 78 79 await this.render(commonTemplate); 80 81 await TopoViz.datacenters[0].nodes[0].selectNode(); 82 assert.ok(this.onNodeSelect.calledOnce); 83 assert.equal(this.onNodeSelect.getCall(0).args[0].node, this.nodes[0]); 84 85 await TopoViz.datacenters[0].nodes[0].selectNode(); 86 assert.ok(this.onNodeSelect.calledTwice); 87 assert.equal(this.onNodeSelect.getCall(1).args[0], null); 88 }); 89 90 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) { 91 this.setProperties({ 92 nodes: [node('dc1', 'node0', 1000, 500)], 93 allocations: [alloc('node0', 'job1', 'group', 100, 100)], 94 onNodeSelect: sinon.spy(), 95 onAllocationSelect: sinon.spy(), 96 }); 97 98 await this.render(commonTemplate); 99 100 await TopoViz.datacenters[0].nodes[0].memoryRects[0].select(); 101 assert.ok(this.onAllocationSelect.calledOnce); 102 assert.equal(this.onAllocationSelect.getCall(0).args[0], this.allocations[0]); 103 assert.ok(this.onNodeSelect.calledOnce); 104 105 await TopoViz.datacenters[0].nodes[0].memoryRects[0].select(); 106 assert.ok(this.onAllocationSelect.calledTwice); 107 assert.equal(this.onAllocationSelect.getCall(1).args[0], null); 108 assert.ok(this.onNodeSelect.calledTwice); 109 assert.ok(this.onNodeSelect.alwaysCalledWith(null)); 110 }); 111 112 test('clicking on an allocation in a deeply nested TopoViz::Node will associate sibling allocations with curves', async function(assert) { 113 this.setProperties({ 114 nodes: [ 115 node('dc1', 'node0', 1000, 500), 116 node('dc1', 'node1', 1000, 500), 117 node('dc1', 'node2', 1000, 500), 118 node('dc2', 'node3', 1000, 500), 119 node('dc2', 'node4', 1000, 500), 120 node('dc2', 'node5', 1000, 500), 121 ], 122 allocations: [ 123 alloc('node0', 'job1', 'group', 100, 100), 124 alloc('node0', 'job1', 'group', 100, 100), 125 alloc('node1', 'job1', 'group', 100, 100), 126 alloc('node2', 'job1', 'group', 100, 100), 127 alloc('node0', 'job1', 'groupTwo', 100, 100), 128 alloc('node1', 'job2', 'group', 100, 100), 129 alloc('node2', 'job2', 'groupTwo', 100, 100), 130 ], 131 onNodeSelect: sinon.spy(), 132 onAllocationSelect: sinon.spy(), 133 }); 134 135 const selectedAllocations = this.allocations.filter( 136 alloc => alloc.belongsTo('job').id() === 'job1' && alloc.taskGroupName === 'group' 137 ); 138 139 await this.render(commonTemplate); 140 141 assert.notOk(TopoViz.allocationAssociationsArePresent); 142 143 await TopoViz.datacenters[0].nodes[0].memoryRects[0].select(); 144 145 assert.ok(TopoViz.allocationAssociationsArePresent); 146 assert.equal(TopoViz.allocationAssociations.length, selectedAllocations.length * 2); 147 148 // Lines get redrawn when the window resizes; make sure the lines persist. 149 await triggerEvent(window, 'resize'); 150 assert.equal(TopoViz.allocationAssociations.length, selectedAllocations.length * 2); 151 152 await TopoViz.datacenters[0].nodes[0].memoryRects[0].select(); 153 assert.notOk(TopoViz.allocationAssociationsArePresent); 154 }); 155 156 test('when the count of sibling allocations is high enough relative to the node count, curves are not rendered', async function(assert) { 157 this.setProperties({ 158 nodes: [node('dc1', 'node0', 1000, 500), node('dc1', 'node1', 1000, 500)], 159 allocations: [ 160 // There need to be at least 10 sibling allocations to trigger this behavior 161 alloc('node0', 'job1', 'group', 100, 100), 162 alloc('node0', 'job1', 'group', 100, 100), 163 alloc('node0', 'job1', 'group', 100, 100), 164 alloc('node0', 'job1', 'group', 100, 100), 165 alloc('node0', 'job1', 'group', 100, 100), 166 alloc('node0', 'job1', 'group', 100, 100), 167 alloc('node1', 'job1', 'group', 100, 100), 168 alloc('node1', 'job1', 'group', 100, 100), 169 alloc('node1', 'job1', 'group', 100, 100), 170 alloc('node1', 'job1', 'group', 100, 100), 171 alloc('node1', 'job1', 'group', 100, 100), 172 alloc('node1', 'job1', 'group', 100, 100), 173 alloc('node0', 'job1', 'groupTwo', 100, 100), 174 ], 175 onNodeSelect: sinon.spy(), 176 onAllocationSelect: sinon.spy(), 177 }); 178 179 await this.render(commonTemplate); 180 assert.notOk(TopoViz.allocationAssociationsArePresent); 181 182 await TopoViz.datacenters[0].nodes[0].memoryRects[0].select(); 183 assert.equal(TopoViz.allocationAssociations.length, 0); 184 185 // Lines get redrawn when the window resizes; make sure that doesn't make the lines show up again 186 await triggerEvent(window, 'resize'); 187 assert.equal(TopoViz.allocationAssociations.length, 0); 188 }); 189 190 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) { 191 const badNode = node('dc1', 'node0', 1000, 500); 192 delete badNode.resources; 193 194 this.setProperties({ 195 nodes: [badNode, node('dc1', 'node1', 1000, 500)], 196 allocations: [ 197 alloc('node0', 'job1', 'group', 100, 100), 198 alloc('node0', 'job1', 'group', 100, 100), 199 alloc('node1', 'job1', 'group', 100, 100), 200 alloc('node1', 'job1', 'group', 100, 100), 201 alloc('node0', 'job1', 'groupTwo', 100, 100), 202 ], 203 onNodeSelect: sinon.spy(), 204 onAllocationSelect: sinon.spy(), 205 onDataError: sinon.spy(), 206 }); 207 208 await this.render(commonTemplate); 209 210 assert.ok(this.onDataError.calledOnce); 211 assert.deepEqual(this.onDataError.getCall(0).args[0], [ 212 { 213 type: 'filtered-nodes', 214 context: [this.nodes[0]], 215 }, 216 ]); 217 218 assert.equal(TopoViz.datacenters[0].nodes.length, 1); 219 }); 220 });