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

     1  import { run } from '@ember/runloop';
     2  import { module, test } from 'qunit';
     3  import { setupRenderingTest } from 'ember-qunit';
     4  import { render, settled } from '@ember/test-helpers';
     5  import { find, click } from 'ember-native-dom-helpers';
     6  import hbs from 'htmlbars-inline-precompile';
     7  import Pretender from 'pretender';
     8  import { logEncode } from '../../mirage/data/logs';
     9  
    10  const HOST = '1.1.1.1:1111';
    11  const allowedConnectionTime = 100;
    12  const commonProps = {
    13    interval: 200,
    14    allocation: {
    15      id: 'alloc-1',
    16      node: {
    17        httpAddr: HOST,
    18      },
    19    },
    20    task: 'task-name',
    21    clientTimeout: allowedConnectionTime,
    22    serverTimeout: allowedConnectionTime,
    23  };
    24  
    25  const logHead = ['HEAD'];
    26  const logTail = ['TAIL'];
    27  const streamFrames = ['one\n', 'two\n', 'three\n', 'four\n', 'five\n'];
    28  let streamPointer = 0;
    29  
    30  module('Integration | Component | task log', function(hooks) {
    31    setupRenderingTest(hooks);
    32  
    33    hooks.beforeEach(function() {
    34      const handler = ({ queryParams }) => {
    35        const { origin, offset, plain, follow } = queryParams;
    36  
    37        let frames;
    38        let data;
    39  
    40        if (origin === 'start' && offset === '0' && plain && !follow) {
    41          frames = logHead;
    42        } else if (origin === 'end' && plain && !follow) {
    43          frames = logTail;
    44        } else {
    45          frames = streamFrames;
    46        }
    47  
    48        if (frames === streamFrames) {
    49          data = queryParams.plain ? frames[streamPointer] : logEncode(frames, streamPointer);
    50          streamPointer++;
    51        } else {
    52          data = queryParams.plain ? frames.join('') : logEncode(frames, frames.length - 1);
    53        }
    54  
    55        return [200, {}, data];
    56      };
    57  
    58      this.server = new Pretender(function() {
    59        this.get(`http://${HOST}/v1/client/fs/logs/:allocation_id`, handler);
    60        this.get('/v1/client/fs/logs/:allocation_id', handler);
    61        this.get('/v1/regions', () => [200, {}, '[]']);
    62      });
    63    });
    64  
    65    hooks.afterEach(function() {
    66      this.server.shutdown();
    67      streamPointer = 0;
    68    });
    69  
    70    test('Basic appearance', async function(assert) {
    71      run.later(run, run.cancelTimers, commonProps.interval);
    72  
    73      this.setProperties(commonProps);
    74      await render(hbs`{{task-log allocation=allocation task=task}}`);
    75  
    76      assert.ok(find('[data-test-log-action="stdout"]'), 'Stdout button');
    77      assert.ok(find('[data-test-log-action="stderr"]'), 'Stderr button');
    78      assert.ok(find('[data-test-log-action="head"]'), 'Head button');
    79      assert.ok(find('[data-test-log-action="tail"]'), 'Tail button');
    80      assert.ok(find('[data-test-log-action="toggle-stream"]'), 'Stream toggle button');
    81  
    82      assert.ok(find('[data-test-log-box].is-full-bleed.is-dark'), 'Body is full-bleed and dark');
    83  
    84      assert.ok(
    85        find('pre.cli-window'),
    86        'Cli is preformatted and using the cli-window component class'
    87      );
    88    });
    89  
    90    test('Streaming starts on creation', async function(assert) {
    91      run.later(run, run.cancelTimers, commonProps.interval);
    92  
    93      this.setProperties(commonProps);
    94      await render(hbs`{{task-log allocation=allocation task=task}}`);
    95  
    96      const logUrlRegex = new RegExp(`${HOST}/v1/client/fs/logs/${commonProps.allocation.id}`);
    97      assert.ok(
    98        this.server.handledRequests.filter(req => logUrlRegex.test(req.url)).length,
    99        'Log requests were made'
   100      );
   101  
   102      await settled();
   103      assert.equal(
   104        find('[data-test-log-cli]').textContent,
   105        streamFrames[0],
   106        'First chunk of streaming log is shown'
   107      );
   108    });
   109  
   110    test('Clicking Head loads the log head', async function(assert) {
   111      run.later(run, run.cancelTimers, commonProps.interval);
   112  
   113      this.setProperties(commonProps);
   114      await render(hbs`{{task-log allocation=allocation task=task}}`);
   115  
   116      click('[data-test-log-action="head"]');
   117  
   118      await settled();
   119      assert.ok(
   120        this.server.handledRequests.find(
   121          ({ queryParams: qp }) => qp.origin === 'start' && qp.plain === 'true' && qp.offset === '0'
   122        ),
   123        'Log head request was made'
   124      );
   125      assert.equal(find('[data-test-log-cli]').textContent, logHead[0], 'Head of the log is shown');
   126    });
   127  
   128    test('Clicking Tail loads the log tail', async function(assert) {
   129      run.later(run, run.cancelTimers, commonProps.interval);
   130  
   131      this.setProperties(commonProps);
   132      await render(hbs`{{task-log allocation=allocation task=task}}`);
   133  
   134      click('[data-test-log-action="tail"]');
   135  
   136      await settled();
   137      assert.ok(
   138        this.server.handledRequests.find(
   139          ({ queryParams: qp }) => qp.origin === 'end' && qp.plain === 'true'
   140        ),
   141        'Log tail request was made'
   142      );
   143      assert.equal(find('[data-test-log-cli]').textContent, logTail[0], 'Tail of the log is shown');
   144    });
   145  
   146    test('Clicking toggleStream starts and stops the log stream', async function(assert) {
   147      run.later(run, run.cancelTimers, commonProps.interval);
   148  
   149      const { interval } = commonProps;
   150      this.setProperties(commonProps);
   151      await render(hbs`{{task-log allocation=allocation task=task interval=interval}}`);
   152  
   153      run.later(() => {
   154        click('[data-test-log-action="toggle-stream"]');
   155      }, interval);
   156  
   157      await settled();
   158      assert.equal(find('[data-test-log-cli]').textContent, streamFrames[0], 'First frame loaded');
   159  
   160      run.later(() => {
   161        assert.equal(
   162          find('[data-test-log-cli]').textContent,
   163          streamFrames[0],
   164          'Still only first frame'
   165        );
   166        click('[data-test-log-action="toggle-stream"]');
   167        run.later(run, run.cancelTimers, interval * 2);
   168      }, interval * 2);
   169  
   170      await settled();
   171      assert.equal(
   172        find('[data-test-log-cli]').textContent,
   173        streamFrames[0] + streamFrames[0] + streamFrames[1],
   174        'Now includes second frame'
   175      );
   176    });
   177  
   178    test('Clicking stderr switches the log to standard error', async function(assert) {
   179      run.later(run, run.cancelTimers, commonProps.interval);
   180  
   181      this.setProperties(commonProps);
   182      await render(hbs`{{task-log allocation=allocation task=task}}`);
   183  
   184      click('[data-test-log-action="stderr"]');
   185      run.later(run, run.cancelTimers, commonProps.interval);
   186  
   187      await settled();
   188      assert.ok(
   189        this.server.handledRequests.filter(req => req.queryParams.type === 'stderr').length,
   190        'stderr log requests were made'
   191      );
   192    });
   193  
   194    test('When the client is inaccessible, task-log falls back to requesting logs through the server', async function(assert) {
   195      run.later(run, run.cancelTimers, allowedConnectionTime * 2);
   196  
   197      // override client response to timeout
   198      this.server.get(
   199        `http://${HOST}/v1/client/fs/logs/:allocation_id`,
   200        () => [400, {}, ''],
   201        allowedConnectionTime * 2
   202      );
   203  
   204      this.setProperties(commonProps);
   205      await render(hbs`{{task-log
   206        allocation=allocation
   207        task=task
   208        clientTimeout=clientTimeout
   209        serverTimeout=serverTimeout}}`);
   210  
   211      const clientUrlRegex = new RegExp(`${HOST}/v1/client/fs/logs/${commonProps.allocation.id}`);
   212      assert.ok(
   213        this.server.handledRequests.filter(req => clientUrlRegex.test(req.url)).length,
   214        'Log request was initially made directly to the client'
   215      );
   216  
   217      await settled();
   218      const serverUrl = `/v1/client/fs/logs/${commonProps.allocation.id}`;
   219      assert.ok(
   220        this.server.handledRequests.filter(req => req.url.startsWith(serverUrl)).length,
   221        'Log request was later made to the server'
   222      );
   223    });
   224  
   225    test('When both the client and the server are inaccessible, an error message is shown', async function(assert) {
   226      run.later(run, run.cancelTimers, allowedConnectionTime * 5);
   227  
   228      // override client and server responses to timeout
   229      this.server.get(
   230        `http://${HOST}/v1/client/fs/logs/:allocation_id`,
   231        () => [400, {}, ''],
   232        allowedConnectionTime * 2
   233      );
   234      this.server.get(
   235        '/v1/client/fs/logs/:allocation_id',
   236        () => [400, {}, ''],
   237        allowedConnectionTime * 2
   238      );
   239  
   240      this.setProperties(commonProps);
   241      await render(hbs`{{task-log
   242        allocation=allocation
   243        task=task
   244        clientTimeout=clientTimeout
   245        serverTimeout=serverTimeout}}`);
   246  
   247      await settled();
   248      const clientUrlRegex = new RegExp(`${HOST}/v1/client/fs/logs/${commonProps.allocation.id}`);
   249      assert.ok(
   250        this.server.handledRequests.filter(req => clientUrlRegex.test(req.url)).length,
   251        'Log request was initially made directly to the client'
   252      );
   253      const serverUrl = `/v1/client/fs/logs/${commonProps.allocation.id}`;
   254      assert.ok(
   255        this.server.handledRequests.filter(req => req.url.startsWith(serverUrl)).length,
   256        'Log request was later made to the server'
   257      );
   258      assert.ok(find('[data-test-connection-error]'), 'An error message is shown');
   259    });
   260  });