diff --git a/ui/app/templates/components/job-page/parts/error.hbs b/ui/app/templates/components/job-page/parts/error.hbs
index 168e2979c..05ddeac1e 100644
--- a/ui/app/templates/components/job-page/parts/error.hbs
+++ b/ui/app/templates/components/job-page/parts/error.hbs
@@ -2,11 +2,11 @@
-
{{errorMessage.title}}
-
{{errorMessage.description}}
+
{{errorMessage.title}}
+
{{errorMessage.description}}
-
+
diff --git a/ui/app/templates/components/job-page/parts/title.hbs b/ui/app/templates/components/job-page/parts/title.hbs
index 2de3064d3..445640d76 100644
--- a/ui/app/templates/components/job-page/parts/title.hbs
+++ b/ui/app/templates/components/job-page/parts/title.hbs
@@ -4,6 +4,7 @@
{{yield}}
{{#if (not (eq job.status "dead"))}}
{{two-step-button
+ data-test-stop
idleText="Stop"
cancelText="Cancel"
confirmText="Yes, Stop"
diff --git a/ui/mirage/config.js b/ui/mirage/config.js
index 6731f341c..689716dd9 100644
--- a/ui/mirage/config.js
+++ b/ui/mirage/config.js
@@ -106,6 +106,12 @@ export default function() {
return new Response(200, {}, '{}');
});
+ this.delete('/job/:id', function(schema, { params }) {
+ const job = schema.jobs.find(params.id);
+ job.update({ status: 'dead' });
+ return new Response(204, {}, '');
+ });
+
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
index a9dd30bf7..10b961fd0 100644
--- a/ui/tests/integration/job-page/periodic-test.js
+++ b/ui/tests/integration/job-page/periodic-test.js
@@ -112,24 +112,132 @@ test('Clicking force launch without proper permissions shows an error message',
`);
return wait().then(() => {
- assert.notOk(find('[data-test-force-error-title]'), 'No error message yet');
+ assert.notOk(find('[data-test-job-error-title]'), 'No error message yet');
click('[data-test-force-launch]');
return wait().then(() => {
assert.equal(
- find('[data-test-force-error-title]').textContent,
+ find('[data-test-job-error-title]').textContent,
'Could Not Force Launch',
'Appropriate error is shown'
);
assert.ok(
- find('[data-test-force-error-body]').textContent.includes('ACL'),
+ find('[data-test-job-error-body]').textContent.includes('ACL'),
'The error message mentions ACLs'
);
- click('[data-test-force-error-close]');
+ click('[data-test-job-error-close]');
- assert.notOk(find('[data-test-force-error-title]'), 'Error message is dismissable');
+ assert.notOk(find('[data-test-job-error-title]'), 'Error message is dismissable');
+ });
+ });
+ });
+});
+
+test('Stopping a job sends a delete request for the job', function(assert) {
+ const mirageJob = this.server.create('job', 'periodic', {
+ childrenCount: 0,
+ createAllocations: false,
+ });
+
+ this.store.findAll('job');
+
+ return wait().then(() => {
+ const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
+
+ 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(() => {
+ click('[data-test-stop] [data-test-idle-button]');
+ return wait().then(() => {
+ click('[data-test-stop] [data-test-confirm-button]');
+
+ return wait().then(() => {
+ const id = job.get('plainId');
+ const namespace = job.get('namespace.name') || 'default';
+ let expectedURL = `/v1/job/${id}`;
+ if (namespace !== 'default') {
+ expectedURL += `?namespace=${namespace}`;
+ }
+
+ assert.ok(
+ server.pretender.handledRequests
+ .filterBy('method', 'DELETE')
+ .find(req => req.url === expectedURL),
+ 'DELETE URL was made correctly'
+ );
+ });
+ });
+ });
+ });
+});
+
+test('Stopping a job without proper permissions shows an error message', function(assert) {
+ server.pretender.delete('/v1/job/:id', () => [403, {}, null]);
+
+ const mirageJob = this.server.create('job', 'periodic', {
+ childrenCount: 0,
+ createAllocations: false,
+ });
+
+ this.store.findAll('job');
+
+ return wait().then(() => {
+ const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
+
+ 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(() => {
+ click('[data-test-stop] [data-test-idle-button]');
+ return wait().then(() => {
+ click('[data-test-stop] [data-test-confirm-button]');
+
+ return wait().then(() => {
+ assert.equal(
+ find('[data-test-job-error-title]').textContent,
+ 'Could Not Stop Job',
+ 'Appropriate error is shown'
+ );
+ assert.ok(
+ find('[data-test-job-error-body]').textContent.includes('ACL'),
+ 'The error message mentions ACLs'
+ );
+
+ click('[data-test-job-error-close]');
+
+ assert.notOk(find('[data-test-job-error-title]'), 'Error message is dismissable');
+ });
});
});
});