github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/ui/tests/acceptance/volume-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 VolumeDetail from 'nomad-ui/tests/pages/storage/volumes/detail';
     9  import Layout from 'nomad-ui/tests/pages/layout';
    10  
    11  const assignWriteAlloc = (volume, alloc) => {
    12    volume.writeAllocs.add(alloc);
    13    volume.allocations.add(alloc);
    14    volume.save();
    15  };
    16  
    17  const assignReadAlloc = (volume, alloc) => {
    18    volume.readAllocs.add(alloc);
    19    volume.allocations.add(alloc);
    20    volume.save();
    21  };
    22  
    23  module('Acceptance | volume detail', function(hooks) {
    24    setupApplicationTest(hooks);
    25    setupMirage(hooks);
    26  
    27    let volume;
    28  
    29    hooks.beforeEach(function() {
    30      server.create('node');
    31      server.create('csi-plugin', { createVolumes: false });
    32      volume = server.create('csi-volume');
    33    });
    34  
    35    test('it passes an accessibility audit', async function(assert) {
    36      await VolumeDetail.visit({ id: volume.id });
    37      await a11yAudit(assert);
    38    });
    39  
    40    test('/csi/volumes/:id should have a breadcrumb trail linking back to Volumes and Storage', async function(assert) {
    41      await VolumeDetail.visit({ id: volume.id });
    42  
    43      assert.equal(Layout.breadcrumbFor('csi.index').text, 'Storage');
    44      assert.equal(Layout.breadcrumbFor('csi.volumes').text, 'Volumes');
    45      assert.equal(Layout.breadcrumbFor('csi.volumes.volume').text, volume.name);
    46    });
    47  
    48    test('/csi/volumes/:id should show the volume name in the title', async function(assert) {
    49      await VolumeDetail.visit({ id: volume.id });
    50  
    51      assert.equal(document.title, `CSI Volume ${volume.name} - Nomad`);
    52      assert.equal(VolumeDetail.title, volume.name);
    53    });
    54  
    55    test('/csi/volumes/:id should list additional details for the volume below the title', async function(assert) {
    56      await VolumeDetail.visit({ id: volume.id });
    57  
    58      assert.ok(VolumeDetail.health.includes(volume.schedulable ? 'Schedulable' : 'Unschedulable'));
    59      assert.ok(VolumeDetail.provider.includes(volume.provider));
    60      assert.ok(VolumeDetail.externalId.includes(volume.externalId));
    61      assert.notOk(
    62        VolumeDetail.hasNamespace,
    63        'Namespace is omitted when there is only one namespace'
    64      );
    65    });
    66  
    67    test('/csi/volumes/:id should list all write allocations the volume is attached to', async function(assert) {
    68      const writeAllocations = server.createList('allocation', 2);
    69      const readAllocations = server.createList('allocation', 3);
    70      writeAllocations.forEach(alloc => assignWriteAlloc(volume, alloc));
    71      readAllocations.forEach(alloc => assignReadAlloc(volume, alloc));
    72  
    73      await VolumeDetail.visit({ id: volume.id });
    74  
    75      assert.equal(VolumeDetail.writeAllocations.length, writeAllocations.length);
    76      writeAllocations
    77        .sortBy('modifyIndex')
    78        .reverse()
    79        .forEach((allocation, idx) => {
    80          assert.equal(allocation.id, VolumeDetail.writeAllocations.objectAt(idx).id);
    81        });
    82    });
    83  
    84    test('/csi/volumes/:id should list all read allocations the volume is attached to', async function(assert) {
    85      const writeAllocations = server.createList('allocation', 2);
    86      const readAllocations = server.createList('allocation', 3);
    87      writeAllocations.forEach(alloc => assignWriteAlloc(volume, alloc));
    88      readAllocations.forEach(alloc => assignReadAlloc(volume, alloc));
    89  
    90      await VolumeDetail.visit({ id: volume.id });
    91  
    92      assert.equal(VolumeDetail.readAllocations.length, readAllocations.length);
    93      readAllocations
    94        .sortBy('modifyIndex')
    95        .reverse()
    96        .forEach((allocation, idx) => {
    97          assert.equal(allocation.id, VolumeDetail.readAllocations.objectAt(idx).id);
    98        });
    99    });
   100  
   101    test('each allocation should have high-level details for the allocation', async function(assert) {
   102      const allocation = server.create('allocation', { clientStatus: 'running' });
   103      assignWriteAlloc(volume, allocation);
   104  
   105      const allocStats = server.db.clientAllocationStats.find(allocation.id);
   106      const taskGroup = server.db.taskGroups.findBy({
   107        name: allocation.taskGroup,
   108        jobId: allocation.jobId,
   109      });
   110  
   111      const tasks = taskGroup.taskIds.map(id => server.db.tasks.find(id));
   112      const cpuUsed = tasks.reduce((sum, task) => sum + task.resources.CPU, 0);
   113      const memoryUsed = tasks.reduce((sum, task) => sum + task.resources.MemoryMB, 0);
   114  
   115      await VolumeDetail.visit({ id: volume.id });
   116  
   117      VolumeDetail.writeAllocations.objectAt(0).as(allocationRow => {
   118        assert.equal(allocationRow.shortId, allocation.id.split('-')[0], 'Allocation short ID');
   119        assert.equal(
   120          allocationRow.createTime,
   121          moment(allocation.createTime / 1000000).format('MMM DD HH:mm:ss ZZ'),
   122          'Allocation create time'
   123        );
   124        assert.equal(
   125          allocationRow.modifyTime,
   126          moment(allocation.modifyTime / 1000000).fromNow(),
   127          'Allocation modify time'
   128        );
   129        assert.equal(allocationRow.status, allocation.clientStatus, 'Client status');
   130        assert.equal(allocationRow.job, server.db.jobs.find(allocation.jobId).name, 'Job name');
   131        assert.ok(allocationRow.taskGroup, 'Task group name');
   132        assert.ok(allocationRow.jobVersion, 'Job Version');
   133        assert.equal(
   134          allocationRow.client,
   135          server.db.nodes.find(allocation.nodeId).id.split('-')[0],
   136          'Node ID'
   137        );
   138        assert.equal(
   139          allocationRow.cpu,
   140          Math.floor(allocStats.resourceUsage.CpuStats.TotalTicks) / cpuUsed,
   141          'CPU %'
   142        );
   143        assert.equal(
   144          allocationRow.cpuTooltip,
   145          `${Math.floor(allocStats.resourceUsage.CpuStats.TotalTicks)} / ${cpuUsed} MHz`,
   146          'Detailed CPU information is in a tooltip'
   147        );
   148        assert.equal(
   149          allocationRow.mem,
   150          allocStats.resourceUsage.MemoryStats.RSS / 1024 / 1024 / memoryUsed,
   151          'Memory used'
   152        );
   153        assert.equal(
   154          allocationRow.memTooltip,
   155          `${formatBytes([allocStats.resourceUsage.MemoryStats.RSS])} / ${memoryUsed} MiB`,
   156          'Detailed memory information is in a tooltip'
   157        );
   158      });
   159    });
   160  
   161    test('each allocation should link to the allocation detail page', async function(assert) {
   162      const allocation = server.create('allocation');
   163      assignWriteAlloc(volume, allocation);
   164  
   165      await VolumeDetail.visit({ id: volume.id });
   166      await VolumeDetail.writeAllocations.objectAt(0).visit();
   167  
   168      assert.equal(currentURL(), `/allocations/${allocation.id}`);
   169    });
   170  
   171    test('when there are no write allocations, the table presents an empty state', async function(assert) {
   172      await VolumeDetail.visit({ id: volume.id });
   173  
   174      assert.ok(VolumeDetail.writeTableIsEmpty);
   175      assert.equal(VolumeDetail.writeEmptyState.headline, 'No Write Allocations');
   176    });
   177  
   178    test('when there are no read allocations, the table presents an empty state', async function(assert) {
   179      await VolumeDetail.visit({ id: volume.id });
   180  
   181      assert.ok(VolumeDetail.readTableIsEmpty);
   182      assert.equal(VolumeDetail.readEmptyState.headline, 'No Read Allocations');
   183    });
   184  
   185    test('the constraints table shows access mode and attachment mode', async function(assert) {
   186      await VolumeDetail.visit({ id: volume.id });
   187  
   188      assert.equal(VolumeDetail.constraints.accessMode, volume.accessMode);
   189      assert.equal(VolumeDetail.constraints.attachmentMode, volume.attachmentMode);
   190    });
   191  });
   192  
   193  // Namespace test: details shows the namespace
   194  module('Acceptance | volume detail (with namespaces)', function(hooks) {
   195    setupApplicationTest(hooks);
   196    setupMirage(hooks);
   197  
   198    let volume;
   199  
   200    hooks.beforeEach(function() {
   201      server.createList('namespace', 2);
   202      server.create('node');
   203      server.create('csi-plugin', { createVolumes: false });
   204      volume = server.create('csi-volume');
   205    });
   206  
   207    test('/csi/volumes/:id detail ribbon includes the namespace of the volume', async function(assert) {
   208      await VolumeDetail.visit({ id: volume.id });
   209  
   210      assert.ok(VolumeDetail.hasNamespace);
   211      assert.ok(VolumeDetail.namespace.includes(volume.namespaceId || 'default'));
   212    });
   213  });