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

     1  import { module, test } from 'qunit';
     2  import { setupRenderingTest } from 'ember-qunit';
     3  import { click, find, render, settled, waitUntil } from '@ember/test-helpers';
     4  import hbs from 'htmlbars-inline-precompile';
     5  import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage';
     6  import { initialize as fragmentSerializerInitializer } from 'nomad-ui/initializers/fragment-serializer';
     7  import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
     8  
     9  const jobName = 'test-job';
    10  const jobId = JSON.stringify([jobName, 'default']);
    11  
    12  const countChange = () => {
    13    const initial = find('[data-test-task-group-count]').textContent;
    14    return () => find('[data-test-task-group-count]').textContent !== initial;
    15  };
    16  
    17  let managementToken;
    18  let clientToken;
    19  
    20  const makeJob = (server, props = {}) => {
    21    // These tests require a job with particular task groups. This requires
    22    // mild Mirage surgery.
    23    const job = server.create('job', {
    24      id: jobName,
    25      groupCount: 0,
    26      createAllocations: false,
    27      shallow: true,
    28      ...props,
    29    });
    30    const noScalingGroup = server.create('task-group', {
    31      job,
    32      name: 'no-scaling',
    33      shallow: true,
    34      withScaling: false,
    35    });
    36    const scalingGroup = server.create('task-group', {
    37      job,
    38      count: 2,
    39      name: 'scaling',
    40      shallow: true,
    41      withScaling: true,
    42    });
    43    job.update({
    44      taskGroupIds: [noScalingGroup.id, scalingGroup.id],
    45    });
    46  };
    47  
    48  module('Integration | Component | task group row', function (hooks) {
    49    setupRenderingTest(hooks);
    50  
    51    hooks.beforeEach(async function () {
    52      fragmentSerializerInitializer(this.owner);
    53      this.store = this.owner.lookup('service:store');
    54      this.token = this.owner.lookup('service:token');
    55      this.server = startMirage();
    56      this.server.create('node');
    57  
    58      managementToken = this.server.create('token');
    59      clientToken = this.server.create('token');
    60      window.localStorage.nomadTokenSecret = managementToken.secretId;
    61    });
    62  
    63    hooks.afterEach(function () {
    64      this.server.shutdown();
    65      window.localStorage.clear();
    66    });
    67  
    68    const commonTemplate = hbs`
    69      <TaskGroupRow @taskGroup={{group}} />
    70    `;
    71  
    72    test('Task group row conditionally shows scaling buttons based on the presence of the scaling attr on the task group', async function (assert) {
    73      assert.expect(3);
    74  
    75      makeJob(this.server, { noActiveDeployment: true });
    76      this.token.fetchSelfTokenAndPolicies.perform();
    77      await settled();
    78  
    79      const job = await this.store.find('job', jobId);
    80      this.set('group', job.taskGroups.findBy('name', 'no-scaling'));
    81  
    82      await render(commonTemplate);
    83      assert.notOk(find('[data-test-scale]'));
    84  
    85      this.set('group', job.taskGroups.findBy('name', 'scaling'));
    86  
    87      await settled();
    88      assert.ok(find('[data-test-scale]'));
    89  
    90      await componentA11yAudit(this.element, assert);
    91    });
    92  
    93    test('Clicking scaling buttons immediately updates the rendered count but debounces the scaling API request', async function (assert) {
    94      makeJob(this.server, { noActiveDeployment: true });
    95      this.token.fetchSelfTokenAndPolicies.perform();
    96      await settled();
    97  
    98      const job = await this.store.find('job', jobId);
    99      this.set('group', job.taskGroups.findBy('name', 'scaling'));
   100  
   101      await render(commonTemplate);
   102      assert.equal(find('[data-test-task-group-count]').textContent, 2);
   103  
   104      click('[data-test-scale="increment"]');
   105      await waitUntil(countChange());
   106      assert.equal(find('[data-test-task-group-count]').textContent, 3);
   107  
   108      click('[data-test-scale="increment"]');
   109      await waitUntil(countChange());
   110      assert.equal(find('[data-test-task-group-count]').textContent, 4);
   111  
   112      assert.notOk(
   113        server.pretender.handledRequests.find(
   114          (req) => req.method === 'POST' && req.url.endsWith('/scale')
   115        )
   116      );
   117  
   118      await settled();
   119      const scaleRequests = server.pretender.handledRequests.filter(
   120        (req) => req.method === 'POST' && req.url.endsWith('/scale')
   121      );
   122      assert.equal(scaleRequests.length, 1);
   123      assert.equal(JSON.parse(scaleRequests[0].requestBody).Count, 4);
   124    });
   125  
   126    test('When the current count is equal to the max count, the increment count button is disabled', async function (assert) {
   127      assert.expect(2);
   128  
   129      makeJob(this.server, { noActiveDeployment: true });
   130      this.token.fetchSelfTokenAndPolicies.perform();
   131      await settled();
   132  
   133      const job = await this.store.find('job', jobId);
   134      const group = job.taskGroups.findBy('name', 'scaling');
   135      group.set('count', group.scaling.max);
   136      this.set('group', group);
   137  
   138      await render(commonTemplate);
   139      assert.ok(find('[data-test-scale="increment"]:disabled'));
   140  
   141      await componentA11yAudit(this.element, assert);
   142    });
   143  
   144    test('When the current count is equal to the min count, the decrement count button is disabled', async function (assert) {
   145      assert.expect(2);
   146  
   147      makeJob(this.server, { noActiveDeployment: true });
   148      this.token.fetchSelfTokenAndPolicies.perform();
   149      await settled();
   150  
   151      const job = await this.store.find('job', jobId);
   152      const group = job.taskGroups.findBy('name', 'scaling');
   153      group.set('count', group.scaling.min);
   154      this.set('group', group);
   155  
   156      await render(commonTemplate);
   157      assert.ok(find('[data-test-scale="decrement"]:disabled'));
   158  
   159      await componentA11yAudit(this.element, assert);
   160    });
   161  
   162    test('When there is an active deployment, both scale buttons are disabled', async function (assert) {
   163      assert.expect(3);
   164  
   165      makeJob(this.server, { activeDeployment: true });
   166      this.token.fetchSelfTokenAndPolicies.perform();
   167      await settled();
   168  
   169      const job = await this.store.find('job', jobId);
   170      this.set('group', job.taskGroups.findBy('name', 'scaling'));
   171  
   172      await render(commonTemplate);
   173      assert.ok(find('[data-test-scale="increment"]:disabled'));
   174      assert.ok(find('[data-test-scale="decrement"]:disabled'));
   175  
   176      await componentA11yAudit(this.element, assert);
   177    });
   178  
   179    test('When the current ACL token does not have the namespace:scale-job or namespace:submit-job policy rule', async function (assert) {
   180      makeJob(this.server, { noActiveDeployment: true });
   181      window.localStorage.nomadTokenSecret = clientToken.secretId;
   182      this.token.fetchSelfTokenAndPolicies.perform();
   183      await settled();
   184  
   185      const job = await this.store.find('job', jobId);
   186      this.set('group', job.taskGroups.findBy('name', 'scaling'));
   187  
   188      await render(commonTemplate);
   189      assert.ok(find('[data-test-scale="increment"]:disabled'));
   190      assert.ok(find('[data-test-scale="decrement"]:disabled'));
   191      assert.ok(
   192        find('[data-test-scale-controls]')
   193          .getAttribute('aria-label')
   194          .includes("You aren't allowed")
   195      );
   196    });
   197  });