Skip to content

Commit d7a788d

Browse files
authored
test(site): e2e: restart workspace with ephemeral parameters (#9304)
1 parent aed891b commit d7a788d

File tree

5 files changed

+219
-52
lines changed

5 files changed

+219
-52
lines changed

site/e2e/helpers.ts

+97-43
Original file line numberDiff line numberDiff line change
@@ -34,52 +34,16 @@ export const createWorkspace = async (
3434
const name = randomName()
3535
await page.getByLabel("name").fill(name)
3636

37-
for (const buildParameter of buildParameters) {
38-
const richParameter = richParameters.find(
39-
(richParam) => richParam.name === buildParameter.name,
40-
)
41-
if (!richParameter) {
42-
throw new Error(
43-
"build parameter is expected to be present in rich parameter schema",
44-
)
45-
}
46-
47-
const parameterLabel = await page.waitForSelector(
48-
"[data-testid='parameter-field-" + richParameter.name + "']",
49-
{ state: "visible" },
50-
)
51-
52-
if (richParameter.type === "bool") {
53-
const parameterField = await parameterLabel.waitForSelector(
54-
"[data-testid='parameter-field-bool'] .MuiRadio-root input[value='" +
55-
buildParameter.value +
56-
"']",
57-
)
58-
await parameterField.check()
59-
} else if (richParameter.options.length > 0) {
60-
const parameterField = await parameterLabel.waitForSelector(
61-
"[data-testid='parameter-field-options'] .MuiRadio-root input[value='" +
62-
buildParameter.value +
63-
"']",
64-
)
65-
await parameterField.check()
66-
} else if (richParameter.type === "list(string)") {
67-
throw new Error("not implemented yet") // FIXME
68-
} else {
69-
// text or number
70-
const parameterField = await parameterLabel.waitForSelector(
71-
"[data-testid='parameter-field-text'] input",
72-
)
73-
await parameterField.fill(buildParameter.value)
74-
}
75-
}
76-
37+
await fillParameters(page, richParameters, buildParameters)
7738
await page.getByTestId("form-submit").click()
7839

7940
await expect(page).toHaveURL("/@admin/" + name)
80-
await page.waitForSelector("[data-testid='build-status']", {
81-
state: "visible",
82-
})
41+
await page.waitForSelector(
42+
"span[data-testid='build-status'] >> text=Running",
43+
{
44+
state: "visible",
45+
},
46+
)
8347
return name
8448
}
8549

@@ -213,6 +177,50 @@ export const sshIntoWorkspace = async (
213177
})
214178
}
215179

180+
export const stopWorkspace = async (page: Page, workspaceName: string) => {
181+
await page.goto("/@admin/" + workspaceName, {
182+
waitUntil: "domcontentloaded",
183+
})
184+
await expect(page).toHaveURL("/@admin/" + workspaceName)
185+
186+
await page.getByTestId("workspace-stop-button").click()
187+
188+
await page.waitForSelector(
189+
"span[data-testid='build-status'] >> text=Stopped",
190+
{
191+
state: "visible",
192+
},
193+
)
194+
}
195+
196+
export const buildWorkspaceWithParameters = async (
197+
page: Page,
198+
workspaceName: string,
199+
richParameters: RichParameter[] = [],
200+
buildParameters: WorkspaceBuildParameter[] = [],
201+
confirm: boolean = false,
202+
) => {
203+
await page.goto("/@admin/" + workspaceName, {
204+
waitUntil: "domcontentloaded",
205+
})
206+
await expect(page).toHaveURL("/@admin/" + workspaceName)
207+
208+
await page.getByTestId("build-parameters-button").click()
209+
210+
await fillParameters(page, richParameters, buildParameters)
211+
await page.getByTestId("build-parameters-submit").click()
212+
if (confirm) {
213+
await page.getByTestId("confirm-button").click()
214+
}
215+
216+
await page.waitForSelector(
217+
"span[data-testid='build-status'] >> text=Running",
218+
{
219+
state: "visible",
220+
},
221+
)
222+
}
223+
216224
// startAgent runs the coder agent with the provided token.
217225
// It awaits the agent to be ready before returning.
218226
export const startAgent = async (page: Page, token: string): Promise<void> => {
@@ -561,3 +569,49 @@ export const echoResponsesWithParameters = (
561569
],
562570
}
563571
}
572+
573+
export const fillParameters = async (
574+
page: Page,
575+
richParameters: RichParameter[] = [],
576+
buildParameters: WorkspaceBuildParameter[] = [],
577+
) => {
578+
for (const buildParameter of buildParameters) {
579+
const richParameter = richParameters.find(
580+
(richParam) => richParam.name === buildParameter.name,
581+
)
582+
if (!richParameter) {
583+
throw new Error(
584+
"build parameter is expected to be present in rich parameter schema",
585+
)
586+
}
587+
588+
const parameterLabel = await page.waitForSelector(
589+
"[data-testid='parameter-field-" + richParameter.name + "']",
590+
{ state: "visible" },
591+
)
592+
593+
if (richParameter.type === "bool") {
594+
const parameterField = await parameterLabel.waitForSelector(
595+
"[data-testid='parameter-field-bool'] .MuiRadio-root input[value='" +
596+
buildParameter.value +
597+
"']",
598+
)
599+
await parameterField.check()
600+
} else if (richParameter.options.length > 0) {
601+
const parameterField = await parameterLabel.waitForSelector(
602+
"[data-testid='parameter-field-options'] .MuiRadio-root input[value='" +
603+
buildParameter.value +
604+
"']",
605+
)
606+
await parameterField.check()
607+
} else if (richParameter.type === "list(string)") {
608+
throw new Error("not implemented yet") // FIXME
609+
} else {
610+
// text or number
611+
const parameterField = await parameterLabel.waitForSelector(
612+
"[data-testid='parameter-field-text'] input",
613+
)
614+
await parameterField.fill(buildParameter.value)
615+
}
616+
}
617+
}

site/e2e/parameters.ts

+27-9
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ export const firstParameter: RichParameter = {
2828
name: "first_parameter",
2929
displayName: "First parameter",
3030
type: "number",
31-
options: [],
3231
description: "This is first parameter.",
3332
icon: "/emojis/1f310.png",
3433
defaultValue: "123",
@@ -43,10 +42,8 @@ export const secondParameter: RichParameter = {
4342
name: "second_parameter",
4443
displayName: "Second parameter",
4544
type: "string",
46-
options: [],
4745
description: "This is second parameter.",
4846
defaultValue: "abc",
49-
icon: "",
5047
order: 2,
5148
}
5249

@@ -56,7 +53,6 @@ export const thirdParameter: RichParameter = {
5653

5754
name: "third_parameter",
5855
type: "string",
59-
options: [],
6056
description: "This is third parameter.",
6157
defaultValue: "",
6258
mutable: true,
@@ -69,10 +65,8 @@ export const fourthParameter: RichParameter = {
6965

7066
name: "fourth_parameter",
7167
type: "bool",
72-
options: [],
7368
description: "This is fourth parameter.",
7469
defaultValue: "true",
75-
icon: "",
7670
order: 3,
7771
}
7872

@@ -105,7 +99,6 @@ export const fifthParameter: RichParameter = {
10599
],
106100
description: "This is fifth parameter.",
107101
defaultValue: "def",
108-
icon: "",
109102
order: 3,
110103
}
111104

@@ -116,7 +109,6 @@ export const sixthParameter: RichParameter = {
116109
name: "sixth_parameter",
117110
displayName: "Sixth parameter",
118111
type: "number",
119-
options: [],
120112
description: "This is sixth parameter.",
121113
icon: "/emojis/1f310.png",
122114
required: true,
@@ -131,8 +123,34 @@ export const seventhParameter: RichParameter = {
131123
name: "seventh_parameter",
132124
displayName: "Seventh parameter",
133125
type: "string",
134-
options: [],
135126
description: "This is seventh parameter.",
136127
required: true,
137128
order: 1,
138129
}
130+
131+
// Build options
132+
133+
export const firstBuildOption: RichParameter = {
134+
...emptyParameter,
135+
136+
name: "first_build_option",
137+
displayName: "First build option",
138+
type: "string",
139+
description: "This is first build option.",
140+
icon: "/emojis/1f310.png",
141+
defaultValue: "ABCDEF",
142+
mutable: true,
143+
ephemeral: true,
144+
}
145+
146+
export const secondBuildOption: RichParameter = {
147+
...emptyParameter,
148+
149+
name: "second_build_option",
150+
displayName: "Second build option",
151+
type: "bool",
152+
description: "This is second build option.",
153+
defaultValue: "false",
154+
mutable: true,
155+
ephemeral: true,
156+
}
+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { test } from "@playwright/test"
2+
import {
3+
buildWorkspaceWithParameters,
4+
createTemplate,
5+
createWorkspace,
6+
echoResponsesWithParameters,
7+
verifyParameters,
8+
} from "../helpers"
9+
10+
import { firstBuildOption, secondBuildOption } from "../parameters"
11+
import { RichParameter } from "../provisionerGenerated"
12+
13+
test("restart workspace with ephemeral parameters", async ({ page }) => {
14+
const richParameters: RichParameter[] = [firstBuildOption, secondBuildOption]
15+
const template = await createTemplate(
16+
page,
17+
echoResponsesWithParameters(richParameters),
18+
)
19+
const workspaceName = await createWorkspace(page, template)
20+
21+
// Verify that build options are default (not selected).
22+
await verifyParameters(page, workspaceName, richParameters, [
23+
{ name: firstBuildOption.name, value: firstBuildOption.defaultValue },
24+
{ name: secondBuildOption.name, value: secondBuildOption.defaultValue },
25+
])
26+
27+
// Now, restart the workspace with ephemeral parameters selected.
28+
const buildParameters = [
29+
{ name: firstBuildOption.name, value: "AAAAA" },
30+
{ name: secondBuildOption.name, value: "true" },
31+
]
32+
await buildWorkspaceWithParameters(
33+
page,
34+
workspaceName,
35+
richParameters,
36+
buildParameters,
37+
true,
38+
)
39+
40+
// Verify that build options are default (not selected).
41+
await verifyParameters(page, workspaceName, richParameters, [
42+
{ name: firstBuildOption.name, value: firstBuildOption.defaultValue },
43+
{ name: secondBuildOption.name, value: secondBuildOption.defaultValue },
44+
])
45+
})

site/e2e/tests/startWorkspace.spec.ts

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { test } from "@playwright/test"
2+
import {
3+
buildWorkspaceWithParameters,
4+
createTemplate,
5+
createWorkspace,
6+
echoResponsesWithParameters,
7+
stopWorkspace,
8+
verifyParameters,
9+
} from "../helpers"
10+
11+
import { firstBuildOption, secondBuildOption } from "../parameters"
12+
import { RichParameter } from "../provisionerGenerated"
13+
14+
test("start workspace with ephemeral parameters", async ({ page }) => {
15+
const richParameters: RichParameter[] = [firstBuildOption, secondBuildOption]
16+
const template = await createTemplate(
17+
page,
18+
echoResponsesWithParameters(richParameters),
19+
)
20+
const workspaceName = await createWorkspace(page, template)
21+
22+
// Verify that build options are default (not selected).
23+
await verifyParameters(page, workspaceName, richParameters, [
24+
{ name: firstBuildOption.name, value: firstBuildOption.defaultValue },
25+
{ name: secondBuildOption.name, value: secondBuildOption.defaultValue },
26+
])
27+
28+
// Stop the workspace
29+
await stopWorkspace(page, workspaceName)
30+
31+
// Now, start the workspace with ephemeral parameters selected.
32+
const buildParameters = [
33+
{ name: firstBuildOption.name, value: "AAAAA" },
34+
{ name: secondBuildOption.name, value: "true" },
35+
]
36+
37+
await buildWorkspaceWithParameters(
38+
page,
39+
workspaceName,
40+
richParameters,
41+
buildParameters,
42+
)
43+
44+
// Verify that build options are default (not selected).
45+
await verifyParameters(page, workspaceName, richParameters, [
46+
{ name: firstBuildOption.name, value: firstBuildOption.defaultValue },
47+
{ name: secondBuildOption.name, value: secondBuildOption.defaultValue },
48+
])
49+
})

site/src/components/WorkspaceActions/Buttons.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ export const StopButton: FC<WorkspaceAction> = ({ handleAction, loading }) => {
9494
loadingPosition="start"
9595
startIcon={<CropSquareIcon />}
9696
onClick={handleAction}
97+
data-testid="workspace-stop-button"
9798
>
9899
Stop
99100
</LoadingButton>

0 commit comments

Comments
 (0)