open-nomad/ui/tests/acceptance/job-run-test.js

316 lines
7.9 KiB
JavaScript
Raw Normal View History

2018-08-17 00:22:58 +00:00
import { assign } from '@ember/polyfills';
import { currentURL } from 'ember-native-dom-helpers';
import { test } from 'qunit';
import moduleForAcceptance from 'nomad-ui/tests/helpers/module-for-acceptance';
import JobRun from 'nomad-ui/tests/pages/jobs/run';
const newJobName = 'new-job';
const jsonJob = overrides => {
return JSON.stringify(
assign(
{},
{
Name: newJobName,
Namespace: 'default',
Datacenters: ['dc1'],
Priority: 50,
TaskGroups: {
redis: {
Tasks: {
redis: {
Driver: 'docker',
},
},
},
},
},
overrides
),
null,
2
);
};
const hclJob = () => `
job "${newJobName}" {
namespace = "default"
datacenters = ["dc1"]
task "redis" {
driver = "docker"
}
}
`;
moduleForAcceptance('Acceptance | job run', {
beforeEach() {
// Required for placing allocations (a result of creating jobs)
server.create('node');
},
});
test('visiting /jobs/run', function(assert) {
JobRun.visit();
andThen(() => {
assert.equal(currentURL(), '/jobs/run');
});
});
test('the page has an editor and an explanation popup', function(assert) {
JobRun.visit();
andThen(() => {
assert.ok(JobRun.editorHelp.isPresent, 'Editor explanation popup is present');
assert.ok(JobRun.editor.isPresent, 'Editor is present');
});
});
test('the explanation popup can be dismissed', function(assert) {
JobRun.visit();
andThen(() => {
JobRun.editorHelp.dismiss();
});
andThen(() => {
assert.notOk(JobRun.editorHelp.isPresent, 'Editor explanation popup is gone');
assert.equal(
window.localStorage.nomadMessageJobEditor,
'false',
'Dismissal is persisted in localStorage'
);
});
});
test('the explanation popup is not shown once the dismissal state is set in localStorage', function(assert) {
window.localStorage.nomadMessageJobEditor = 'false';
JobRun.visit();
andThen(() => {
assert.notOk(JobRun.editorHelp.isPresent, 'Editor explanation popup is gone');
});
});
test('submitting a json job skips the parse endpoint', function(assert) {
const spec = jsonJob();
JobRun.visit();
andThen(() => {
JobRun.editor.fillIn(spec);
JobRun.plan();
});
andThen(() => {
const requests = server.pretender.handledRequests.mapBy('url');
assert.notOk(requests.includes('/v1/jobs/parse'), 'JSON job spec is not parsed');
assert.ok(requests.includes(`/v1/job/${newJobName}/plan`), 'JSON job spec is still planned');
});
});
test('submitting an hcl job requires the parse endpoint', function(assert) {
const spec = hclJob();
JobRun.visit();
andThen(() => {
JobRun.editor.fillIn(spec);
JobRun.plan();
});
andThen(() => {
const requests = server.pretender.handledRequests.mapBy('url');
assert.ok(requests.includes('/v1/jobs/parse'), 'HCL job spec is parsed first');
assert.ok(requests.includes(`/v1/job/${newJobName}/plan`), 'HCL job spec is planned');
assert.ok(
requests.indexOf('/v1/jobs/parse') < requests.indexOf(`/v1/job/${newJobName}/plan`),
'Parse comes before Plan'
);
});
});
test('when a job is successfully parsed and planned, the plan is shown to the user', function(assert) {
const spec = hclJob();
JobRun.visit();
andThen(() => {
JobRun.editor.fillIn(spec);
JobRun.plan();
});
andThen(() => {
assert.ok(JobRun.planOutput, 'The plan is outputted');
assert.notOk(JobRun.editor.isPresent, 'The editor is replaced with the plan output');
assert.ok(JobRun.planHelp.isPresent, 'The plan explanation popup is shown');
});
});
test('from the plan screen, the cancel button goes back to the editor with the job still in tact', function(assert) {
const spec = hclJob();
JobRun.visit();
andThen(() => {
JobRun.editor.fillIn(spec);
JobRun.plan();
});
andThen(() => {
JobRun.cancel();
});
andThen(() => {
assert.ok(JobRun.editor.isPresent, 'The editor is shown again');
assert.notOk(JobRun.planOutpu, 'The plan is gone');
assert.equal(JobRun.editor.contents, spec, 'The spec that was planned is still in the editor');
});
});
test('from the plan screen, the submit button submits the job and redirects to the job overview page', function(assert) {
const spec = hclJob();
JobRun.visit();
andThen(() => {
JobRun.editor.fillIn(spec);
JobRun.plan();
});
andThen(() => {
JobRun.run();
});
andThen(() => {
assert.equal(
currentURL(),
`/jobs/${newJobName}`,
`Redirected to the job overview page for ${newJobName}`
);
const runRequest = server.pretender.handledRequests.find(
req => req.method === 'POST' && req.url === '/v1/jobs'
);
const planRequest = server.pretender.handledRequests.find(
req => req.method === 'POST' && req.url === '/v1/jobs/parse'
);
assert.ok(runRequest, 'A POST request was made to run the new job');
assert.deepEqual(
JSON.parse(runRequest.requestBody).Job,
JSON.parse(planRequest.responseText),
'The Job payload parameter is equivalent to the result of the parse request'
);
});
});
test('when parse fails, the parse error message is shown', function(assert) {
const spec = hclJob();
const errorMessage = 'Parse Failed!! :o';
server.pretender.post('/v1/jobs/parse', () => [400, {}, errorMessage]);
JobRun.visit();
andThen(() => {
JobRun.editor.fillIn(spec);
JobRun.plan();
});
andThen(() => {
assert.notOk(JobRun.planError.isPresent, 'Plan error is not shown');
assert.notOk(JobRun.runError.isPresent, 'Run error is not shown');
assert.ok(JobRun.parseError.isPresent, 'Parse error is shown');
assert.equal(
JobRun.parseError.message,
errorMessage,
'The error message from the server is shown in the error in the UI'
);
});
});
test('when plan fails, the plan error message is shown', function(assert) {
const spec = hclJob();
const errorMessage = 'Parse Failed!! :o';
server.pretender.post(`/v1/job/${newJobName}/plan`, () => [400, {}, errorMessage]);
JobRun.visit();
andThen(() => {
JobRun.editor.fillIn(spec);
JobRun.plan();
});
andThen(() => {
assert.notOk(JobRun.parseError.isPresent, 'Parse error is not shown');
assert.notOk(JobRun.runError.isPresent, 'Run error is not shown');
assert.ok(JobRun.planError.isPresent, 'Plan error is shown');
assert.equal(
JobRun.planError.message,
errorMessage,
'The error message from the server is shown in the error in the UI'
);
});
});
test('when run fails, the run error message is shown', function(assert) {
const spec = hclJob();
const errorMessage = 'Parse Failed!! :o';
server.pretender.post('/v1/jobs', () => [400, {}, errorMessage]);
JobRun.visit();
andThen(() => {
JobRun.editor.fillIn(spec);
JobRun.plan();
});
andThen(() => {
JobRun.run();
});
andThen(() => {
assert.notOk(JobRun.planError.isPresent, 'Plan error is not shown');
assert.notOk(JobRun.parseError.isPresent, 'Parse error is not shown');
assert.ok(JobRun.runError.isPresent, 'Run error is shown');
assert.equal(
JobRun.runError.message,
errorMessage,
'The error message from the server is shown in the error in the UI'
);
});
});
test('when submitting a job to a different namespace, the redirect to the job overview page takes namespace into account', function(assert) {
const newNamespace = 'second-namespace';
server.create('namespace', { id: newNamespace });
const spec = jsonJob({ Namespace: newNamespace });
JobRun.visit();
andThen(() => {
JobRun.editor.fillIn(spec);
JobRun.plan();
});
andThen(() => {
JobRun.run();
});
andThen(() => {
assert.equal(
currentURL(),
`/jobs/${newJobName}?namespace=${newNamespace}`,
`Redirected to the job overview page for ${newJobName} and switched the namespace to ${newNamespace}`
);
});
});