Skip to content
This repository was archived by the owner on May 14, 2025. It is now read-only.

Commit 5a71163

Browse files
ghillertcppwfs
authored andcommitted
gh-632 Fix Job Executions are not showing up on Jobs tab
gh-637 Fix Job Execution Ids not shown on Task details page * Add Job Execution ids being shown as buttons * Link buttons to Job Execution details page * Add tests fixed misspell
1 parent e5ee884 commit 5a71163

File tree

4 files changed

+108
-6
lines changed

4 files changed

+108
-6
lines changed

ui/src/app/jobs/jobs.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ <h1>Batch Job Executions</h1>
2727
</tr>
2828
</thead>
2929
<tbody>
30-
<tr *ngFor="let item of jobExecutions.items | searchFilter: jobExecutions.filter | paginate: jobExecutions.getPaginationInstance(); index as i">
30+
<tr *ngFor="let item of jobExecutions.items | paginate: jobExecutions.getPaginationInstance(); index as i">
3131
<td>{{ item.name }} <app-definition-status [jobExecution]="item"></app-definition-status></td>
3232
<td><a href="javascript:void(0);" (click)="viewTaskExecutionDetails(item)">{{ item.taskExecutionId }}</a></td>
3333
<td>{{ item.jobInstanceId }}</td>
34-
<td>{{ item.taskExecutionId }}</td>
34+
<td>{{ item.jobExecutionId }}</td>
3535
<td>{{ item.startTimeFormatted }}</td>
3636
<td>{{ item.stepExecutionCount }}</td>
3737
<td><app-job-execution-status [status]="item.status"></app-job-execution-status></td>

ui/src/app/tasks/task-details/task-details.component.html

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,20 @@
3636
<td>Batch Job</td>
3737
<td>
3838
<span *ngIf="taskExecution.jobExecutionIds.length > 0" class="glyphicon glyphicon-ok text-info"></span>
39-
<span *ngIf="taskExecution.jobExecutionIds.length == 0" class="glyphicon glyphicon-remove"></span>
39+
<span *ngIf="taskExecution.jobExecutionIds.length == 0" class="glyphicon glyphicon-remove text-danger"></span>
4040
</td>
4141
</tr>
4242
<tr>
4343
<td>Job Execution Ids</td>
44-
<td></td>
44+
<td *ngIf="taskExecution.jobExecutionIds.length > 0" id="jobExecutionIds">
45+
<button class="btn btn-default" type="button" (click)="goToJobExecution(jobExecutionId)"
46+
*ngFor="let jobExecutionId of taskExecution.jobExecutionIds">
47+
{{ jobExecutionId }}
48+
</button>
49+
</td>
50+
<td *ngIf="taskExecution.jobExecutionIds.length == 0">
51+
N/A
52+
</td>
4553
</tr>
4654
<tr>
4755
<td>Start Time</td>

ui/src/app/tasks/task-details/task-details.component.spec.ts

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,18 @@ describe('TaskExecutionsDetailsComponent', () => {
3636
errorMessage: null,
3737
externalExecutionId: 'footask-d465ffe7-6874-42f7-ab04-191e9e6c6376'
3838
}};
39-
39+
const commonTestExecutionDetailsWithJobIds = { 1: {
40+
executionId: 1,
41+
exitCode: 0,
42+
taskName: 'footask',
43+
startTime: moment('2017-08-10T05:46:19.079Z'),
44+
endTime: moment('2017-08-10T05:46:19.098Z'),
45+
exitMessage: null,
46+
arguments: ['--spring.cloud.task.executionid=1'],
47+
jobExecutionIds: [1, 2, 3],
48+
errorMessage: null,
49+
externalExecutionId: 'footask-d465ffe7-6874-42f7-ab04-191e9e6c6376'
50+
}};
4051

4152
beforeEach(async(() => {
4253
activeRoute = new MockActivatedRoute();
@@ -99,7 +110,56 @@ describe('TaskExecutionsDetailsComponent', () => {
99110
expect(des[12].nativeElement.textContent).toContain('Batch Job');
100111
expect(des[13].query(By.css('span')).nativeElement.classList.contains('glyphicon-remove')).toBe(true);
101112
expect(des[14].nativeElement.textContent).toContain('Job Execution Ids');
102-
expect(des[15].nativeElement.textContent).toBe('');
113+
expect(des[15].nativeElement.textContent).toContain('N/A');
114+
expect(des[16].nativeElement.textContent).toContain('Start Time');
115+
expect(des[17].nativeElement.textContent).toContain(expectedStart);
116+
expect(des[18].nativeElement.textContent).toContain('End Time');
117+
expect(des[19].nativeElement.textContent).toContain(expectedStop);
118+
expect(des[20].nativeElement.textContent).toContain('Duration');
119+
expect(des[21].nativeElement.textContent).toContain('00:00:00.019');
120+
expect(des[22].nativeElement.textContent).toContain('Exit Code');
121+
expect(des[23].nativeElement.textContent).toContain('0');
122+
expect(des[24].nativeElement.textContent).toContain('Exit Message');
123+
expect(des[25].nativeElement.textContent).toContain('N/A');
124+
});
125+
126+
it('Execution details should get populated with Job Execution Ids', () => {
127+
activeRoute.testParams = commonTestParams;
128+
tasksService.testExecutionDetails = commonTestExecutionDetailsWithJobIds;
129+
130+
de = fixture.debugElement.query(By.css('div'));
131+
el = de.nativeElement;
132+
fixture.detectChanges();
133+
const expectedStart = moment('2017-08-10T05:46:19.079Z').format('Y-MM-DD[T]HH:mm:ss.SSS[Z]');
134+
const expectedStop = moment('2017-08-10T05:46:19.098Z').format('Y-MM-DD[T]HH:mm:ss.SSS[Z]');
135+
136+
expect(el.textContent).toContain('Task Execution Details - Execution ID: 1');
137+
138+
const des: DebugElement[] = fixture.debugElement.queryAll(By.css('tbody td'));
139+
expect(des.length).toBe(26);
140+
expect(des[0].nativeElement.textContent).toContain('Execution Id');
141+
expect(des[1].nativeElement.textContent).toContain(commonTestExecutionDetails[1].executionId);
142+
expect(des[2].nativeElement.textContent).toContain('Task Name');
143+
expect(des[3].nativeElement.textContent).toContain('footask');
144+
expect(des[4].nativeElement.textContent).toContain('Arguments');
145+
expect(des[5].nativeElement.textContent).toContain('--spring.cloud.task.executionid=1');
146+
expect(des[6].nativeElement.textContent).toContain('External Execution Id');
147+
expect(des[7].nativeElement.textContent).toContain('footask-d465ffe7-6874-42f7-ab04-191e9e6c6376');
148+
expect(des[8].nativeElement.textContent).toContain('Start Time');
149+
expect(des[9].nativeElement.textContent).toContain(expectedStart);
150+
expect(des[10].nativeElement.textContent).toContain('End Time');
151+
expect(des[11].nativeElement.textContent).toContain(expectedStop);
152+
expect(des[12].nativeElement.textContent).toContain('Batch Job');
153+
154+
expect(des[13].query(By.css('span')).nativeElement.classList.contains('glyphicon-ok')).toBe(true);
155+
expect(des[14].nativeElement.textContent).toContain('Job Execution Ids');
156+
const jobExecutionIdButtons = fixture.debugElement.queryAll(By.css('#jobExecutionIds button'));
157+
expect(jobExecutionIdButtons.length).toEqual(3);
158+
159+
expect(jobExecutionIdButtons[0].nativeElement.innerHTML.trim()).toEqual('1');
160+
expect(jobExecutionIdButtons[1].nativeElement.innerHTML.trim()).toEqual('2');
161+
expect(jobExecutionIdButtons[2].nativeElement.innerHTML.trim()).toEqual('3');
162+
103163
expect(des[16].nativeElement.textContent).toContain('Start Time');
104164
expect(des[17].nativeElement.textContent).toContain(expectedStart);
105165
expect(des[18].nativeElement.textContent).toContain('End Time');
@@ -123,4 +183,28 @@ describe('TaskExecutionsDetailsComponent', () => {
123183
el.click();
124184
expect(navigate).toHaveBeenCalledWith(['tasks/executions']);
125185
});
186+
187+
it('Job Execution Id button should navigate to job execution details page on click', () => {
188+
activeRoute.testParams = commonTestParams;
189+
tasksService.testExecutionDetails = commonTestExecutionDetailsWithJobIds;
190+
191+
de = fixture.debugElement.query(By.css('div'));
192+
el = de.nativeElement;
193+
fixture.detectChanges();
194+
195+
const jobExecutionIdButtons = fixture.debugElement.queryAll(By.css('#jobExecutionIds button'));
196+
197+
const navigate = spyOn((<any>component).router, 'navigate');
198+
fixture.detectChanges();
199+
200+
jobExecutionIdButtons[0].nativeElement.click();
201+
expect(navigate).toHaveBeenCalledWith(['jobs/executions/1']);
202+
203+
jobExecutionIdButtons[1].nativeElement.click();
204+
expect(navigate).toHaveBeenCalledWith(['jobs/executions/1']);
205+
206+
jobExecutionIdButtons[2].nativeElement.click();
207+
expect(navigate).toHaveBeenCalledWith(['jobs/executions/1']);
208+
});
209+
126210
});

ui/src/app/tasks/task-details/task-details.component.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,14 @@ export class TaskExecutionsDetailsComponent implements OnInit, OnDestroy {
5656
back() {
5757
this.router.navigate(['tasks/executions']);
5858
}
59+
60+
/**
61+
* Redirect user to the page for the provided Job Execution Id.
62+
*
63+
* @param jobExecutionId Id of the Job Execution
64+
*/
65+
goToJobExecution(jobExecutionId: number) {
66+
this.router.navigate(['jobs/executions/' + jobExecutionId]);
67+
}
68+
5969
}

0 commit comments

Comments
 (0)