github.com/zoomfoo/nomad@v0.8.5-0.20180907175415-f28fd3a1a056/ui/tests/integration/task-log-test.js (about)

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