From 497b024e0ff6fa46f5c554591cd9098f64bd1e5b Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Wed, 19 Apr 2023 11:37:02 +0200 Subject: [PATCH 01/19] Form is populated --- site/e2e/pom/CreateTemplatePage.ts | 33 +++++++++++++++++++ site/e2e/pom/TemplatesPage.ts | 26 +++++++++++++++ site/e2e/tests/basicScenario.spec.ts | 25 ++++++++++++++ site/e2e/tests/listTemplates.spec.ts | 9 ----- site/src/components/FormFooter/FormFooter.tsx | 3 ++ .../CreateTemplatePage/CreateTemplateForm.tsx | 6 +++- .../pages/TemplatesPage/TemplatesPageView.tsx | 7 +++- 7 files changed, 98 insertions(+), 11 deletions(-) create mode 100644 site/e2e/pom/CreateTemplatePage.ts create mode 100644 site/e2e/pom/TemplatesPage.ts create mode 100644 site/e2e/tests/basicScenario.spec.ts delete mode 100644 site/e2e/tests/listTemplates.spec.ts diff --git a/site/e2e/pom/CreateTemplatePage.ts b/site/e2e/pom/CreateTemplatePage.ts new file mode 100644 index 0000000000000..c29cadebdadfc --- /dev/null +++ b/site/e2e/pom/CreateTemplatePage.ts @@ -0,0 +1,33 @@ +import { expect, Locator, Page } from "@playwright/test" +import { BasePom } from "./BasePom" + +export class CreateTemplatePage extends BasePom { + readonly createTemplateForm: Locator + readonly createTemplateButton: Locator + + constructor(baseURL: string | undefined, page: Page) { + super(baseURL, `/templates`, page) + + this.createTemplateForm = page.getByTestId("form-create-template") + this.createTemplateButton = page.getByTestId("button-create-template") + } + + async loaded() { + await expect(this.page).toHaveTitle("Create Template - Coder") + + await this.createTemplateForm.waitFor({ state: "visible" }) + await this.createTemplateButton.waitFor({ state: "visible" }) + } + + async fillIn() { + await this.createTemplateForm.getByLabel("Name *").fill("my-first-template") + await this.createTemplateForm + .getByLabel("Display name") + .fill("My First Template") + await this.createTemplateForm + .getByLabel("Description") + .fill("This is my first template.") + + await this.createTemplateButton.click() + } +} diff --git a/site/e2e/pom/TemplatesPage.ts b/site/e2e/pom/TemplatesPage.ts new file mode 100644 index 0000000000000..04a763306a0ae --- /dev/null +++ b/site/e2e/pom/TemplatesPage.ts @@ -0,0 +1,26 @@ +import { expect, Locator, Page } from "@playwright/test" +import { BasePom } from "./BasePom" + +export class TemplatesPage extends BasePom { + readonly addTemplateButton: Locator + + constructor(baseURL: string | undefined, page: Page) { + super(baseURL, `/templates`, page) + + this.addTemplateButton = page.getByTestId("button-add-template") + } + + async goto() { + await this.page.goto(this.url, { waitUntil: "networkidle" }) + } + + async loaded() { + await expect(this.page).toHaveTitle("Templates - Coder") + + await this.addTemplateButton.waitFor({ state: "visible" }) + } + + async addTemplate() { + await this.addTemplateButton.click() + } +} diff --git a/site/e2e/tests/basicScenario.spec.ts b/site/e2e/tests/basicScenario.spec.ts new file mode 100644 index 0000000000000..9494591dd9a6b --- /dev/null +++ b/site/e2e/tests/basicScenario.spec.ts @@ -0,0 +1,25 @@ +import { test } from "@playwright/test" +import { getStatePath } from "../helpers" +import { TemplatesPage } from "../pom/TemplatesPage" +import { CreateTemplatePage } from "../pom/CreateTemplatePage" + +test.use({ storageState: getStatePath("authState") }) + +test("Basic scenario", async ({ page, baseURL }) => { + const templatesPage = new TemplatesPage(baseURL, page) + const createTemplatePage = new CreateTemplatePage(baseURL, page) + + await test.step("Load empty templates page", async () => { + await templatesPage.goto() + await templatesPage.loaded() + }) + + await test.step("Upload a template", async () => { + await templatesPage.addTemplate() + await createTemplatePage.loaded() + + await createTemplatePage.fillIn() + + await page.waitForTimeout(5 * 60 * 1000) // FIXME + }) +}) diff --git a/site/e2e/tests/listTemplates.spec.ts b/site/e2e/tests/listTemplates.spec.ts deleted file mode 100644 index 4d3569bfb47f3..0000000000000 --- a/site/e2e/tests/listTemplates.spec.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { test, expect } from "@playwright/test" -import { getStatePath } from "../helpers" - -test.use({ storageState: getStatePath("authState") }) - -test("list templates", async ({ page, baseURL }) => { - await page.goto(`${baseURL}/templates`, { waitUntil: "networkidle" }) - await expect(page).toHaveTitle("Templates - Coder") -}) diff --git a/site/src/components/FormFooter/FormFooter.tsx b/site/src/components/FormFooter/FormFooter.tsx index 804f3ef791546..2939faaec8977 100644 --- a/site/src/components/FormFooter/FormFooter.tsx +++ b/site/src/components/FormFooter/FormFooter.tsx @@ -16,6 +16,7 @@ export interface FormFooterProps { styles?: FormFooterStyles submitLabel?: string submitDisabled?: boolean + submitTestId?: string } export const FormFooter: FC = ({ @@ -23,6 +24,7 @@ export const FormFooter: FC = ({ isLoading, submitDisabled, submitLabel = Language.defaultSubmitLabel, + submitTestId, styles = defaultStyles(), }) => { return ( @@ -35,6 +37,7 @@ export const FormFooter: FC = ({ color="primary" type="submit" disabled={submitDisabled} + data-testid={submitTestId} > {submitLabel} diff --git a/site/src/pages/CreateTemplatePage/CreateTemplateForm.tsx b/site/src/pages/CreateTemplatePage/CreateTemplateForm.tsx index da6dcea1c2533..5c7de16d88cff 100644 --- a/site/src/pages/CreateTemplatePage/CreateTemplateForm.tsx +++ b/site/src/pages/CreateTemplatePage/CreateTemplateForm.tsx @@ -225,7 +225,10 @@ export const CreateTemplateForm: FC = ({ const { t: commonT } = useTranslation("common") return ( - + {/* General info */} = ({ onCancel={onCancel} isLoading={isSubmitting} submitLabel={jobError ? "Retry" : "Create template"} + submitTestId="button-create-template" /> ) diff --git a/site/src/pages/TemplatesPage/TemplatesPageView.tsx b/site/src/pages/TemplatesPage/TemplatesPageView.tsx index de63ab467ce6e..a22691ea89569 100644 --- a/site/src/pages/TemplatesPage/TemplatesPageView.tsx +++ b/site/src/pages/TemplatesPage/TemplatesPageView.tsx @@ -158,7 +158,12 @@ export const TemplatesPageView: FC< > Starter templates - From 41e7cbb3c31d8e15e4ceed2ff797e099eb794b62 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Wed, 19 Apr 2023 13:00:59 +0200 Subject: [PATCH 02/19] Template upload --- site/e2e/pom/CreateTemplatePage.ts | 3 +++ site/e2e/testdata/docker.tar | Bin 0 -> 10240 bytes site/e2e/tests/logout.spec.ts | 17 ----------------- .../CreateTemplatePage/TemplateUpload.tsx | 1 + 4 files changed, 4 insertions(+), 17 deletions(-) create mode 100644 site/e2e/testdata/docker.tar delete mode 100644 site/e2e/tests/logout.spec.ts diff --git a/site/e2e/pom/CreateTemplatePage.ts b/site/e2e/pom/CreateTemplatePage.ts index c29cadebdadfc..7daad5b9ba3db 100644 --- a/site/e2e/pom/CreateTemplatePage.ts +++ b/site/e2e/pom/CreateTemplatePage.ts @@ -27,6 +27,9 @@ export class CreateTemplatePage extends BasePom { await this.createTemplateForm .getByLabel("Description") .fill("This is my first template.") + await this.createTemplateForm + .getByTestId("form-template-upload") + .setInputFiles("./e2e/testdata/docker.tar") await this.createTemplateButton.click() } diff --git a/site/e2e/testdata/docker.tar b/site/e2e/testdata/docker.tar new file mode 100644 index 0000000000000000000000000000000000000000..54d015ced3107070a4591c360c968fb024dc093b GIT binary patch literal 10240 zcmeHMZByGw66WjaSM-`x4z?o61`Jo!vbS7dlhg)C8MxF{k}|S1wzNnZ-DqUu&63}K zPtQogfRhbd$%n18i&)l7Pj^qhcV}?8e{gi@WzovF`*iWy-r8E>=gxNDJi8nA9ZS9K z?d_G`*5=lBx4*Tq(Oc>Edi{;f73zLFmToXtr4AI)N~Yzn;__zw?k|9i$9EV1`tPpm zI(d+ZT{;j`k;;OSoDO7oDU=h5GE_;S6PfSQpvvh=s>`wnLQ#^;DX8HnmZheuO!5gS zF-c0TW|U;XM3jyWCgm=@No5$MPbe~Y-#JOh7=3>DcFimDiNm}&t2LD4oJpDpO{^a+ zq9>%l!9^$|p-79YNCOQ%l04BD9=(o5PKACxF7L{VHoU-dqSMPi)fAO&WF5IQa`u9hDiD_Koqhp9wC8INS3 zB07IT63o+u(J`CCZf|pQbLXO#;Cn6d$jWd|8IE%*gyHwir4rR|S3<$!YGZh}7HeIU zyT0F;lc$AJ!C0!yOQa7KO%s?w>EA!QPG=1$tJ1)+MHv|dtYzHK2_jq**BBd%VD82u z&=sV?x1T{|^z@dY?K+N2r>D>Tv!}0W12txk)j?zOK?Rh#PC`QlJO8SZG-3snc=@+X z!2@No$~C_~Mc|Pc!3A^xu`4PI5n}yFD&aV<1qEp-=}M%b#4!d_$*3}B`knLj;?9V9 z^uHdyMVL(7@7uV)ApY|<$N%mAPIqIwYvTXrW`BkHi;#Wowg2<@Z}oo@%D%RE86PY7 zGx@*U@9*5vKLW`1GXH-IUEIa_^Wfx&su6-xJ5(j!$0gpPs%x*u`6ie)NS7eWrli;zfP~Z&?rHOh(k*+Un9` zIEN`Vgq_zXgI^9_49I5&8&qF0aNkwrpM1}dd_4Va3)|28f3Mr!=)?cFdOI84&3;|~ zcbESECpG%8V{KtY9~?qC_}?l~A{sWOQ)!k7^#_;Td-WSpT{U8*W43(r-2n>zpdKu_ z(!%b?AF1o@cwM`7Z2)Y^zZl#7if%E|O|R?qZjfF(*N$T+$#2}6 z1O{_!UmhJxG?F?FOdmQU&8Q%UP(&g}t7qCVGz{ZpQYqW=G_4(a#E-s*d~LVCGnoGa zj=~^^^Jh2;#OTvZyGY5H+5LOO*vDWAd^dP4^I4ErxYmrMvI78vFp`?P;?kqF5?vl# zrbK5~uVv9XfFPmP|DU}$8}6TA#GGZ;!GfFmVG`9MvO&#s`ku+- zNd(cBX*Dqb^=;;{U^_}mj8105Iy&AWf^9D8+7B+mK8i;CPIK@76P+_M!d_F|n0>E_ zx<)oU-I>Q^$34uAS57Cay|Nlbk{P$0wm~TllxR+Z1rw+{>|e16QXPk}2ruhQbi?ka zd9|m0v-XnY@U3ZpOYTu0C<*os>BqPZR<^NnMKphyjydK^OmZJ}bQ+9A%5$Y=b_eX2LKLJ`0HMk;Jh=e1b}(eg*i(F4 z(Bv0(P-A{Jjau14tl;-n>bi+qZN_B@*I1hBVi8K1`2(;5y1r+9!-c%I++RqIgw}-EjNlBD398NZP?V@) z83#Qq@MG;)ndEDo&J%jW5+AeWo7^PyS`p~jLr+(w;t6%^AmsbbI_+8rK0RK4x6bKm zaZKR5nAshK(`vv*>X65L;Nep#%+y9h0|oR(!VGQZ<3samBYLfvRXQ(WZ>S%HT3hFk z5KJZVz=1iy&I&=888#2*TfR(eGRE_z8Z)u>8d1!W`V{+&Zrw!rReFw*uR+fx4d$ot z1KW&e2t{n}5W7k+1WsqWrW#Z~Wiz*x*Y3whkO0q(YaTyG6Ocv}hKiLIP2hoCHPt>? zkFL)LFWCuu8|Xc_RlrH)PBklF53HCsoic`1blec%N+2bMV(orH#s4nUlXk$~WWnEo z_w8G+TmS3%jEe8zS*ARbX7V8ItiLmqr);$RVaiWW4p6J?KRY}=8=jr~a(KM==)*nI zT3(9$y2HmAaqSc4C#Skav;YcQDhw3^;nuQY7h`X+iKdCVt(gqj6Tn&LGuga3Z0iO? zqPA9x)SJtT9&6Gt!#&4P<|q)&=ce&sZk8EId952fJR^NsqGMG&I0rmzgs_BON?<90 Vr397|SV~|ifu#hN68H;A;D1@#JNp0t literal 0 HcmV?d00001 diff --git a/site/e2e/tests/logout.spec.ts b/site/e2e/tests/logout.spec.ts deleted file mode 100644 index 5f8f4c892afeb..0000000000000 --- a/site/e2e/tests/logout.spec.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { test, expect } from "@playwright/test" -import { getStatePath } from "../helpers" - -test.use({ storageState: getStatePath("authState") }) - -test("signing out redirects to login page", async ({ page, baseURL }) => { - await page.goto(`${baseURL}/`, { waitUntil: "networkidle" }) - - await page.getByTestId("user-dropdown-trigger").click() - await page.getByRole("menuitem", { name: "Sign Out" }).click() - - await expect( - page.getByRole("heading", { name: "Sign in to Coder" }), - ).toBeVisible() - - expect(page.url()).toMatch(/\/login$/) // ensure we're on the login page with no query params -}) diff --git a/site/src/pages/CreateTemplatePage/TemplateUpload.tsx b/site/src/pages/CreateTemplatePage/TemplateUpload.tsx index 4212bb057881f..3fc659d1cac6b 100644 --- a/site/src/pages/CreateTemplatePage/TemplateUpload.tsx +++ b/site/src/pages/CreateTemplatePage/TemplateUpload.tsx @@ -127,6 +127,7 @@ export const TemplateUpload: FC = ({ ref={inputRef} className={styles.input} accept=".tar" + data-testid="form-template-upload" onChange={(event) => { const file = event.currentTarget.files?.[0] if (file) { From 65a0eeca555fee18329a0f6769bed33088744e6a Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Wed, 19 Apr 2023 18:07:07 +0200 Subject: [PATCH 03/19] More cases --- site/e2e/pom/CreateTemplatePage.ts | 20 +++++++------- site/e2e/pom/CreateWorkspacePage.ts | 27 +++++++++++++++++++ site/e2e/pom/TemplatePage.ts | 22 +++++++++++++++ site/e2e/pom/TemplatesPage.ts | 4 +-- site/e2e/pom/WorkspacePage.ts | 22 +++++++++++++++ site/e2e/pom/index.ts | 2 -- site/e2e/tests/basicScenario.spec.ts | 23 +++++++++++++++- .../TemplateLayout/TemplatePageHeader.tsx | 1 + .../WorkspaceStatusBadge.tsx | 3 ++- .../CreateWorkspacePageView.tsx | 3 ++- .../TemplateSummaryPageView.tsx | 2 +- 11 files changed, 110 insertions(+), 19 deletions(-) create mode 100644 site/e2e/pom/CreateWorkspacePage.ts create mode 100644 site/e2e/pom/TemplatePage.ts create mode 100644 site/e2e/pom/WorkspacePage.ts delete mode 100644 site/e2e/pom/index.ts diff --git a/site/e2e/pom/CreateTemplatePage.ts b/site/e2e/pom/CreateTemplatePage.ts index 7daad5b9ba3db..e7163fab3cdc9 100644 --- a/site/e2e/pom/CreateTemplatePage.ts +++ b/site/e2e/pom/CreateTemplatePage.ts @@ -3,34 +3,32 @@ import { BasePom } from "./BasePom" export class CreateTemplatePage extends BasePom { readonly createTemplateForm: Locator - readonly createTemplateButton: Locator + readonly submitButton: Locator constructor(baseURL: string | undefined, page: Page) { super(baseURL, `/templates`, page) this.createTemplateForm = page.getByTestId("form-create-template") - this.createTemplateButton = page.getByTestId("button-create-template") + this.submitButton = page.getByTestId("button-create-template") } async loaded() { await expect(this.page).toHaveTitle("Create Template - Coder") await this.createTemplateForm.waitFor({ state: "visible" }) - await this.createTemplateButton.waitFor({ state: "visible" }) + await this.submitButton.waitFor({ state: "visible" }) } - async fillIn() { - await this.createTemplateForm.getByLabel("Name *").fill("my-first-template") + async submitForm() { await this.createTemplateForm - .getByLabel("Display name") - .fill("My First Template") + .getByTestId("form-template-upload") + .setInputFiles("./e2e/testdata/docker.tar") + await this.createTemplateForm.getByLabel("Name *").fill("my-first-template") + await this.createTemplateForm.getByLabel("Display name").fill("My First Template") await this.createTemplateForm .getByLabel("Description") .fill("This is my first template.") - await this.createTemplateForm - .getByTestId("form-template-upload") - .setInputFiles("./e2e/testdata/docker.tar") - await this.createTemplateButton.click() + await this.submitButton.click() } } diff --git a/site/e2e/pom/CreateWorkspacePage.ts b/site/e2e/pom/CreateWorkspacePage.ts new file mode 100644 index 0000000000000..b838e48932b87 --- /dev/null +++ b/site/e2e/pom/CreateWorkspacePage.ts @@ -0,0 +1,27 @@ +import { expect, Locator, Page } from "@playwright/test" +import { BasePom } from "./BasePom" + +export class CreateWorkspacePage extends BasePom { + readonly createWorkspaceForm: Locator + readonly submitButton: Locator + + constructor(baseURL: string | undefined, page: Page) { + super(baseURL, `/templates/docker/workspace`, page) + + this.createWorkspaceForm = page.getByTestId("form-create-workspace") + this.submitButton = page.getByTestId("button-create-workspace") + } + + async loaded() { + await expect(this.page).toHaveTitle("Create Workspace - Coder") + + await this.createWorkspaceForm.waitFor({ state: "visible" }) + await this.submitButton.waitFor({ state: "visible" }) + } + + async submitForm() { + await this.createWorkspaceForm.getByLabel("Workspace Name").fill("my-first-workspace") + + await this.submitButton.click() + } +} diff --git a/site/e2e/pom/TemplatePage.ts b/site/e2e/pom/TemplatePage.ts new file mode 100644 index 0000000000000..dfd7628a2bf39 --- /dev/null +++ b/site/e2e/pom/TemplatePage.ts @@ -0,0 +1,22 @@ +import { expect, Locator, Page } from "@playwright/test" +import { BasePom } from "./BasePom" + +export class TemplatePage extends BasePom { + readonly createWorkspaceButton: Locator + + constructor(baseURL: string | undefined, page: Page) { + super(baseURL, `/templates/docker`, page) + + this.createWorkspaceButton = page.getByTestId("button-create-workspace") + } + + async loaded() { + await this.createWorkspaceButton.waitFor({ state: "visible" }) + + await expect(this.page).toHaveTitle("My First Template ยท Template - Coder") + } + + async createWorkspace() { + await this.createWorkspaceButton.click() + } +} diff --git a/site/e2e/pom/TemplatesPage.ts b/site/e2e/pom/TemplatesPage.ts index 04a763306a0ae..2f6de52a268ee 100644 --- a/site/e2e/pom/TemplatesPage.ts +++ b/site/e2e/pom/TemplatesPage.ts @@ -15,9 +15,9 @@ export class TemplatesPage extends BasePom { } async loaded() { - await expect(this.page).toHaveTitle("Templates - Coder") - await this.addTemplateButton.waitFor({ state: "visible" }) + + await expect(this.page).toHaveTitle("Templates - Coder") } async addTemplate() { diff --git a/site/e2e/pom/WorkspacePage.ts b/site/e2e/pom/WorkspacePage.ts new file mode 100644 index 0000000000000..b21c09b0c06ac --- /dev/null +++ b/site/e2e/pom/WorkspacePage.ts @@ -0,0 +1,22 @@ +import { expect, Locator, Page } from "@playwright/test" +import { BasePom } from "./BasePom" + +export class WorkspacePage extends BasePom { + readonly stopWorkspaceButton: Locator + + constructor(baseURL: string | undefined, page: Page) { + super(baseURL, `/templates/docker/workspace`, page) + + this.stopWorkspaceButton = page.getByTestId("button-stop-workspace") + } + + async loaded() { + await this.stopWorkspaceButton.waitFor({ state: "visible" }) + + await expect(this.page).toHaveTitle("admin/workspace-1 - Coder") + } + + async stop() { + await this.stopWorkspaceButton.click() + } +} diff --git a/site/e2e/pom/index.ts b/site/e2e/pom/index.ts deleted file mode 100644 index b050895f83720..0000000000000 --- a/site/e2e/pom/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./SignInPage" -export * from "./WorkspacesPage" diff --git a/site/e2e/tests/basicScenario.spec.ts b/site/e2e/tests/basicScenario.spec.ts index 9494591dd9a6b..52021081c908d 100644 --- a/site/e2e/tests/basicScenario.spec.ts +++ b/site/e2e/tests/basicScenario.spec.ts @@ -2,12 +2,18 @@ import { test } from "@playwright/test" import { getStatePath } from "../helpers" import { TemplatesPage } from "../pom/TemplatesPage" import { CreateTemplatePage } from "../pom/CreateTemplatePage" +import { TemplatePage } from "../pom/TemplatePage" +import { CreateWorkspacePage } from "../pom/CreateWorkspacePage" +import { WorkspacePage } from "../pom/WorkspacePage" test.use({ storageState: getStatePath("authState") }) test("Basic scenario", async ({ page, baseURL }) => { const templatesPage = new TemplatesPage(baseURL, page) const createTemplatePage = new CreateTemplatePage(baseURL, page) + const templatePage = new TemplatePage(baseURL, page) + const createWorkspacePage = new CreateWorkspacePage(baseURL, page) + const workspacePage = new WorkspacePage(baseURL, page) await test.step("Load empty templates page", async () => { await templatesPage.goto() @@ -18,8 +24,23 @@ test("Basic scenario", async ({ page, baseURL }) => { await templatesPage.addTemplate() await createTemplatePage.loaded() - await createTemplatePage.fillIn() + await createTemplatePage.submitForm() + await templatePage.loaded() + }) + + await test.step("Start a workspace", async() => { + await templatePage.createWorkspace() + await createWorkspacePage.loaded() + + await createWorkspacePage.submitForm() + await workspacePage.loaded() + }) + + // await test.step("Workspace is up and running", async() => { + // await workspacePage.isRunning() + // }) + await test.step("Finally", async() => { await page.waitForTimeout(5 * 60 * 1000) // FIXME }) }) diff --git a/site/src/components/TemplateLayout/TemplatePageHeader.tsx b/site/src/components/TemplateLayout/TemplatePageHeader.tsx index ef978ca99e511..cc61a5c96c539 100644 --- a/site/src/components/TemplateLayout/TemplatePageHeader.tsx +++ b/site/src/components/TemplateLayout/TemplatePageHeader.tsx @@ -103,6 +103,7 @@ const CreateWorkspaceButton: FC<{ startIcon={} component={RouterLink} to={`/templates/${templateName}/workspace`} + data-testid="button-create-workspace" > Create workspace diff --git a/site/src/components/WorkspaceStatusBadge/WorkspaceStatusBadge.tsx b/site/src/components/WorkspaceStatusBadge/WorkspaceStatusBadge.tsx index 0a23ac7409bfa..b62ae6593cf24 100644 --- a/site/src/components/WorkspaceStatusBadge/WorkspaceStatusBadge.tsx +++ b/site/src/components/WorkspaceStatusBadge/WorkspaceStatusBadge.tsx @@ -100,5 +100,6 @@ export const WorkspaceStatusBadge: FC< PropsWithChildren > = ({ build, className }) => { const { text, icon, type } = getStatus(build.status) - return + return } diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx index ee7bc7e2e5750..30f54676d3f86 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx @@ -211,7 +211,7 @@ export const CreateWorkspacePageView: FC< return ( - + {/* General info */} diff --git a/site/src/pages/TemplatePage/TemplateSummaryPage/TemplateSummaryPageView.tsx b/site/src/pages/TemplatePage/TemplateSummaryPage/TemplateSummaryPageView.tsx index 47babcc06ade8..08d74351824fb 100644 --- a/site/src/pages/TemplatePage/TemplateSummaryPage/TemplateSummaryPageView.tsx +++ b/site/src/pages/TemplatePage/TemplateSummaryPage/TemplateSummaryPageView.tsx @@ -51,7 +51,7 @@ export const TemplateSummaryPageView: FC = ({ {daus && } - + ) } From 3cac0ee4fe7e94b5a3f3346fddae26b55b5cb096 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Thu, 20 Apr 2023 11:30:28 +0200 Subject: [PATCH 04/19] WIP --- site/e2e/pom/WorkspacePage.ts | 13 ++++++++++++- site/e2e/tests/basicScenario.spec.ts | 14 +++++++++++--- site/src/components/Pill/Pill.tsx | 4 +++- site/src/components/WorkspaceActions/Buttons.tsx | 1 + .../WorkspaceStatusBadge/WorkspaceStatusBadge.tsx | 2 +- 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/site/e2e/pom/WorkspacePage.ts b/site/e2e/pom/WorkspacePage.ts index b21c09b0c06ac..4a4e022d227b3 100644 --- a/site/e2e/pom/WorkspacePage.ts +++ b/site/e2e/pom/WorkspacePage.ts @@ -2,21 +2,32 @@ import { expect, Locator, Page } from "@playwright/test" import { BasePom } from "./BasePom" export class WorkspacePage extends BasePom { + readonly workspaceRunningBadge: Locator + readonly workspaceStoppedBadge: Locator readonly stopWorkspaceButton: Locator constructor(baseURL: string | undefined, page: Page) { super(baseURL, `/templates/docker/workspace`, page) + this.workspaceRunningBadge = page.getByTestId("badge-workspace-status-running") + this.workspaceStoppedBadge = page.getByTestId("badge-workspace-status-stopped") this.stopWorkspaceButton = page.getByTestId("button-stop-workspace") } async loaded() { await this.stopWorkspaceButton.waitFor({ state: "visible" }) + await expect(this.page).toHaveTitle("admin/my-first-workspace - Coder") + } - await expect(this.page).toHaveTitle("admin/workspace-1 - Coder") + async isRunning() { + await this.workspaceRunningBadge.waitFor({ state: "visible" }) } async stop() { await this.stopWorkspaceButton.click() } + + async isStopped() { + await this.workspaceStoppedBadge.waitFor({ state: "visible" }) + } } diff --git a/site/e2e/tests/basicScenario.spec.ts b/site/e2e/tests/basicScenario.spec.ts index 52021081c908d..6518805e5b563 100644 --- a/site/e2e/tests/basicScenario.spec.ts +++ b/site/e2e/tests/basicScenario.spec.ts @@ -36,9 +36,17 @@ test("Basic scenario", async ({ page, baseURL }) => { await workspacePage.loaded() }) - // await test.step("Workspace is up and running", async() => { - // await workspacePage.isRunning() - // }) + await test.step("Workspace is up and running", async() => { + await workspacePage.isRunning() + }) + + await test.step("Stop the workspace", async() => { + await workspacePage.stop() + }) + + await test.step("Workspace is stopped", async() => { + await workspacePage.isStopped() + }) await test.step("Finally", async() => { await page.waitForTimeout(5 * 60 * 1000) // FIXME diff --git a/site/src/components/Pill/Pill.tsx b/site/src/components/Pill/Pill.tsx index d812ea2b66e1d..e872df04b3d4d 100644 --- a/site/src/components/Pill/Pill.tsx +++ b/site/src/components/Pill/Pill.tsx @@ -10,16 +10,18 @@ export interface PillProps { type?: PaletteIndex lightBorder?: boolean title?: string + dataTestId?: string } export const Pill: FC = (props) => { - const { className, icon, text = false, title } = props + const { className, icon, text = false, title, dataTestId } = props const styles = useStyles(props) return (
{icon &&
{icon}
} {text} diff --git a/site/src/components/WorkspaceActions/Buttons.tsx b/site/src/components/WorkspaceActions/Buttons.tsx index d6207952a4ac8..71156d25f0123 100644 --- a/site/src/components/WorkspaceActions/Buttons.tsx +++ b/site/src/components/WorkspaceActions/Buttons.tsx @@ -61,6 +61,7 @@ export const StopButton: FC> = ({ startIcon={} onClick={handleAction} className={styles.fixedWidth} + data-testid="button-stop-workspace" > {t("actionButton.stop")} diff --git a/site/src/components/WorkspaceStatusBadge/WorkspaceStatusBadge.tsx b/site/src/components/WorkspaceStatusBadge/WorkspaceStatusBadge.tsx index b62ae6593cf24..e6da7397ec79d 100644 --- a/site/src/components/WorkspaceStatusBadge/WorkspaceStatusBadge.tsx +++ b/site/src/components/WorkspaceStatusBadge/WorkspaceStatusBadge.tsx @@ -100,6 +100,6 @@ export const WorkspaceStatusBadge: FC< PropsWithChildren > = ({ build, className }) => { const { text, icon, type } = getStatus(build.status) - return } From 5396dcdbcf967581dd76d440cb23a11a828b4ef8 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Thu, 20 Apr 2023 12:28:30 +0200 Subject: [PATCH 05/19] Wait for agent ready --- site/e2e/playwright.config.ts | 1 + site/e2e/pom/CreateTemplatePage.ts | 8 +++++--- site/e2e/pom/CreateWorkspacePage.ts | 4 +++- site/e2e/pom/WorkspacePage.ts | 18 ++++++++++++++++-- site/e2e/tests/basicScenario.spec.ts | 10 +++++----- site/src/components/Resources/AgentStatus.tsx | 1 + site/src/components/Resources/AgentVersion.tsx | 3 ++- .../components/TerminalLink/TerminalLink.tsx | 1 + .../WorkspaceStatusBadge.tsx | 11 +++++++++-- .../CreateWorkspacePageView.tsx | 5 ++++- .../TemplateSummaryPageView.tsx | 2 +- 11 files changed, 48 insertions(+), 16 deletions(-) diff --git a/site/e2e/playwright.config.ts b/site/e2e/playwright.config.ts index 43c01871dddc0..61d22a6e6aabc 100644 --- a/site/e2e/playwright.config.ts +++ b/site/e2e/playwright.config.ts @@ -20,6 +20,7 @@ const config: PlaywrightTestConfig = { port, reuseExistingServer: false, }, + timeout: 120 * 1000, } export default config diff --git a/site/e2e/pom/CreateTemplatePage.ts b/site/e2e/pom/CreateTemplatePage.ts index e7163fab3cdc9..33b087f8d6046 100644 --- a/site/e2e/pom/CreateTemplatePage.ts +++ b/site/e2e/pom/CreateTemplatePage.ts @@ -21,10 +21,12 @@ export class CreateTemplatePage extends BasePom { async submitForm() { await this.createTemplateForm - .getByTestId("form-template-upload") - .setInputFiles("./e2e/testdata/docker.tar") + .getByTestId("form-template-upload") + .setInputFiles("./e2e/testdata/docker.tar") await this.createTemplateForm.getByLabel("Name *").fill("my-first-template") - await this.createTemplateForm.getByLabel("Display name").fill("My First Template") + await this.createTemplateForm + .getByLabel("Display name") + .fill("My First Template") await this.createTemplateForm .getByLabel("Description") .fill("This is my first template.") diff --git a/site/e2e/pom/CreateWorkspacePage.ts b/site/e2e/pom/CreateWorkspacePage.ts index b838e48932b87..dbb075e011d6f 100644 --- a/site/e2e/pom/CreateWorkspacePage.ts +++ b/site/e2e/pom/CreateWorkspacePage.ts @@ -20,7 +20,9 @@ export class CreateWorkspacePage extends BasePom { } async submitForm() { - await this.createWorkspaceForm.getByLabel("Workspace Name").fill("my-first-workspace") + await this.createWorkspaceForm + .getByLabel("Workspace Name") + .fill("my-first-workspace") await this.submitButton.click() } diff --git a/site/e2e/pom/WorkspacePage.ts b/site/e2e/pom/WorkspacePage.ts index 4a4e022d227b3..1d73d7bb772b3 100644 --- a/site/e2e/pom/WorkspacePage.ts +++ b/site/e2e/pom/WorkspacePage.ts @@ -4,13 +4,23 @@ import { BasePom } from "./BasePom" export class WorkspacePage extends BasePom { readonly workspaceRunningBadge: Locator readonly workspaceStoppedBadge: Locator + readonly terminalButton: Locator + readonly agentVersion: Locator + readonly agentLifecycleReady: Locator readonly stopWorkspaceButton: Locator constructor(baseURL: string | undefined, page: Page) { super(baseURL, `/templates/docker/workspace`, page) - this.workspaceRunningBadge = page.getByTestId("badge-workspace-status-running") - this.workspaceStoppedBadge = page.getByTestId("badge-workspace-status-stopped") + this.workspaceRunningBadge = page.getByTestId( + "badge-workspace-status-running", + ) + this.workspaceStoppedBadge = page.getByTestId( + "badge-workspace-status-stopped", + ) + this.terminalButton = page.getByTestId("button-terminal") + this.agentVersion = page.getByTestId("agent-version") + this.agentLifecycleReady = page.getByTestId("agent-lifecycle-ready") this.stopWorkspaceButton = page.getByTestId("button-stop-workspace") } @@ -21,6 +31,10 @@ export class WorkspacePage extends BasePom { async isRunning() { await this.workspaceRunningBadge.waitFor({ state: "visible" }) + await this.terminalButton.waitFor({ state: "visible" }) + await this.agentVersion.waitFor({ state: "visible" }) + await this.agentLifecycleReady.waitFor({ state: "visible" }) + await this.page.waitForTimeout(1000) // Wait for 1s to snapshot the agent status on the video } async stop() { diff --git a/site/e2e/tests/basicScenario.spec.ts b/site/e2e/tests/basicScenario.spec.ts index 6518805e5b563..88bac3377d626 100644 --- a/site/e2e/tests/basicScenario.spec.ts +++ b/site/e2e/tests/basicScenario.spec.ts @@ -28,7 +28,7 @@ test("Basic scenario", async ({ page, baseURL }) => { await templatePage.loaded() }) - await test.step("Start a workspace", async() => { + await test.step("Start a workspace", async () => { await templatePage.createWorkspace() await createWorkspacePage.loaded() @@ -36,19 +36,19 @@ test("Basic scenario", async ({ page, baseURL }) => { await workspacePage.loaded() }) - await test.step("Workspace is up and running", async() => { + await test.step("Workspace is up and running", async () => { await workspacePage.isRunning() }) - await test.step("Stop the workspace", async() => { + await test.step("Stop the workspace", async () => { await workspacePage.stop() }) - await test.step("Workspace is stopped", async() => { + await test.step("Workspace is stopped", async () => { await workspacePage.isStopped() }) - await test.step("Finally", async() => { + await test.step("Finally", async () => { await page.waitForTimeout(5 * 60 * 1000) // FIXME }) }) diff --git a/site/src/components/Resources/AgentStatus.tsx b/site/src/components/Resources/AgentStatus.tsx index eedd521034e02..f0a962617dad8 100644 --- a/site/src/components/Resources/AgentStatus.tsx +++ b/site/src/components/Resources/AgentStatus.tsx @@ -28,6 +28,7 @@ const ReadyLifecycle: React.FC = () => { role="status" aria-label={t("agentStatus.connected.ready")} className={combineClasses([styles.status, styles.connected])} + data-testid="agent-lifecycle-ready" /> ) } diff --git a/site/src/components/Resources/AgentVersion.tsx b/site/src/components/Resources/AgentVersion.tsx index 2f21e79ecff39..27381f91ec77f 100644 --- a/site/src/components/Resources/AgentVersion.tsx +++ b/site/src/components/Resources/AgentVersion.tsx @@ -19,7 +19,7 @@ export const AgentVersion: FC<{ ) if (!outdated) { - return {displayVersion} + return {displayVersion} } return ( @@ -31,6 +31,7 @@ export const AgentVersion: FC<{ onMouseEnter={() => setIsOpen(true)} onMouseLeave={() => setIsOpen(false)} className={styles.trigger} + data-testid="agent-version" > Agent Outdated diff --git a/site/src/components/TerminalLink/TerminalLink.tsx b/site/src/components/TerminalLink/TerminalLink.tsx index ded51c01d9f94..2c80d26d5a295 100644 --- a/site/src/components/TerminalLink/TerminalLink.tsx +++ b/site/src/components/TerminalLink/TerminalLink.tsx @@ -42,6 +42,7 @@ export const TerminalLink: FC> = ({ href={href} className={combineClasses([styles.link, className])} target="_blank" + data-testid="button-terminal" onClick={(event) => { event.preventDefault() window.open( diff --git a/site/src/components/WorkspaceStatusBadge/WorkspaceStatusBadge.tsx b/site/src/components/WorkspaceStatusBadge/WorkspaceStatusBadge.tsx index e6da7397ec79d..97ddebc1100b8 100644 --- a/site/src/components/WorkspaceStatusBadge/WorkspaceStatusBadge.tsx +++ b/site/src/components/WorkspaceStatusBadge/WorkspaceStatusBadge.tsx @@ -100,6 +100,13 @@ export const WorkspaceStatusBadge: FC< PropsWithChildren > = ({ build, className }) => { const { text, icon, type } = getStatus(build.status) - return + return ( + + ) } diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx index 30f54676d3f86..6f48e117f6579 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx @@ -211,7 +211,10 @@ export const CreateWorkspacePageView: FC< return ( - + {/* General info */} = ({ {daus && } - + ) } From 4e3f6839167f10a226f3c50652bf3230536d91b3 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Thu, 20 Apr 2023 12:34:36 +0200 Subject: [PATCH 06/19] video resolution --- site/e2e/playwright.config.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/site/e2e/playwright.config.ts b/site/e2e/playwright.config.ts index 61d22a6e6aabc..0d9b60f303a82 100644 --- a/site/e2e/playwright.config.ts +++ b/site/e2e/playwright.config.ts @@ -13,7 +13,11 @@ const config: PlaywrightTestConfig = { globalSetup: require.resolve("./globalSetup"), use: { baseURL: `http://localhost:${port}`, - video: "retain-on-failure", + video: { + mode: "retain-on-failure", + size: { width: 1280, height: 768 }, + }, + viewport: { width: 1280, height: 768 }, }, webServer: { command: `go run -tags embed ${coderMain} server --global-config $(mktemp -d -t e2e-XXXXXXXXXX)`, From ee59c2a87cec7383c7d9051557dbcae84fb4ae9d Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Thu, 20 Apr 2023 13:51:07 +0200 Subject: [PATCH 07/19] Scenario covered --- site/e2e/playwright.config.ts | 2 +- site/e2e/pom/WorkspacePage.ts | 49 ++++++++++++++++--- site/e2e/tests/basicScenario.spec.ts | 13 ++--- .../Dialogs/DeleteDialog/DeleteDialog.tsx | 1 + site/src/components/Dialogs/Dialog.tsx | 1 + .../WorkspaceActions/WorkspaceActions.tsx | 5 +- 6 files changed, 54 insertions(+), 17 deletions(-) diff --git a/site/e2e/playwright.config.ts b/site/e2e/playwright.config.ts index 0d9b60f303a82..8d80af672e0dd 100644 --- a/site/e2e/playwright.config.ts +++ b/site/e2e/playwright.config.ts @@ -24,7 +24,7 @@ const config: PlaywrightTestConfig = { port, reuseExistingServer: false, }, - timeout: 120 * 1000, + timeout: 5 * 60 * 1000, } export default config diff --git a/site/e2e/pom/WorkspacePage.ts b/site/e2e/pom/WorkspacePage.ts index 1d73d7bb772b3..af84c3ba355c2 100644 --- a/site/e2e/pom/WorkspacePage.ts +++ b/site/e2e/pom/WorkspacePage.ts @@ -2,26 +2,45 @@ import { expect, Locator, Page } from "@playwright/test" import { BasePom } from "./BasePom" export class WorkspacePage extends BasePom { + readonly workspaceOptionsButton: Locator + readonly deleteWorkspaceMenuItem: Locator + readonly stopWorkspaceButton: Locator + readonly workspaceRunningBadge: Locator readonly workspaceStoppedBadge: Locator + readonly workspaceDeletedBadge: Locator + readonly terminalButton: Locator readonly agentVersion: Locator readonly agentLifecycleReady: Locator - readonly stopWorkspaceButton: Locator + + readonly deleteDialogConfirmation: Locator + readonly deleteDialogConfirm: Locator constructor(baseURL: string | undefined, page: Page) { super(baseURL, `/templates/docker/workspace`, page) + this.workspaceOptionsButton = page.getByTestId("workspace-options-button") + this.deleteWorkspaceMenuItem = page.getByTestId("menuitem-delete-workspace") + this.stopWorkspaceButton = page.getByTestId("button-stop-workspace") + this.workspaceRunningBadge = page.getByTestId( "badge-workspace-status-running", ) this.workspaceStoppedBadge = page.getByTestId( "badge-workspace-status-stopped", ) + this.workspaceDeletedBadge = page.getByTestId( + "badge-workspace-status-deleted", + ) this.terminalButton = page.getByTestId("button-terminal") this.agentVersion = page.getByTestId("agent-version") this.agentLifecycleReady = page.getByTestId("agent-lifecycle-ready") - this.stopWorkspaceButton = page.getByTestId("button-stop-workspace") + + this.deleteDialogConfirmation = page.getByTestId( + "delete-dialog-confirmation", + ) + this.deleteDialogConfirm = page.getByTestId("delete-dialog-confirm") } async loaded() { @@ -29,19 +48,35 @@ export class WorkspacePage extends BasePom { await expect(this.page).toHaveTitle("admin/my-first-workspace - Coder") } + async stop() { + await this.stopWorkspaceButton.click() + } + + async delete() { + await this.workspaceOptionsButton.click() + await this.deleteWorkspaceMenuItem.click() + + await this.deleteDialogConfirmation.waitFor({ state: "visible" }) + await this.deleteDialogConfirmation + .getByLabel("Name of workspace to delete") + .fill("my-first-workspace") + + await this.page.waitForTimeout(1000) // Wait for 1s to snapshot the delete dialog before submitting + await this.deleteDialogConfirm.click() + } + async isRunning() { await this.workspaceRunningBadge.waitFor({ state: "visible" }) await this.terminalButton.waitFor({ state: "visible" }) await this.agentVersion.waitFor({ state: "visible" }) await this.agentLifecycleReady.waitFor({ state: "visible" }) - await this.page.waitForTimeout(1000) // Wait for 1s to snapshot the agent status on the video - } - - async stop() { - await this.stopWorkspaceButton.click() } async isStopped() { await this.workspaceStoppedBadge.waitFor({ state: "visible" }) } + + async isDeleted() { + await this.workspaceDeletedBadge.waitFor({ state: "visible" }) + } } diff --git a/site/e2e/tests/basicScenario.spec.ts b/site/e2e/tests/basicScenario.spec.ts index 88bac3377d626..7ed3dd5f7e11d 100644 --- a/site/e2e/tests/basicScenario.spec.ts +++ b/site/e2e/tests/basicScenario.spec.ts @@ -34,21 +34,18 @@ test("Basic scenario", async ({ page, baseURL }) => { await createWorkspacePage.submitForm() await workspacePage.loaded() - }) - - await test.step("Workspace is up and running", async () => { await workspacePage.isRunning() + await page.waitForTimeout(1000) // Wait for 1s to snapshot the agent status on the video }) await test.step("Stop the workspace", async () => { await workspacePage.stop() - }) - - await test.step("Workspace is stopped", async () => { await workspacePage.isStopped() }) - await test.step("Finally", async () => { - await page.waitForTimeout(5 * 60 * 1000) // FIXME + await test.step("Delete the workspace", async () => { + await workspacePage.delete() + await workspacePage.isDeleted() + await page.waitForTimeout(1000) // Wait to show the deleted workspace }) }) diff --git a/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx b/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx index 326239604730c..68d7d65f571c1 100644 --- a/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx +++ b/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx @@ -57,6 +57,7 @@ export const DeleteDialog: FC> = ({ label={t("deleteDialog.confirmLabel", { entity })} error={hasError} helperText={hasError && t("deleteDialog.incorrectName", { entity })} + data-testid="delete-dialog-confirmation" /> ) diff --git a/site/src/components/Dialogs/Dialog.tsx b/site/src/components/Dialogs/Dialog.tsx index 7f249c74c590b..9073f3d495a57 100644 --- a/site/src/components/Dialogs/Dialog.tsx +++ b/site/src/components/Dialogs/Dialog.tsx @@ -75,6 +75,7 @@ export const DialogActionButtons: React.FC = ({ [styles.errorButton]: type === "delete", [styles.successButton]: type === "success", })} + data-testid={type + "-dialog-confirm"} > {confirmText} diff --git a/site/src/components/WorkspaceActions/WorkspaceActions.tsx b/site/src/components/WorkspaceActions/WorkspaceActions.tsx index 2cc4bbfcac203..aa79e457e9396 100644 --- a/site/src/components/WorkspaceActions/WorkspaceActions.tsx +++ b/site/src/components/WorkspaceActions/WorkspaceActions.tsx @@ -163,7 +163,10 @@ export const WorkspaceActions: FC = ({ Change version )} - + Delete From 05f2ee155727c99c438ccc282414416ca1349e8a Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Thu, 20 Apr 2023 14:06:44 +0200 Subject: [PATCH 08/19] fix-fork --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 925fe1fa18dd6..549cf117e50e0 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -601,7 +601,7 @@ jobs: working-directory: site - name: Upload Playwright Failed Tests - if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' && !github.event.pull_request.head.repo.fork + if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' uses: actions/upload-artifact@v3 with: name: failed-test-videos From a022d142ffcd2d4f7ae3e28d45bfbdfcf49324c2 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Thu, 20 Apr 2023 14:27:49 +0200 Subject: [PATCH 09/19] Fixes --- site/e2e/constants.ts | 1 + site/e2e/helpers.ts | 24 ------------------------ site/e2e/playwright.config.ts | 4 ++-- site/e2e/pom/SignInPage.ts | 17 ----------------- site/e2e/states/.gitkeep | 0 5 files changed, 3 insertions(+), 43 deletions(-) delete mode 100644 site/e2e/pom/SignInPage.ts delete mode 100644 site/e2e/states/.gitkeep diff --git a/site/e2e/constants.ts b/site/e2e/constants.ts index 1e56c3d8b3b28..405a5203a667f 100644 --- a/site/e2e/constants.ts +++ b/site/e2e/constants.ts @@ -1,5 +1,6 @@ // Default port from the server export const defaultPort = 3000 +export const defaultEndpoint = `localhost:${defaultPort}` // Credentials for the first user export const username = "admin" diff --git a/site/e2e/helpers.ts b/site/e2e/helpers.ts index 1b8defa88c4e2..e3c7091503cc1 100644 --- a/site/e2e/helpers.ts +++ b/site/e2e/helpers.ts @@ -1,29 +1,5 @@ -import { Page } from "@playwright/test" import path from "path" -export const buttons = { - starterTemplates: "Starter templates", - dockerTemplate: "Develop in Docker", - useTemplate: "Use template", - createTemplate: "Create template", - createWorkspace: "Create workspace", - submitCreateWorkspace: "Create workspace", - stopWorkspace: "Stop", - startWorkspace: "Start", -} - -export const clickButton = async (page: Page, name: string): Promise => { - await page.getByRole("button", { name, exact: true }).click() -} - -export const fillInput = async ( - page: Page, - label: string, - value: string, -): Promise => { - await page.fill(`text=${label}`, value) -} - const statesDir = path.join(__dirname, "./states") export const getStatePath = (name: string): string => { diff --git a/site/e2e/playwright.config.ts b/site/e2e/playwright.config.ts index 8d80af672e0dd..7a9ac16a711ac 100644 --- a/site/e2e/playwright.config.ts +++ b/site/e2e/playwright.config.ts @@ -1,6 +1,6 @@ import { PlaywrightTestConfig } from "@playwright/test" import path from "path" -import { defaultPort } from "./constants" +import { defaultPort, defaultEndpoint } from "./constants" const port = process.env.CODER_E2E_PORT ? Number(process.env.CODER_E2E_PORT) @@ -12,7 +12,7 @@ const config: PlaywrightTestConfig = { testDir: "tests", globalSetup: require.resolve("./globalSetup"), use: { - baseURL: `http://localhost:${port}`, + baseURL: `http://${defaultEndpoint}`, video: { mode: "retain-on-failure", size: { width: 1280, height: 768 }, diff --git a/site/e2e/pom/SignInPage.ts b/site/e2e/pom/SignInPage.ts deleted file mode 100644 index 362674588f6c0..0000000000000 --- a/site/e2e/pom/SignInPage.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Page } from "@playwright/test" -import { BasePom } from "./BasePom" - -export class SignInPage extends BasePom { - constructor(baseURL: string | undefined, page: Page) { - super(baseURL, "/login", page) - } - - async submitBuiltInAuthentication( - email: string, - password: string, - ): Promise { - await this.page.fill("text=Email", email) - await this.page.fill("text=Password", password) - await this.page.click('button:has-text("Sign In")') - } -} diff --git a/site/e2e/states/.gitkeep b/site/e2e/states/.gitkeep deleted file mode 100644 index e69de29bb2d1d..0000000000000 From b80b9709c65451f41d4488d9c770017058a8fbe0 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Thu, 20 Apr 2023 14:29:44 +0200 Subject: [PATCH 10/19] increase timeout --- site/e2e/playwright.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/e2e/playwright.config.ts b/site/e2e/playwright.config.ts index 7a9ac16a711ac..0730cff9b11ab 100644 --- a/site/e2e/playwright.config.ts +++ b/site/e2e/playwright.config.ts @@ -24,7 +24,7 @@ const config: PlaywrightTestConfig = { port, reuseExistingServer: false, }, - timeout: 5 * 60 * 1000, + timeout: 10 * 60 * 1000, } export default config From 152ab5db4a71bd3653072c443979ffd14f5f2b61 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Thu, 20 Apr 2023 15:37:17 +0200 Subject: [PATCH 11/19] test.slow --- site/e2e/playwright.config.ts | 2 +- site/e2e/tests/basicScenario.spec.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/site/e2e/playwright.config.ts b/site/e2e/playwright.config.ts index 0730cff9b11ab..962a599e4dff7 100644 --- a/site/e2e/playwright.config.ts +++ b/site/e2e/playwright.config.ts @@ -24,7 +24,7 @@ const config: PlaywrightTestConfig = { port, reuseExistingServer: false, }, - timeout: 10 * 60 * 1000, + timeout: 3 * 60 * 1000, } export default config diff --git a/site/e2e/tests/basicScenario.spec.ts b/site/e2e/tests/basicScenario.spec.ts index 7ed3dd5f7e11d..ce636bae639ff 100644 --- a/site/e2e/tests/basicScenario.spec.ts +++ b/site/e2e/tests/basicScenario.spec.ts @@ -9,6 +9,8 @@ import { WorkspacePage } from "../pom/WorkspacePage" test.use({ storageState: getStatePath("authState") }) test("Basic scenario", async ({ page, baseURL }) => { + test.slow() + const templatesPage = new TemplatesPage(baseURL, page) const createTemplatePage = new CreateTemplatePage(baseURL, page) const templatePage = new TemplatePage(baseURL, page) From d7179b201a59ce2807476b2b5ed274ebbc0c524b Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Fri, 28 Apr 2023 11:05:01 +0200 Subject: [PATCH 12/19] debug --- .github/workflows/ci.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 549cf117e50e0..88944eb323809 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -608,6 +608,20 @@ jobs: path: ./site/test-results/**/*.webm retention-days: 7 + - run: docker ps -a + working-directory: site + + - run: docker cp coder-admin-my-first-workspace:/tmp/ logs + working-directory: site + + - name: Upload docker logs + if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' + uses: actions/upload-artifact@v3 + with: + name: docker-logs + path: ./site/logs/*.log + retention-days: 7 + chromatic: # REMARK: this is only used to build storybook and deploy it to Chromatic. runs-on: ubuntu-latest From e23e2506d4f46172d86fdc924cde3f2dd1fd9423 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Fri, 28 Apr 2023 11:43:32 +0200 Subject: [PATCH 13/19] fix --- .../src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx index 1e1a2ee32fc9e..12e6cd3f41144 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx @@ -162,13 +162,10 @@ export const CreateWorkspacePageView: FC< return ( -<<<<<<< HEAD -======= - {Boolean(props.hasTemplateErrors) && ( {Boolean( @@ -231,7 +228,6 @@ export const CreateWorkspacePageView: FC< /> )} ->>>>>>> main {/* General info */} Date: Fri, 28 Apr 2023 12:05:29 +0200 Subject: [PATCH 14/19] wip --- .github/workflows/ci.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 73ce953f2aa94..bd14f57b54da6 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -616,9 +616,11 @@ jobs: retention-days: 7 - run: docker ps -a + if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' working-directory: site - run: docker cp coder-admin-my-first-workspace:/tmp/ logs + if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' working-directory: site - name: Upload docker logs From fc9d62b5e8d7ba7a2d5ca194d11e8438673ea27e Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Fri, 28 Apr 2023 12:33:11 +0200 Subject: [PATCH 15/19] wip --- .github/workflows/ci.yaml | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index bd14f57b54da6..9ec80ac7a514a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -619,17 +619,25 @@ jobs: if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' working-directory: site - - run: docker cp coder-admin-my-first-workspace:/tmp/ logs + - run: docker exec -it coder-admin-my-first-workspace ps aux if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' working-directory: site - - name: Upload docker logs + - run: docker exec -it coder-admin-my-first-workspace ls -la /tmp/ if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' - uses: actions/upload-artifact@v3 - with: - name: docker-logs - path: ./site/logs/*.log - retention-days: 7 + working-directory: site + + - run: docker exec -it coder-admin-my-first-workspace cat '/tmp/coder-agent-init.log' + if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' + working-directory: site + + - run: docker exec -it coder-admin-my-first-workspace cat '/tmp/coder-agent.log' + if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' + working-directory: site + + - run: docker exec -it coder-admin-my-first-workspace cat '/tmp/coder-startup-script.log' + if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' + working-directory: site chromatic: # REMARK: this is only used to build storybook and deploy it to Chromatic. From 9ad436e80f72153eca76f5f556d182b3854280b0 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Fri, 28 Apr 2023 12:51:24 +0200 Subject: [PATCH 16/19] wip --- .github/workflows/ci.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 9ec80ac7a514a..d658bab4cc731 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -619,23 +619,23 @@ jobs: if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' working-directory: site - - run: docker exec -it coder-admin-my-first-workspace ps aux + - run: docker exec coder-admin-my-first-workspace ps aux if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' working-directory: site - - run: docker exec -it coder-admin-my-first-workspace ls -la /tmp/ + - run: docker exec coder-admin-my-first-workspace ls -la /tmp/ if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' working-directory: site - - run: docker exec -it coder-admin-my-first-workspace cat '/tmp/coder-agent-init.log' + - run: docker exec coder-admin-my-first-workspace cat '/tmp/coder-agent-init.log' if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' working-directory: site - - run: docker exec -it coder-admin-my-first-workspace cat '/tmp/coder-agent.log' + - run: docker exec coder-admin-my-first-workspace cat '/tmp/coder-agent.log' if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' working-directory: site - - run: docker exec -it coder-admin-my-first-workspace cat '/tmp/coder-startup-script.log' + - run: docker exec coder-admin-my-first-workspace cat '/tmp/coder-startup-script.log' if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' working-directory: site From 611182c99d59844fe613d8e7080309bcfd0cae99 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Fri, 28 Apr 2023 13:19:53 +0200 Subject: [PATCH 17/19] Increase timeout --- site/e2e/playwright.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/e2e/playwright.config.ts b/site/e2e/playwright.config.ts index 962a599e4dff7..0730cff9b11ab 100644 --- a/site/e2e/playwright.config.ts +++ b/site/e2e/playwright.config.ts @@ -24,7 +24,7 @@ const config: PlaywrightTestConfig = { port, reuseExistingServer: false, }, - timeout: 3 * 60 * 1000, + timeout: 10 * 60 * 1000, } export default config From 77de2cedb247766cc9335b80dd19012219fe3cd3 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Fri, 28 Apr 2023 13:52:01 +0200 Subject: [PATCH 18/19] debug: bootstrap --- provisionersdk/scripts/bootstrap_linux.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/provisionersdk/scripts/bootstrap_linux.sh b/provisionersdk/scripts/bootstrap_linux.sh index abd91d163d0e0..ed1c6ecf6bc4d 100644 --- a/provisionersdk/scripts/bootstrap_linux.sh +++ b/provisionersdk/scripts/bootstrap_linux.sh @@ -20,7 +20,7 @@ while :; do # will have available. status="" if command -v curl >/dev/null 2>&1; then - curl -fsSL --compressed "${BINARY_URL}" -o "${BINARY_NAME}" && break + curl -fsSL --compressed "${BINARY_URL}" -o "${BINARY_NAME}" 2>>/tmp/coder-startup-script.log && break status=$? elif command -v wget >/dev/null 2>&1; then wget -q "${BINARY_URL}" -O "${BINARY_NAME}" && break From 0f3355770f180fb8eefaac87ba2283a6af7180cd Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Fri, 28 Apr 2023 14:41:29 +0200 Subject: [PATCH 19/19] more debug --- provisionersdk/scripts/bootstrap_linux.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/provisionersdk/scripts/bootstrap_linux.sh b/provisionersdk/scripts/bootstrap_linux.sh index ed1c6ecf6bc4d..6f461b97f926a 100644 --- a/provisionersdk/scripts/bootstrap_linux.sh +++ b/provisionersdk/scripts/bootstrap_linux.sh @@ -20,7 +20,7 @@ while :; do # will have available. status="" if command -v curl >/dev/null 2>&1; then - curl -fsSL --compressed "${BINARY_URL}" -o "${BINARY_NAME}" 2>>/tmp/coder-startup-script.log && break + curl -fsSL --compressed "${BINARY_URL}" -o "${BINARY_NAME}" -v 2>>/tmp/coder-startup-script.log && break status=$? elif command -v wget >/dev/null 2>&1; then wget -q "${BINARY_URL}" -O "${BINARY_NAME}" && break