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  });