Skip to content

Commit e17ca38

Browse files
committed
Fix test for schedule
1 parent d3081e8 commit e17ca38

File tree

4 files changed

+93
-98
lines changed

4 files changed

+93
-98
lines changed

site/src/pages/TemplateSettingsPage/TemplateSchedulePage/TemplateSchedulePage.test.tsx

Lines changed: 31 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -3,111 +3,71 @@ import userEvent from "@testing-library/user-event"
33
import * as API from "api/api"
44
import { UpdateTemplateMeta } from "api/typesGenerated"
55
import { Language as FooterFormLanguage } from "components/FormFooter/FormFooter"
6-
import { MockTemplate } from "../../../testHelpers/entities"
7-
import { renderWithAuth } from "../../../testHelpers/renderHelpers"
6+
import {
7+
MockEntitlementsWithScheduling,
8+
MockTemplate,
9+
} from "../../../testHelpers/entities"
10+
import {
11+
renderWithTemplateSettingsLayout,
12+
waitForLoaderToBeRemoved,
13+
} from "../../../testHelpers/renderHelpers"
814
import { getValidationSchema } from "./TemplateScheduleForm"
915
import TemplateSchedulePage from "./TemplateSchedulePage"
1016
import i18next from "i18next"
1117

1218
const { t } = i18next
1319

1420
const validFormValues = {
15-
name: "Name",
16-
display_name: "A display name",
17-
description: "A description",
18-
icon: "vscode.png",
19-
// these are the form values which are actually hours
2021
default_ttl_ms: 1,
2122
max_ttl_ms: 2,
22-
allow_user_cancel_workspace_jobs: false,
2323
}
2424

2525
const renderTemplateSchedulePage = async () => {
26-
renderWithAuth(<TemplateSchedulePage />, {
27-
route: `/templates/${MockTemplate.name}/settings`,
28-
path: `/templates/:template/settings`,
29-
extraRoutes: [{ path: "templates/:template", element: <></> }],
26+
renderWithTemplateSettingsLayout(<TemplateSchedulePage />, {
27+
route: `/templates/${MockTemplate.name}/settings/schedule`,
28+
path: `/templates/:template/settings/schedule`,
3029
})
31-
// Wait the form to be rendered
32-
const label = t("nameLabel", { ns: "TemplateSchedulePage" })
33-
await screen.findAllByLabelText(label)
30+
await waitForLoaderToBeRemoved()
3431
}
3532

3633
const fillAndSubmitForm = async ({
37-
name,
38-
display_name,
39-
description,
4034
default_ttl_ms,
4135
max_ttl_ms,
42-
icon,
43-
allow_user_cancel_workspace_jobs,
44-
}: Required<UpdateTemplateMeta>) => {
45-
const label = t("nameLabel", { ns: "TemplateSchedulePage" })
46-
const nameField = await screen.findByLabelText(label)
47-
await userEvent.clear(nameField)
48-
await userEvent.type(nameField, name)
49-
50-
const displayNameLabel = t("displayNameLabel", { ns: "TemplateSchedulePage" })
51-
52-
const displayNameField = await screen.findByLabelText(displayNameLabel)
53-
await userEvent.clear(displayNameField)
54-
await userEvent.type(displayNameField, display_name)
55-
56-
const descriptionLabel = t("descriptionLabel", { ns: "TemplateSchedulePage" })
57-
const descriptionField = await screen.findByLabelText(descriptionLabel)
58-
await userEvent.clear(descriptionField)
59-
await userEvent.type(descriptionField, description)
60-
61-
const iconLabel = t("iconLabel", { ns: "TemplateSchedulePage" })
62-
const iconField = await screen.findByLabelText(iconLabel)
63-
await userEvent.clear(iconField)
64-
await userEvent.type(iconField, icon)
65-
66-
const defaultTtlLabel = t("defaultTtlLabel", { ns: "TemplateSchedulePage" })
36+
}: {
37+
default_ttl_ms: number
38+
max_ttl_ms: number
39+
}) => {
40+
const user = userEvent.setup()
41+
const defaultTtlLabel = t("defaultTtlLabel", { ns: "templateSettingsPage" })
6742
const defaultTtlField = await screen.findByLabelText(defaultTtlLabel)
68-
await userEvent.clear(defaultTtlField)
69-
await userEvent.type(defaultTtlField, default_ttl_ms.toString())
70-
71-
const entitlements = await API.getEntitlements()
72-
if (entitlements.features["advanced_template_scheduling"].enabled) {
73-
const maxTtlLabel = t("maxTtlLabel", { ns: "TemplateSchedulePage" })
74-
const maxTtlField = await screen.findByLabelText(maxTtlLabel)
75-
await userEvent.clear(maxTtlField)
76-
await userEvent.type(maxTtlField, max_ttl_ms.toString())
77-
}
43+
await user.clear(defaultTtlField)
44+
await user.type(defaultTtlField, default_ttl_ms.toString())
7845

79-
const allowCancelJobsField = screen.getByRole("checkbox")
80-
// checkbox is checked by default, so it must be clicked to get unchecked
81-
if (!allow_user_cancel_workspace_jobs) {
82-
await userEvent.click(allowCancelJobsField)
83-
}
46+
const maxTtlLabel = t("maxTtlLabel", { ns: "templateSettingsPage" })
47+
const maxTtlField = await screen.findByLabelText(maxTtlLabel)
48+
await user.clear(maxTtlField)
49+
await user.type(maxTtlField, max_ttl_ms.toString())
8450

8551
const submitButton = await screen.findByText(
8652
FooterFormLanguage.defaultSubmitLabel,
8753
)
88-
await userEvent.click(submitButton)
54+
await user.click(submitButton)
8955
}
9056

9157
describe("TemplateSchedulePage", () => {
92-
it("renders", async () => {
93-
const { t } = i18next
94-
const pageTitle = t("title", {
95-
ns: "TemplateSchedulePage",
96-
})
97-
await renderTemplateSchedulePage()
98-
const element = await screen.findByText(pageTitle)
99-
expect(element).toBeDefined()
58+
beforeEach(() => {
59+
jest
60+
.spyOn(API, "getEntitlements")
61+
.mockResolvedValue(MockEntitlementsWithScheduling)
10062
})
10163

10264
it("succeeds", async () => {
10365
await renderTemplateSchedulePage()
104-
10566
jest.spyOn(API, "updateTemplateMeta").mockResolvedValueOnce({
10667
...MockTemplate,
10768
...validFormValues,
10869
})
10970
await fillAndSubmitForm(validFormValues)
110-
11171
await waitFor(() => expect(API.updateTemplateMeta).toBeCalledTimes(1))
11272
})
11373

@@ -125,11 +85,8 @@ describe("TemplateSchedulePage", () => {
12585
expect(API.updateTemplateMeta).toBeCalledWith(
12686
"test-template",
12787
expect.objectContaining({
128-
...validFormValues,
129-
// convert from the display value (hours) to ms
13088
default_ttl_ms: validFormValues.default_ttl_ms * 3600000,
131-
// this value is undefined if not entitled
132-
max_ttl_ms: undefined,
89+
max_ttl_ms: validFormValues.max_ttl_ms * 3600000,
13390
}),
13491
),
13592
)
@@ -160,29 +117,7 @@ describe("TemplateSchedulePage", () => {
160117
}
161118
const validate = () => getValidationSchema().validateSync(values)
162119
expect(validate).toThrowError(
163-
t("defaultTTLMaxError", { ns: "TemplateSchedulePage" }),
164-
)
165-
})
166-
167-
it("allows a description of 128 chars", () => {
168-
const values: UpdateTemplateMeta = {
169-
...validFormValues,
170-
description:
171-
"Nam quis nulla. Integer malesuada. In in enim a arcu imperdiet malesuada. Sed vel lectus. Donec odio urna, tempus molestie, port",
172-
}
173-
const validate = () => getValidationSchema().validateSync(values)
174-
expect(validate).not.toThrowError()
175-
})
176-
177-
it("disallows a description of 128 + 1 chars", () => {
178-
const values: UpdateTemplateMeta = {
179-
...validFormValues,
180-
description:
181-
"Nam quis nulla. Integer malesuada. In in enim a arcu imperdiet malesuada. Sed vel lectus. Donec odio urna, tempus molestie, port a",
182-
}
183-
const validate = () => getValidationSchema().validateSync(values)
184-
expect(validate).toThrowError(
185-
t("descriptionMaxError", { ns: "TemplateSchedulePage" }),
120+
t("defaultTTLMaxError", { ns: "templateSettingsPage" }),
186121
)
187122
})
188123
})

site/src/testHelpers/entities.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,9 +657,10 @@ export const MockWorkspace: TypesGen.Workspace = {
657657
owner_id: MockUser.id,
658658
owner_name: MockUser.username,
659659
autostart_schedule: MockWorkspaceAutostartEnabled.schedule,
660-
ttl_ms: 2 * 60 * 60 * 1000, // 2 hours as milliseconds
660+
ttl_ms: 2 * 60 * 60 * 1000,
661661
latest_build: MockWorkspaceBuild,
662662
last_used_at: "",
663+
organization_id: MockOrganization.id,
663664
}
664665

665666
export const MockStoppedWorkspace: TypesGen.Workspace = {
@@ -1270,6 +1271,20 @@ export const MockEntitlementsWithAuditLog: TypesGen.Entitlements = {
12701271
}),
12711272
}
12721273

1274+
export const MockEntitlementsWithScheduling: TypesGen.Entitlements = {
1275+
errors: [],
1276+
warnings: [],
1277+
has_license: true,
1278+
require_telemetry: false,
1279+
trial: false,
1280+
features: withDefaultFeatures({
1281+
advanced_template_scheduling: {
1282+
enabled: true,
1283+
entitlement: "entitled",
1284+
},
1285+
}),
1286+
}
1287+
12731288
export const MockExperiments: TypesGen.Experiment[] = []
12741289

12751290
export const MockAuditLog: TypesGen.AuditLog = {

site/src/testHelpers/renderHelpers.tsx

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { AppProviders } from "app"
88
import { DashboardLayout } from "components/Dashboard/DashboardLayout"
99
import { createMemoryHistory } from "history"
1010
import { i18n } from "i18n"
11+
import { TemplateSettingsLayout } from "pages/TemplateSettingsPage/TemplateSettingsLayout"
1112
import { FC, ReactElement } from "react"
1213
import { I18nextProvider } from "react-i18next"
1314
import {
@@ -86,6 +87,50 @@ export function renderWithAuth(
8687
}
8788
}
8889

90+
export function renderWithTemplateSettingsLayout(
91+
element: JSX.Element,
92+
{
93+
path = "/",
94+
route = "/",
95+
extraRoutes = [],
96+
nonAuthenticatedRoutes = [],
97+
}: RenderWithAuthOptions = {},
98+
) {
99+
const routes: RouteObject[] = [
100+
{
101+
element: <RequireAuth />,
102+
children: [
103+
{
104+
element: <DashboardLayout />,
105+
children: [
106+
{
107+
element: <TemplateSettingsLayout />,
108+
children: [{ path, element }, ...extraRoutes],
109+
},
110+
],
111+
},
112+
],
113+
},
114+
...nonAuthenticatedRoutes,
115+
]
116+
117+
const router = createMemoryRouter(routes, { initialEntries: [route] })
118+
119+
const renderResult = wrappedRender(
120+
<I18nextProvider i18n={i18n}>
121+
<AppProviders>
122+
<RouterProvider router={router} />
123+
</AppProviders>
124+
</I18nextProvider>,
125+
)
126+
127+
return {
128+
user: MockUser,
129+
router,
130+
...renderResult,
131+
}
132+
}
133+
89134
export const waitForLoaderToBeRemoved = (): Promise<void> =>
90135
waitForElementToBeRemoved(() => screen.getByTestId("loader"))
91136

site/src/xServices/entitlements/entitlementsXService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export const entitlementsMachine = createMachine(
5858
}),
5959
},
6060
services: {
61-
getEntitlements: API.getEntitlements,
61+
getEntitlements: () => API.getEntitlements(),
6262
},
6363
},
6464
)

0 commit comments

Comments
 (0)