Files
nomad/ui/tests/acceptance/plugin-allocations-test.js
Phil Renaud 1976202cd6 Feature: Dynamic Host Volumes in the UI (#25224)
* DHV UI init

* /csi routes to /storage routes and a routeRedirector util (#25163)

* /csi routes to /storage routes and a routeRedirector util

* Tests and routes move csi/ to storage/

* Changelog added

* [ui] Storage UI overhaul + Dynamic Host Volumes UI (#25226)

* Storage index page and DHV model properties

* Naive version of a storage overview page

* Experimental fetch of alloc data dirs

* Fetch ephemeral disks and static host volumes as an ember concurrency task and nice table stylings

* Playing nice with section header labels to make eslint happy even though wcag was already cool with it

* inlined the storage type explainers and reordered things, plus tooltips and keynav

* Bones of a dynamic host volume individual page

* Woooo dynamic host volume model, adapter, and serializer with embedded alloc relationships

* Couple test fixes

* async:false relationship for dhv.hasMany('alloc') to prevent a ton of xhr requests

* DHV request type at index routemodel and better serialization

* Pagination and searching and query params oh my

* Test retrofits for csi volumes

* Really fantastic flake gets fixed

* DHV detail page acceptance test and a bunch of mirage hooks

* Seed so that the actions test has a guaranteed task

* removed ephemeral disk and static host volume manual scanning

* CapacityBytes and capabilities table added to DHV detail page

* Debugging actions flyout test

* was becoming clear that faker.seed editing was causing havoc elsewhere so might as well not boil the ocean and just tell this test to do what I want it to

* Post-create job gets taskCount instead of count

* CSI volumes now get /csi route prefix at detail level

* lazyclick method for unused keynav removed

* keyboard nav and table-watcher for DHV added

* Addressed PR comments, changed up capabilities table and id references, etc.

* Capabilities table for DHV and ID in details header

* Testfixes for pluginID and capabilities table on DHV page
2025-03-10 14:46:02 -04:00

180 lines
5.2 KiB
JavaScript

/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
/* eslint-disable qunit/require-expect */
import { module, test } from 'qunit';
import { currentURL } from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';
import { setupMirage } from 'ember-cli-mirage/test-support';
import a11yAudit from 'nomad-ui/tests/helpers/a11y-audit';
import pageSizeSelect from './behaviors/page-size-select';
import PluginAllocations from 'nomad-ui/tests/pages/storage/plugins/plugin/allocations';
module('Acceptance | plugin allocations', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
let plugin;
hooks.beforeEach(function () {
server.create('node-pool');
server.create('node');
window.localStorage.clear();
});
test('it passes an accessibility audit', async function (assert) {
plugin = server.create('csi-plugin', {
shallow: true,
controllerRequired: true,
controllersExpected: 3,
nodesExpected: 3,
});
await PluginAllocations.visit({ id: plugin.id });
await a11yAudit(assert);
});
test('/storage/plugins/:id/allocations shows all allocations in a single table', async function (assert) {
plugin = server.create('csi-plugin', {
shallow: true,
controllerRequired: true,
controllersExpected: 3,
nodesExpected: 3,
});
await PluginAllocations.visit({ id: plugin.id });
assert.equal(PluginAllocations.allocations.length, 6);
});
pageSizeSelect({
resourceName: 'allocation',
pageObject: PluginAllocations,
pageObjectList: PluginAllocations.allocations,
async setup() {
const total = PluginAllocations.pageSize;
plugin = server.create('csi-plugin', {
shallow: true,
controllerRequired: true,
controllersExpected: Math.floor(total / 2),
nodesExpected: Math.ceil(total / 2),
});
await PluginAllocations.visit({ id: plugin.id });
},
});
testFacet('Health', {
facet: PluginAllocations.facets.health,
paramName: 'healthy',
async beforeEach() {
plugin = server.create('csi-plugin', {
shallow: true,
controllerRequired: true,
controllersExpected: 3,
nodesExpected: 3,
});
await PluginAllocations.visit({ id: plugin.id });
},
filter: (allocation, selection) =>
selection.includes(allocation.healthy.toString()),
});
testFacet('Type', {
facet: PluginAllocations.facets.type,
paramName: 'type',
async beforeEach() {
plugin = server.create('csi-plugin', {
shallow: true,
controllerRequired: true,
controllersExpected: 3,
nodesExpected: 3,
});
await PluginAllocations.visit({ id: plugin.id });
},
filter: (allocation, selection) => {
if (selection.length === 0 || selection.length === 2) return true;
if (selection[0] === 'controller')
return plugin.controllers.models.includes(allocation);
return plugin.nodes.models.includes(allocation);
},
});
function testFacet(label, { facet, paramName, beforeEach, filter }) {
test(`the ${label} facet filters the allocations list by ${label}`, async function (assert) {
let option;
await beforeEach();
await facet.toggle();
option = facet.options.objectAt(0);
await option.toggle();
const selection = [option.key];
const allAllocations = [
...plugin.controllers.models,
...plugin.nodes.models,
];
const expectedAllocations = allAllocations
.filter((allocation) => filter(allocation, selection))
.sortBy('updateTime');
PluginAllocations.allocations.forEach((allocation, index) => {
assert.equal(allocation.id, expectedAllocations[index].allocID);
});
});
test(`selecting multiple options in the ${label} facet results in a broader search`, async function (assert) {
const selection = [];
await beforeEach();
await facet.toggle();
const option1 = facet.options.objectAt(0);
const option2 = facet.options.objectAt(1);
await option1.toggle();
selection.push(option1.key);
await option2.toggle();
selection.push(option2.key);
const allAllocations = [
...plugin.controllers.models,
...plugin.nodes.models,
];
const expectedAllocations = allAllocations
.filter((allocation) => filter(allocation, selection))
.sortBy('updateTime');
PluginAllocations.allocations.forEach((allocation, index) => {
assert.equal(allocation.id, expectedAllocations[index].allocID);
});
});
test(`selecting options in the ${label} facet updates the ${paramName} query param`, async function (assert) {
const selection = [];
await beforeEach();
await facet.toggle();
const option1 = facet.options.objectAt(0);
const option2 = facet.options.objectAt(1);
await option1.toggle();
selection.push(option1.key);
await option2.toggle();
selection.push(option2.key);
const queryString = `${paramName}=${window.encodeURIComponent(
JSON.stringify(selection)
)}`;
assert.equal(
currentURL(),
`/storage/plugins/${plugin.id}/allocations?${queryString}`
);
});
}
});