github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/ui/tests/integration/components/job-page/service-test.js (about)

     1  import { assign } from '@ember/polyfills';
     2  import { module, test } from 'qunit';
     3  import { setupRenderingTest } from 'ember-qunit';
     4  import { click, find, render } from '@ember/test-helpers';
     5  import hbs from 'htmlbars-inline-precompile';
     6  import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage';
     7  import { startJob, stopJob, expectError, expectDeleteRequest, expectStartRequest } from './helpers';
     8  import Job from 'nomad-ui/tests/pages/jobs/detail';
     9  import { initialize as fragmentSerializerInitializer } from 'nomad-ui/initializers/fragment-serializer';
    10  import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
    11  
    12  module('Integration | Component | job-page/service', function(hooks) {
    13    setupRenderingTest(hooks);
    14  
    15    hooks.beforeEach(function() {
    16      fragmentSerializerInitializer(this.owner);
    17      window.localStorage.clear();
    18      this.store = this.owner.lookup('service:store');
    19      this.server = startMirage();
    20      this.server.create('namespace');
    21    });
    22  
    23    hooks.afterEach(function() {
    24      Job.removeContext();
    25      this.server.shutdown();
    26      window.localStorage.clear();
    27    });
    28  
    29    const commonTemplate = hbs`
    30      <JobPage::Service
    31        @job={{job}}
    32        @sortProperty={{sortProperty}}
    33        @sortDescending={{sortDescending}}
    34        @currentPage={{currentPage}}
    35        @gotoJob={{gotoJob}} />
    36    `;
    37  
    38    const commonProperties = job => ({
    39      job,
    40      sortProperty: 'name',
    41      sortDescending: true,
    42      currentPage: 1,
    43      gotoJob() {},
    44    });
    45  
    46    const makeMirageJob = (server, props = {}) =>
    47      server.create(
    48        'job',
    49        assign(
    50          {
    51            type: 'service',
    52            createAllocations: false,
    53            status: 'running',
    54          },
    55          props
    56        )
    57      );
    58  
    59    test('Stopping a job sends a delete request for the job', async function(assert) {
    60      const mirageJob = makeMirageJob(this.server);
    61      await this.store.findAll('job');
    62  
    63      const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
    64  
    65      this.setProperties(commonProperties(job));
    66      await render(commonTemplate);
    67  
    68      await stopJob();
    69      expectDeleteRequest(assert, this.server, job);
    70    });
    71  
    72    test('Stopping a job without proper permissions shows an error message', async function(assert) {
    73      this.server.pretender.delete('/v1/job/:id', () => [403, {}, '']);
    74  
    75      const mirageJob = makeMirageJob(this.server);
    76      await this.store.findAll('job');
    77  
    78      const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
    79  
    80      this.setProperties(commonProperties(job));
    81      await render(commonTemplate);
    82  
    83      await stopJob();
    84      expectError(assert, 'Could Not Stop Job');
    85  
    86      await componentA11yAudit(this.element, assert);
    87    });
    88  
    89    test('Starting a job sends a post request for the job using the current definition', async function(assert) {
    90      const mirageJob = makeMirageJob(this.server, { status: 'dead' });
    91      await this.store.findAll('job');
    92  
    93      const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
    94  
    95      this.setProperties(commonProperties(job));
    96      await render(commonTemplate);
    97  
    98      await startJob();
    99      expectStartRequest(assert, this.server, job);
   100    });
   101  
   102    test('Starting a job without proper permissions shows an error message', async function(assert) {
   103      this.server.pretender.post('/v1/job/:id', () => [403, {}, '']);
   104  
   105      const mirageJob = makeMirageJob(this.server, { status: 'dead' });
   106      await this.store.findAll('job');
   107  
   108      const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
   109  
   110      this.setProperties(commonProperties(job));
   111      await render(commonTemplate);
   112  
   113      await startJob();
   114      expectError(assert, 'Could Not Start Job');
   115    });
   116  
   117    test('Recent allocations shows allocations in the job context', async function(assert) {
   118      this.server.create('node');
   119      const mirageJob = makeMirageJob(this.server, { createAllocations: true });
   120      await this.store.findAll('job');
   121  
   122      const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
   123  
   124      this.setProperties(commonProperties(job));
   125      await render(commonTemplate);
   126  
   127      const allocation = this.server.db.allocations.sortBy('modifyIndex').reverse()[0];
   128      const allocationRow = Job.allocations.objectAt(0);
   129  
   130      assert.equal(allocationRow.shortId, allocation.id.split('-')[0], 'ID');
   131      assert.equal(allocationRow.taskGroup, allocation.taskGroup, 'Task Group name');
   132  
   133      await componentA11yAudit(this.element, assert);
   134    });
   135  
   136    test('Recent allocations caps out at five', async function(assert) {
   137      this.server.create('node');
   138      const mirageJob = makeMirageJob(this.server);
   139      this.server.createList('allocation', 10);
   140  
   141      await this.store.findAll('job');
   142  
   143      const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
   144  
   145      this.setProperties(commonProperties(job));
   146      await render(commonTemplate);
   147  
   148      assert.equal(Job.allocations.length, 5, 'Capped at 5 allocations');
   149      assert.ok(
   150        Job.viewAllAllocations.includes(job.get('allocations.length') + ''),
   151        `View link mentions ${job.get('allocations.length')} allocations`
   152      );
   153    });
   154  
   155    test('Recent allocations shows an empty message when the job has no allocations', async function(assert) {
   156      this.server.create('node');
   157      const mirageJob = makeMirageJob(this.server);
   158  
   159      await this.store.findAll('job');
   160  
   161      const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
   162  
   163      this.setProperties(commonProperties(job));
   164      await render(commonTemplate);
   165  
   166      assert.ok(
   167        Job.recentAllocationsEmptyState.headline.includes('No Allocations'),
   168        'No allocations empty message'
   169      );
   170  
   171      await componentA11yAudit(this.element, assert);
   172    });
   173  
   174    test('Active deployment can be promoted', async function(assert) {
   175      this.server.create('node');
   176      const mirageJob = makeMirageJob(this.server, { activeDeployment: true });
   177  
   178      await this.store.findAll('job');
   179  
   180      const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
   181      const deployment = await job.get('latestDeployment');
   182  
   183      this.setProperties(commonProperties(job));
   184      await render(commonTemplate);
   185  
   186      await click('[data-test-promote-canary]');
   187  
   188      const requests = this.server.pretender.handledRequests;
   189  
   190      assert.ok(
   191        requests
   192          .filterBy('method', 'POST')
   193          .findBy('url', `/v1/deployment/promote/${deployment.get('id')}`),
   194        'A promote POST request was made'
   195      );
   196    });
   197  
   198    test('When promoting the active deployment fails, an error is shown', async function(assert) {
   199      this.server.pretender.post('/v1/deployment/promote/:id', () => [403, {}, '']);
   200  
   201      this.server.create('node');
   202      const mirageJob = makeMirageJob(this.server, { activeDeployment: true });
   203  
   204      await this.store.findAll('job');
   205  
   206      const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
   207  
   208      this.setProperties(commonProperties(job));
   209      await render(commonTemplate);
   210  
   211      await click('[data-test-promote-canary]');
   212  
   213      assert.equal(
   214        find('[data-test-job-error-title]').textContent,
   215        'Could Not Promote Deployment',
   216        'Appropriate error is shown'
   217      );
   218      assert.ok(
   219        find('[data-test-job-error-body]').textContent.includes('ACL'),
   220        'The error message mentions ACLs'
   221      );
   222  
   223      await componentA11yAudit(this.element, assert);
   224  
   225      await click('[data-test-job-error-close]');
   226  
   227      assert.notOk(find('[data-test-job-error-title]'), 'Error message is dismissable');
   228    });
   229  
   230    test('Active deployment can be failed', async function(assert) {
   231      this.server.create('node');
   232      const mirageJob = makeMirageJob(this.server, { activeDeployment: true });
   233  
   234      await this.store.findAll('job');
   235  
   236      const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
   237      const deployment = await job.get('latestDeployment');
   238  
   239      this.setProperties(commonProperties(job));
   240      await render(commonTemplate);
   241  
   242      await click('[data-test-active-deployment] [data-test-idle-button]');
   243      await click('[data-test-active-deployment] [data-test-confirm-button]');
   244  
   245      const requests = this.server.pretender.handledRequests;
   246  
   247      assert.ok(
   248        requests
   249          .filterBy('method', 'POST')
   250          .findBy('url', `/v1/deployment/fail/${deployment.get('id')}`),
   251        'A fail POST request was made'
   252      );
   253    });
   254  
   255    test('When failing the active deployment fails, an error is shown', async function(assert) {
   256      this.server.pretender.post('/v1/deployment/fail/:id', () => [403, {}, '']);
   257  
   258      this.server.create('node');
   259      const mirageJob = makeMirageJob(this.server, { activeDeployment: true });
   260  
   261      await this.store.findAll('job');
   262  
   263      const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
   264  
   265      this.setProperties(commonProperties(job));
   266      await render(commonTemplate);
   267  
   268      await click('[data-test-active-deployment] [data-test-idle-button]');
   269      await click('[data-test-active-deployment] [data-test-confirm-button]');
   270  
   271      assert.equal(
   272        find('[data-test-job-error-title]').textContent,
   273        'Could Not Fail Deployment',
   274        'Appropriate error is shown'
   275      );
   276      assert.ok(
   277        find('[data-test-job-error-body]').textContent.includes('ACL'),
   278        'The error message mentions ACLs'
   279      );
   280  
   281      await componentA11yAudit(this.element, assert);
   282  
   283      await click('[data-test-job-error-close]');
   284  
   285      assert.notOk(find('[data-test-job-error-title]'), 'Error message is dismissable');
   286    });
   287  });