github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/ui/tests/integration/components/fs/file-test.js (about)

     1  import { module, test } from 'qunit';
     2  import { setupRenderingTest } from 'ember-qunit';
     3  import { find, click, render, settled } from '@ember/test-helpers';
     4  import hbs from 'htmlbars-inline-precompile';
     5  import Pretender from 'pretender';
     6  import { logEncode } from '../../../../mirage/data/logs';
     7  import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
     8  
     9  const { assign } = Object;
    10  const HOST = '1.1.1.1:1111';
    11  
    12  module('Integration | Component | fs/file', function (hooks) {
    13    setupRenderingTest(hooks);
    14  
    15    hooks.beforeEach(function () {
    16      this.server = new Pretender(function () {
    17        this.get('/v1/agent/members', () => [
    18          200,
    19          {},
    20          JSON.stringify({ ServerRegion: 'default', Members: [] }),
    21        ]);
    22        this.get('/v1/regions', () => [
    23          200,
    24          {},
    25          JSON.stringify(['default', 'region-2']),
    26        ]);
    27        this.get('/v1/client/fs/stream/:alloc_id', () => [
    28          200,
    29          {},
    30          logEncode(['Hello World'], 0),
    31        ]);
    32        this.get('/v1/client/fs/cat/:alloc_id', () => [200, {}, 'Hello World']);
    33        this.get('/v1/client/fs/readat/:alloc_id', () => [
    34          200,
    35          {},
    36          'Hello World',
    37        ]);
    38      });
    39      this.system = this.owner.lookup('service:system');
    40    });
    41  
    42    hooks.afterEach(function () {
    43      this.server.shutdown();
    44      window.localStorage.clear();
    45    });
    46  
    47    const commonTemplate = hbs`
    48      <Fs::File @allocation={{this.allocation}} @taskState={{this.taskState}} @file={{this.file}} @stat={{this.stat}} />
    49    `;
    50  
    51    const fileStat = (type, size = 0) => ({
    52      stat: {
    53        Size: size,
    54        ContentType: type,
    55      },
    56    });
    57    const makeProps = (props = {}) =>
    58      assign(
    59        {},
    60        {
    61          allocation: {
    62            id: 'alloc-1',
    63            node: {
    64              httpAddr: HOST,
    65            },
    66          },
    67          taskState: {
    68            name: 'task-name',
    69          },
    70          file: 'path/to/file',
    71          stat: {
    72            Size: 12345,
    73            ContentType: 'text/plain',
    74          },
    75        },
    76        props
    77      );
    78  
    79    test('When a file is text-based, the file mode is streaming', async function (assert) {
    80      assert.expect(3);
    81  
    82      const props = makeProps(fileStat('text/plain', 500));
    83      this.setProperties(props);
    84  
    85      await render(commonTemplate);
    86  
    87      assert.ok(
    88        find('[data-test-file-box] [data-test-log-cli]'),
    89        'The streaming file component was rendered'
    90      );
    91      assert.notOk(
    92        find('[data-test-file-box] [data-test-image-file]'),
    93        'The image file component was not rendered'
    94      );
    95  
    96      await componentA11yAudit(this.element, assert);
    97    });
    98  
    99    test('When a file is an image, the file mode is image', async function (assert) {
   100      assert.expect(3);
   101  
   102      const props = makeProps(fileStat('image/png', 1234));
   103      this.setProperties(props);
   104  
   105      await render(commonTemplate);
   106  
   107      assert.ok(
   108        find('[data-test-file-box] [data-test-image-file]'),
   109        'The image file component was rendered'
   110      );
   111      assert.notOk(
   112        find('[data-test-file-box] [data-test-log-cli]'),
   113        'The streaming file component was not rendered'
   114      );
   115  
   116      await componentA11yAudit(this.element, assert);
   117    });
   118  
   119    test('When the file is neither text-based or an image, the unsupported file type empty state is shown', async function (assert) {
   120      assert.expect(4);
   121  
   122      const props = makeProps(fileStat('wat/ohno', 1234));
   123      this.setProperties(props);
   124  
   125      await render(commonTemplate);
   126  
   127      assert.notOk(
   128        find('[data-test-file-box] [data-test-image-file]'),
   129        'The image file component was not rendered'
   130      );
   131      assert.notOk(
   132        find('[data-test-file-box] [data-test-log-cli]'),
   133        'The streaming file component was not rendered'
   134      );
   135      assert.ok(
   136        find('[data-test-unsupported-type]'),
   137        'Unsupported file type message is shown'
   138      );
   139      await componentA11yAudit(this.element, assert);
   140    });
   141  
   142    test('The unsupported file type empty state includes a link to the raw file', async function (assert) {
   143      const props = makeProps(fileStat('wat/ohno', 1234));
   144      this.setProperties(props);
   145  
   146      await render(commonTemplate);
   147  
   148      assert.ok(
   149        find('[data-test-unsupported-type] [data-test-log-action="raw"]'),
   150        'Unsupported file type message includes a link to the raw file'
   151      );
   152  
   153      assert.notOk(
   154        find('[data-test-header] [data-test-log-action="raw"]'),
   155        'Raw link is no longer in the header'
   156      );
   157    });
   158  
   159    test('The view raw button goes to the correct API url', async function (assert) {
   160      const props = makeProps(fileStat('image/png', 1234));
   161      this.setProperties(props);
   162  
   163      await render(commonTemplate);
   164      click('[data-test-log-action="raw"]');
   165      await settled();
   166      assert.ok(
   167        this.server.handledRequests.find(
   168          ({ url: url }) =>
   169            url ===
   170            `/v1/client/fs/cat/${props.allocation.id}?path=${encodeURIComponent(
   171              `${props.taskState.name}/${props.file}`
   172            )}`
   173        ),
   174        'Request to file is made'
   175      );
   176    });
   177  
   178    test('The view raw button respects the active region', async function (assert) {
   179      const region = 'region-2';
   180      window.localStorage.nomadActiveRegion = region;
   181  
   182      const props = makeProps(fileStat('image/png', 1234));
   183      this.setProperties(props);
   184  
   185      await this.system.get('regions');
   186      await render(commonTemplate);
   187  
   188      click('[data-test-log-action="raw"]');
   189      await settled();
   190      assert.ok(
   191        this.server.handledRequests.find(
   192          ({ url: url }) =>
   193            url ===
   194            `/v1/client/fs/cat/${props.allocation.id}?path=${encodeURIComponent(
   195              `${props.taskState.name}/${props.file}`
   196            )}&region=${region}`
   197        ),
   198        'Request to file is made with region'
   199      );
   200    });
   201  
   202    test('The head and tail buttons are not shown when the file is small', async function (assert) {
   203      const props = makeProps(fileStat('application/json', 5000));
   204      this.setProperties(props);
   205  
   206      await render(commonTemplate);
   207  
   208      assert.notOk(find('[data-test-log-action="head"]'), 'No head button');
   209      assert.notOk(find('[data-test-log-action="tail"]'), 'No tail button');
   210  
   211      this.set('stat.Size', 100000);
   212  
   213      await settled();
   214  
   215      assert.ok(find('[data-test-log-action="head"]'), 'Head button is shown');
   216      assert.ok(find('[data-test-log-action="tail"]'), 'Tail button is shown');
   217    });
   218  
   219    test('The  head and tail buttons are not shown for an image file', async function (assert) {
   220      const props = makeProps(fileStat('image/svg', 5000));
   221      this.setProperties(props);
   222  
   223      await render(commonTemplate);
   224  
   225      assert.notOk(find('[data-test-log-action="head"]'), 'No head button');
   226      assert.notOk(find('[data-test-log-action="tail"]'), 'No tail button');
   227  
   228      this.set('stat.Size', 100000);
   229  
   230      await settled();
   231  
   232      assert.notOk(find('[data-test-log-action="head"]'), 'Still no head button');
   233      assert.notOk(find('[data-test-log-action="tail"]'), 'Still no tail button');
   234    });
   235  
   236    test('Yielded content goes in the top-left header area', async function (assert) {
   237      assert.expect(2);
   238  
   239      const props = makeProps(fileStat('image/svg', 5000));
   240      this.setProperties(props);
   241  
   242      await render(hbs`
   243        <Fs::File @allocation={{this.allocation}} @taskState={{this.taskState}} @file={{this.file}} @stat={{this.stat}}>
   244          <div data-test-yield-spy>Yielded content</div>
   245        </Fs::File>
   246      `);
   247  
   248      assert.ok(
   249        find('[data-test-header] [data-test-yield-spy]'),
   250        'Yielded content shows up in the header'
   251      );
   252  
   253      await componentA11yAudit(this.element, assert);
   254    });
   255  
   256    test('The body is full-bleed and dark when the file is streaming', async function (assert) {
   257      const props = makeProps(fileStat('application/json', 5000));
   258      this.setProperties(props);
   259  
   260      await render(commonTemplate);
   261  
   262      const classes = Array.from(find('[data-test-file-box]').classList);
   263      assert.ok(classes.includes('is-dark'), 'Body is dark');
   264      assert.ok(classes.includes('is-full-bleed'), 'Body is full-bleed');
   265    });
   266  
   267    test('The body has padding and a light background when the file is not streaming', async function (assert) {
   268      const props = makeProps(fileStat('image/jpeg', 5000));
   269      this.setProperties(props);
   270  
   271      await render(commonTemplate);
   272  
   273      let classes = Array.from(find('[data-test-file-box]').classList);
   274      assert.notOk(classes.includes('is-dark'), 'Body is not dark');
   275      assert.notOk(classes.includes('is-full-bleed'), 'Body is not full-bleed');
   276  
   277      this.set('stat.ContentType', 'something/unknown');
   278  
   279      await settled();
   280  
   281      classes = Array.from(find('[data-test-file-box]').classList);
   282      assert.notOk(classes.includes('is-dark'), 'Body is still not dark');
   283      assert.notOk(
   284        classes.includes('is-full-bleed'),
   285        'Body is still not full-bleed'
   286      );
   287    });
   288  });