github.com/ferranbt/nomad@v0.9.3-0.20190607002617-85c449b7667c/ui/tests/acceptance/task-group-detail-test.js (about)

     1  import { currentURL } from '@ember/test-helpers';
     2  import { module, test } from 'qunit';
     3  import { setupApplicationTest } from 'ember-qunit';
     4  import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
     5  import { formatBytes } from 'nomad-ui/helpers/format-bytes';
     6  import TaskGroup from 'nomad-ui/tests/pages/jobs/job/task-group';
     7  import JobsList from 'nomad-ui/tests/pages/jobs/list';
     8  import moment from 'moment';
     9  
    10  let job;
    11  let taskGroup;
    12  let tasks;
    13  let allocations;
    14  
    15  const sum = (total, n) => total + n;
    16  
    17  module('Acceptance | task group detail', function(hooks) {
    18    setupApplicationTest(hooks);
    19    setupMirage(hooks);
    20  
    21    hooks.beforeEach(async function() {
    22      server.create('agent');
    23      server.create('node', 'forceIPv4');
    24  
    25      job = server.create('job', {
    26        groupsCount: 2,
    27        createAllocations: false,
    28      });
    29  
    30      const taskGroups = server.db.taskGroups.where({ jobId: job.id });
    31      taskGroup = taskGroups[0];
    32  
    33      tasks = taskGroup.taskIds.map(id => server.db.tasks.find(id));
    34  
    35      server.create('node', 'forceIPv4');
    36  
    37      allocations = server.createList('allocation', 2, {
    38        jobId: job.id,
    39        taskGroup: taskGroup.name,
    40        clientStatus: 'running',
    41      });
    42  
    43      // Allocations associated to a different task group on the job to
    44      // assert that they aren't showing up in on this page in error.
    45      server.createList('allocation', 3, {
    46        jobId: job.id,
    47        taskGroup: taskGroups[1].name,
    48        clientStatus: 'running',
    49      });
    50  
    51      // Set a static name to make the search test deterministic
    52      server.db.allocations.forEach(alloc => {
    53        alloc.name = 'aaaaa';
    54      });
    55  
    56      // Mark the first alloc as rescheduled
    57      allocations[0].update({
    58        nextAllocation: allocations[1].id,
    59      });
    60      allocations[1].update({
    61        previousAllocation: allocations[0].id,
    62      });
    63  
    64      await TaskGroup.visit({ id: job.id, name: taskGroup.name });
    65    });
    66  
    67    test('/jobs/:id/:task-group should list high-level metrics for the allocation', async function(assert) {
    68      const totalCPU = tasks.mapBy('Resources.CPU').reduce(sum, 0);
    69      const totalMemory = tasks.mapBy('Resources.MemoryMB').reduce(sum, 0);
    70      const totalDisk = taskGroup.ephemeralDisk.SizeMB;
    71  
    72      assert.equal(TaskGroup.tasksCount, `# Tasks ${tasks.length}`, '# Tasks');
    73      assert.equal(
    74        TaskGroup.cpu,
    75        `Reserved CPU ${totalCPU} MHz`,
    76        'Aggregated CPU reservation for all tasks'
    77      );
    78      assert.equal(
    79        TaskGroup.mem,
    80        `Reserved Memory ${totalMemory} MiB`,
    81        'Aggregated Memory reservation for all tasks'
    82      );
    83      assert.equal(
    84        TaskGroup.disk,
    85        `Reserved Disk ${totalDisk} MiB`,
    86        'Aggregated Disk reservation for all tasks'
    87      );
    88    });
    89  
    90    test('/jobs/:id/:task-group should have breadcrumbs for job and jobs', async function(assert) {
    91      assert.equal(TaskGroup.breadcrumbFor('jobs.index').text, 'Jobs', 'First breadcrumb says jobs');
    92      assert.equal(
    93        TaskGroup.breadcrumbFor('jobs.job.index').text,
    94        job.name,
    95        'Second breadcrumb says the job name'
    96      );
    97      assert.equal(
    98        TaskGroup.breadcrumbFor('jobs.job.task-group').text,
    99        taskGroup.name,
   100        'Third breadcrumb says the job name'
   101      );
   102    });
   103  
   104    test('/jobs/:id/:task-group first breadcrumb should link to jobs', async function(assert) {
   105      await TaskGroup.breadcrumbFor('jobs.index').visit();
   106      assert.equal(currentURL(), '/jobs', 'First breadcrumb links back to jobs');
   107    });
   108  
   109    test('/jobs/:id/:task-group second breadcrumb should link to the job for the task group', async function(assert) {
   110      await TaskGroup.breadcrumbFor('jobs.job.index').visit();
   111      assert.equal(
   112        currentURL(),
   113        `/jobs/${job.id}`,
   114        'Second breadcrumb links back to the job for the task group'
   115      );
   116    });
   117  
   118    test('/jobs/:id/:task-group should list one page of allocations for the task group', async function(assert) {
   119      server.createList('allocation', TaskGroup.pageSize, {
   120        jobId: job.id,
   121        taskGroup: taskGroup.name,
   122        clientStatus: 'running',
   123      });
   124  
   125      await JobsList.visit();
   126      await TaskGroup.visit({ id: job.id, name: taskGroup.name });
   127  
   128      assert.ok(
   129        server.db.allocations.where({ jobId: job.id }).length > TaskGroup.pageSize,
   130        'There are enough allocations to invoke pagination'
   131      );
   132  
   133      assert.equal(
   134        TaskGroup.allocations.length,
   135        TaskGroup.pageSize,
   136        'All allocations for the task group'
   137      );
   138    });
   139  
   140    test('each allocation should show basic information about the allocation', async function(assert) {
   141      const allocation = allocations.sortBy('modifyIndex').reverse()[0];
   142      const allocationRow = TaskGroup.allocations.objectAt(0);
   143  
   144      assert.equal(allocationRow.shortId, allocation.id.split('-')[0], 'Allocation short id');
   145      assert.equal(
   146        allocationRow.createTime,
   147        moment(allocation.createTime / 1000000).format('MMM DD HH:mm:ss ZZ'),
   148        'Allocation create time'
   149      );
   150      assert.equal(
   151        allocationRow.modifyTime,
   152        moment(allocation.modifyTime / 1000000).fromNow(),
   153        'Allocation modify time'
   154      );
   155      assert.equal(allocationRow.status, allocation.clientStatus, 'Client status');
   156      assert.equal(allocationRow.jobVersion, allocation.jobVersion, 'Job Version');
   157      assert.equal(
   158        allocationRow.client,
   159        server.db.nodes.find(allocation.nodeId).id.split('-')[0],
   160        'Node ID'
   161      );
   162  
   163      await allocationRow.visitClient();
   164  
   165      assert.equal(currentURL(), `/clients/${allocation.nodeId}`, 'Node links to node page');
   166    });
   167  
   168    test('each allocation should show stats about the allocation', async function(assert) {
   169      const allocation = allocations.sortBy('name')[0];
   170      const allocationRow = TaskGroup.allocations.objectAt(0);
   171  
   172      const allocStats = server.db.clientAllocationStats.find(allocation.id);
   173      const tasks = taskGroup.taskIds.map(id => server.db.tasks.find(id));
   174  
   175      const cpuUsed = tasks.reduce((sum, task) => sum + task.Resources.CPU, 0);
   176      const memoryUsed = tasks.reduce((sum, task) => sum + task.Resources.MemoryMB, 0);
   177  
   178      assert.equal(
   179        allocationRow.cpu,
   180        Math.floor(allocStats.resourceUsage.CpuStats.TotalTicks) / cpuUsed,
   181        'CPU %'
   182      );
   183  
   184      assert.equal(
   185        allocationRow.cpuTooltip,
   186        `${Math.floor(allocStats.resourceUsage.CpuStats.TotalTicks)} / ${cpuUsed} MHz`,
   187        'Detailed CPU information is in a tooltip'
   188      );
   189  
   190      assert.equal(
   191        allocationRow.mem,
   192        allocStats.resourceUsage.MemoryStats.RSS / 1024 / 1024 / memoryUsed,
   193        'Memory used'
   194      );
   195  
   196      assert.equal(
   197        allocationRow.memTooltip,
   198        `${formatBytes([allocStats.resourceUsage.MemoryStats.RSS])} / ${memoryUsed} MiB`,
   199        'Detailed memory information is in a tooltip'
   200      );
   201    });
   202  
   203    test('when the allocation search has no matches, there is an empty message', async function(assert) {
   204      await TaskGroup.search('zzzzzz');
   205  
   206      assert.ok(TaskGroup.isEmpty, 'Empty state is shown');
   207      assert.equal(
   208        TaskGroup.emptyState.headline,
   209        'No Matches',
   210        'Empty state has an appropriate message'
   211      );
   212    });
   213  
   214    test('when the allocation has reschedule events, the allocation row is denoted with an icon', async function(assert) {
   215      const rescheduleRow = TaskGroup.allocationFor(allocations[0].id);
   216      const normalRow = TaskGroup.allocationFor(allocations[1].id);
   217  
   218      assert.ok(rescheduleRow.rescheduled, 'Reschedule row has a reschedule icon');
   219      assert.notOk(normalRow.rescheduled, 'Normal row has no reschedule icon');
   220    });
   221  
   222    test('when the job for the task group is not found, an error message is shown, but the URL persists', async function(assert) {
   223      await TaskGroup.visit({ id: 'not-a-real-job', name: 'not-a-real-task-group' });
   224  
   225      assert.equal(
   226        server.pretender.handledRequests.findBy('status', 404).url,
   227        '/v1/job/not-a-real-job',
   228        'A request to the nonexistent job is made'
   229      );
   230      assert.equal(currentURL(), '/jobs/not-a-real-job/not-a-real-task-group', 'The URL persists');
   231      assert.ok(TaskGroup.error.isPresent, 'Error message is shown');
   232      assert.equal(TaskGroup.error.title, 'Not Found', 'Error message is for 404');
   233    });
   234  
   235    test('when the task group is not found on the job, an error message is shown, but the URL persists', async function(assert) {
   236      await TaskGroup.visit({ id: job.id, name: 'not-a-real-task-group' });
   237  
   238      assert.ok(
   239        server.pretender.handledRequests
   240          .filterBy('status', 200)
   241          .mapBy('url')
   242          .includes(`/v1/job/${job.id}`),
   243        'A request to the job is made and succeeds'
   244      );
   245      assert.equal(currentURL(), `/jobs/${job.id}/not-a-real-task-group`, 'The URL persists');
   246      assert.ok(TaskGroup.error.isPresent, 'Error message is shown');
   247      assert.equal(TaskGroup.error.title, 'Not Found', 'Error message is for 404');
   248    });
   249  });