open-nomad/ui/tests/integration/components/job-page/service-test.js
Jai Bhagat 3350f3fb11 ui: apply new qunit linting rules to tests
Async tests should use  in integrations tests.
Acceptance tests are using Mirage and can't use
since we can't know the number of assertions.
2022-01-20 10:01:35 -05:00

326 lines
9.4 KiB
JavaScript

import { assign } from '@ember/polyfills';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { click, find, render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage';
import {
startJob,
stopJob,
expectError,
expectDeleteRequest,
expectStartRequest,
} from './helpers';
import Job from 'nomad-ui/tests/pages/jobs/detail';
import { initialize as fragmentSerializerInitializer } from 'nomad-ui/initializers/fragment-serializer';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
module('Integration | Component | job-page/service', function (hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function () {
fragmentSerializerInitializer(this.owner);
window.localStorage.clear();
this.store = this.owner.lookup('service:store');
this.server = startMirage();
this.server.create('namespace');
});
hooks.afterEach(function () {
Job.removeContext();
this.server.shutdown();
window.localStorage.clear();
});
const commonTemplate = hbs`
<JobPage::Service
@job={{job}}
@sortProperty={{sortProperty}}
@sortDescending={{sortDescending}}
@currentPage={{currentPage}}
@gotoJob={{gotoJob}} />
`;
const commonProperties = (job) => ({
job,
sortProperty: 'name',
sortDescending: true,
currentPage: 1,
gotoJob() {},
});
const makeMirageJob = (server, props = {}) =>
server.create(
'job',
assign(
{
type: 'service',
createAllocations: false,
status: 'running',
},
props
)
);
test('Stopping a job sends a delete request for the job', async function (assert) {
assert.expect(1);
const mirageJob = makeMirageJob(this.server);
await this.store.findAll('job');
const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
this.setProperties(commonProperties(job));
await render(commonTemplate);
await stopJob();
expectDeleteRequest(assert, this.server, job);
});
test('Stopping a job without proper permissions shows an error message', async function (assert) {
assert.expect(4);
this.server.pretender.delete('/v1/job/:id', () => [403, {}, '']);
const mirageJob = makeMirageJob(this.server);
await this.store.findAll('job');
const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
this.setProperties(commonProperties(job));
await render(commonTemplate);
await stopJob();
expectError(assert, 'Could Not Stop Job');
await componentA11yAudit(this.element, assert);
});
test('Starting a job sends a post request for the job using the current definition', async function (assert) {
assert.expect(2);
const mirageJob = makeMirageJob(this.server, { status: 'dead' });
await this.store.findAll('job');
const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
this.setProperties(commonProperties(job));
await render(commonTemplate);
await startJob();
expectStartRequest(assert, this.server, job);
});
test('Starting a job without proper permissions shows an error message', async function (assert) {
assert.expect(3);
this.server.pretender.post('/v1/job/:id', () => [403, {}, '']);
const mirageJob = makeMirageJob(this.server, { status: 'dead' });
await this.store.findAll('job');
const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
this.setProperties(commonProperties(job));
await render(commonTemplate);
await startJob();
expectError(assert, 'Could Not Start Job');
});
test('Recent allocations shows allocations in the job context', async function (assert) {
assert.expect(3);
this.server.create('node');
const mirageJob = makeMirageJob(this.server, { createAllocations: true });
await this.store.findAll('job');
const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
this.setProperties(commonProperties(job));
await render(commonTemplate);
const allocation = this.server.db.allocations
.sortBy('modifyIndex')
.reverse()[0];
const allocationRow = Job.allocations.objectAt(0);
assert.equal(allocationRow.shortId, allocation.id.split('-')[0], 'ID');
assert.equal(
allocationRow.taskGroup,
allocation.taskGroup,
'Task Group name'
);
await componentA11yAudit(this.element, assert);
});
test('Recent allocations caps out at five', async function (assert) {
this.server.create('node');
const mirageJob = makeMirageJob(this.server);
this.server.createList('allocation', 10);
await this.store.findAll('job');
const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
this.setProperties(commonProperties(job));
await render(commonTemplate);
assert.equal(Job.allocations.length, 5, 'Capped at 5 allocations');
assert.ok(
Job.viewAllAllocations.includes(job.get('allocations.length') + ''),
`View link mentions ${job.get('allocations.length')} allocations`
);
});
test('Recent allocations shows an empty message when the job has no allocations', async function (assert) {
assert.expect(2);
this.server.create('node');
const mirageJob = makeMirageJob(this.server);
await this.store.findAll('job');
const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
this.setProperties(commonProperties(job));
await render(commonTemplate);
assert.ok(
Job.recentAllocationsEmptyState.headline.includes('No Allocations'),
'No allocations empty message'
);
await componentA11yAudit(this.element, assert);
});
test('Active deployment can be promoted', async function (assert) {
this.server.create('node');
const mirageJob = makeMirageJob(this.server, { activeDeployment: true });
await this.store.findAll('job');
const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
const deployment = await job.get('latestDeployment');
this.setProperties(commonProperties(job));
await render(commonTemplate);
await click('[data-test-promote-canary]');
const requests = this.server.pretender.handledRequests;
assert.ok(
requests
.filterBy('method', 'POST')
.findBy('url', `/v1/deployment/promote/${deployment.get('id')}`),
'A promote POST request was made'
);
});
test('When promoting the active deployment fails, an error is shown', async function (assert) {
assert.expect(4);
this.server.pretender.post('/v1/deployment/promote/:id', () => [
403,
{},
'',
]);
this.server.create('node');
const mirageJob = makeMirageJob(this.server, { activeDeployment: true });
await this.store.findAll('job');
const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
this.setProperties(commonProperties(job));
await render(commonTemplate);
await click('[data-test-promote-canary]');
assert.equal(
find('[data-test-job-error-title]').textContent,
'Could Not Promote Deployment',
'Appropriate error is shown'
);
assert.ok(
find('[data-test-job-error-body]').textContent.includes('ACL'),
'The error message mentions ACLs'
);
await componentA11yAudit(this.element, assert);
await click('[data-test-job-error-close]');
assert.notOk(
find('[data-test-job-error-title]'),
'Error message is dismissable'
);
});
test('Active deployment can be failed', async function (assert) {
this.server.create('node');
const mirageJob = makeMirageJob(this.server, { activeDeployment: true });
await this.store.findAll('job');
const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
const deployment = await job.get('latestDeployment');
this.setProperties(commonProperties(job));
await render(commonTemplate);
await click('[data-test-active-deployment] [data-test-idle-button]');
await click('[data-test-active-deployment] [data-test-confirm-button]');
const requests = this.server.pretender.handledRequests;
assert.ok(
requests
.filterBy('method', 'POST')
.findBy('url', `/v1/deployment/fail/${deployment.get('id')}`),
'A fail POST request was made'
);
});
test('When failing the active deployment fails, an error is shown', async function (assert) {
assert.expect(4);
this.server.pretender.post('/v1/deployment/fail/:id', () => [403, {}, '']);
this.server.create('node');
const mirageJob = makeMirageJob(this.server, { activeDeployment: true });
await this.store.findAll('job');
const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
this.setProperties(commonProperties(job));
await render(commonTemplate);
await click('[data-test-active-deployment] [data-test-idle-button]');
await click('[data-test-active-deployment] [data-test-confirm-button]');
assert.equal(
find('[data-test-job-error-title]').textContent,
'Could Not Fail Deployment',
'Appropriate error is shown'
);
assert.ok(
find('[data-test-job-error-body]').textContent.includes('ACL'),
'The error message mentions ACLs'
);
await componentA11yAudit(this.element, assert);
await click('[data-test-job-error-close]');
assert.notOk(
find('[data-test-job-error-title]'),
'Error message is dismissable'
);
});
});