github.com/hspak/nomad@v0.7.2-0.20180309000617-bc4ae22a39a5/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: 50,
    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      });
    60    },
    61    afterEach() {
    62      this.server.shutdown();
    63      streamPointer = 0;
    64    },
    65  });
    66  
    67  test('Basic appearance', function(assert) {
    68    this.setProperties(commonProps);
    69    this.render(hbs`{{task-log allocation=allocation task=task}}`);
    70  
    71    assert.ok(find('[data-test-log-action="stdout"]'), 'Stdout button');
    72    assert.ok(find('[data-test-log-action="stderr"]'), 'Stderr button');
    73    assert.ok(find('[data-test-log-action="head"]'), 'Head button');
    74    assert.ok(find('[data-test-log-action="tail"]'), 'Tail button');
    75    assert.ok(find('[data-test-log-action="toggle-stream"]'), 'Stream toggle button');
    76  
    77    assert.ok(find('[data-test-log-box].is-full-bleed.is-dark'), 'Body is full-bleed and dark');
    78  
    79    assert.ok(find('pre.cli-window'), 'Cli is preformatted and using the cli-window component class');
    80  });
    81  
    82  test('Streaming starts on creation', function(assert) {
    83    run.later(run, run.cancelTimers, commonProps.interval);
    84  
    85    this.setProperties(commonProps);
    86    this.render(hbs`{{task-log allocation=allocation task=task}}`);
    87  
    88    const logUrlRegex = new RegExp(`${HOST}/v1/client/fs/logs/${commonProps.allocation.id}`);
    89    assert.ok(
    90      this.server.handledRequests.filter(req => logUrlRegex.test(req.url)).length,
    91      'Log requests were made'
    92    );
    93  
    94    return wait().then(() => {
    95      assert.equal(
    96        find('[data-test-log-cli]').textContent,
    97        streamFrames[0],
    98        'First chunk of streaming log is shown'
    99      );
   100    });
   101  });
   102  
   103  test('Clicking Head loads the log head', function(assert) {
   104    this.setProperties(commonProps);
   105    this.render(hbs`{{task-log allocation=allocation task=task}}`);
   106  
   107    click('[data-test-log-action="head"]');
   108  
   109    return wait().then(() => {
   110      assert.ok(
   111        this.server.handledRequests.find(
   112          ({ queryParams: qp }) => qp.origin === 'start' && qp.plain === 'true' && qp.offset === '0'
   113        ),
   114        'Log head request was made'
   115      );
   116      assert.equal(find('[data-test-log-cli]').textContent, logHead[0], 'Head of the log is shown');
   117    });
   118  });
   119  
   120  test('Clicking Tail loads the log tail', function(assert) {
   121    this.setProperties(commonProps);
   122    this.render(hbs`{{task-log allocation=allocation task=task}}`);
   123  
   124    click('[data-test-log-action="tail"]');
   125  
   126    return wait().then(() => {
   127      assert.ok(
   128        this.server.handledRequests.find(
   129          ({ queryParams: qp }) => qp.origin === 'end' && qp.plain === 'true'
   130        ),
   131        'Log tail request was made'
   132      );
   133      assert.equal(find('[data-test-log-cli]').textContent, logTail[0], 'Tail of the log is shown');
   134    });
   135  });
   136  
   137  test('Clicking toggleStream starts and stops the log stream', function(assert) {
   138    const { interval } = commonProps;
   139    this.setProperties(commonProps);
   140    this.render(hbs`{{task-log allocation=allocation task=task interval=interval}}`);
   141  
   142    run.later(() => {
   143      click('[data-test-log-action="toggle-stream"]');
   144    }, interval);
   145  
   146    return wait().then(() => {
   147      assert.equal(find('[data-test-log-cli]').textContent, streamFrames[0], 'First frame loaded');
   148  
   149      run.later(() => {
   150        assert.equal(
   151          find('[data-test-log-cli]').textContent,
   152          streamFrames[0],
   153          'Still only first frame'
   154        );
   155        click('[data-test-log-action="toggle-stream"]');
   156        run.later(run, run.cancelTimers, interval * 2);
   157      }, interval * 2);
   158  
   159      return wait().then(() => {
   160        assert.equal(
   161          find('[data-test-log-cli]').textContent,
   162          streamFrames[0] + streamFrames[0] + streamFrames[1],
   163          'Now includes second frame'
   164        );
   165      });
   166    });
   167  });
   168  
   169  test('Clicking stderr switches the log to standard error', function(assert) {
   170    this.setProperties(commonProps);
   171    this.render(hbs`{{task-log allocation=allocation task=task}}`);
   172  
   173    click('[data-test-log-action="stderr"]');
   174    run.later(run, run.cancelTimers, commonProps.interval);
   175  
   176    return wait().then(() => {
   177      assert.ok(
   178        this.server.handledRequests.filter(req => req.queryParams.type === 'stderr').length,
   179        'stderr log requests were made'
   180      );
   181    });
   182  });
   183  
   184  test('When the client is inaccessible, task-log falls back to requesting logs through the server', function(assert) {
   185    run.later(run, run.cancelTimers, allowedConnectionTime * 2);
   186  
   187    // override client response to timeout
   188    this.server.get(
   189      `http://${HOST}/v1/client/fs/logs/:allocation_id`,
   190      () => [400, {}, ''],
   191      allowedConnectionTime * 2
   192    );
   193  
   194    this.setProperties(commonProps);
   195    this.render(
   196      hbs`{{task-log
   197        allocation=allocation
   198        task=task
   199        clientTimeout=clientTimeout
   200        serverTimeout=serverTimeout}}`
   201    );
   202  
   203    const clientUrlRegex = new RegExp(`${HOST}/v1/client/fs/logs/${commonProps.allocation.id}`);
   204    assert.ok(
   205      this.server.handledRequests.filter(req => clientUrlRegex.test(req.url)).length,
   206      'Log request was initially made directly to the client'
   207    );
   208  
   209    return wait().then(() => {
   210      const serverUrl = `/v1/client/fs/logs/${commonProps.allocation.id}`;
   211      assert.ok(
   212        this.server.handledRequests.filter(req => req.url.startsWith(serverUrl)).length,
   213        'Log request was later made to the server'
   214      );
   215    });
   216  });
   217  
   218  test('When both the client and the server are inaccessible, an error message is shown', function(assert) {
   219    run.later(run, run.cancelTimers, allowedConnectionTime * 5);
   220  
   221    // override client and server responses to timeout
   222    this.server.get(
   223      `http://${HOST}/v1/client/fs/logs/:allocation_id`,
   224      () => [400, {}, ''],
   225      allowedConnectionTime * 2
   226    );
   227    this.server.get(
   228      '/v1/client/fs/logs/:allocation_id',
   229      () => [400, {}, ''],
   230      allowedConnectionTime * 2
   231    );
   232  
   233    this.setProperties(commonProps);
   234    this.render(
   235      hbs`{{task-log
   236        allocation=allocation
   237        task=task
   238        clientTimeout=clientTimeout
   239        serverTimeout=serverTimeout}}`
   240    );
   241  
   242    return wait().then(() => {
   243      const clientUrlRegex = new RegExp(`${HOST}/v1/client/fs/logs/${commonProps.allocation.id}`);
   244      assert.ok(
   245        this.server.handledRequests.filter(req => clientUrlRegex.test(req.url)).length,
   246        'Log request was initially made directly to the client'
   247      );
   248      const serverUrl = `/v1/client/fs/logs/${commonProps.allocation.id}`;
   249      assert.ok(
   250        this.server.handledRequests.filter(req => req.url.startsWith(serverUrl)).length,
   251        'Log request was later made to the server'
   252      );
   253      assert.ok(find('[data-test-connection-error]'), 'An error message is shown');
   254    });
   255  });