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

     1  import { module, test } from 'qunit';
     2  import { setupRenderingTest } from 'ember-qunit';
     3  import { click, find, findAll, render } from '@ember/test-helpers';
     4  import hbs from 'htmlbars-inline-precompile';
     5  import moment from 'moment';
     6  import { create, collection } from 'ember-cli-page-object';
     7  import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage';
     8  import pageSizeSelect from 'nomad-ui/tests/acceptance/behaviors/page-size-select';
     9  import pageSizeSelectPageObject from 'nomad-ui/tests/pages/components/page-size-select';
    10  import {
    11    jobURL,
    12    stopJob,
    13    startJob,
    14    purgeJob,
    15    expectError,
    16    expectDeleteRequest,
    17    expectStartRequest,
    18    expectPurgeRequest,
    19  } from './helpers';
    20  import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
    21  
    22  // A minimum viable page object to use with the pageSizeSelect behavior
    23  const PeriodicJobPage = create({
    24    pageSize: 25,
    25    jobs: collection('[data-test-job-row]'),
    26    pageSizeSelect: pageSizeSelectPageObject(),
    27  });
    28  
    29  module('Integration | Component | job-page/periodic', function (hooks) {
    30    setupRenderingTest(hooks);
    31  
    32    hooks.beforeEach(function () {
    33      window.localStorage.clear();
    34      this.store = this.owner.lookup('service:store');
    35      this.server = startMirage();
    36      this.server.create('namespace');
    37    });
    38  
    39    hooks.afterEach(function () {
    40      this.server.shutdown();
    41      window.localStorage.clear();
    42    });
    43  
    44    const commonTemplate = hbs`
    45      <JobPage::Periodic
    46        @job={{job}}
    47        @sortProperty={{sortProperty}}
    48        @sortDescending={{sortDescending}}
    49        @currentPage={{currentPage}}
    50      />
    51    `;
    52  
    53    const commonProperties = (job) => ({
    54      job,
    55      sortProperty: 'name',
    56      sortDescending: true,
    57      currentPage: 1,
    58    });
    59  
    60    test('Clicking Force Launch launches a new periodic child job', async function (assert) {
    61      const childrenCount = 3;
    62  
    63      this.server.create('job', 'periodic', {
    64        id: 'parent',
    65        childrenCount,
    66        createAllocations: false,
    67      });
    68  
    69      await this.store.findAll('job');
    70  
    71      const job = this.store.peekAll('job').findBy('plainId', 'parent');
    72  
    73      this.setProperties(commonProperties(job));
    74      await render(commonTemplate);
    75  
    76      const currentJobCount = server.db.jobs.length;
    77  
    78      assert.equal(
    79        findAll('[data-test-job-row] [data-test-job-name]').length,
    80        childrenCount,
    81        'The new periodic job launch is in the children list'
    82      );
    83  
    84      await click('[data-test-force-launch]');
    85  
    86      const expectedURL = jobURL(job, '/periodic/force');
    87  
    88      assert.ok(
    89        this.server.pretender.handledRequests
    90          .filterBy('method', 'POST')
    91          .find((req) => req.url === expectedURL),
    92        'POST URL was correct'
    93      );
    94  
    95      assert.equal(
    96        server.db.jobs.length,
    97        currentJobCount + 1,
    98        'POST request was made'
    99      );
   100    });
   101  
   102    test('Clicking force launch without proper permissions shows an error message', async function (assert) {
   103      this.server.pretender.post('/v1/job/:id/periodic/force', () => [
   104        403,
   105        {},
   106        '',
   107      ]);
   108  
   109      this.server.create('job', 'periodic', {
   110        id: 'parent',
   111        childrenCount: 1,
   112        createAllocations: false,
   113        status: 'running',
   114      });
   115  
   116      await this.store.findAll('job');
   117  
   118      const job = this.store.peekAll('job').findBy('plainId', 'parent');
   119  
   120      this.setProperties(commonProperties(job));
   121      await render(commonTemplate);
   122  
   123      assert.notOk(find('[data-test-job-error-title]'), 'No error message yet');
   124  
   125      await click('[data-test-force-launch]');
   126  
   127      assert.equal(
   128        find('[data-test-job-error-title]').textContent,
   129        'Could Not Force Launch',
   130        'Appropriate error is shown'
   131      );
   132      assert.ok(
   133        find('[data-test-job-error-body]').textContent.includes('ACL'),
   134        'The error message mentions ACLs'
   135      );
   136  
   137      await click('[data-test-job-error-close]');
   138  
   139      assert.notOk(
   140        find('[data-test-job-error-title]'),
   141        'Error message is dismissable'
   142      );
   143    });
   144  
   145    test('Stopping a job sends a delete request for the job', async function (assert) {
   146      assert.expect(1);
   147  
   148      const mirageJob = this.server.create('job', 'periodic', {
   149        childrenCount: 0,
   150        createAllocations: false,
   151        status: 'running',
   152      });
   153  
   154      let job;
   155      await this.store.findAll('job');
   156  
   157      job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
   158  
   159      this.setProperties(commonProperties(job));
   160      await render(commonTemplate);
   161      await stopJob();
   162  
   163      expectDeleteRequest(assert, this.server, job);
   164    });
   165  
   166    test('Stopping a job without proper permissions shows an error message', async function (assert) {
   167      assert.expect(4);
   168  
   169      this.server.pretender.delete('/v1/job/:id', () => [403, {}, '']);
   170  
   171      const mirageJob = this.server.create('job', 'periodic', {
   172        childrenCount: 0,
   173        createAllocations: false,
   174        status: 'running',
   175      });
   176  
   177      await this.store.findAll('job');
   178  
   179      const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
   180  
   181      this.setProperties(commonProperties(job));
   182      await render(commonTemplate);
   183  
   184      await stopJob();
   185      expectError(assert, 'Could Not Stop Job');
   186  
   187      await componentA11yAudit(this.element, assert);
   188    });
   189  
   190    test('Starting a job sends a post request for the job using the current definition', async function (assert) {
   191      assert.expect(2);
   192  
   193      const mirageJob = this.server.create('job', 'periodic', {
   194        childrenCount: 0,
   195        createAllocations: false,
   196        status: 'dead',
   197      });
   198      await this.store.findAll('job');
   199  
   200      const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
   201  
   202      this.setProperties(commonProperties(job));
   203      await render(commonTemplate);
   204  
   205      await startJob();
   206      expectStartRequest(assert, this.server, job);
   207    });
   208  
   209    test('Starting a job without proper permissions shows an error message', async function (assert) {
   210      assert.expect(3);
   211  
   212      this.server.pretender.post('/v1/job/:id', () => [403, {}, '']);
   213  
   214      const mirageJob = this.server.create('job', 'periodic', {
   215        childrenCount: 0,
   216        createAllocations: false,
   217        status: 'dead',
   218      });
   219      await this.store.findAll('job');
   220  
   221      const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
   222  
   223      this.setProperties(commonProperties(job));
   224      await render(commonTemplate);
   225  
   226      await startJob();
   227  
   228      await expectError(assert, 'Could Not Start Job');
   229    });
   230  
   231    test('Purging a job sends a purge request for the job', async function (assert) {
   232      assert.expect(1);
   233  
   234      const mirageJob = this.server.create('job', 'periodic', {
   235        childrenCount: 0,
   236        createAllocations: false,
   237        status: 'dead',
   238      });
   239      await this.store.findAll('job');
   240  
   241      const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
   242  
   243      this.setProperties(commonProperties(job));
   244      await render(commonTemplate);
   245  
   246      await purgeJob();
   247      expectPurgeRequest(assert, this.server, job);
   248    });
   249  
   250    test('Each job row includes the submitted time', async function (assert) {
   251      this.server.create('job', 'periodic', {
   252        id: 'parent',
   253        childrenCount: 1,
   254        createAllocations: false,
   255      });
   256  
   257      await this.store.findAll('job');
   258  
   259      const job = this.store.peekAll('job').findBy('plainId', 'parent');
   260  
   261      this.setProperties(commonProperties(job));
   262      await render(commonTemplate);
   263  
   264      assert.equal(
   265        find('[data-test-job-submit-time]').textContent.trim(),
   266        moment(job.get('children.firstObject.submitTime')).format(
   267          'MMM DD HH:mm:ss ZZ'
   268        ),
   269        'The new periodic job launch is in the children list'
   270      );
   271    });
   272  
   273    pageSizeSelect({
   274      resourceName: 'job',
   275      pageObject: PeriodicJobPage,
   276      pageObjectList: PeriodicJobPage.jobs,
   277      async setup() {
   278        this.server.create('job', 'periodic', {
   279          id: 'parent',
   280          childrenCount: PeriodicJobPage.pageSize,
   281          createAllocations: false,
   282        });
   283  
   284        await this.store.findAll('job');
   285  
   286        const job = this.store.peekAll('job').findBy('plainId', 'parent');
   287  
   288        this.setProperties(commonProperties(job));
   289        await render(commonTemplate);
   290      },
   291    });
   292  });