github.com/hernad/nomad@v1.6.112/ui/tests/acceptance/task-logs-test.js (about)

     1  /**
     2   * Copyright (c) HashiCorp, Inc.
     3   * SPDX-License-Identifier: MPL-2.0
     4   */
     5  
     6  /* eslint-disable qunit/require-expect */
     7  import {
     8    click,
     9    currentURL,
    10    findAll,
    11    triggerKeyEvent,
    12  } from '@ember/test-helpers';
    13  import { run } from '@ember/runloop';
    14  import { module, test } from 'qunit';
    15  import { setupApplicationTest } from 'ember-qunit';
    16  import { setupMirage } from 'ember-cli-mirage/test-support';
    17  import a11yAudit from 'nomad-ui/tests/helpers/a11y-audit';
    18  import TaskLogs from 'nomad-ui/tests/pages/allocations/task/logs';
    19  import percySnapshot from '@percy/ember';
    20  import faker from 'nomad-ui/mirage/faker';
    21  
    22  let allocation;
    23  let task;
    24  let job;
    25  
    26  module('Acceptance | task logs', function (hooks) {
    27    setupApplicationTest(hooks);
    28    setupMirage(hooks);
    29  
    30    hooks.beforeEach(async function () {
    31      faker.seed(1);
    32      server.create('agent');
    33      server.create('node-pool');
    34      server.create('node', 'forceIPv4');
    35      job = server.create('job', { createAllocations: false });
    36  
    37      allocation = server.create('allocation', {
    38        jobId: job.id,
    39        clientStatus: 'running',
    40      });
    41      task = server.db.taskStates.where({ allocationId: allocation.id })[0];
    42  
    43      run.later(run, run.cancelTimers, 1000);
    44    });
    45  
    46    test('it passes an accessibility audit', async function (assert) {
    47      await TaskLogs.visit({ id: allocation.id, name: task.name });
    48      await a11yAudit(assert);
    49      await percySnapshot(assert);
    50    });
    51  
    52    test('/allocation/:id/:task_name/logs should have a log component', async function (assert) {
    53      await TaskLogs.visit({ id: allocation.id, name: task.name });
    54      assert.equal(
    55        currentURL(),
    56        `/allocations/${allocation.id}/${task.name}/logs`,
    57        'No redirect'
    58      );
    59      assert.ok(TaskLogs.hasTaskLog, 'Task log component found');
    60      assert.ok(document.title.includes(`Task ${task.name}`));
    61    });
    62  
    63    test('the stdout log immediately starts streaming', async function (assert) {
    64      await TaskLogs.visit({ id: allocation.id, name: task.name });
    65      const node = server.db.nodes.find(allocation.nodeId);
    66      const logUrlRegex = new RegExp(
    67        `${node.httpAddr}/v1/client/fs/logs/${allocation.id}`
    68      );
    69      assert.ok(
    70        server.pretender.handledRequests.filter((req) =>
    71          logUrlRegex.test(req.url)
    72        ).length,
    73        'Log requests were made'
    74      );
    75    });
    76  
    77    test('logs can be word-wrapped', async function (assert) {
    78      await TaskLogs.visit({ id: allocation.id, name: task.name });
    79  
    80      assert.dom('[data-test-word-wrap-toggle]').isNotChecked();
    81      assert.dom('[data-test-output]').doesNotHaveClass('wrapped');
    82  
    83      run.later(() => {
    84        run.cancelTimers();
    85      }, 100);
    86      await click('[data-test-word-wrap-toggle]');
    87      assert.dom('[data-test-word-wrap-toggle]').isChecked();
    88      assert.dom('[data-test-output]').hasClass('wrapped');
    89  
    90      run.later(() => {
    91        run.cancelTimers();
    92      }, 100);
    93      await click('[data-test-word-wrap-toggle]');
    94      assert.dom('[data-test-word-wrap-toggle]').isNotChecked();
    95      assert.dom('[data-test-output]').doesNotHaveClass('wrapped');
    96  
    97      window.localStorage.clear();
    98    });
    99  
   100    test('logs in sidebar can be word-wrapped', async function (assert) {
   101      await TaskLogs.visitParentJob({
   102        id: job.id,
   103        allocationId: allocation.id,
   104        name: task.name,
   105      });
   106  
   107      run.later(() => {
   108        run.cancelTimers();
   109      }, 500);
   110  
   111      const taskRow = [
   112        ...findAll('.task-sub-row').filter((row) => {
   113          return row.textContent.includes(task.name);
   114        }),
   115      ][0];
   116  
   117      await click(taskRow.querySelector('button.logs-sidebar-trigger'));
   118  
   119      assert.dom('[data-test-word-wrap-toggle]').isNotChecked();
   120      assert.dom('[data-test-output]').doesNotHaveClass('wrapped');
   121  
   122      run.later(() => {
   123        run.cancelTimers();
   124      }, 500);
   125  
   126      // type "ww" to trigger word wrap
   127      const W_KEY = 87;
   128      triggerKeyEvent('.sidebar', 'keydown', W_KEY);
   129      await triggerKeyEvent('.sidebar', 'keydown', W_KEY);
   130  
   131      assert.dom('[data-test-word-wrap-toggle]').isChecked();
   132      assert.dom('[data-test-output]').hasClass('wrapped');
   133  
   134      run.later(() => {
   135        run.cancelTimers();
   136      }, 100);
   137  
   138      triggerKeyEvent('.sidebar', 'keydown', W_KEY);
   139      await triggerKeyEvent('.sidebar', 'keydown', W_KEY);
   140      assert.dom('[data-test-word-wrap-toggle]').isNotChecked();
   141      assert.dom('[data-test-output]').doesNotHaveClass('wrapped');
   142  
   143      window.localStorage.clear();
   144    });
   145  
   146    test('logs are accessible in a sidebar context', async function (assert) {
   147      await TaskLogs.visitParentJob({
   148        id: job.id,
   149        allocationId: allocation.id,
   150        name: task.name,
   151      });
   152      assert.notOk(TaskLogs.sidebarIsPresent, 'Sidebar is not present');
   153  
   154      run.later(() => {
   155        run.cancelTimers();
   156      }, 500);
   157  
   158      const taskRow = [
   159        ...findAll('.task-sub-row').filter((row) => {
   160          return row.textContent.includes(task.name);
   161        }),
   162      ][0];
   163  
   164      await click(taskRow.querySelector('button.logs-sidebar-trigger'));
   165  
   166      assert.ok(TaskLogs.sidebarIsPresent, 'Sidebar is present');
   167      assert
   168        .dom('.task-context-sidebar h1.title')
   169        .includesText(task.name, 'Sidebar title is correct');
   170      assert
   171        .dom('.task-context-sidebar h1.title')
   172        .includesText(task.state, 'Task state is correctly displayed');
   173      await percySnapshot(assert, {
   174        percyCSS: `
   175          .allocation-row td { display: none; }
   176          .task-events table td:nth-child(1) { color: transparent; }
   177        `,
   178      });
   179  
   180      await click('.sidebar button.close');
   181      assert.notOk(TaskLogs.sidebarIsPresent, 'Sidebar is not present');
   182    });
   183  });