open-nomad/ui/tests/acceptance/job-versions-test.js
Buck Doyle 90ecbdf522
Add job version revert buttons (#10336)
This adds a Revert two-step button to the JobVersions component for
not-current versions, which redirects to the overview on success. It
checks the job version before and after reversion to mitigate the edge
case where reverting to an otherwise-identical version has no effect, as
discussed in #10337.

It uses existing facilities for handling other errors and disabling the
button when permissions are lacking.
2021-04-20 08:33:16 -05:00

168 lines
6.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { currentURL } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { setupMirage } from 'ember-cli-mirage/test-support';
import a11yAudit from 'nomad-ui/tests/helpers/a11y-audit';
import Versions from 'nomad-ui/tests/pages/jobs/job/versions';
import Layout from 'nomad-ui/tests/pages/layout';
import moment from 'moment';
let job;
let namespace;
let versions;
module('Acceptance | job versions', function(hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
hooks.beforeEach(async function() {
server.create('namespace');
namespace = server.create('namespace');
job = server.create('job', { namespaceId: namespace.id, createAllocations: false });
versions = server.db.jobVersions.where({ jobId: job.id });
const managementToken = server.create('token');
window.localStorage.nomadTokenSecret = managementToken.secretId;
await Versions.visit({ id: job.id, namespace: namespace.id });
});
test('it passes an accessibility audit', async function(assert) {
await a11yAudit(assert);
});
test('/jobs/:id/versions should list all job versions', async function(assert) {
assert.ok(Versions.versions.length, versions.length, 'Each version gets a row in the timeline');
assert.equal(document.title, `Job ${job.name} versions - Nomad`);
});
test('each version mentions the version number, the stability, and the submitted time', async function(assert) {
const version = versions.sortBy('submitTime').reverse()[0];
const formattedSubmitTime = moment(version.submitTime / 1000000).format(
"MMM DD, 'YY HH:mm:ss ZZ"
);
const versionRow = Versions.versions.objectAt(0);
assert.ok(versionRow.text.includes(`Version #${version.version}`), 'Version #');
assert.equal(versionRow.stability, version.stable.toString(), 'Stability');
assert.equal(versionRow.submitTime, formattedSubmitTime, 'Submit time');
});
test('all versions but the current one have a button to revert to that version', async function(assert) {
let versionRowToRevertTo;
Versions.versions.forEach((versionRow) => {
if (versionRow.number === job.version) {
assert.ok(versionRow.revertToButton.isHidden);
} else {
assert.ok(versionRow.revertToButton.isPresent);
versionRowToRevertTo = versionRow;
}
});
if (versionRowToRevertTo) {
const versionNumberRevertingTo = versionRowToRevertTo.number;
await versionRowToRevertTo.revertToButton.idle();
await versionRowToRevertTo.revertToButton.confirm();
const revertRequest = this.server.pretender.handledRequests.find(request => request.url.includes('revert'));
assert.equal(revertRequest.url, `/v1/job/${job.id}/revert?namespace=${namespace.id}`);
assert.deepEqual(JSON.parse(revertRequest.requestBody), {
JobID: job.id,
JobVersion: versionNumberRevertingTo,
});
assert.equal(currentURL(), `/jobs/${job.id}?namespace=${namespace.id}`);
}
});
test('when reversion fails, the error message from the API is piped through to the alert', async function(assert) {
const versionRowToRevertTo = Versions.versions.filter(versionRow => versionRow.revertToButton.isPresent)[0];
if (versionRowToRevertTo) {
const message = 'A plaintext error message';
server.pretender.post('/v1/job/:id/revert', () => [500, {}, message]);
await versionRowToRevertTo.revertToButton.idle();
await versionRowToRevertTo.revertToButton.confirm();
assert.ok(Layout.inlineError.isShown);
assert.ok(Layout.inlineError.isDanger);
assert.ok(Layout.inlineError.title.includes('Could Not Revert'));
assert.equal(Layout.inlineError.message, message);
await Layout.inlineError.dismiss();
assert.notOk(Layout.inlineError.isShown);
} else {
assert.expect(0);
}
});
test('when reversion has no effect, the error message explains', async function(assert) {
const versionRowToRevertTo = Versions.versions.filter(versionRow => versionRow.revertToButton.isPresent)[0];
if (versionRowToRevertTo) {
// The default Mirage implementation updates the job version as passed in, this does nothing
server.pretender.post('/v1/job/:id/revert', () => [200, {}, '']);
await versionRowToRevertTo.revertToButton.idle();
await versionRowToRevertTo.revertToButton.confirm();
assert.ok(Layout.inlineError.isShown);
assert.ok(Layout.inlineError.isWarning);
assert.ok(Layout.inlineError.title.includes('Reversion Had No Effect'));
assert.equal(Layout.inlineError.message, 'Reverting to an identical older version doesnt produce a new version');
} else {
assert.expect(0);
}
});
test('when the job for the versions is not found, an error message is shown, but the URL persists', async function(assert) {
await Versions.visit({ id: 'not-a-real-job' });
assert.equal(
server.pretender.handledRequests
.filter(request => !request.url.includes('policy'))
.findBy('status', 404).url,
'/v1/job/not-a-real-job',
'A request to the nonexistent job is made'
);
assert.equal(currentURL(), '/jobs/not-a-real-job/versions', 'The URL persists');
assert.ok(Versions.error.isPresent, 'Error message is shown');
assert.equal(Versions.error.title, 'Not Found', 'Error message is for 404');
});
});
module('Acceptance | job versions (with client token)', function(hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
hooks.beforeEach(async function() {
job = server.create('job', { createAllocations: false });
versions = server.db.jobVersions.where({ jobId: job.id });
server.create('token');
const clientToken = server.create('token');
window.localStorage.nomadTokenSecret = clientToken.secretId;
await Versions.visit({ id: job.id });
});
test('reversion buttons are disabled when the token lacks permissions', async function(assert) {
const versionRowWithReversion = Versions.versions.filter(versionRow => versionRow.revertToButton.isPresent)[0];
if (versionRowWithReversion) {
assert.ok(versionRowWithReversion.revertToButtonIsDisabled);
} else {
assert.expect(0);
}
window.localStorage.clear();
});
});