-
Notifications
You must be signed in to change notification settings - Fork 881
fix: ui: workspace bumpers now honour template max_ttl #3532
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
Changes from all commits
5eb9317
c57fed2
7bdf392
35e5146
0c24962
28220d5
c68b931
494213f
9c8d4d5
ca8b95f
4aa6eaf
ff50a83
b8ada49
f9832b1
e69ff7f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,11 +27,13 @@ import { WorkspacePage } from "./WorkspacePage" | |
|
||
// It renders the workspace page and waits for it be loaded | ||
const renderWorkspacePage = async () => { | ||
const getTemplateMock = jest.spyOn(api, "getTemplate").mockResolvedValueOnce(MockTemplate) | ||
renderWithAuth(<WorkspacePage />, { | ||
route: `/@${MockWorkspace.owner_name}/${MockWorkspace.name}`, | ||
path: "/@:username/:workspace", | ||
}) | ||
await screen.findByText(MockWorkspace.name) | ||
expect(getTemplateMock).toBeCalled() | ||
} | ||
|
||
/** | ||
|
@@ -50,10 +52,10 @@ const testButton = async (label: string, actionMock: jest.SpyInstance) => { | |
expect(actionMock).toBeCalled() | ||
} | ||
|
||
const testStatus = async (mock: Workspace, label: string) => { | ||
const testStatus = async (ws: Workspace, label: string) => { | ||
server.use( | ||
rest.get(`/api/v2/users/:username/workspace/:workspaceName`, (req, res, ctx) => { | ||
return res(ctx.status(200), ctx.json(mock)) | ||
return res(ctx.status(200), ctx.json(ws)) | ||
}), | ||
) | ||
await renderWorkspacePage() | ||
|
@@ -181,6 +183,7 @@ describe("Workspace Page", () => { | |
|
||
describe("Resources", () => { | ||
it("shows the status of each agent in each resource", async () => { | ||
const getTemplateMock = jest.spyOn(api, "getTemplate").mockResolvedValueOnce(MockTemplate) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's generally better to test things that are apparent to the user than internals like whether a function was called, but sometimes it's necessary. Is this one of the cases where testing user-apparent effects is too hard? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure -- I'll try seeing if I can make some assertions about child components here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, it seems like testing properties of child components is considered somewhat of an anti-pattern. I'll factor some more stuff out to a util file and test it separately. |
||
renderWithAuth(<WorkspacePage />, { | ||
route: `/@${MockWorkspace.owner_name}/${MockWorkspace.name}`, | ||
path: "/@:username/:workspace", | ||
|
@@ -197,6 +200,7 @@ describe("Workspace Page", () => { | |
DisplayAgentStatusLanguage[MockWorkspaceAgentDisconnected.status], | ||
) | ||
expect(agent2Status.length).toEqual(2) | ||
expect(getTemplateMock).toBeCalled() | ||
}) | ||
}) | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,7 @@ import { FullScreenLoader } from "../../components/Loader/FullScreenLoader" | |
import { Workspace, WorkspaceErrors } from "../../components/Workspace/Workspace" | ||
import { firstOrItem } from "../../util/array" | ||
import { pageTitle } from "../../util/page" | ||
import { canExtendDeadline, canReduceDeadline, maxDeadline, minDeadline } from "../../util/schedule" | ||
import { getFaviconByStatus } from "../../util/workspace" | ||
import { selectUser } from "../../xServices/auth/authSelectors" | ||
import { XServiceContext } from "../../xServices/StateContext" | ||
|
@@ -35,6 +36,8 @@ export const WorkspacePage: React.FC = () => { | |
const { | ||
workspace, | ||
getWorkspaceError, | ||
template, | ||
refreshTemplateError, | ||
resources, | ||
getResourcesError, | ||
builds, | ||
|
@@ -63,12 +66,16 @@ export const WorkspacePage: React.FC = () => { | |
return ( | ||
<div className={styles.error}> | ||
{getWorkspaceError && <ErrorSummary error={getWorkspaceError} />} | ||
{refreshTemplateError && <ErrorSummary error={refreshTemplateError} />} | ||
{checkPermissionsError && <ErrorSummary error={checkPermissionsError} />} | ||
</div> | ||
) | ||
} else if (!workspace) { | ||
return <FullScreenLoader /> | ||
} else if (!template) { | ||
return <FullScreenLoader /> | ||
} else { | ||
const deadline = dayjs(workspace.latest_build.deadline).utc() | ||
const favicon = getFaviconByStatus(workspace.latest_build) | ||
return ( | ||
<> | ||
|
@@ -85,7 +92,7 @@ export const WorkspacePage: React.FC = () => { | |
bannerSend({ | ||
type: "UPDATE_DEADLINE", | ||
workspaceId: workspace.id, | ||
newDeadline: dayjs(workspace.latest_build.deadline).utc().add(4, "hours"), | ||
newDeadline: dayjs.min(deadline.add(4, "hours"), maxDeadline(workspace, template)), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You don't have to change this here, but I'm wondering if we want to try to push logic like this into XState. Instead of one There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I was wondering that but didn't want to over-complicate the machine. :-) |
||
}) | ||
}, | ||
}} | ||
|
@@ -94,22 +101,22 @@ export const WorkspacePage: React.FC = () => { | |
bannerSend({ | ||
type: "UPDATE_DEADLINE", | ||
workspaceId: workspace.id, | ||
newDeadline: boundedDeadline( | ||
dayjs(workspace.latest_build.deadline).utc().add(-1, "hours"), | ||
dayjs(), | ||
), | ||
newDeadline: dayjs.max(deadline.add(-1, "hours"), minDeadline()), | ||
}) | ||
}, | ||
onDeadlinePlus: () => { | ||
bannerSend({ | ||
type: "UPDATE_DEADLINE", | ||
workspaceId: workspace.id, | ||
newDeadline: boundedDeadline( | ||
dayjs(workspace.latest_build.deadline).utc().add(1, "hours"), | ||
dayjs(), | ||
), | ||
newDeadline: dayjs.min(deadline.add(1, "hours"), maxDeadline(workspace, template)), | ||
}) | ||
}, | ||
deadlineMinusEnabled: () => { | ||
return canReduceDeadline(deadline) | ||
}, | ||
deadlinePlusEnabled: () => { | ||
return canExtendDeadline(deadline, workspace, template) | ||
}, | ||
}} | ||
workspace={workspace} | ||
handleStart={() => workspaceSend("START")} | ||
|
@@ -139,12 +146,6 @@ export const WorkspacePage: React.FC = () => { | |
} | ||
} | ||
|
||
export const boundedDeadline = (newDeadline: dayjs.Dayjs, now: dayjs.Dayjs): dayjs.Dayjs => { | ||
const minDeadline = now.add(30, "minutes") | ||
const maxDeadline = now.add(24, "hours") | ||
return dayjs.min(dayjs.max(minDeadline, newDeadline), maxDeadline) | ||
} | ||
|
||
const useStyles = makeStyles((theme) => ({ | ||
error: { | ||
margin: theme.spacing(2), | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
review: moved to
util/workspace.ts
EDIT: actually moved to
util/schedule.ts
which is a more sensible place for it