github.com/hernad/nomad@v1.6.112/ui/tests/acceptance/job-definition-test.js (about)

     1  /**
     2   * Copyright (c) HashiCorp, Inc.
     3   * SPDX-License-Identifier: MPL-2.0
     4   */
     5  
     6  import { click, currentURL } from '@ember/test-helpers';
     7  import percySnapshot from '@percy/ember';
     8  import { module, test } from 'qunit';
     9  import { setupApplicationTest } from 'ember-qunit';
    10  import { setupMirage } from 'ember-cli-mirage/test-support';
    11  import a11yAudit from 'nomad-ui/tests/helpers/a11y-audit';
    12  import setupCodeMirror from 'nomad-ui/tests/helpers/codemirror';
    13  import Definition from 'nomad-ui/tests/pages/jobs/job/definition';
    14  import { JOB_JSON } from 'nomad-ui/tests/utils/generate-raw-json-job';
    15  
    16  let job;
    17  
    18  module('Acceptance | job definition', function (hooks) {
    19    setupApplicationTest(hooks);
    20    setupMirage(hooks);
    21    setupCodeMirror(hooks);
    22  
    23    hooks.beforeEach(async function () {
    24      server.create('node-pool');
    25      server.create('node');
    26      server.create('job');
    27      job = server.db.jobs[0];
    28      await Definition.visit({ id: job.id });
    29    });
    30  
    31    test('it passes an accessibility audit', async function (assert) {
    32      assert.expect(1);
    33  
    34      await a11yAudit(assert, 'scrollable-region-focusable');
    35    });
    36  
    37    test('visiting /jobs/:job_id/definition', async function (assert) {
    38      assert.equal(currentURL(), `/jobs/${job.id}/definition`);
    39      assert.equal(document.title, `Job ${job.name} definition - Nomad`);
    40    });
    41  
    42    test('the job definition page starts in read-only view', async function (assert) {
    43      assert.dom('[data-test-job-spec-view]').exists('Read-only Editor appears.');
    44    });
    45  
    46    test('the job definition page requests the job to display in an unmutated form', async function (assert) {
    47      const jobURL = `/v1/job/${job.id}`;
    48      const jobRequests = server.pretender.handledRequests
    49        .map((req) => req.url.split('?')[0])
    50        .filter((url) => url === jobURL);
    51      assert.strictEqual(
    52        jobRequests.length,
    53        2,
    54        'Two requests for the job were made'
    55      );
    56    });
    57  
    58    test('the job definition can be edited', async function (assert) {
    59      assert
    60        .dom('[data-test-job-editor]')
    61        .doesNotExist('Editor not shown on load.');
    62  
    63      await Definition.edit();
    64  
    65      assert.ok(
    66        Definition.editor.isPresent,
    67        'Editor is shown after clicking edit'
    68      );
    69      assert.notOk(Definition.jsonViewer, 'Editor replaces the JSON viewer');
    70    });
    71  
    72    test('when in editing mode, the action can be canceled, showing the read-only definition again', async function (assert) {
    73      await Definition.edit();
    74  
    75      await Definition.editor.cancelEditing();
    76      assert.dom('[data-test-job-spec-view]').exists('Read-only Editor appears.');
    77      assert.dom('[data-test-job-editor]').doesNotExist('The editor is gone');
    78    });
    79  
    80    test('when in editing mode, the editor is prepopulated with the job definition', async function (assert) {
    81      assert.expect(1);
    82  
    83      const requests = server.pretender.handledRequests;
    84      const jobSubmission = requests.findBy(
    85        'url',
    86        `/v1/job/${job.id}/submission?version=1`
    87      ).responseText;
    88      const formattedJobDefinition = JSON.parse(jobSubmission).Source;
    89  
    90      await Definition.edit();
    91      await percySnapshot(assert);
    92  
    93      assert.equal(
    94        Definition.editor.editor.contents,
    95        formattedJobDefinition,
    96        'The editor already has the job definition in it'
    97      );
    98    });
    99  
   100    test('when changes are submitted, the site redirects to the job overview page', async function (assert) {
   101      await Definition.edit();
   102  
   103      const cm = getCodeMirrorInstance(['data-test-editor']);
   104      cm.setValue(`{}`);
   105  
   106      await click('[data-test-plan]');
   107      await Definition.editor.run();
   108      assert.equal(
   109        currentURL(),
   110        `/jobs/${job.id}@default`,
   111        'Now on the job overview page'
   112      );
   113    });
   114  
   115    test('when the job for the definition is not found, an error message is shown, but the URL persists', async function (assert) {
   116      assert.expect(4);
   117      await Definition.visit({ id: 'not-a-real-job' });
   118      await percySnapshot(assert);
   119  
   120      assert.equal(
   121        server.pretender.handledRequests
   122          .filter((request) => !request.url.includes('policy'))
   123          .findBy('status', 404).url,
   124        '/v1/job/not-a-real-job',
   125        'A request to the nonexistent job is made'
   126      );
   127      assert.equal(
   128        currentURL(),
   129        '/jobs/not-a-real-job/definition',
   130        'The URL persists'
   131      );
   132      assert.ok(Definition.error.isPresent, 'Error message is shown');
   133      assert.equal(
   134        Definition.error.title,
   135        'Not Found',
   136        'Error message is for 404'
   137      );
   138    });
   139  });
   140  
   141  module('Acceptance | job definition | full specification', function (hooks) {
   142    setupApplicationTest(hooks);
   143    setupMirage(hooks);
   144    setupCodeMirror(hooks);
   145  
   146    hooks.beforeEach(async function () {
   147      server.create('node-pool');
   148      server.create('node');
   149      server.create('job');
   150      job = server.db.jobs[0];
   151    });
   152  
   153    test('it allows users to select between full specification and JSON definition', async function (assert) {
   154      assert.expect(3);
   155      const specification_response = {
   156        Format: 'hcl2',
   157        JobID: 'example',
   158        JobIndex: 223,
   159        Namespace: 'default',
   160        Source:
   161          'variable "datacenter" {\n  description = "The datacenter to run the job in"\n  type        = string\n  default     = "dc1"\n}\n\njob "example" {\n  datacenters = [var.datacenter]\n\n  group "example-group" {\n    task "example-task" {\n      driver = "docker"\n\n      config {\n        image = "redis:3.2"\n      }\n\n      resources {\n        cpu    = 500\n        memory = 256\n      }\n    }\n  }\n}\n',
   162        VariableFlags: { datacenter: 'dc2' },
   163        Variables: '',
   164        Version: 0,
   165      };
   166      server.get('/job/:id', () => JOB_JSON);
   167      server.get('/job/:id/submission', () => specification_response);
   168  
   169      await Definition.visit({ id: job.id });
   170      await percySnapshot(assert);
   171  
   172      assert
   173        .dom('[data-test-select="job-spec"]')
   174        .exists('A select button exists and defaults to full definition');
   175      let codeMirror = getCodeMirrorInstance('[data-test-editor]');
   176      assert.equal(
   177        codeMirror.getValue(),
   178        specification_response.Source,
   179        'Shows the full definition as written by the user'
   180      );
   181  
   182      await click('[data-test-select-full]');
   183      codeMirror = getCodeMirrorInstance('[data-test-editor]');
   184      assert.propContains(JSON.parse(codeMirror.getValue()), JOB_JSON);
   185    });
   186  });