diff --git a/ui/app/templates/components/job-page/parts/recent-allocations.hbs b/ui/app/templates/components/job-page/parts/recent-allocations.hbs index b9c9edb90..4a0c22965 100644 --- a/ui/app/templates/components/job-page/parts/recent-allocations.hbs +++ b/ui/app/templates/components/job-page/parts/recent-allocations.hbs @@ -30,15 +30,15 @@ {{/t.body}} {{/list-table}} {{else}} -
-

No Allocations

-

No allocations have been placed.

+
+

No Allocations

+

No allocations have been placed.

{{/if}}
{{#if job.allocations.length}}
-

{{#link-to "jobs.job.allocations" job}} +

{{#link-to "jobs.job.allocations" job}} View all {{job.allocations.length}} {{pluralize "allocation" job.allocations.length}} {{/link-to}}

diff --git a/ui/tests/integration/job-page/service-test.js b/ui/tests/integration/job-page/service-test.js index 5b9bf69f3..aef698a14 100644 --- a/ui/tests/integration/job-page/service-test.js +++ b/ui/tests/integration/job-page/service-test.js @@ -1,19 +1,23 @@ import { getOwner } from '@ember/application'; +import { assign } from '@ember/polyfills'; import { test, moduleForComponent } from 'ember-qunit'; import wait from 'ember-test-helpers/wait'; import hbs from 'htmlbars-inline-precompile'; import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage'; import { stopJob, expectStopError, expectDeleteRequest } from './helpers'; +import Job from 'nomad-ui/tests/pages/jobs/detail'; moduleForComponent('job-page/service', 'Integration | Component | job-page/service', { integration: true, beforeEach() { + Job.setContext(this); window.localStorage.clear(); this.store = getOwner(this).lookup('service:store'); this.server = startMirage(); this.server.create('namespace'); }, afterEach() { + Job.removeContext(); this.server.shutdown(); window.localStorage.clear(); }, @@ -36,12 +40,18 @@ const commonProperties = job => ({ gotoJob() {}, }); -const makeMirageJob = server => - server.create('job', { - type: 'service', - createAllocations: false, - status: 'running', - }); +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', function(assert) { let job; @@ -80,3 +90,78 @@ test('Stopping a job without proper permissions shows an error message', functio .then(stopJob) .then(expectStopError(assert)); }); + +test('Recent allocations shows allocations in the job context', function(assert) { + let job; + + this.server.create('node'); + const mirageJob = makeMirageJob(this.server, { createAllocations: true }); + this.store.findAll('job'); + + return wait() + .then(() => { + job = this.store.peekAll('job').findBy('plainId', mirageJob.id); + + this.setProperties(commonProperties(job)); + this.render(commonTemplate); + + return wait(); + }) + .then(() => { + 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'); + }); +}); + +test('Recent allocations caps out at five', function(assert) { + let job; + + this.server.create('node'); + const mirageJob = makeMirageJob(this.server); + this.server.createList('allocation', 10); + + this.store.findAll('job'); + + return wait().then(() => { + job = this.store.peekAll('job').findBy('plainId', mirageJob.id); + + this.setProperties(commonProperties(job)); + this.render(commonTemplate); + + return wait().then(() => { + 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', function(assert) { + let job; + + this.server.create('node'); + const mirageJob = makeMirageJob(this.server); + + this.store.findAll('job'); + + return wait() + .then(() => { + job = this.store.peekAll('job').findBy('plainId', mirageJob.id); + + this.setProperties(commonProperties(job)); + this.render(commonTemplate); + + return wait(); + }) + .then(() => { + assert.ok( + Job.recentAllocationsEmptyState.headline.includes('No Allocations'), + 'No allocations empty message' + ); + }); +}); diff --git a/ui/tests/pages/jobs/detail.js b/ui/tests/pages/jobs/detail.js index 2208a8003..0f5d21bdc 100644 --- a/ui/tests/pages/jobs/detail.js +++ b/ui/tests/pages/jobs/detail.js @@ -8,6 +8,8 @@ import { visitable, } from 'ember-cli-page-object'; +import allocations from 'nomad-ui/tests/pages/components/allocations'; + export default create({ visit: visitable('/jobs/:id'), @@ -29,10 +31,18 @@ export default create({ return this.stats.toArray().findBy('id', id); }, + ...allocations(), + + viewAllAllocations: text('[data-test-view-all-allocations]'), + error: { isPresent: isPresent('[data-test-error]'), title: text('[data-test-error-title]'), message: text('[data-test-error-message]'), seekHelp: clickable('[data-test-error-message] a'), }, + + recentAllocationsEmptyState: { + headline: text('[data-test-empty-recent-allocations-headline]'), + }, });