diff --git a/ui/app/templates/components/job-page/periodic.hbs b/ui/app/templates/components/job-page/periodic.hbs index 065c8c96e..6a815b332 100644 --- a/ui/app/templates/components/job-page/periodic.hbs +++ b/ui/app/templates/components/job-page/periodic.hbs @@ -10,7 +10,7 @@ {{job.name}} {{job.status}} periodic - +
diff --git a/ui/mirage/config.js b/ui/mirage/config.js index b32c70b7c..c17c7d3e5 100644 --- a/ui/mirage/config.js +++ b/ui/mirage/config.js @@ -11,6 +11,7 @@ export function findLeader(schema) { } export default function() { + const server = this; this.timing = 0; // delay for each request, automatically set to 0 during testing this.namespace = 'v1'; @@ -58,6 +59,22 @@ export default function() { return this.serialize(deployments.where({ jobId: params.id })); }); + this.post('/job/:id/periodic/force', function(schema, { params }) { + // Create the child job + const parent = schema.jobs.find(params.id); + + // Use the server instead of the schema to leverage the job factory + server.create('job', 'periodicChild', { + parentId: parent.id, + namespaceId: parent.namespaceId, + namespace: parent.namespace, + createAllocations: parent.createAllocations, + }); + + // Return bogus, since the response is normally just eval information + return new Response(200, {}, '{}'); + }); + this.get('/deployment/:id'); this.get('/job/:id/evaluations', function({ evaluations }, { params }) { diff --git a/ui/tests/integration/job-page/periodic-test.js b/ui/tests/integration/job-page/periodic-test.js new file mode 100644 index 000000000..6c6c379a5 --- /dev/null +++ b/ui/tests/integration/job-page/periodic-test.js @@ -0,0 +1,89 @@ +import { run } from '@ember/runloop'; +import { getOwner } from '@ember/application'; +import { test, moduleForComponent } from 'ember-qunit'; +import { click, find, findAll } from 'ember-native-dom-helpers'; +import wait from 'ember-test-helpers/wait'; +import hbs from 'htmlbars-inline-precompile'; +import sinon from 'sinon'; +import { clickTrigger } from 'ember-power-select/test-support/helpers'; +import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage'; + +moduleForComponent('job-page/periodic', 'Integration | Component | job-page/periodic', { + integration: true, + beforeEach() { + window.localStorage.clear(); + this.store = getOwner(this).lookup('service:store'); + this.server = startMirage(); + this.server.create('namespace'); + }, + afterEach() { + this.server.shutdown(); + window.localStorage.clear(); + }, +}); + +test('Clicking Force Launch launches a new periodic child job', function(assert) { + const childrenCount = 3; + + this.server.create('job', 'periodic', { + id: 'parent', + childrenCount, + createAllocations: false, + }); + + this.store.findAll('job'); + + return wait().then(() => { + const job = this.store.peekAll('job').findBy('plainId', 'parent'); + this.setProperties({ + job, + sortProperty: 'name', + sortDescending: true, + currentPage: 1, + gotoJob: () => {}, + }); + + this.render(hbs` + {{job-page/periodic + job=job + sortProperty=sortProperty + sortDescending=sortDescending + currentPage=currentPage + gotoJob=gotoJob}} + `); + + return wait().then(() => { + const currentJobCount = server.db.jobs.length; + + assert.equal( + findAll('[data-test-job-name]').length, + childrenCount, + 'The new periodic job launch is in the children list' + ); + + click('[data-test-force-launch]'); + + return wait().then(() => { + const id = job.get('plainId'); + const namespace = job.get('namespace.name') || 'default'; + + assert.ok( + server.pretender.handledRequests + .filterBy('method', 'POST') + .find(req => req.url === `/v1/job/${id}/periodic/force?namespace=${namespace}`), + 'POST URL was correct' + ); + + assert.ok(server.db.jobs.length, currentJobCount + 1, 'POST request was made'); + + return wait().then(() => { + assert.equal( + findAll('[data-test-job-name]').length, + childrenCount + 1, + 'The new periodic job launch is in the children list' + ); + }); + }); + }); + }); +});