From 47bbc4d3c52d89220578f1f2afea11575ac26de2 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Thu, 24 Aug 2023 14:02:55 +0200 Subject: [PATCH 1/4] Restart ephemeral parameters --- site/e2e/helpers.ts | 73 ++++++++++++++++++++++++- site/e2e/parameters.ts | 36 +++++++++--- site/e2e/tests/restartWorkspace.spec.ts | 39 +++++++++++++ 3 files changed, 136 insertions(+), 12 deletions(-) create mode 100644 site/e2e/tests/restartWorkspace.spec.ts diff --git a/site/e2e/helpers.ts b/site/e2e/helpers.ts index 6525fa3b01f9f..a2c3de6f511fe 100644 --- a/site/e2e/helpers.ts +++ b/site/e2e/helpers.ts @@ -77,9 +77,12 @@ export const createWorkspace = async ( await page.getByTestId("form-submit").click() await expect(page).toHaveURL("/@admin/" + name) - await page.waitForSelector("[data-testid='build-status']", { - state: "visible", - }) + await page.waitForSelector( + "span[data-testid='build-status'] >> text=Running", + { + state: "visible", + }, + ) return name } @@ -213,6 +216,70 @@ export const sshIntoWorkspace = async ( }) } +export const restartWorkspace = async ( + page: Page, + workspaceName: string, + richParameters: RichParameter[] = [], + buildParameters: WorkspaceBuildParameter[] = [], +) => { + await page.goto("/@admin/" + workspaceName, { + waitUntil: "domcontentloaded", + }) + await expect(page).toHaveURL("/@admin/" + workspaceName) + + await page.getByTestId("build-parameters-button").click() + + for (const buildParameter of buildParameters) { + const richParameter = richParameters.find( + (richParam) => richParam.name === buildParameter.name, + ) + if (!richParameter) { + throw new Error( + "build parameter is expected to be present in rich parameter schema", + ) + } + + const parameterLabel = await page.waitForSelector( + "[data-testid='parameter-field-" + richParameter.name + "']", + { state: "visible" }, + ) + + if (richParameter.type === "bool") { + const parameterField = await parameterLabel.waitForSelector( + "[data-testid='parameter-field-bool'] .MuiRadio-root input[value='" + + buildParameter.value + + "']", + ) + await parameterField.check() + } else if (richParameter.options.length > 0) { + const parameterField = await parameterLabel.waitForSelector( + "[data-testid='parameter-field-options'] .MuiRadio-root input[value='" + + buildParameter.value + + "']", + ) + await parameterField.check() + } else if (richParameter.type === "list(string)") { + throw new Error("not implemented yet") // FIXME + } else { + // text or number + const parameterField = await parameterLabel.waitForSelector( + "[data-testid='parameter-field-text'] input", + ) + await parameterField.fill(buildParameter.value) + } + } + + await page.getByTestId("build-parameters-submit").click() + await page.getByTestId("confirm-button").click() + + await page.waitForSelector( + "span[data-testid='build-status'] >> text=Running", + { + state: "visible", + }, + ) +} + // startAgent runs the coder agent with the provided token. // It awaits the agent to be ready before returning. export const startAgent = async (page: Page, token: string): Promise => { diff --git a/site/e2e/parameters.ts b/site/e2e/parameters.ts index c575fdcf83162..240eeb0f8566c 100644 --- a/site/e2e/parameters.ts +++ b/site/e2e/parameters.ts @@ -28,7 +28,6 @@ export const firstParameter: RichParameter = { name: "first_parameter", displayName: "First parameter", type: "number", - options: [], description: "This is first parameter.", icon: "/emojis/1f310.png", defaultValue: "123", @@ -43,10 +42,8 @@ export const secondParameter: RichParameter = { name: "second_parameter", displayName: "Second parameter", type: "string", - options: [], description: "This is second parameter.", defaultValue: "abc", - icon: "", order: 2, } @@ -56,7 +53,6 @@ export const thirdParameter: RichParameter = { name: "third_parameter", type: "string", - options: [], description: "This is third parameter.", defaultValue: "", mutable: true, @@ -69,10 +65,8 @@ export const fourthParameter: RichParameter = { name: "fourth_parameter", type: "bool", - options: [], description: "This is fourth parameter.", defaultValue: "true", - icon: "", order: 3, } @@ -105,7 +99,6 @@ export const fifthParameter: RichParameter = { ], description: "This is fifth parameter.", defaultValue: "def", - icon: "", order: 3, } @@ -116,7 +109,6 @@ export const sixthParameter: RichParameter = { name: "sixth_parameter", displayName: "Sixth parameter", type: "number", - options: [], description: "This is sixth parameter.", icon: "/emojis/1f310.png", required: true, @@ -131,8 +123,34 @@ export const seventhParameter: RichParameter = { name: "seventh_parameter", displayName: "Seventh parameter", type: "string", - options: [], description: "This is seventh parameter.", required: true, order: 1, } + +// Build options + +export const firstBuildOption: RichParameter = { + ...emptyParameter, + + name: "first_build_option", + displayName: "First build option", + type: "string", + description: "This is first build option.", + icon: "/emojis/1f310.png", + defaultValue: "ABCDEF", + mutable: true, + ephemeral: true, +} + +export const secondBuildOption: RichParameter = { + ...emptyParameter, + + name: "second_build_option", + displayName: "Second build option", + type: "bool", + description: "This is second build option.", + defaultValue: "false", + mutable: true, + ephemeral: true, +} diff --git a/site/e2e/tests/restartWorkspace.spec.ts b/site/e2e/tests/restartWorkspace.spec.ts new file mode 100644 index 0000000000000..0c910cedf2dac --- /dev/null +++ b/site/e2e/tests/restartWorkspace.spec.ts @@ -0,0 +1,39 @@ +import { test } from "@playwright/test" +import { + createTemplate, + createWorkspace, + echoResponsesWithParameters, + restartWorkspace, + verifyParameters, +} from "../helpers" + +import { firstBuildOption, secondBuildOption } from "../parameters" +import { RichParameter } from "../provisionerGenerated" + +test("restart workspace with ephemeral parameters", async ({ page }) => { + const richParameters: RichParameter[] = [firstBuildOption, secondBuildOption] + const template = await createTemplate( + page, + echoResponsesWithParameters(richParameters), + ) + const workspaceName = await createWorkspace(page, template) + + // Verify that build options are default (not selected). + await verifyParameters(page, workspaceName, richParameters, [ + { name: firstBuildOption.name, value: firstBuildOption.defaultValue }, + { name: secondBuildOption.name, value: secondBuildOption.defaultValue }, + ]) + + // Now, restart the workspace with ephemeral parameters selected. + const buildParameters = [ + { name: firstBuildOption.name, value: "AAAAA" }, + { name: secondBuildOption.name, value: "true" }, + ] + await restartWorkspace(page, workspaceName, richParameters, buildParameters) + + // Verify that build options are default (not selected). + await verifyParameters(page, workspaceName, richParameters, [ + { name: firstBuildOption.name, value: buildParameters[0].value }, + { name: secondBuildOption.name, value: buildParameters[1].value }, + ]) +}) From 0b8d6d8c544481ba8726f36b7b3bf0f105dab9f0 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Fri, 25 Aug 2023 11:49:14 +0200 Subject: [PATCH 2/4] start workspace with ephemerals --- site/e2e/helpers.ts | 27 ++++++++++- site/e2e/tests/restartWorkspace.spec.ts | 7 +-- site/e2e/tests/startWorkspace.spec.ts | 45 +++++++++++++++++++ .../components/WorkspaceActions/Buttons.tsx | 1 + 4 files changed, 75 insertions(+), 5 deletions(-) create mode 100644 site/e2e/tests/startWorkspace.spec.ts diff --git a/site/e2e/helpers.ts b/site/e2e/helpers.ts index 4f30637f5298e..df102715f3d0c 100644 --- a/site/e2e/helpers.ts +++ b/site/e2e/helpers.ts @@ -216,11 +216,31 @@ export const sshIntoWorkspace = async ( }) } -export const restartWorkspace = async ( +export const stopWorkspace = async ( + page: Page, + workspaceName: string, +) => { + await page.goto("/@admin/" + workspaceName, { + waitUntil: "domcontentloaded", + }) + await expect(page).toHaveURL("/@admin/" + workspaceName) + + await page.getByTestId("workspace-stop-button").click() + + await page.waitForSelector( + "span[data-testid='build-status'] >> text=Stopped", + { + state: "visible", + }, + ) +} + +export const buildWorkspaceWithParameters = async ( page: Page, workspaceName: string, richParameters: RichParameter[] = [], buildParameters: WorkspaceBuildParameter[] = [], + confirm: boolean = false, ) => { await page.goto("/@admin/" + workspaceName, { waitUntil: "domcontentloaded", @@ -270,7 +290,10 @@ export const restartWorkspace = async ( } await page.getByTestId("build-parameters-submit").click() - await page.getByTestId("confirm-button").click() + + if (confirm) { + await page.getByTestId("confirm-button").click() + } await page.waitForSelector( "span[data-testid='build-status'] >> text=Running", diff --git a/site/e2e/tests/restartWorkspace.spec.ts b/site/e2e/tests/restartWorkspace.spec.ts index 0c910cedf2dac..157876f7eba52 100644 --- a/site/e2e/tests/restartWorkspace.spec.ts +++ b/site/e2e/tests/restartWorkspace.spec.ts @@ -1,9 +1,9 @@ import { test } from "@playwright/test" import { + buildWorkspaceWithParameters, createTemplate, createWorkspace, echoResponsesWithParameters, - restartWorkspace, verifyParameters, } from "../helpers" @@ -29,9 +29,10 @@ test("restart workspace with ephemeral parameters", async ({ page }) => { { name: firstBuildOption.name, value: "AAAAA" }, { name: secondBuildOption.name, value: "true" }, ] - await restartWorkspace(page, workspaceName, richParameters, buildParameters) + await buildWorkspaceWithParameters(page, workspaceName, richParameters, buildParameters, true) - // Verify that build options are default (not selected). + // FIXME: verify that build options are default (not selected). + // It is the opposite now until the site logic is corrected. await verifyParameters(page, workspaceName, richParameters, [ { name: firstBuildOption.name, value: buildParameters[0].value }, { name: secondBuildOption.name, value: buildParameters[1].value }, diff --git a/site/e2e/tests/startWorkspace.spec.ts b/site/e2e/tests/startWorkspace.spec.ts new file mode 100644 index 0000000000000..2620c1d644767 --- /dev/null +++ b/site/e2e/tests/startWorkspace.spec.ts @@ -0,0 +1,45 @@ +import { test } from "@playwright/test" +import { + buildWorkspaceWithParameters, + createTemplate, + createWorkspace, + echoResponsesWithParameters, + stopWorkspace, + verifyParameters, +} from "../helpers" + +import { firstBuildOption, secondBuildOption } from "../parameters" +import { RichParameter } from "../provisionerGenerated" + +test("start workspace with ephemeral parameters", async ({ page }) => { + const richParameters: RichParameter[] = [firstBuildOption, secondBuildOption] + const template = await createTemplate( + page, + echoResponsesWithParameters(richParameters), + ) + const workspaceName = await createWorkspace(page, template) + + // Verify that build options are default (not selected). + await verifyParameters(page, workspaceName, richParameters, [ + { name: firstBuildOption.name, value: firstBuildOption.defaultValue }, + { name: secondBuildOption.name, value: secondBuildOption.defaultValue }, + ]) + + // Stop the workspace + await stopWorkspace(page, workspaceName) + + // Now, start the workspace with ephemeral parameters selected. + const buildParameters = [ + { name: firstBuildOption.name, value: "AAAAA" }, + { name: secondBuildOption.name, value: "true" }, + ] + + await buildWorkspaceWithParameters(page, workspaceName, richParameters, buildParameters) + + // FIXME: verify that build options are default (not selected). + // It is the opposite now until the site logic is corrected. + await verifyParameters(page, workspaceName, richParameters, [ + { name: firstBuildOption.name, value: buildParameters[0].value }, + { name: secondBuildOption.name, value: buildParameters[1].value }, + ]) +}) diff --git a/site/src/components/WorkspaceActions/Buttons.tsx b/site/src/components/WorkspaceActions/Buttons.tsx index 4d62e0bb9cc32..e2a005929a5a7 100644 --- a/site/src/components/WorkspaceActions/Buttons.tsx +++ b/site/src/components/WorkspaceActions/Buttons.tsx @@ -94,6 +94,7 @@ export const StopButton: FC = ({ handleAction, loading }) => { loadingPosition="start" startIcon={} onClick={handleAction} + data-testid="workspace-stop-button" > Stop From ca7feaa6104960e3d0863405dbabff4bcffbd573 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Fri, 25 Aug 2023 11:58:48 +0200 Subject: [PATCH 3/4] refactor --- site/e2e/helpers.ts | 134 +++++++++--------------- site/e2e/tests/restartWorkspace.spec.ts | 8 +- site/e2e/tests/startWorkspace.spec.ts | 7 +- 3 files changed, 62 insertions(+), 87 deletions(-) diff --git a/site/e2e/helpers.ts b/site/e2e/helpers.ts index df102715f3d0c..8743b13730b08 100644 --- a/site/e2e/helpers.ts +++ b/site/e2e/helpers.ts @@ -34,46 +34,7 @@ export const createWorkspace = async ( const name = randomName() await page.getByLabel("name").fill(name) - for (const buildParameter of buildParameters) { - const richParameter = richParameters.find( - (richParam) => richParam.name === buildParameter.name, - ) - if (!richParameter) { - throw new Error( - "build parameter is expected to be present in rich parameter schema", - ) - } - - const parameterLabel = await page.waitForSelector( - "[data-testid='parameter-field-" + richParameter.name + "']", - { state: "visible" }, - ) - - if (richParameter.type === "bool") { - const parameterField = await parameterLabel.waitForSelector( - "[data-testid='parameter-field-bool'] .MuiRadio-root input[value='" + - buildParameter.value + - "']", - ) - await parameterField.check() - } else if (richParameter.options.length > 0) { - const parameterField = await parameterLabel.waitForSelector( - "[data-testid='parameter-field-options'] .MuiRadio-root input[value='" + - buildParameter.value + - "']", - ) - await parameterField.check() - } else if (richParameter.type === "list(string)") { - throw new Error("not implemented yet") // FIXME - } else { - // text or number - const parameterField = await parameterLabel.waitForSelector( - "[data-testid='parameter-field-text'] input", - ) - await parameterField.fill(buildParameter.value) - } - } - + await fillParameters(page, richParameters, buildParameters) await page.getByTestId("form-submit").click() await expect(page).toHaveURL("/@admin/" + name) @@ -216,10 +177,7 @@ export const sshIntoWorkspace = async ( }) } -export const stopWorkspace = async ( - page: Page, - workspaceName: string, -) => { +export const stopWorkspace = async (page: Page, workspaceName: string) => { await page.goto("/@admin/" + workspaceName, { waitUntil: "domcontentloaded", }) @@ -249,48 +207,8 @@ export const buildWorkspaceWithParameters = async ( await page.getByTestId("build-parameters-button").click() - for (const buildParameter of buildParameters) { - const richParameter = richParameters.find( - (richParam) => richParam.name === buildParameter.name, - ) - if (!richParameter) { - throw new Error( - "build parameter is expected to be present in rich parameter schema", - ) - } - - const parameterLabel = await page.waitForSelector( - "[data-testid='parameter-field-" + richParameter.name + "']", - { state: "visible" }, - ) - - if (richParameter.type === "bool") { - const parameterField = await parameterLabel.waitForSelector( - "[data-testid='parameter-field-bool'] .MuiRadio-root input[value='" + - buildParameter.value + - "']", - ) - await parameterField.check() - } else if (richParameter.options.length > 0) { - const parameterField = await parameterLabel.waitForSelector( - "[data-testid='parameter-field-options'] .MuiRadio-root input[value='" + - buildParameter.value + - "']", - ) - await parameterField.check() - } else if (richParameter.type === "list(string)") { - throw new Error("not implemented yet") // FIXME - } else { - // text or number - const parameterField = await parameterLabel.waitForSelector( - "[data-testid='parameter-field-text'] input", - ) - await parameterField.fill(buildParameter.value) - } - } - + await fillParameters(page, richParameters, buildParameters) await page.getByTestId("build-parameters-submit").click() - if (confirm) { await page.getByTestId("confirm-button").click() } @@ -651,3 +569,49 @@ export const echoResponsesWithParameters = ( ], } } + +export const fillParameters = async ( + page: Page, + richParameters: RichParameter[] = [], + buildParameters: WorkspaceBuildParameter[] = [], +) => { + for (const buildParameter of buildParameters) { + const richParameter = richParameters.find( + (richParam) => richParam.name === buildParameter.name, + ) + if (!richParameter) { + throw new Error( + "build parameter is expected to be present in rich parameter schema", + ) + } + + const parameterLabel = await page.waitForSelector( + "[data-testid='parameter-field-" + richParameter.name + "']", + { state: "visible" }, + ) + + if (richParameter.type === "bool") { + const parameterField = await parameterLabel.waitForSelector( + "[data-testid='parameter-field-bool'] .MuiRadio-root input[value='" + + buildParameter.value + + "']", + ) + await parameterField.check() + } else if (richParameter.options.length > 0) { + const parameterField = await parameterLabel.waitForSelector( + "[data-testid='parameter-field-options'] .MuiRadio-root input[value='" + + buildParameter.value + + "']", + ) + await parameterField.check() + } else if (richParameter.type === "list(string)") { + throw new Error("not implemented yet") // FIXME + } else { + // text or number + const parameterField = await parameterLabel.waitForSelector( + "[data-testid='parameter-field-text'] input", + ) + await parameterField.fill(buildParameter.value) + } + } +} diff --git a/site/e2e/tests/restartWorkspace.spec.ts b/site/e2e/tests/restartWorkspace.spec.ts index 157876f7eba52..0cae848172490 100644 --- a/site/e2e/tests/restartWorkspace.spec.ts +++ b/site/e2e/tests/restartWorkspace.spec.ts @@ -29,7 +29,13 @@ test("restart workspace with ephemeral parameters", async ({ page }) => { { name: firstBuildOption.name, value: "AAAAA" }, { name: secondBuildOption.name, value: "true" }, ] - await buildWorkspaceWithParameters(page, workspaceName, richParameters, buildParameters, true) + await buildWorkspaceWithParameters( + page, + workspaceName, + richParameters, + buildParameters, + true, + ) // FIXME: verify that build options are default (not selected). // It is the opposite now until the site logic is corrected. diff --git a/site/e2e/tests/startWorkspace.spec.ts b/site/e2e/tests/startWorkspace.spec.ts index 2620c1d644767..7c580ec1f288d 100644 --- a/site/e2e/tests/startWorkspace.spec.ts +++ b/site/e2e/tests/startWorkspace.spec.ts @@ -34,7 +34,12 @@ test("start workspace with ephemeral parameters", async ({ page }) => { { name: secondBuildOption.name, value: "true" }, ] - await buildWorkspaceWithParameters(page, workspaceName, richParameters, buildParameters) + await buildWorkspaceWithParameters( + page, + workspaceName, + richParameters, + buildParameters, + ) // FIXME: verify that build options are default (not selected). // It is the opposite now until the site logic is corrected. From 135b1e4f20baf81945a283f03c775b18008b56a1 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Fri, 25 Aug 2023 12:29:39 +0200 Subject: [PATCH 4/4] FIXMEs --- site/e2e/tests/restartWorkspace.spec.ts | 7 +++---- site/e2e/tests/startWorkspace.spec.ts | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/site/e2e/tests/restartWorkspace.spec.ts b/site/e2e/tests/restartWorkspace.spec.ts index 0cae848172490..eb5d0c99c0217 100644 --- a/site/e2e/tests/restartWorkspace.spec.ts +++ b/site/e2e/tests/restartWorkspace.spec.ts @@ -37,10 +37,9 @@ test("restart workspace with ephemeral parameters", async ({ page }) => { true, ) - // FIXME: verify that build options are default (not selected). - // It is the opposite now until the site logic is corrected. + // Verify that build options are default (not selected). await verifyParameters(page, workspaceName, richParameters, [ - { name: firstBuildOption.name, value: buildParameters[0].value }, - { name: secondBuildOption.name, value: buildParameters[1].value }, + { name: firstBuildOption.name, value: firstBuildOption.defaultValue }, + { name: secondBuildOption.name, value: secondBuildOption.defaultValue }, ]) }) diff --git a/site/e2e/tests/startWorkspace.spec.ts b/site/e2e/tests/startWorkspace.spec.ts index 7c580ec1f288d..232ac27299849 100644 --- a/site/e2e/tests/startWorkspace.spec.ts +++ b/site/e2e/tests/startWorkspace.spec.ts @@ -41,10 +41,9 @@ test("start workspace with ephemeral parameters", async ({ page }) => { buildParameters, ) - // FIXME: verify that build options are default (not selected). - // It is the opposite now until the site logic is corrected. + // Verify that build options are default (not selected). await verifyParameters(page, workspaceName, richParameters, [ - { name: firstBuildOption.name, value: buildParameters[0].value }, - { name: secondBuildOption.name, value: buildParameters[1].value }, + { name: firstBuildOption.name, value: firstBuildOption.defaultValue }, + { name: secondBuildOption.name, value: secondBuildOption.defaultValue }, ]) })