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 });