open-nomad/ui/tests/integration/components/topo-viz/datacenter-test.js
2021-03-31 09:29:14 -07:00

172 lines
5.3 KiB
JavaScript

import { find } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import { setupMirage } from 'ember-cli-mirage/test-support';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
import { create } from 'ember-cli-page-object';
import sinon from 'sinon';
import faker from 'nomad-ui/mirage/faker';
import topoVizDatacenterPageObject from 'nomad-ui/tests/pages/components/topo-viz/datacenter';
import { formatBytes, formatHertz } from 'nomad-ui/utils/units';
const TopoVizDatacenter = create(topoVizDatacenterPageObject());
const nodeGen = (name, datacenter, memory, cpu, allocations = []) => ({
datacenter,
memory,
cpu,
node: { name },
allocations: allocations.map(alloc => ({
memory: alloc.memory,
cpu: alloc.cpu,
memoryPercent: alloc.memory / memory,
cpuPercent: alloc.cpu / cpu,
allocation: {
id: faker.random.uuid(),
isScheduled: true,
},
})),
});
// Used in Array#reduce to sum by a property common to an array of objects
const sumBy = prop => (sum, obj) => (sum += obj[prop]);
module('Integration | Component | TopoViz::Datacenter', function(hooks) {
setupRenderingTest(hooks);
setupMirage(hooks);
const commonProps = props => ({
isSingleColumn: true,
isDense: false,
heightScale: () => 50,
onAllocationSelect: sinon.spy(),
onNodeSelect: sinon.spy(),
...props,
});
const commonTemplate = hbs`
<TopoViz::Datacenter
@datacenter={{this.datacenter}}
@isSingleColumn={{this.isSingleColumn}}
@isDense={{this.isDense}}
@heightScale={{this.heightScale}}
@onAllocationSelect={{this.onAllocationSelect}}
@onNodeSelect={{this.onNodeSelect}} />
`;
test('presents as a div with a label and a FlexMasonry with a collection of nodes', async function(assert) {
this.setProperties(
commonProps({
datacenter: {
name: 'dc1',
nodes: [nodeGen('node-1', 'dc1', 1000, 500)],
},
})
);
await this.render(commonTemplate);
assert.ok(TopoVizDatacenter.isPresent);
assert.equal(TopoVizDatacenter.nodes.length, this.datacenter.nodes.length);
await componentA11yAudit(this.element, assert);
});
test('datacenter stats are an aggregate of node stats', async function(assert) {
this.setProperties(
commonProps({
datacenter: {
name: 'dc1',
nodes: [
nodeGen('node-1', 'dc1', 1000, 500, [
{ memory: 100, cpu: 300 },
{ memory: 200, cpu: 50 },
]),
nodeGen('node-2', 'dc1', 1500, 100, [
{ memory: 50, cpu: 80 },
{ memory: 100, cpu: 20 },
]),
nodeGen('node-3', 'dc1', 2000, 300),
nodeGen('node-4', 'dc1', 3000, 200),
],
},
})
);
await this.render(commonTemplate);
const allocs = this.datacenter.nodes.reduce(
(allocs, node) => allocs.concat(node.allocations),
[]
);
const memoryReserved = allocs.reduce(sumBy('memory'), 0);
const cpuReserved = allocs.reduce(sumBy('cpu'), 0);
const memoryTotal = this.datacenter.nodes.reduce(sumBy('memory'), 0);
const cpuTotal = this.datacenter.nodes.reduce(sumBy('cpu'), 0);
assert.ok(TopoVizDatacenter.label.includes(this.datacenter.name));
assert.ok(TopoVizDatacenter.label.includes(`${this.datacenter.nodes.length} Nodes`));
assert.ok(TopoVizDatacenter.label.includes(`${allocs.length} Allocs`));
assert.ok(
TopoVizDatacenter.label.includes(
`${formatBytes(memoryReserved, 'MiB')}/${formatBytes(memoryTotal, 'MiB')}`
)
);
assert.ok(
TopoVizDatacenter.label.includes(
`${formatHertz(cpuReserved, 'MHz')}/${formatHertz(cpuTotal, 'MHz')}`
)
);
});
test('when @isSingleColumn is true, the FlexMasonry layout gets one column, otherwise it gets two', async function(assert) {
this.setProperties(
commonProps({
isSingleColumn: true,
datacenter: {
name: 'dc1',
nodes: [nodeGen('node-1', 'dc1', 1000, 500), nodeGen('node-2', 'dc1', 1000, 500)],
},
})
);
await this.render(commonTemplate);
assert.ok(find('[data-test-flex-masonry].flex-masonry-columns-1'));
this.set('isSingleColumn', false);
assert.ok(find('[data-test-flex-masonry].flex-masonry-columns-2'));
});
test('args get passed down to the TopViz::Node children', async function(assert) {
const heightSpy = sinon.spy();
this.setProperties(
commonProps({
isDense: true,
heightScale: (...args) => {
heightSpy(...args);
return 50;
},
datacenter: {
name: 'dc1',
nodes: [nodeGen('node-1', 'dc1', 1000, 500, [{ memory: 100, cpu: 300 }])],
},
})
);
await this.render(commonTemplate);
TopoVizDatacenter.nodes[0].as(async TopoVizNode => {
assert.notOk(TopoVizNode.labelIsPresent);
assert.ok(heightSpy.calledWith(this.datacenter.nodes[0].memory));
await TopoVizNode.selectNode();
assert.ok(this.onNodeSelect.calledWith(this.datacenter.nodes[0]));
await TopoVizNode.memoryRects[0].select();
assert.ok(this.onAllocationSelect.calledWith(this.datacenter.nodes[0].allocations[0]));
});
});
});