github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/ui/tests/acceptance/plugin-detail-test.js (about)

     1  import { module, test } from 'qunit';
     2  import { currentURL } from '@ember/test-helpers';
     3  import { setupApplicationTest } from 'ember-qunit';
     4  import { setupMirage } from 'ember-cli-mirage/test-support';
     5  import a11yAudit from 'nomad-ui/tests/helpers/a11y-audit';
     6  import moment from 'moment';
     7  import { formatBytes } from 'nomad-ui/helpers/format-bytes';
     8  import PluginDetail from 'nomad-ui/tests/pages/storage/plugins/detail';
     9  import Layout from 'nomad-ui/tests/pages/layout';
    10  
    11  module('Acceptance | plugin detail', function(hooks) {
    12    setupApplicationTest(hooks);
    13    setupMirage(hooks);
    14  
    15    let plugin;
    16  
    17    hooks.beforeEach(function() {
    18      server.create('node');
    19      plugin = server.create('csi-plugin', { controllerRequired: true });
    20    });
    21  
    22    test('it passes an accessibility audit', async function(assert) {
    23      await PluginDetail.visit({ id: plugin.id });
    24      await a11yAudit(assert);
    25    });
    26  
    27    test('/csi/plugins/:id should have a breadcrumb trail linking back to Plugins and Storage', async function(assert) {
    28      await PluginDetail.visit({ id: plugin.id });
    29  
    30      assert.equal(Layout.breadcrumbFor('csi.index').text, 'Storage');
    31      assert.equal(Layout.breadcrumbFor('csi.plugins').text, 'Plugins');
    32      assert.equal(Layout.breadcrumbFor('csi.plugins.plugin').text, plugin.id);
    33    });
    34  
    35    test('/csi/plugins/:id should show the plugin name in the title', async function(assert) {
    36      await PluginDetail.visit({ id: plugin.id });
    37  
    38      assert.equal(document.title, `CSI Plugin ${plugin.id} - Nomad`);
    39      assert.equal(PluginDetail.title, plugin.id);
    40    });
    41  
    42    test('/csi/plugins/:id should list additional details for the plugin below the title', async function(assert) {
    43      await PluginDetail.visit({ id: plugin.id });
    44  
    45      assert.ok(
    46        PluginDetail.controllerHealth.includes(
    47          `${Math.round((plugin.controllersHealthy / plugin.controllersExpected) * 100)}%`
    48        )
    49      );
    50      assert.ok(
    51        PluginDetail.controllerHealth.includes(
    52          `${plugin.controllersHealthy}/${plugin.controllersExpected}`
    53        )
    54      );
    55      assert.ok(
    56        PluginDetail.nodeHealth.includes(
    57          `${Math.round((plugin.nodesHealthy / plugin.nodesExpected) * 100)}%`
    58        )
    59      );
    60      assert.ok(PluginDetail.nodeHealth.includes(`${plugin.nodesHealthy}/${plugin.nodesExpected}`));
    61      assert.ok(PluginDetail.provider.includes(plugin.provider));
    62    });
    63  
    64    test('/csi/plugins/:id should list all the controller plugin allocations for the plugin', async function(assert) {
    65      await PluginDetail.visit({ id: plugin.id });
    66  
    67      assert.equal(PluginDetail.controllerAllocations.length, plugin.controllers.length);
    68      plugin.controllers.models
    69        .sortBy('updateTime')
    70        .reverse()
    71        .forEach((allocation, idx) => {
    72          assert.equal(PluginDetail.controllerAllocations.objectAt(idx).id, allocation.allocID);
    73        });
    74    });
    75  
    76    test('/csi/plugins/:id should list all the node plugin allocations for the plugin', async function(assert) {
    77      await PluginDetail.visit({ id: plugin.id });
    78  
    79      assert.equal(PluginDetail.nodeAllocations.length, plugin.nodes.length);
    80      plugin.nodes.models
    81        .sortBy('updateTime')
    82        .reverse()
    83        .forEach((allocation, idx) => {
    84          assert.equal(PluginDetail.nodeAllocations.objectAt(idx).id, allocation.allocID);
    85        });
    86    });
    87  
    88    test('each allocation should have high-level details for the allocation', async function(assert) {
    89      const controller = plugin.controllers.models.sortBy('updateTime').reverse()[0];
    90      const allocation = server.db.allocations.find(controller.allocID);
    91      const allocStats = server.db.clientAllocationStats.find(allocation.id);
    92      const taskGroup = server.db.taskGroups.findBy({
    93        name: allocation.taskGroup,
    94        jobId: allocation.jobId,
    95      });
    96  
    97      const tasks = taskGroup.taskIds.map(id => server.db.tasks.find(id));
    98      const cpuUsed = tasks.reduce((sum, task) => sum + task.resources.CPU, 0);
    99      const memoryUsed = tasks.reduce((sum, task) => sum + task.resources.MemoryMB, 0);
   100  
   101      await PluginDetail.visit({ id: plugin.id });
   102  
   103      PluginDetail.controllerAllocations.objectAt(0).as(allocationRow => {
   104        assert.equal(allocationRow.shortId, allocation.id.split('-')[0], 'Allocation short ID');
   105        assert.equal(
   106          allocationRow.createTime,
   107          moment(allocation.createTime / 1000000).format('MMM D')
   108        );
   109        assert.equal(
   110          allocationRow.createTooltip,
   111          moment(allocation.createTime / 1000000).format('MMM DD HH:mm:ss ZZ')
   112        );
   113        assert.equal(allocationRow.modifyTime, moment(allocation.modifyTime / 1000000).fromNow());
   114        assert.equal(allocationRow.health, controller.healthy ? 'Healthy' : 'Unhealthy');
   115        assert.equal(
   116          allocationRow.client,
   117          server.db.nodes.find(allocation.nodeId).id.split('-')[0],
   118          'Node ID'
   119        );
   120        assert.equal(allocationRow.job, server.db.jobs.find(allocation.jobId).name, 'Job name');
   121        assert.ok(allocationRow.taskGroup, 'Task group name');
   122        assert.ok(allocationRow.jobVersion, 'Job Version');
   123        assert.equal(
   124          allocationRow.cpu,
   125          Math.floor(allocStats.resourceUsage.CpuStats.TotalTicks) / cpuUsed,
   126          'CPU %'
   127        );
   128        assert.equal(
   129          allocationRow.cpuTooltip,
   130          `${Math.floor(allocStats.resourceUsage.CpuStats.TotalTicks)} / ${cpuUsed} MHz`,
   131          'Detailed CPU information is in a tooltip'
   132        );
   133        assert.equal(
   134          allocationRow.mem,
   135          allocStats.resourceUsage.MemoryStats.RSS / 1024 / 1024 / memoryUsed,
   136          'Memory used'
   137        );
   138        assert.equal(
   139          allocationRow.memTooltip,
   140          `${formatBytes([allocStats.resourceUsage.MemoryStats.RSS])} / ${memoryUsed} MiB`,
   141          'Detailed memory information is in a tooltip'
   142        );
   143      });
   144    });
   145  
   146    test('each allocation should link to the allocation detail page', async function(assert) {
   147      const controller = plugin.controllers.models.sortBy('updateTime').reverse()[0];
   148  
   149      await PluginDetail.visit({ id: plugin.id });
   150      await PluginDetail.controllerAllocations.objectAt(0).visit();
   151  
   152      assert.equal(currentURL(), `/allocations/${controller.allocID}`);
   153    });
   154  
   155    test('when there are no plugin allocations, the tables present empty states', async function(assert) {
   156      const emptyPlugin = server.create('csi-plugin', {
   157        controllerRequired: true,
   158        controllersHealthy: 0,
   159        controllersExpected: 0,
   160        nodesHealthy: 0,
   161        nodesExpected: 0,
   162      });
   163  
   164      await PluginDetail.visit({ id: emptyPlugin.id });
   165  
   166      assert.ok(PluginDetail.controllerTableIsEmpty);
   167      assert.equal(PluginDetail.controllerEmptyState.headline, 'No Controller Plugin Allocations');
   168  
   169      assert.ok(PluginDetail.nodeTableIsEmpty);
   170      assert.equal(PluginDetail.nodeEmptyState.headline, 'No Node Plugin Allocations');
   171    });
   172  
   173    test('when the plugin is node-only, the controller information is omitted', async function(assert) {
   174      const nodeOnlyPlugin = server.create('csi-plugin', { controllerRequired: false });
   175  
   176      await PluginDetail.visit({ id: nodeOnlyPlugin.id });
   177  
   178      assert.notOk(PluginDetail.controllerAvailabilityIsPresent);
   179      assert.ok(PluginDetail.nodeAvailabilityIsPresent);
   180  
   181      assert.notOk(PluginDetail.controllerHealthIsPresent);
   182      assert.notOk(PluginDetail.controllerTableIsPresent);
   183    });
   184  
   185    test('when there are more than 10 controller or node allocations, only 10 are shown', async function(assert) {
   186      const manyAllocationsPlugin = server.create('csi-plugin', {
   187        shallow: true,
   188        controllerRequired: false,
   189        nodesExpected: 15,
   190      });
   191  
   192      await PluginDetail.visit({ id: manyAllocationsPlugin.id });
   193  
   194      assert.equal(PluginDetail.nodeAllocations.length, 10);
   195    });
   196  
   197    test('the View All links under each allocation table link to a filtered view of the plugins allocation list', async function(assert) {
   198      const serialize = arr => window.encodeURIComponent(JSON.stringify(arr));
   199  
   200      await PluginDetail.visit({ id: plugin.id });
   201      assert.ok(
   202        PluginDetail.goToControllerAllocationsText.includes(plugin.controllers.models.length)
   203      );
   204      await PluginDetail.goToControllerAllocations();
   205      assert.equal(
   206        currentURL(),
   207        `/csi/plugins/${plugin.id}/allocations?type=${serialize(['controller'])}`
   208      );
   209  
   210      await PluginDetail.visit({ id: plugin.id });
   211      assert.ok(PluginDetail.goToNodeAllocationsText.includes(plugin.nodes.models.length));
   212      await PluginDetail.goToNodeAllocations();
   213      assert.equal(currentURL(), `/csi/plugins/${plugin.id}/allocations?type=${serialize(['node'])}`);
   214    });
   215  });