Skip to content

feat(site): do not show popover on update deadline #11921

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Resolve PR suggestions
  • Loading branch information
BrunoQuaresma committed Jan 30, 2024
commit f7ac8a53c4387ea7df8e88a59699af2a5c5820dd
129 changes: 48 additions & 81 deletions site/src/pages/WorkspacePage/WorkspaceScheduleControls.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,9 @@ const Wrapper = () => {
return <WorkspaceScheduleControls workspace={workspace} canUpdateSchedule />;
};

test("add 3 hours to deadline", async () => {
const user = userEvent.setup();
const baseDeadline = dayjs().add(3, "hour");
const updateDeadlineSpy = jest
.spyOn(API, "putWorkspaceExtension")
.mockResolvedValue();
const BASE_DEADLINE = dayjs().add(3, "hour");

const renderScheduleControls = async () => {
server.use(
rest.get(
"/api/v2/users/:username/workspace/:workspaceName",
Expand All @@ -40,7 +37,7 @@ test("add 3 hours to deadline", async () => {
...MockWorkspace,
latest_build: {
...MockWorkspace.latest_build,
deadline: baseDeadline.toISOString(),
deadline: BASE_DEADLINE.toISOString(),
},
}),
);
Expand All @@ -58,18 +55,26 @@ test("add 3 hours to deadline", async () => {
</ThemeProvider>,
);
await screen.findByTestId("schedule-controls");

// Check if base deadline is displayed correctly
expect(screen.getByText("Stop in 3 hours")).toBeInTheDocument();
};

test("add 3 hours to deadline", async () => {
const user = userEvent.setup();
const updateDeadlineSpy = jest
.spyOn(API, "putWorkspaceExtension")
.mockResolvedValue();

const addButton = screen.getByLabelText("Add hour");
await renderScheduleControls();

const addButton = screen.getByRole("button", {
name: /add 1 hour to deadline/i,
});
await user.click(addButton);
await user.click(addButton);
await user.click(addButton);
await screen.findByText(
"Workspace shutdown time has been successfully updated.",
);
expect(updateDeadlineSpy).toHaveBeenCalledTimes(1);
expect(screen.getByText("Stop in 6 hours")).toBeInTheDocument();

// Mocks are used here because the 'usedDeadline' is a dayjs object, which
Expand All @@ -78,55 +83,26 @@ test("add 3 hours to deadline", async () => {
const usedDeadline = updateDeadlineSpy.mock.calls[0][1];
expect(usedWorkspaceId).toEqual(MockWorkspace.id);
expect(usedDeadline.toISOString()).toEqual(
baseDeadline.add(3, "hour").toISOString(),
BASE_DEADLINE.add(3, "hour").toISOString(),
);
});

test("remove 3 hours to deadline", async () => {
const user = userEvent.setup();
const baseDeadline = dayjs().add(3, "hour");
const updateDeadlineSpy = jest
.spyOn(API, "putWorkspaceExtension")
.mockResolvedValue();
server.use(
rest.get(
"/api/v2/users/:username/workspace/:workspaceName",
(req, res, ctx) => {
return res(
ctx.status(200),
ctx.json({
...MockWorkspace,
latest_build: {
...MockWorkspace.latest_build,
deadline: baseDeadline.toISOString(),
},
}),
);
},
),
);
render(
<ThemeProvider>
<QueryClientProvider client={new QueryClient()}>
<RouterProvider
router={createMemoryRouter([{ path: "/", element: <Wrapper /> }])}
/>
</QueryClientProvider>
<GlobalSnackbar />
</ThemeProvider>,
);
await screen.findByTestId("schedule-controls");

// Check if base deadline is displayed correctly
expect(screen.getByText("Stop in 3 hours")).toBeInTheDocument();
await renderScheduleControls();

const subButton = screen.getByLabelText("Subtract hour");
const subButton = screen.getByRole("button", {
name: /subtract 1 hour from deadline/i,
});
await user.click(subButton);
await user.click(subButton);
await screen.findByText(
"Workspace shutdown time has been successfully updated.",
);
expect(updateDeadlineSpy).toHaveBeenCalledTimes(1);
expect(screen.getByText("Stop in an hour")).toBeInTheDocument();

// Mocks are used here because the 'usedDeadline' is a dayjs object, which
Expand All @@ -135,55 +111,46 @@ test("remove 3 hours to deadline", async () => {
const usedDeadline = updateDeadlineSpy.mock.calls[0][1];
expect(usedWorkspaceId).toEqual(MockWorkspace.id);
expect(usedDeadline.toISOString()).toEqual(
baseDeadline.subtract(2, "hour").toISOString(),
BASE_DEADLINE.subtract(2, "hour").toISOString(),
);
});

test("rollback to previous deadline on error", async () => {
const user = userEvent.setup();
const baseDeadline = dayjs().add(3, "hour");
const initialScheduleMessage = "Stop in 3 hours";
jest.spyOn(API, "putWorkspaceExtension").mockRejectedValue({});

await renderScheduleControls();

const addButton = screen.getByRole("button", {
name: /add 1 hour to deadline/i,
});
await user.click(addButton);
await user.click(addButton);
await user.click(addButton);
await screen.findByText(
"We couldn't update your workspace shutdown time. Please try again.",
);
// In case of an error, the schedule message should remain unchanged
expect(screen.getByText(initialScheduleMessage)).toBeInTheDocument();
});

test("request is only sent once when clicking multiple times", async () => {
const user = userEvent.setup();
const updateDeadlineSpy = jest
.spyOn(API, "putWorkspaceExtension")
.mockRejectedValue({});
server.use(
rest.get(
"/api/v2/users/:username/workspace/:workspaceName",
(req, res, ctx) => {
return res(
ctx.status(200),
ctx.json({
...MockWorkspace,
latest_build: {
...MockWorkspace.latest_build,
deadline: baseDeadline.toISOString(),
},
}),
);
},
),
);
render(
<ThemeProvider>
<QueryClientProvider client={new QueryClient()}>
<RouterProvider
router={createMemoryRouter([{ path: "/", element: <Wrapper /> }])}
/>
</QueryClientProvider>
<GlobalSnackbar />
</ThemeProvider>,
);
await screen.findByTestId("schedule-controls");
.mockResolvedValue();

// Check if base deadline is displayed correctly
expect(screen.getByText("Stop in 3 hours")).toBeInTheDocument();
await renderScheduleControls();

const addButton = screen.getByLabelText("Add hour");
const addButton = screen.getByRole("button", {
name: /add 1 hour to deadline/i,
});
await user.click(addButton);
await user.click(addButton);
await user.click(addButton);
await screen.findByText(
"We couldn't update your workspace shutdown time. Please try again.",
"Workspace shutdown time has been successfully updated.",
);
expect(updateDeadlineSpy).toHaveBeenCalledTimes(1);
expect(screen.getByText("Stop in 3 hours")).toBeInTheDocument();
});
8 changes: 4 additions & 4 deletions site/src/pages/WorkspacePage/WorkspaceScheduleControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
import { useMutation, useQueryClient } from "react-query";
import { Dayjs } from "dayjs";
import { visuallyHidden } from "@mui/utils";

export interface WorkspaceScheduleControlsProps {
workspace: Workspace;
Expand Down Expand Up @@ -100,21 +101,19 @@ export const WorkspaceScheduleControls: FC<WorkspaceScheduleControlsProps> = ({
<div css={styles.scheduleControls}>
<Tooltip title="Subtract 1 hour from deadline">
<IconButton
aria-label="Subtract hour"
disabled={!deadlineMinusEnabled}
size="small"
title=""
css={styles.scheduleButton}
onClick={() => {
handleDeadlineChange(deadline.subtract(1, "h"));
}}
>
<RemoveIcon />
<span style={visuallyHidden}>Subtract 1 hour</span>
</IconButton>
</Tooltip>
<Tooltip title="Add 1 to deadline">
<Tooltip title="Add 1 hour to deadline">
<IconButton
aria-label="Add hour"
disabled={!deadlinePlusEnabled}
size="small"
css={styles.scheduleButton}
Expand All @@ -123,6 +122,7 @@ export const WorkspaceScheduleControls: FC<WorkspaceScheduleControlsProps> = ({
}}
>
<AddIcon />
<span style={visuallyHidden}>Add 1 hour</span>
</IconButton>
</Tooltip>
</div>
Expand Down