Skip to content

Commit bec7ec3

Browse files
authored
[TSPS-704] Uses outputExpirationDate for Deletion Date in Job History page (#5451)
1 parent fdd1b62 commit bec7ec3

File tree

4 files changed

+70
-18
lines changed

4 files changed

+70
-18
lines changed

src/libs/ajax/teaspoons/teaspoons-models.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ export interface PipelineRun {
6666
timeSubmitted: string;
6767
timeCompleted?: string;
6868
quotaConsumed?: number;
69+
outputExpirationDate?: string;
6970
}
7071

7172
export interface GetPipelineRunsResponse {

src/pages/scientificServices/pipelines/utils/mock-utils.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,5 +98,7 @@ export function mockPipelineRun(status: PipelineRunStatus): PipelineRun {
9898
timeSubmitted: '2023-10-01T00:00:00Z',
9999
timeCompleted: status === 'SUCCEEDED' || status === 'FAILED' ? new Date().toISOString() : undefined,
100100
quotaConsumed: status === 'SUCCEEDED' ? 500 : undefined,
101+
outputExpirationDate:
102+
status === 'SUCCEEDED' ? new Date(Date.now() + 14 * 24 * 60 * 60 * 1000).toISOString() : undefined, // job outputs expire in 14 days
101103
};
102104
}

src/pages/scientificServices/pipelines/views/JobHistory.test.tsx

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { screen, waitFor } from '@testing-library/react';
1+
import { formatDatetime } from '@terra-ui-packages/core-utils';
2+
import { screen, waitFor, within } from '@testing-library/react';
23
import userEvent from '@testing-library/user-event';
34
import React from 'react';
45
import { Teaspoons, TeaspoonsContract } from 'src/libs/ajax/teaspoons/Teaspoons';
@@ -174,6 +175,7 @@ describe('job history table', () => {
174175
...mockPipelineRun('SUCCEEDED'),
175176
timeSubmitted: fifteenDaysAgo,
176177
timeCompleted: fifteenDaysAgo,
178+
outputExpirationDate: new Date(Date.now()).toISOString(),
177179
};
178180
const pipelineRuns = [pipelineRun];
179181

@@ -195,9 +197,21 @@ describe('job history table', () => {
195197
expect(screen.getAllByText(pipelineRun.jobId)).toHaveLength(2);
196198
});
197199

198-
const viewOutputsButton = screen.getByText('View Outputs');
200+
const table = screen.getByRole('table');
201+
const rows = within(table).getAllByRole('row');
202+
const dataRow = within(rows[1]).getAllByRole('cell');
203+
204+
const viewOutputsButton = within(dataRow[7]).getByText('View Outputs');
199205
expect(viewOutputsButton).toBeInTheDocument();
200206
expect(viewOutputsButton).toBeDisabled();
207+
208+
const user = userEvent.setup();
209+
await user.hover(viewOutputsButton);
210+
211+
const tooltip = await within(dataRow[7]).findByText(
212+
'The outputs for this job have been deleted. Outputs are available for 14 days after job completion.'
213+
);
214+
expect(tooltip).toBeInTheDocument();
201215
});
202216

203217
it('shows View Error button for FAILED jobs', async () => {
@@ -462,6 +476,41 @@ describe('job history table', () => {
462476
const pipelineRun = {
463477
...mockPipelineRun('SUCCEEDED'),
464478
timeCompleted: '2023-10-15T14:00:00Z',
479+
outputExpirationDate: '2023-10-29T14:00:00Z',
480+
};
481+
const pipelineRuns = [pipelineRun];
482+
483+
const mockPipelineRunResponse = {
484+
pageToken: null,
485+
results: pipelineRuns,
486+
totalResults: 1,
487+
};
488+
489+
asMockedFn(Teaspoons).mockReturnValue(
490+
partial<TeaspoonsContract>({
491+
getAllPipelineRuns: jest.fn().mockReturnValue(mockPipelineRunResponse),
492+
})
493+
);
494+
495+
render(<JobHistory />);
496+
497+
await waitFor(() => {
498+
expect(screen.getAllByText(pipelineRun.jobId)).toHaveLength(2);
499+
});
500+
501+
const table = screen.getByRole('table');
502+
const rows = within(table).getAllByRole('row');
503+
const cells = within(rows[1]).getAllByRole('cell');
504+
expect(cells[5]).toHaveTextContent('Oct 29, 2023');
505+
});
506+
507+
it('displays the deletion date in red for job outputs expiring within 3 days', async () => {
508+
const twoDaysFromNow = new Date(Date.now() + 2 * 24 * 60 * 60 * 1000).toISOString();
509+
const twelveDaysAgo = new Date(Date.now() - 12 * 24 * 60 * 60 * 1000).toISOString();
510+
const pipelineRun = {
511+
...mockPipelineRun('SUCCEEDED'),
512+
timeCompleted: twelveDaysAgo,
513+
outputExpirationDate: twoDaysFromNow,
465514
};
466515
const pipelineRuns = [pipelineRun];
467516

@@ -483,7 +532,15 @@ describe('job history table', () => {
483532
expect(screen.getAllByText(pipelineRun.jobId)).toHaveLength(2);
484533
});
485534

486-
expect(screen.getByText('Oct 15, 2023')).toBeInTheDocument();
535+
const table = screen.getByRole('table');
536+
const rows = within(table).getAllByRole('row');
537+
const cells = within(rows[1]).getAllByRole('cell');
538+
expect(cells[5]).toHaveTextContent(formatDatetime(twoDaysFromNow));
539+
540+
// assert the date text is in red
541+
const deletionDateDiv = within(cells[5]).getByText(formatDatetime(twoDaysFromNow)).parentElement!;
542+
const style = window.getComputedStyle(deletionDateDiv);
543+
expect(style.color).toBe('rgb(219, 50, 20)');
487544
});
488545
});
489546
});

src/pages/scientificServices/pipelines/views/JobHistory.tsx

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -284,13 +284,11 @@ const CompletedCell = ({ pipelineRun }: CellProps): ReactNode => {
284284
};
285285

286286
const DataDeletionDateCell = ({ pipelineRun }: CellProps): ReactNode => {
287-
if (!pipelineRun.timeCompleted || !(pipelineRun.status === 'SUCCEEDED')) {
287+
if (!pipelineRun.outputExpirationDate || !(pipelineRun.status === 'SUCCEEDED')) {
288288
return <div>N/A</div>;
289289
}
290290

291-
const completionDate = new Date(pipelineRun?.timeCompleted);
292-
const deletionDate = new Date(completionDate);
293-
deletionDate.setDate(deletionDate.getDate() + TEASPOONS_FILE_OUTPUT_TTL_DAYS);
291+
const deletionDate = new Date(pipelineRun?.outputExpirationDate);
294292

295293
const today = new Date();
296294
const threeDaysFromNow = new Date();
@@ -339,9 +337,12 @@ const ActionCell = ({ pipelineRun }: CellProps): ReactNode => {
339337
return <ViewErrorModal pipelineRun={pipelineRun} onDismiss={errorModal.close} />;
340338
});
341339

342-
const jobOutputsDeleted =
340+
// `!!` converts the expression to a boolean
341+
const jobOutputsDeleted = !!(
343342
pipelineRun.status === 'SUCCEEDED' &&
344-
(hoursElapsedSinceCompletion(pipelineRun) ?? -1) > 24 * TEASPOONS_FILE_OUTPUT_TTL_DAYS; // 24 hours * 14 days
343+
pipelineRun.outputExpirationDate &&
344+
new Date() >= new Date(pipelineRun.outputExpirationDate)
345+
);
345346

346347
return (
347348
<div>
@@ -505,12 +506,3 @@ const hoursElapsedSinceSubmission = (pipelineRun: PipelineRun): number => {
505506
const currentTime = new Date();
506507
return (currentTime.getTime() - submittedTime.getTime()) / (1000 * 60 * 60);
507508
};
508-
509-
const hoursElapsedSinceCompletion = (pipelineRun: PipelineRun): number | undefined => {
510-
if (!pipelineRun.timeCompleted) {
511-
return undefined;
512-
}
513-
const completedTime = new Date(pipelineRun.timeCompleted);
514-
const currentTime = new Date();
515-
return (currentTime.getTime() - completedTime.getTime()) / (1000 * 60 * 60);
516-
};

0 commit comments

Comments
 (0)