github.com/hernad/nomad@v1.6.112/ui/tests/integration/components/topo-viz/datacenter-test.js (about)

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