+
{{#list-table source=sortedEvaluations as |t|}}
{{#t.head}}
ID |
diff --git a/ui/mirage/factories/job.js b/ui/mirage/factories/job.js
index 296b634c5..b18d16d71 100644
--- a/ui/mirage/factories/job.js
+++ b/ui/mirage/factories/job.js
@@ -44,6 +44,9 @@ export default Factory.extend({
// When true, an evaluation with a high modify index and placement failures is created
failedPlacements: false,
+ // When true, no evaluations have failed placements
+ noFailedPlacements: false,
+
afterCreate(job, server) {
const groups = server.createList('task-group', job.groupsCount, {
job,
@@ -89,7 +92,9 @@ export default Factory.extend({
});
server.createList('evaluation', faker.random.number({ min: 1, max: 5 }), { job });
- server.createList('evaluation', faker.random.number(3), 'withPlacementFailures', { job });
+ if (!job.noFailedPlacements) {
+ server.createList('evaluation', faker.random.number(3), 'withPlacementFailures', { job });
+ }
if (job.failedPlacements) {
server.create('evaluation', 'withPlacementFailures', {
diff --git a/ui/tests/acceptance/job-detail-test.js b/ui/tests/acceptance/job-detail-test.js
index 512c572e4..cf3b1bcc5 100644
--- a/ui/tests/acceptance/job-detail-test.js
+++ b/ui/tests/acceptance/job-detail-test.js
@@ -296,6 +296,83 @@ test('the active deployment section can be expanded to show task groups and allo
});
});
+test('the evaluations table lists evaluations sorted by modify index', function(assert) {
+ job = server.create('job');
+ const evaluations = server.db.evaluations
+ .where({ jobId: job.id })
+ .sortBy('modifyIndex')
+ .reverse();
+
+ visit(`/jobs/${job.id}`);
+
+ andThen(() => {
+ assert.equal(
+ findAll('.evaluations tbody tr').length,
+ evaluations.length,
+ 'A row for each evaluation'
+ );
+
+ evaluations.forEach((evaluation, index) => {
+ const row = $(findAll('.evaluations tbody tr')[index]);
+ assert.equal(
+ row.find('td:eq(0)').text(),
+ evaluation.id.split('-')[0],
+ `Short ID, row ${index}`
+ );
+ });
+
+ const firstEvaluation = evaluations[0];
+ const row = $(findAll('.evaluations tbody tr')[0]);
+ assert.equal(row.find('td:eq(1)').text(), '' + firstEvaluation.priority, 'Priority');
+ assert.equal(row.find('td:eq(2)').text(), firstEvaluation.triggeredBy, 'Triggered By');
+ assert.equal(row.find('td:eq(3)').text(), firstEvaluation.status, 'Status');
+ });
+});
+
+test('when the job has placement failures, they are called out', function(assert) {
+ job = server.create('job', { failedPlacements: true });
+ const failedEvaluation = server.db.evaluations
+ .where({ jobId: job.id })
+ .filter(evaluation => evaluation.failedTGAllocs)
+ .sortBy('modifyIndex')
+ .reverse()[0];
+
+ const failedTaskGroupNames = Object.keys(failedEvaluation.failedTGAllocs);
+
+ visit(`/jobs/${job.id}`);
+
+ andThen(() => {
+ assert.ok(find('.placement-failures'), 'Placement failures section found');
+
+ const taskGroupLabels = findAll('.placement-failures h3.title').map(title =>
+ title.textContent.trim()
+ );
+ failedTaskGroupNames.forEach(name => {
+ assert.ok(
+ taskGroupLabels.find(label => label.includes(name)),
+ `${name} included in placement failures list`
+ );
+ assert.ok(
+ taskGroupLabels.find(label =>
+ label.includes(failedEvaluation.failedTGAllocs[name].CoalescedFailures + 1)
+ ),
+ 'The number of unplaced allocs = CoalescedFailures + 1'
+ );
+ });
+ });
+});
+
+test('when the job has no placement failures, the placement failures section is gone', function(
+ assert
+) {
+ job = server.create('job', { noFailedPlacements: true });
+ visit(`/jobs/${job.id}`);
+
+ andThen(() => {
+ assert.notOk(find('.placement-failures'), 'Placement failures section not found');
+ });
+});
+
test('when the job is not found, an error message is shown, but the URL persists', function(
assert
) {