github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/ui/tests/unit/utils/log-test.js (about)

     1  import EmberObject from '@ember/object';
     2  import RSVP from 'rsvp';
     3  import { run } from '@ember/runloop';
     4  import sinon from 'sinon';
     5  import { module, test } from 'qunit';
     6  import _Log from 'nomad-ui/utils/classes/log';
     7  
     8  import { settled } from '@ember/test-helpers';
     9  
    10  let startSpy, stopSpy, initSpy, fetchSpy;
    11  
    12  const MockStreamer = EmberObject.extend({
    13    init() {
    14      this.poll = {
    15        isRunning: false,
    16      };
    17  
    18      initSpy(...arguments);
    19    },
    20  
    21    start() {
    22      this.poll.isRunning = true;
    23      startSpy(...arguments);
    24    },
    25  
    26    stop() {
    27      this.poll.isRunning = true;
    28      stopSpy(...arguments);
    29    },
    30  
    31    step(chunk) {
    32      if (this.poll.isRunning) {
    33        this.write(chunk);
    34      }
    35    },
    36  });
    37  
    38  const Log = _Log.extend({
    39    init() {
    40      this._super();
    41      const props = this.logStreamer.getProperties(
    42        'url',
    43        'params',
    44        'logFetch',
    45        'write'
    46      );
    47      this.set('logStreamer', MockStreamer.create(props));
    48    },
    49  });
    50  
    51  module('Unit | Util | Log', function (hooks) {
    52    hooks.beforeEach(function () {
    53      initSpy = sinon.spy();
    54      startSpy = sinon.spy();
    55      stopSpy = sinon.spy();
    56      fetchSpy = sinon.spy();
    57    });
    58  
    59    const makeMocks = (output) => ({
    60      url: '/test-url/',
    61      params: {
    62        a: 'param',
    63        another: 'one',
    64      },
    65      logFetch: function () {
    66        fetchSpy(...arguments);
    67        return RSVP.Promise.resolve({
    68          text() {
    69            return output;
    70          },
    71        });
    72      },
    73    });
    74  
    75    test('logStreamer is created on init', async function (assert) {
    76      const log = Log.create(makeMocks(''));
    77  
    78      assert.ok(log.get('logStreamer'), 'logStreamer property is defined');
    79      assert.ok(initSpy.calledOnce, 'logStreamer init was called');
    80    });
    81  
    82    test('gotoHead builds the correct URL', async function (assert) {
    83      assert.expect(1);
    84  
    85      const mocks = makeMocks('');
    86      const expectedUrl = `${mocks.url}?a=param&another=one&offset=0&origin=start`;
    87      const log = Log.create(mocks);
    88  
    89      run(() => {
    90        log.get('gotoHead').perform();
    91        assert.ok(
    92          fetchSpy.calledWith(expectedUrl),
    93          `gotoHead URL was ${expectedUrl}`
    94        );
    95      });
    96    });
    97  
    98    test('When gotoHead returns too large of a log, the log is truncated', async function (assert) {
    99      const longLog = Array(50001).fill('a').join('');
   100      const encodedLongLog = `{"Offset":0,"Data":"${window.btoa(longLog)}"}`;
   101      const truncationMessage =
   102        '\n\n---------- TRUNCATED: Click "tail" to view the bottom of the log ----------';
   103  
   104      const mocks = makeMocks(encodedLongLog);
   105      const log = Log.create(mocks);
   106  
   107      run(() => {
   108        log.get('gotoHead').perform();
   109      });
   110  
   111      await settled();
   112      assert.ok(
   113        log.get('output').toString().endsWith(truncationMessage),
   114        'Truncation message is shown'
   115      );
   116      assert.equal(
   117        log.get('output').toString().length,
   118        50000 + truncationMessage.length,
   119        'Output is truncated the appropriate amount'
   120      );
   121    });
   122  
   123    test('gotoTail builds the correct URL', async function (assert) {
   124      assert.expect(1);
   125  
   126      const mocks = makeMocks('');
   127      const expectedUrl = `${mocks.url}?a=param&another=one&offset=50000&origin=end`;
   128      const log = Log.create(mocks);
   129  
   130      run(() => {
   131        log.get('gotoTail').perform();
   132        assert.ok(
   133          fetchSpy.calledWith(expectedUrl),
   134          `gotoTail URL was ${expectedUrl}`
   135        );
   136      });
   137    });
   138  
   139    test('startStreaming starts the log streamer', async function (assert) {
   140      const log = Log.create(makeMocks(''));
   141  
   142      log.startStreaming();
   143      assert.ok(startSpy.calledOnce, 'Streaming started');
   144      assert.equal(
   145        log.get('logPointer'),
   146        'tail',
   147        'Streaming points the log to the tail'
   148      );
   149    });
   150  
   151    test('When the log streamer calls `write`, the output is appended', async function (assert) {
   152      const log = Log.create(makeMocks(''));
   153      const chunk1 = 'Hello';
   154      const chunk2 = ' World';
   155      const chunk3 = '\n\nEOF';
   156  
   157      log.startStreaming();
   158      assert.equal(log.get('output'), '', 'No output yet');
   159  
   160      log.get('logStreamer').step(chunk1);
   161      assert.equal(log.get('output'), chunk1, 'First chunk written');
   162  
   163      log.get('logStreamer').step(chunk2);
   164      assert.equal(log.get('output'), chunk1 + chunk2, 'Second chunk written');
   165  
   166      log.get('logStreamer').step(chunk3);
   167      assert.equal(
   168        log.get('output'),
   169        chunk1 + chunk2 + chunk3,
   170        'Third chunk written'
   171      );
   172    });
   173  
   174    test('stop stops the log streamer', async function (assert) {
   175      const log = Log.create(makeMocks(''));
   176  
   177      log.stop();
   178      assert.ok(stopSpy.calledOnce, 'Streaming stopped');
   179    });
   180  });