From 0dbd3856a35c541f99b977551fcbb7cef186a443 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Tue, 17 Dec 2024 00:52:00 +0000 Subject: [PATCH 01/11] idk --- site/e2e/helpers.ts | 14 +++++++++++++- site/e2e/hooks.ts | 2 +- site/e2e/playwright.config.ts | 9 ++------- .../createFirstUser.spec.ts} | 8 +++----- site/e2e/tests/app.spec.ts | 6 +++++- site/e2e/tests/auditLogs.spec.ts | 12 ++++++++++-- site/e2e/tests/deployment/appearance.spec.ts | 8 +++++++- site/e2e/tests/deployment/general.spec.ts | 8 +++++++- site/e2e/tests/deployment/idpOrgSync.spec.ts | 13 +++++++------ site/e2e/tests/deployment/licenses.spec.ts | 8 +++++++- site/e2e/tests/deployment/network.spec.ts | 9 ++++++++- site/e2e/tests/deployment/observability.spec.ts | 9 ++++++++- site/e2e/tests/deployment/security.spec.ts | 9 ++++++++- site/e2e/tests/deployment/userAuth.spec.ts | 9 ++++++++- site/e2e/tests/deployment/workspaceProxies.spec.ts | 7 +++++++ site/e2e/tests/externalAuth.spec.ts | 9 ++++++--- site/e2e/tests/groups/addMembers.spec.ts | 9 +++++++-- .../tests/groups/addUsersToDefaultGroup.spec.ts | 6 +++++- site/e2e/tests/groups/createGroup.spec.ts | 7 ++++++- site/e2e/tests/groups/removeGroup.spec.ts | 9 +++++++-- site/e2e/tests/groups/removeMember.spec.ts | 9 +++++++-- site/e2e/tests/organizationMembers.spec.ts | 10 ++++++++-- site/e2e/tests/organizations.spec.ts | 2 +- site/e2e/tests/outdatedAgent.spec.ts | 6 +++++- site/e2e/tests/outdatedCLI.spec.ts | 6 +++++- site/e2e/tests/templates/listTemplates.spec.ts | 6 +++++- .../tests/templates/updateTemplateSchedule.spec.ts | 8 ++++++-- site/e2e/tests/updateTemplate.spec.ts | 6 +++++- .../e2e/tests/users/createUserWithPassword.spec.ts | 6 +++++- site/e2e/tests/users/removeUser.spec.ts | 8 ++++++-- site/e2e/tests/webTerminal.spec.ts | 10 ++++++---- .../tests/workspaces/autoCreateWorkspace.spec.ts | 7 +++++++ site/e2e/tests/workspaces/createWorkspace.spec.ts | 6 +++++- site/e2e/tests/workspaces/restartWorkspace.spec.ts | 6 +++++- site/e2e/tests/workspaces/startWorkspace.spec.ts | 8 ++++++-- site/e2e/tests/workspaces/updateWorkspace.spec.ts | 8 ++++++-- 36 files changed, 220 insertions(+), 63 deletions(-) rename site/e2e/{global.setup.ts => setup/createFirstUser.spec.ts} (87%) diff --git a/site/e2e/helpers.ts b/site/e2e/helpers.ts index 0a93e049da33f..acd945a675d64 100644 --- a/site/e2e/helpers.ts +++ b/site/e2e/helpers.ts @@ -1,6 +1,5 @@ import { type ChildProcess, exec, spawn } from "node:child_process"; import { randomUUID } from "node:crypto"; -import * as fs from "node:fs"; import net from "node:net"; import path from "node:path"; import { Duplex } from "node:stream"; @@ -19,7 +18,9 @@ import { coderMain, coderPort, defaultOrganizationName, + email, license, + password, premiumTestsRequired, prometheusPort, requireTerraformTests, @@ -60,6 +61,17 @@ export function requireTerraformProvisioner() { test.skip(!requireTerraformTests); } +type LoginOptions = { + email: string; + password: string; +}; + +export async function login(page: Page, options?: LoginOptions) { + await page.getByLabel("Email").fill(options?.email || email); + await page.getByLabel("Password").fill(options?.password || password); + await page.getByRole("button", { name: "Sign In" }).click(); +} + /** * createWorkspace creates a workspace for a template. It does not wait for it * to be running, but it does navigate to the page. diff --git a/site/e2e/hooks.ts b/site/e2e/hooks.ts index bf9681ed43d5d..2b8c4d2287cb2 100644 --- a/site/e2e/hooks.ts +++ b/site/e2e/hooks.ts @@ -2,7 +2,7 @@ import http from "node:http"; import type { BrowserContext, Page } from "@playwright/test"; import { coderPort, gitAuth } from "./constants"; -export const beforeCoderTest = async (page: Page) => { +export const beforeCoderTest = (page: Page) => { page.on("console", (msg) => console.info(`[onConsole] ${msg.text()}`)); page.on("request", (request) => { diff --git a/site/e2e/playwright.config.ts b/site/e2e/playwright.config.ts index ea55bf398e7df..a840cabd6b993 100644 --- a/site/e2e/playwright.config.ts +++ b/site/e2e/playwright.config.ts @@ -13,9 +13,6 @@ import { export const wsEndpoint = process.env.CODER_E2E_WS_ENDPOINT; -// This is where auth cookies are stored! -export const storageState = path.join(__dirname, ".auth.json"); - // If running terraform tests, verify the requirements exist in the // environment. // @@ -58,17 +55,15 @@ export default defineConfig({ projects: [ { name: "testsSetup", - testMatch: /global.setup\.ts/, + testMatch: /setup\/.*\.spec\.ts/, }, { name: "tests", - testMatch: /.*\.spec\.ts/, + testMatch: /tests\/.*\.spec\.ts/, dependencies: ["testsSetup"], - use: { storageState }, timeout: 30_000, }, ], - reporter: [["./reporter.ts"]], use: { actionTimeout: 5000, baseURL: `http://localhost:${coderPort}`, diff --git a/site/e2e/global.setup.ts b/site/e2e/setup/createFirstUser.spec.ts similarity index 87% rename from site/e2e/global.setup.ts rename to site/e2e/setup/createFirstUser.spec.ts index f39a2d475804e..07e798ab1c36a 100644 --- a/site/e2e/global.setup.ts +++ b/site/e2e/setup/createFirstUser.spec.ts @@ -1,10 +1,9 @@ import { expect, test } from "@playwright/test"; import { API } from "api/api"; import { Language } from "pages/CreateUserPage/CreateUserForm"; -import { setupApiCalls } from "./api"; -import * as constants from "./constants"; -import { expectUrl } from "./expectUrl"; -import { storageState } from "./playwright.config"; +import { setupApiCalls } from "../api"; +import * as constants from "../constants"; +import { expectUrl } from "../expectUrl"; test("setup deployment", async ({ page }) => { await page.goto("/", { waitUntil: "domcontentloaded" }); @@ -23,7 +22,6 @@ test("setup deployment", async ({ page }) => { await page.getByTestId("create").click(); await expectUrl(page).toHavePathName("/workspaces"); - await page.context().storageState({ path: storageState }); await page.getByTestId("button-select-template").isVisible(); diff --git a/site/e2e/tests/app.spec.ts b/site/e2e/tests/app.spec.ts index 9682fcb5751dc..384c96afcfaac 100644 --- a/site/e2e/tests/app.spec.ts +++ b/site/e2e/tests/app.spec.ts @@ -4,13 +4,17 @@ import { test } from "@playwright/test"; import { createTemplate, createWorkspace, + login, startAgent, stopAgent, stopWorkspace, } from "../helpers"; import { beforeCoderTest } from "../hooks"; -test.beforeEach(({ page }) => beforeCoderTest(page)); +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); +}); test("app", async ({ context, page }) => { test.setTimeout(75_000); diff --git a/site/e2e/tests/auditLogs.spec.ts b/site/e2e/tests/auditLogs.spec.ts index b99cea3ec2818..cb591225c7e10 100644 --- a/site/e2e/tests/auditLogs.spec.ts +++ b/site/e2e/tests/auditLogs.spec.ts @@ -1,8 +1,16 @@ import { expect, test } from "@playwright/test"; -import { createTemplate, createWorkspace, requiresLicense } from "../helpers"; +import { + createTemplate, + createWorkspace, + login, + requiresLicense, +} from "../helpers"; import { beforeCoderTest } from "../hooks"; -test.beforeEach(({ page }) => beforeCoderTest(page)); +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); +}); test("inspecting and filtering audit logs", async ({ page }) => { requiresLicense(); diff --git a/site/e2e/tests/deployment/appearance.spec.ts b/site/e2e/tests/deployment/appearance.spec.ts index 7d6bffd77fc2a..c2b129c632cb3 100644 --- a/site/e2e/tests/deployment/appearance.spec.ts +++ b/site/e2e/tests/deployment/appearance.spec.ts @@ -1,6 +1,12 @@ import { chromium, expect, test } from "@playwright/test"; import { expectUrl } from "../../expectUrl"; -import { randomName, requiresLicense } from "../../helpers"; +import { login, randomName, requiresLicense } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; + +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); +}); test("set application name", async ({ page }) => { requiresLicense(); diff --git a/site/e2e/tests/deployment/general.spec.ts b/site/e2e/tests/deployment/general.spec.ts index e4aa5fa1fe832..260a094bcfc93 100644 --- a/site/e2e/tests/deployment/general.spec.ts +++ b/site/e2e/tests/deployment/general.spec.ts @@ -2,10 +2,16 @@ import { expect, test } from "@playwright/test"; import { API } from "api/api"; import { setupApiCalls } from "../../api"; import { e2eFakeExperiment1, e2eFakeExperiment2 } from "../../constants"; +import { login } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; -test("experiments", async ({ page }) => { +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); await setupApiCalls(page); +}); +test("experiments", async ({ page }) => { // Load experiments from backend API const availableExperiments = await API.getAvailableExperiments(); diff --git a/site/e2e/tests/deployment/idpOrgSync.spec.ts b/site/e2e/tests/deployment/idpOrgSync.spec.ts index 6db2955edba97..6195af39f2be6 100644 --- a/site/e2e/tests/deployment/idpOrgSync.spec.ts +++ b/site/e2e/tests/deployment/idpOrgSync.spec.ts @@ -7,13 +7,17 @@ import { } from "../../api"; import { randomName, requiresLicense } from "../../helpers"; import { beforeCoderTest } from "../../hooks"; +import { login } from "../../helpers"; -test.describe("IdpOrgSyncPage", () => { - test.beforeEach(async ({ page }) => await beforeCoderTest(page)); +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); + await setupApiCalls(page); +}); +test.describe("IdpOrgSyncPage", () => { test("add new IdP organization mapping with API", async ({ page }) => { requiresLicense(); - await setupApiCalls(page); await createOrganizationSyncSettings(); @@ -38,7 +42,6 @@ test.describe("IdpOrgSyncPage", () => { test("delete a IdP org to coder org mapping row", async ({ page }) => { requiresLicense(); - await setupApiCalls(page); await createOrganizationSyncSettings(); await page.goto("/deployment/idp-org-sync", { waitUntil: "domcontentloaded", @@ -106,7 +109,6 @@ test.describe("IdpOrgSyncPage", () => { page, }) => { requiresLicense(); - await setupApiCalls(page); await page.goto("/deployment/idp-org-sync", { waitUntil: "domcontentloaded", @@ -121,7 +123,6 @@ test.describe("IdpOrgSyncPage", () => { test("add new IdP organization mapping with UI", async ({ page }) => { requiresLicense(); - await setupApiCalls(page); const orgName = randomName(); diff --git a/site/e2e/tests/deployment/licenses.spec.ts b/site/e2e/tests/deployment/licenses.spec.ts index c0082ed99a7ae..4352f94293599 100644 --- a/site/e2e/tests/deployment/licenses.spec.ts +++ b/site/e2e/tests/deployment/licenses.spec.ts @@ -1,5 +1,11 @@ import { expect, test } from "@playwright/test"; -import { requiresLicense } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; +import { login, requiresLicense } from "../../helpers"; + +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); +}); test("license was added successfully", async ({ page }) => { requiresLicense(); diff --git a/site/e2e/tests/deployment/network.spec.ts b/site/e2e/tests/deployment/network.spec.ts index c2c6f0f1c9cf3..00bfecefbde04 100644 --- a/site/e2e/tests/deployment/network.spec.ts +++ b/site/e2e/tests/deployment/network.spec.ts @@ -8,9 +8,16 @@ import { verifyConfigFlagNumber, verifyConfigFlagString, } from "../../api"; +import { beforeCoderTest } from "../../hooks"; +import { login } from "../../helpers"; -test("enabled network settings", async ({ page }) => { +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); await setupApiCalls(page); +}); + +test("enabled network settings", async ({ page }) => { const config = await API.getDeploymentConfig(); await page.goto("/deployment/network", { waitUntil: "domcontentloaded" }); diff --git a/site/e2e/tests/deployment/observability.spec.ts b/site/e2e/tests/deployment/observability.spec.ts index f252fd3784bac..75519acd4ea67 100644 --- a/site/e2e/tests/deployment/observability.spec.ts +++ b/site/e2e/tests/deployment/observability.spec.ts @@ -8,9 +8,16 @@ import { verifyConfigFlagEmpty, verifyConfigFlagString, } from "../../api"; +import { beforeCoderTest } from "../../hooks"; +import { login } from "../../helpers"; -test("enabled observability settings", async ({ page }) => { +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); await setupApiCalls(page); +}); + +test("enabled observability settings", async ({ page }) => { const config = await API.getDeploymentConfig(); await page.goto("/deployment/observability", { diff --git a/site/e2e/tests/deployment/security.spec.ts b/site/e2e/tests/deployment/security.spec.ts index b9c202a648232..583e74fef7d23 100644 --- a/site/e2e/tests/deployment/security.spec.ts +++ b/site/e2e/tests/deployment/security.spec.ts @@ -8,9 +8,16 @@ import { verifyConfigFlagNumber, verifyConfigFlagString, } from "../../api"; +import { beforeCoderTest } from "../../hooks"; +import { login } from "../../helpers"; -test("enabled security settings", async ({ page }) => { +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); await setupApiCalls(page); +}); + +test("enabled security settings", async ({ page }) => { const config = await API.getDeploymentConfig(); await page.goto("/deployment/security", { waitUntil: "domcontentloaded" }); diff --git a/site/e2e/tests/deployment/userAuth.spec.ts b/site/e2e/tests/deployment/userAuth.spec.ts index 11d8fc5bcc76a..49a1667365eb1 100644 --- a/site/e2e/tests/deployment/userAuth.spec.ts +++ b/site/e2e/tests/deployment/userAuth.spec.ts @@ -7,9 +7,16 @@ import { verifyConfigFlagEntries, verifyConfigFlagString, } from "../../api"; +import { beforeCoderTest } from "../../hooks"; +import { login } from "../../helpers"; -test("login with OIDC", async ({ page }) => { +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); await setupApiCalls(page); +}); + +test("login with OIDC", async ({ page }) => { const config = await API.getDeploymentConfig(); await page.goto("/deployment/userauth", { waitUntil: "domcontentloaded" }); diff --git a/site/e2e/tests/deployment/workspaceProxies.spec.ts b/site/e2e/tests/deployment/workspaceProxies.spec.ts index 0e6edd544cc60..d13d8a47a5366 100644 --- a/site/e2e/tests/deployment/workspaceProxies.spec.ts +++ b/site/e2e/tests/deployment/workspaceProxies.spec.ts @@ -4,6 +4,13 @@ import { setupApiCalls } from "../../api"; import { coderPort, workspaceProxyPort } from "../../constants"; import { randomName, requiresLicense } from "../../helpers"; import { startWorkspaceProxy, stopWorkspaceProxy } from "../../proxy"; +import { beforeCoderTest } from "../../hooks"; +import { login } from "../../helpers"; + +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); +}); test("default proxy is online", async ({ page }) => { requiresLicense(); diff --git a/site/e2e/tests/externalAuth.spec.ts b/site/e2e/tests/externalAuth.spec.ts index bb882dfcdd2db..5cfc874028125 100644 --- a/site/e2e/tests/externalAuth.spec.ts +++ b/site/e2e/tests/externalAuth.spec.ts @@ -8,6 +8,7 @@ import { createTemplate, createWorkspace, echoResponsesWithExternalAuth, + login, } from "../helpers"; import { beforeCoderTest, resetExternalAuthKey } from "../hooks"; @@ -31,9 +32,11 @@ test.beforeAll(async ({ baseURL }) => { }); }); -test.beforeEach(async ({ context }) => resetExternalAuthKey(context)); - -test.beforeEach(({ page }) => beforeCoderTest(page)); +test.beforeEach(async ({ context, page }) => { + beforeCoderTest(page); + await login(page); + await resetExternalAuthKey(context); +}); // Ensures that a Git auth provider with the device flow functions and completes! test("external auth device", async ({ page }) => { diff --git a/site/e2e/tests/groups/addMembers.spec.ts b/site/e2e/tests/groups/addMembers.spec.ts index 5ef18992f38a8..e93d1b72fbfa8 100644 --- a/site/e2e/tests/groups/addMembers.spec.ts +++ b/site/e2e/tests/groups/addMembers.spec.ts @@ -7,12 +7,17 @@ import { } from "../../api"; import { requiresLicense } from "../../helpers"; import { beforeCoderTest } from "../../hooks"; +import { login } from "../../helpers"; -test.beforeEach(async ({ page }) => await beforeCoderTest(page)); +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); + await setupApiCalls(page); +}); test("add members", async ({ page, baseURL }) => { requiresLicense(); - await setupApiCalls(page); + const orgId = await getCurrentOrgId(); const group = await createGroup(orgId); const numberOfMembers = 3; diff --git a/site/e2e/tests/groups/addUsersToDefaultGroup.spec.ts b/site/e2e/tests/groups/addUsersToDefaultGroup.spec.ts index 5524589a1bea8..2a4b70e4f017a 100644 --- a/site/e2e/tests/groups/addUsersToDefaultGroup.spec.ts +++ b/site/e2e/tests/groups/addUsersToDefaultGroup.spec.ts @@ -2,8 +2,12 @@ import { expect, test } from "@playwright/test"; import { createUser, getCurrentOrgId, setupApiCalls } from "../../api"; import { requiresLicense } from "../../helpers"; import { beforeCoderTest } from "../../hooks"; +import { login } from "../../helpers"; -test.beforeEach(async ({ page }) => await beforeCoderTest(page)); +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); +}); const DEFAULT_GROUP_NAME = "Everyone"; diff --git a/site/e2e/tests/groups/createGroup.spec.ts b/site/e2e/tests/groups/createGroup.spec.ts index 3d770a5f1cf08..4706bdf5034ad 100644 --- a/site/e2e/tests/groups/createGroup.spec.ts +++ b/site/e2e/tests/groups/createGroup.spec.ts @@ -1,11 +1,16 @@ import { expect, test } from "@playwright/test"; import { randomName, requiresLicense } from "../../helpers"; import { beforeCoderTest } from "../../hooks"; +import { login } from "../../helpers"; -test.beforeEach(async ({ page }) => await beforeCoderTest(page)); +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); +}); test("create group", async ({ page, baseURL }) => { requiresLicense(); + await page.goto(`${baseURL}/groups`, { waitUntil: "domcontentloaded" }); await expect(page).toHaveTitle("Groups - Coder"); diff --git a/site/e2e/tests/groups/removeGroup.spec.ts b/site/e2e/tests/groups/removeGroup.spec.ts index ef88280a1836a..600e2e999fe4c 100644 --- a/site/e2e/tests/groups/removeGroup.spec.ts +++ b/site/e2e/tests/groups/removeGroup.spec.ts @@ -2,12 +2,17 @@ import { expect, test } from "@playwright/test"; import { createGroup, getCurrentOrgId, setupApiCalls } from "../../api"; import { requiresLicense } from "../../helpers"; import { beforeCoderTest } from "../../hooks"; +import { login } from "../../helpers"; -test.beforeEach(async ({ page }) => await beforeCoderTest(page)); +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); + await setupApiCalls(page); +}); test("remove group", async ({ page, baseURL }) => { requiresLicense(); - await setupApiCalls(page); + const orgId = await getCurrentOrgId(); const group = await createGroup(orgId); diff --git a/site/e2e/tests/groups/removeMember.spec.ts b/site/e2e/tests/groups/removeMember.spec.ts index 0b0f5fa048363..baff47fbc1cd2 100644 --- a/site/e2e/tests/groups/removeMember.spec.ts +++ b/site/e2e/tests/groups/removeMember.spec.ts @@ -8,12 +8,17 @@ import { } from "../../api"; import { requiresLicense } from "../../helpers"; import { beforeCoderTest } from "../../hooks"; +import { login } from "../../helpers"; -test.beforeEach(async ({ page }) => await beforeCoderTest(page)); +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); + await setupApiCalls(page); +}); test("remove member", async ({ page, baseURL }) => { requiresLicense(); - await setupApiCalls(page); + const orgId = await getCurrentOrgId(); const [group, member] = await Promise.all([ createGroup(orgId), diff --git a/site/e2e/tests/organizationMembers.spec.ts b/site/e2e/tests/organizationMembers.spec.ts index a761f7c723132..de20ebd9778e7 100644 --- a/site/e2e/tests/organizationMembers.spec.ts +++ b/site/e2e/tests/organizationMembers.spec.ts @@ -1,10 +1,16 @@ import { expect, test } from "@playwright/test"; import { setupApiCalls } from "../api"; -import { createOrganization, createUser, requiresLicense } from "../helpers"; +import { + createOrganization, + createUser, + login, + requiresLicense, +} from "../helpers"; import { beforeCoderTest } from "../hooks"; test.beforeEach(async ({ page }) => { - await beforeCoderTest(page); + beforeCoderTest(page); + await login(page); await setupApiCalls(page); }); diff --git a/site/e2e/tests/organizations.spec.ts b/site/e2e/tests/organizations.spec.ts index 8d26020618643..e60806485c794 100644 --- a/site/e2e/tests/organizations.spec.ts +++ b/site/e2e/tests/organizations.spec.ts @@ -5,7 +5,7 @@ import { randomName, requiresLicense } from "../helpers"; import { beforeCoderTest } from "../hooks"; test.beforeEach(async ({ page }) => { - await beforeCoderTest(page); + beforeCoderTest(page); await setupApiCalls(page); }); diff --git a/site/e2e/tests/outdatedAgent.spec.ts b/site/e2e/tests/outdatedAgent.spec.ts index 422074d92e341..6e0cb89211c21 100644 --- a/site/e2e/tests/outdatedAgent.spec.ts +++ b/site/e2e/tests/outdatedAgent.spec.ts @@ -8,13 +8,17 @@ import { startAgentWithCommand, stopAgent, stopWorkspace, + login, } from "../helpers"; import { beforeCoderTest } from "../hooks"; // we no longer support versions w/o DRPC const agentVersion = "v2.12.1"; -test.beforeEach(({ page }) => beforeCoderTest(page)); +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); +}); test(`ssh with agent ${agentVersion}`, async ({ page }) => { test.setTimeout(60_000); diff --git a/site/e2e/tests/outdatedCLI.spec.ts b/site/e2e/tests/outdatedCLI.spec.ts index 3470367c63546..48b8b9e00f0ea 100644 --- a/site/e2e/tests/outdatedCLI.spec.ts +++ b/site/e2e/tests/outdatedCLI.spec.ts @@ -8,13 +8,17 @@ import { startAgent, stopAgent, stopWorkspace, + login, } from "../helpers"; import { beforeCoderTest } from "../hooks"; // we no longer support versions prior to Tailnet v2 API support: https://github.com/coder/coder/commit/059e533544a0268acbc8831006b2858ead2f0d8e const clientVersion = "v2.8.0"; -test.beforeEach(({ page }) => beforeCoderTest(page)); +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); +}); test(`ssh with client ${clientVersion}`, async ({ page }) => { test.setTimeout(60_000); diff --git a/site/e2e/tests/templates/listTemplates.spec.ts b/site/e2e/tests/templates/listTemplates.spec.ts index ec69d1adfc104..df9ecd66844b6 100644 --- a/site/e2e/tests/templates/listTemplates.spec.ts +++ b/site/e2e/tests/templates/listTemplates.spec.ts @@ -1,7 +1,11 @@ import { expect, test } from "@playwright/test"; import { beforeCoderTest } from "../../hooks"; +import { login } from "../../helpers"; -test.beforeEach(({ page }) => beforeCoderTest(page)); +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); +}); test("list templates", async ({ page, baseURL }) => { await page.goto(`${baseURL}/templates`, { waitUntil: "domcontentloaded" }); diff --git a/site/e2e/tests/templates/updateTemplateSchedule.spec.ts b/site/e2e/tests/templates/updateTemplateSchedule.spec.ts index ee8301557ed24..4dece57370fac 100644 --- a/site/e2e/tests/templates/updateTemplateSchedule.spec.ts +++ b/site/e2e/tests/templates/updateTemplateSchedule.spec.ts @@ -2,14 +2,18 @@ import { expect, test } from "@playwright/test"; import { API } from "api/api"; import { getCurrentOrgId, setupApiCalls } from "../../api"; import { beforeCoderTest } from "../../hooks"; +import { login } from "../../helpers"; -test.beforeEach(({ page }) => beforeCoderTest(page)); +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); + await setupApiCalls(page); +}); test("update template schedule settings without override other settings", async ({ page, baseURL, }) => { - await setupApiCalls(page); const orgId = await getCurrentOrgId(); const templateVersion = await API.createTemplateVersion(orgId, { storage_method: "file" as const, diff --git a/site/e2e/tests/updateTemplate.spec.ts b/site/e2e/tests/updateTemplate.spec.ts index 55cbfae6f5460..87f2bc0b902b3 100644 --- a/site/e2e/tests/updateTemplate.spec.ts +++ b/site/e2e/tests/updateTemplate.spec.ts @@ -8,8 +8,12 @@ import { updateTemplateSettings, } from "../helpers"; import { beforeCoderTest } from "../hooks"; +import { login } from "../helpers"; -test.beforeEach(({ page }) => beforeCoderTest(page)); +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); +}); test("template update with new name redirects on successful submit", async ({ page, diff --git a/site/e2e/tests/users/createUserWithPassword.spec.ts b/site/e2e/tests/users/createUserWithPassword.spec.ts index 20396a6ac17eb..b09ae1692b87f 100644 --- a/site/e2e/tests/users/createUserWithPassword.spec.ts +++ b/site/e2e/tests/users/createUserWithPassword.spec.ts @@ -1,8 +1,12 @@ import { test } from "@playwright/test"; import { createUser } from "../../helpers"; import { beforeCoderTest } from "../../hooks"; +import { login } from "../../helpers"; -test.beforeEach(async ({ page }) => await beforeCoderTest(page)); +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); +}); test("create user with password", async ({ page }) => { await createUser(page); diff --git a/site/e2e/tests/users/removeUser.spec.ts b/site/e2e/tests/users/removeUser.spec.ts index f414d26b74bc8..3019fee918456 100644 --- a/site/e2e/tests/users/removeUser.spec.ts +++ b/site/e2e/tests/users/removeUser.spec.ts @@ -1,11 +1,15 @@ import { expect, test } from "@playwright/test"; import { createUser, getCurrentOrgId, setupApiCalls } from "../../api"; import { beforeCoderTest } from "../../hooks"; +import { login } from "../../helpers"; -test.beforeEach(async ({ page }) => await beforeCoderTest(page)); +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); + await setupApiCalls(page); +}); test("remove user", async ({ page, baseURL }) => { - await setupApiCalls(page); const orgId = await getCurrentOrgId(); const user = await createUser(orgId); diff --git a/site/e2e/tests/webTerminal.spec.ts b/site/e2e/tests/webTerminal.spec.ts index fc6baec7daa67..70e33a9277e5e 100644 --- a/site/e2e/tests/webTerminal.spec.ts +++ b/site/e2e/tests/webTerminal.spec.ts @@ -8,8 +8,12 @@ import { stopAgent, } from "../helpers"; import { beforeCoderTest } from "../hooks"; +import { login } from "../helpers"; -test.beforeEach(({ page }) => beforeCoderTest(page)); +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); +}); test("web terminal", async ({ context, page }) => { test.setTimeout(75_000); @@ -24,9 +28,7 @@ test("web terminal", async ({ context, page }) => { agents: [ { token, - displayApps: { - webTerminal: true, - }, + displayApps: { webTerminal: true }, order: 0, }, ], diff --git a/site/e2e/tests/workspaces/autoCreateWorkspace.spec.ts b/site/e2e/tests/workspaces/autoCreateWorkspace.spec.ts index 4bb052b4e8bbb..96625ca9dfc15 100644 --- a/site/e2e/tests/workspaces/autoCreateWorkspace.spec.ts +++ b/site/e2e/tests/workspaces/autoCreateWorkspace.spec.ts @@ -7,6 +7,13 @@ import { } from "../../helpers"; import { emptyParameter } from "../../parameters"; import type { RichParameter } from "../../provisionerGenerated"; +import { beforeCoderTest } from "../../hooks"; +import { login } from "../../helpers"; + +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); +}); test("create workspace in auto mode", async ({ page }) => { const richParameters: RichParameter[] = [ diff --git a/site/e2e/tests/workspaces/createWorkspace.spec.ts b/site/e2e/tests/workspaces/createWorkspace.spec.ts index 372e9573fe9be..c9e97af488d78 100644 --- a/site/e2e/tests/workspaces/createWorkspace.spec.ts +++ b/site/e2e/tests/workspaces/createWorkspace.spec.ts @@ -20,8 +20,12 @@ import { thirdParameter, } from "../../parameters"; import type { RichParameter } from "../../provisionerGenerated"; +import { login } from "../../helpers"; -test.beforeEach(({ page }) => beforeCoderTest(page)); +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); +}); test("create workspace", async ({ page }) => { const template = await createTemplate(page, { diff --git a/site/e2e/tests/workspaces/restartWorkspace.spec.ts b/site/e2e/tests/workspaces/restartWorkspace.spec.ts index 36fbb6bc9a6c8..f72e3ef775b36 100644 --- a/site/e2e/tests/workspaces/restartWorkspace.spec.ts +++ b/site/e2e/tests/workspaces/restartWorkspace.spec.ts @@ -9,8 +9,12 @@ import { import { beforeCoderTest } from "../../hooks"; import { firstBuildOption, secondBuildOption } from "../../parameters"; import type { RichParameter } from "../../provisionerGenerated"; +import { login } from "../../helpers"; -test.beforeEach(({ page }) => beforeCoderTest(page)); +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); +}); test("restart workspace with ephemeral parameters", async ({ page }) => { const richParameters: RichParameter[] = [firstBuildOption, secondBuildOption]; diff --git a/site/e2e/tests/workspaces/startWorkspace.spec.ts b/site/e2e/tests/workspaces/startWorkspace.spec.ts index 684525130fa85..e8be9e4edabcd 100644 --- a/site/e2e/tests/workspaces/startWorkspace.spec.ts +++ b/site/e2e/tests/workspaces/startWorkspace.spec.ts @@ -7,11 +7,15 @@ import { stopWorkspace, verifyParameters, } from "../../helpers"; -import { beforeCoderTest } from "../../hooks"; import { firstBuildOption, secondBuildOption } from "../../parameters"; import type { RichParameter } from "../../provisionerGenerated"; +import { beforeCoderTest } from "../../hooks"; +import { login } from "../../helpers"; -test.beforeEach(({ page }) => beforeCoderTest(page)); +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); +}); test("start workspace with ephemeral parameters", async ({ page }) => { const richParameters: RichParameter[] = [firstBuildOption, secondBuildOption]; diff --git a/site/e2e/tests/workspaces/updateWorkspace.spec.ts b/site/e2e/tests/workspaces/updateWorkspace.spec.ts index 8018856495c40..11223c6744995 100644 --- a/site/e2e/tests/workspaces/updateWorkspace.spec.ts +++ b/site/e2e/tests/workspaces/updateWorkspace.spec.ts @@ -8,7 +8,6 @@ import { updateWorkspaceParameters, verifyParameters, } from "../../helpers"; -import { beforeCoderTest } from "../../hooks"; import { fifthParameter, firstParameter, @@ -17,8 +16,13 @@ import { sixthParameter, } from "../../parameters"; import type { RichParameter } from "../../provisionerGenerated"; +import { beforeCoderTest } from "../../hooks"; +import { login } from "../../helpers"; -test.beforeEach(({ page }) => beforeCoderTest(page)); +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); +}); test("update workspace, new optional, immutable parameter added", async ({ page, From ce83286aa3253762e15080ddeb99a4b02cbef535 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Wed, 18 Dec 2024 20:37:47 +0000 Subject: [PATCH 02/11] yaaaaaaaaaay --- site/e2e/helpers.ts | 2 ++ site/e2e/tests/auditLogs.spec.ts | 32 +++++++++++-------- site/e2e/tests/organizationGroups.spec.ts | 5 +-- site/e2e/tests/organizations.spec.ts | 3 +- .../customRoles/customRoles.spec.ts | 13 ++++---- 5 files changed, 32 insertions(+), 23 deletions(-) diff --git a/site/e2e/helpers.ts b/site/e2e/helpers.ts index acd945a675d64..a7b214c5b174d 100644 --- a/site/e2e/helpers.ts +++ b/site/e2e/helpers.ts @@ -67,9 +67,11 @@ type LoginOptions = { }; export async function login(page: Page, options?: LoginOptions) { + await page.goto("/login"); await page.getByLabel("Email").fill(options?.email || email); await page.getByLabel("Password").fill(options?.password || password); await page.getByRole("button", { name: "Sign In" }).click(); + await expectUrl(page).toHavePathName("/workspaces"); } /** diff --git a/site/e2e/tests/auditLogs.spec.ts b/site/e2e/tests/auditLogs.spec.ts index cb591225c7e10..f8fb0704bb9d9 100644 --- a/site/e2e/tests/auditLogs.spec.ts +++ b/site/e2e/tests/auditLogs.spec.ts @@ -23,17 +23,21 @@ test("inspecting and filtering audit logs", async ({ page }) => { // Go to the audit history await page.goto("/audit"); + const loginMessage = `${userName} logged in`; + const startedWorkspaceMessage = `${userName} started workspace ${workspaceName}`; + // Make sure those things we did all actually show up - await expect(page.getByText(`${userName} logged in`)).toBeVisible(); + await expect(page.getByText(loginMessage).first()).toBeVisible(); + + await page.getByText("All actions").click(); + await page.getByText("Create", { exact: true }).click(); + await expect( page.getByText(`${userName} created template ${templateName}`), ).toBeVisible(); await expect( page.getByText(`${userName} created workspace ${workspaceName}`), ).toBeVisible(); - await expect( - page.getByText(`${userName} started workspace ${workspaceName}`), - ).toBeVisible(); // Make sure we can inspect the details of the log item const createdWorkspace = page.locator(".MuiTableRow-root", { @@ -46,9 +50,14 @@ test("inspecting and filtering audit logs", async ({ page }) => { await expect( createdWorkspace.getByText(`name: "${workspaceName}"`), ).toBeVisible(); + await page.getByLabel("Clear search").click(); + await expect(page.getByText("All actions")).toBeVisible(); - const startedWorkspaceMessage = `${userName} started workspace ${workspaceName}`; - const loginMessage = `${userName} logged in`; + await page.getByText("All actions").click(); + await page.getByText("Start", { exact: true }).click(); + await expect(page.getByText(startedWorkspaceMessage)).toBeVisible(); + await page.getByLabel("Clear search").click(); + await expect(page.getByText("All actions")).toBeVisible(); // Filter by resource type await page.getByText("All resource types").click(); @@ -59,19 +68,14 @@ test("inspecting and filtering audit logs", async ({ page }) => { await expect(page.getByText(startedWorkspaceMessage)).toBeVisible(); // Logins should no longer be visible await expect(page.getByText(loginMessage)).not.toBeVisible(); - - // Clear filters, everything should be visible again await page.getByLabel("Clear search").click(); - await expect(page.getByText(startedWorkspaceMessage)).toBeVisible(); - await expect(page.getByText(loginMessage)).toBeVisible(); + await expect(page.getByText("All resource types")).toBeVisible(); // Filter by action type await page.getByText("All actions").click(); - const loginOption = page.getByText("Login"); - await loginOption.scrollIntoViewIfNeeded({ timeout: 5000 }); - await loginOption.click(); + await page.getByText("Login").click(); // Logins should be visible - await expect(page.getByText(loginMessage)).toBeVisible(); + await expect(page.getByText(loginMessage).first()).toBeVisible(); // Our workspace build should no longer be visible await expect(page.getByText(startedWorkspaceMessage)).not.toBeVisible(); }); diff --git a/site/e2e/tests/organizationGroups.spec.ts b/site/e2e/tests/organizationGroups.spec.ts index 0a049191b97df..c4ef61a3eddeb 100644 --- a/site/e2e/tests/organizationGroups.spec.ts +++ b/site/e2e/tests/organizationGroups.spec.ts @@ -6,11 +6,12 @@ import { setupApiCalls, } from "../api"; import { expectUrl } from "../expectUrl"; -import { randomName, requiresLicense } from "../helpers"; +import { login, randomName, requiresLicense } from "../helpers"; import { beforeCoderTest } from "../hooks"; test.beforeEach(async ({ page }) => { - await beforeCoderTest(page); + beforeCoderTest(page); + await login(page); await setupApiCalls(page); }); diff --git a/site/e2e/tests/organizations.spec.ts b/site/e2e/tests/organizations.spec.ts index e60806485c794..c7ea60e64eb14 100644 --- a/site/e2e/tests/organizations.spec.ts +++ b/site/e2e/tests/organizations.spec.ts @@ -1,11 +1,12 @@ import { expect, test } from "@playwright/test"; import { setupApiCalls } from "../api"; import { expectUrl } from "../expectUrl"; -import { randomName, requiresLicense } from "../helpers"; +import { login, randomName, requiresLicense } from "../helpers"; import { beforeCoderTest } from "../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); + await login(page); await setupApiCalls(page); }); diff --git a/site/e2e/tests/organizations/customRoles/customRoles.spec.ts b/site/e2e/tests/organizations/customRoles/customRoles.spec.ts index 99f8801de8141..a9e49c0921740 100644 --- a/site/e2e/tests/organizations/customRoles/customRoles.spec.ts +++ b/site/e2e/tests/organizations/customRoles/customRoles.spec.ts @@ -6,17 +6,22 @@ import { setupApiCalls, } from "../../../api"; import { + login, randomName, requiresLicense, requiresUnlicensed, } from "../../../helpers"; import { beforeCoderTest } from "../../../hooks"; +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); +}); + test.describe("CustomRolesPage", () => { - test.beforeEach(async ({ page }) => await beforeCoderTest(page)); + requiresLicense(); test("create custom role and cancel edit changes", async ({ page }) => { - requiresLicense(); await setupApiCalls(page); const org = await createOrganizationWithName(randomName()); @@ -50,7 +55,6 @@ test.describe("CustomRolesPage", () => { }); test("create custom role, edit role and save changes", async ({ page }) => { - requiresLicense(); await setupApiCalls(page); const org = await createOrganizationWithName(randomName()); @@ -101,7 +105,6 @@ test.describe("CustomRolesPage", () => { test("displays built-in role without edit/delete options", async ({ page, }) => { - requiresLicense(); await setupApiCalls(page); const org = await createOrganizationWithName(randomName()); @@ -122,7 +125,6 @@ test.describe("CustomRolesPage", () => { }); test("create custom role with UI", async ({ page }) => { - requiresLicense(); await setupApiCalls(page); const org = await createOrganizationWithName(randomName()); @@ -162,7 +164,6 @@ test.describe("CustomRolesPage", () => { }); test("delete custom role", async ({ page }) => { - requiresLicense(); await setupApiCalls(page); const org = await createOrganizationWithName(randomName()); From 621af375c46b3c9c7b1195d5c2a4318862d6498a Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Wed, 18 Dec 2024 20:43:24 +0000 Subject: [PATCH 03/11] =?UTF-8?q?=F0=9F=A7=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- site/e2e/tests/deployment/idpOrgSync.spec.ts | 2 +- site/e2e/tests/deployment/licenses.spec.ts | 2 +- site/e2e/tests/deployment/network.spec.ts | 2 +- site/e2e/tests/deployment/observability.spec.ts | 2 +- site/e2e/tests/deployment/security.spec.ts | 2 +- site/e2e/tests/deployment/userAuth.spec.ts | 2 +- site/e2e/tests/deployment/workspaceProxies.spec.ts | 4 ++-- site/e2e/tests/groups/addMembers.spec.ts | 2 +- site/e2e/tests/groups/addUsersToDefaultGroup.spec.ts | 2 +- site/e2e/tests/groups/createGroup.spec.ts | 2 +- site/e2e/tests/groups/removeGroup.spec.ts | 2 +- site/e2e/tests/groups/removeMember.spec.ts | 2 +- site/e2e/tests/outdatedAgent.spec.ts | 2 +- site/e2e/tests/outdatedCLI.spec.ts | 2 +- site/e2e/tests/templates/listTemplates.spec.ts | 2 +- site/e2e/tests/templates/updateTemplateSchedule.spec.ts | 2 +- site/e2e/tests/updateTemplate.spec.ts | 2 +- site/e2e/tests/users/createUserWithPassword.spec.ts | 2 +- site/e2e/tests/users/removeUser.spec.ts | 2 +- site/e2e/tests/webTerminal.spec.ts | 2 +- site/e2e/tests/workspaces/autoCreateWorkspace.spec.ts | 4 ++-- site/e2e/tests/workspaces/createWorkspace.spec.ts | 2 +- site/e2e/tests/workspaces/restartWorkspace.spec.ts | 2 +- site/e2e/tests/workspaces/startWorkspace.spec.ts | 4 ++-- site/e2e/tests/workspaces/updateWorkspace.spec.ts | 4 ++-- 25 files changed, 29 insertions(+), 29 deletions(-) diff --git a/site/e2e/tests/deployment/idpOrgSync.spec.ts b/site/e2e/tests/deployment/idpOrgSync.spec.ts index 6195af39f2be6..5743fd83f49e9 100644 --- a/site/e2e/tests/deployment/idpOrgSync.spec.ts +++ b/site/e2e/tests/deployment/idpOrgSync.spec.ts @@ -6,8 +6,8 @@ import { setupApiCalls, } from "../../api"; import { randomName, requiresLicense } from "../../helpers"; -import { beforeCoderTest } from "../../hooks"; import { login } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/deployment/licenses.spec.ts b/site/e2e/tests/deployment/licenses.spec.ts index 4352f94293599..734fedea91058 100644 --- a/site/e2e/tests/deployment/licenses.spec.ts +++ b/site/e2e/tests/deployment/licenses.spec.ts @@ -1,6 +1,6 @@ import { expect, test } from "@playwright/test"; -import { beforeCoderTest } from "../../hooks"; import { login, requiresLicense } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/deployment/network.spec.ts b/site/e2e/tests/deployment/network.spec.ts index 00bfecefbde04..d4898ea3e8c13 100644 --- a/site/e2e/tests/deployment/network.spec.ts +++ b/site/e2e/tests/deployment/network.spec.ts @@ -8,8 +8,8 @@ import { verifyConfigFlagNumber, verifyConfigFlagString, } from "../../api"; -import { beforeCoderTest } from "../../hooks"; import { login } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/deployment/observability.spec.ts b/site/e2e/tests/deployment/observability.spec.ts index 75519acd4ea67..b15f192a241d7 100644 --- a/site/e2e/tests/deployment/observability.spec.ts +++ b/site/e2e/tests/deployment/observability.spec.ts @@ -8,8 +8,8 @@ import { verifyConfigFlagEmpty, verifyConfigFlagString, } from "../../api"; -import { beforeCoderTest } from "../../hooks"; import { login } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/deployment/security.spec.ts b/site/e2e/tests/deployment/security.spec.ts index 583e74fef7d23..2d8bb0032691b 100644 --- a/site/e2e/tests/deployment/security.spec.ts +++ b/site/e2e/tests/deployment/security.spec.ts @@ -8,8 +8,8 @@ import { verifyConfigFlagNumber, verifyConfigFlagString, } from "../../api"; -import { beforeCoderTest } from "../../hooks"; import { login } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/deployment/userAuth.spec.ts b/site/e2e/tests/deployment/userAuth.spec.ts index 49a1667365eb1..1f97ce90dfac4 100644 --- a/site/e2e/tests/deployment/userAuth.spec.ts +++ b/site/e2e/tests/deployment/userAuth.spec.ts @@ -7,8 +7,8 @@ import { verifyConfigFlagEntries, verifyConfigFlagString, } from "../../api"; -import { beforeCoderTest } from "../../hooks"; import { login } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/deployment/workspaceProxies.spec.ts b/site/e2e/tests/deployment/workspaceProxies.spec.ts index d13d8a47a5366..f12cd23565978 100644 --- a/site/e2e/tests/deployment/workspaceProxies.spec.ts +++ b/site/e2e/tests/deployment/workspaceProxies.spec.ts @@ -3,9 +3,9 @@ import { API } from "api/api"; import { setupApiCalls } from "../../api"; import { coderPort, workspaceProxyPort } from "../../constants"; import { randomName, requiresLicense } from "../../helpers"; -import { startWorkspaceProxy, stopWorkspaceProxy } from "../../proxy"; -import { beforeCoderTest } from "../../hooks"; import { login } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; +import { startWorkspaceProxy, stopWorkspaceProxy } from "../../proxy"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/groups/addMembers.spec.ts b/site/e2e/tests/groups/addMembers.spec.ts index e93d1b72fbfa8..5b70e8910dc55 100644 --- a/site/e2e/tests/groups/addMembers.spec.ts +++ b/site/e2e/tests/groups/addMembers.spec.ts @@ -6,8 +6,8 @@ import { setupApiCalls, } from "../../api"; import { requiresLicense } from "../../helpers"; -import { beforeCoderTest } from "../../hooks"; import { login } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/groups/addUsersToDefaultGroup.spec.ts b/site/e2e/tests/groups/addUsersToDefaultGroup.spec.ts index 2a4b70e4f017a..049049265d5ae 100644 --- a/site/e2e/tests/groups/addUsersToDefaultGroup.spec.ts +++ b/site/e2e/tests/groups/addUsersToDefaultGroup.spec.ts @@ -1,8 +1,8 @@ import { expect, test } from "@playwright/test"; import { createUser, getCurrentOrgId, setupApiCalls } from "../../api"; import { requiresLicense } from "../../helpers"; -import { beforeCoderTest } from "../../hooks"; import { login } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/groups/createGroup.spec.ts b/site/e2e/tests/groups/createGroup.spec.ts index 4706bdf5034ad..fbfb775c5b950 100644 --- a/site/e2e/tests/groups/createGroup.spec.ts +++ b/site/e2e/tests/groups/createGroup.spec.ts @@ -1,7 +1,7 @@ import { expect, test } from "@playwright/test"; import { randomName, requiresLicense } from "../../helpers"; -import { beforeCoderTest } from "../../hooks"; import { login } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/groups/removeGroup.spec.ts b/site/e2e/tests/groups/removeGroup.spec.ts index 600e2e999fe4c..06d13fd0dfccf 100644 --- a/site/e2e/tests/groups/removeGroup.spec.ts +++ b/site/e2e/tests/groups/removeGroup.spec.ts @@ -1,8 +1,8 @@ import { expect, test } from "@playwright/test"; import { createGroup, getCurrentOrgId, setupApiCalls } from "../../api"; import { requiresLicense } from "../../helpers"; -import { beforeCoderTest } from "../../hooks"; import { login } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/groups/removeMember.spec.ts b/site/e2e/tests/groups/removeMember.spec.ts index baff47fbc1cd2..3b5727cc42dba 100644 --- a/site/e2e/tests/groups/removeMember.spec.ts +++ b/site/e2e/tests/groups/removeMember.spec.ts @@ -7,8 +7,8 @@ import { setupApiCalls, } from "../../api"; import { requiresLicense } from "../../helpers"; -import { beforeCoderTest } from "../../hooks"; import { login } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/outdatedAgent.spec.ts b/site/e2e/tests/outdatedAgent.spec.ts index 6e0cb89211c21..e5eefd5eb9712 100644 --- a/site/e2e/tests/outdatedAgent.spec.ts +++ b/site/e2e/tests/outdatedAgent.spec.ts @@ -4,11 +4,11 @@ import { createTemplate, createWorkspace, downloadCoderVersion, + login, sshIntoWorkspace, startAgentWithCommand, stopAgent, stopWorkspace, - login, } from "../helpers"; import { beforeCoderTest } from "../hooks"; diff --git a/site/e2e/tests/outdatedCLI.spec.ts b/site/e2e/tests/outdatedCLI.spec.ts index 48b8b9e00f0ea..8b80c4f158e7c 100644 --- a/site/e2e/tests/outdatedCLI.spec.ts +++ b/site/e2e/tests/outdatedCLI.spec.ts @@ -4,11 +4,11 @@ import { createTemplate, createWorkspace, downloadCoderVersion, + login, sshIntoWorkspace, startAgent, stopAgent, stopWorkspace, - login, } from "../helpers"; import { beforeCoderTest } from "../hooks"; diff --git a/site/e2e/tests/templates/listTemplates.spec.ts b/site/e2e/tests/templates/listTemplates.spec.ts index df9ecd66844b6..6defbe10f40dd 100644 --- a/site/e2e/tests/templates/listTemplates.spec.ts +++ b/site/e2e/tests/templates/listTemplates.spec.ts @@ -1,6 +1,6 @@ import { expect, test } from "@playwright/test"; -import { beforeCoderTest } from "../../hooks"; import { login } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/templates/updateTemplateSchedule.spec.ts b/site/e2e/tests/templates/updateTemplateSchedule.spec.ts index 4dece57370fac..3c4d7e2341611 100644 --- a/site/e2e/tests/templates/updateTemplateSchedule.spec.ts +++ b/site/e2e/tests/templates/updateTemplateSchedule.spec.ts @@ -1,8 +1,8 @@ import { expect, test } from "@playwright/test"; import { API } from "api/api"; import { getCurrentOrgId, setupApiCalls } from "../../api"; -import { beforeCoderTest } from "../../hooks"; import { login } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/updateTemplate.spec.ts b/site/e2e/tests/updateTemplate.spec.ts index 87f2bc0b902b3..4e4e311798aab 100644 --- a/site/e2e/tests/updateTemplate.spec.ts +++ b/site/e2e/tests/updateTemplate.spec.ts @@ -7,8 +7,8 @@ import { requiresLicense, updateTemplateSettings, } from "../helpers"; -import { beforeCoderTest } from "../hooks"; import { login } from "../helpers"; +import { beforeCoderTest } from "../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/users/createUserWithPassword.spec.ts b/site/e2e/tests/users/createUserWithPassword.spec.ts index b09ae1692b87f..ec6006a81dac5 100644 --- a/site/e2e/tests/users/createUserWithPassword.spec.ts +++ b/site/e2e/tests/users/createUserWithPassword.spec.ts @@ -1,7 +1,7 @@ import { test } from "@playwright/test"; import { createUser } from "../../helpers"; -import { beforeCoderTest } from "../../hooks"; import { login } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/users/removeUser.spec.ts b/site/e2e/tests/users/removeUser.spec.ts index 3019fee918456..c44d64b39c13c 100644 --- a/site/e2e/tests/users/removeUser.spec.ts +++ b/site/e2e/tests/users/removeUser.spec.ts @@ -1,7 +1,7 @@ import { expect, test } from "@playwright/test"; import { createUser, getCurrentOrgId, setupApiCalls } from "../../api"; -import { beforeCoderTest } from "../../hooks"; import { login } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/webTerminal.spec.ts b/site/e2e/tests/webTerminal.spec.ts index 70e33a9277e5e..a4923d7684e31 100644 --- a/site/e2e/tests/webTerminal.spec.ts +++ b/site/e2e/tests/webTerminal.spec.ts @@ -7,8 +7,8 @@ import { startAgent, stopAgent, } from "../helpers"; -import { beforeCoderTest } from "../hooks"; import { login } from "../helpers"; +import { beforeCoderTest } from "../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/workspaces/autoCreateWorkspace.spec.ts b/site/e2e/tests/workspaces/autoCreateWorkspace.spec.ts index 96625ca9dfc15..bdf19f7ce0b8a 100644 --- a/site/e2e/tests/workspaces/autoCreateWorkspace.spec.ts +++ b/site/e2e/tests/workspaces/autoCreateWorkspace.spec.ts @@ -5,10 +5,10 @@ import { createWorkspace, echoResponsesWithParameters, } from "../../helpers"; +import { login } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; import { emptyParameter } from "../../parameters"; import type { RichParameter } from "../../provisionerGenerated"; -import { beforeCoderTest } from "../../hooks"; -import { login } from "../../helpers"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/workspaces/createWorkspace.spec.ts b/site/e2e/tests/workspaces/createWorkspace.spec.ts index c9e97af488d78..3da239edcfa9a 100644 --- a/site/e2e/tests/workspaces/createWorkspace.spec.ts +++ b/site/e2e/tests/workspaces/createWorkspace.spec.ts @@ -8,6 +8,7 @@ import { requireTerraformProvisioner, verifyParameters, } from "../../helpers"; +import { login } from "../../helpers"; import { beforeCoderTest } from "../../hooks"; import { fifthParameter, @@ -20,7 +21,6 @@ import { thirdParameter, } from "../../parameters"; import type { RichParameter } from "../../provisionerGenerated"; -import { login } from "../../helpers"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/workspaces/restartWorkspace.spec.ts b/site/e2e/tests/workspaces/restartWorkspace.spec.ts index f72e3ef775b36..b65fa95208239 100644 --- a/site/e2e/tests/workspaces/restartWorkspace.spec.ts +++ b/site/e2e/tests/workspaces/restartWorkspace.spec.ts @@ -6,10 +6,10 @@ import { echoResponsesWithParameters, verifyParameters, } from "../../helpers"; +import { login } from "../../helpers"; import { beforeCoderTest } from "../../hooks"; import { firstBuildOption, secondBuildOption } from "../../parameters"; import type { RichParameter } from "../../provisionerGenerated"; -import { login } from "../../helpers"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/workspaces/startWorkspace.spec.ts b/site/e2e/tests/workspaces/startWorkspace.spec.ts index e8be9e4edabcd..d22c8f4f3457e 100644 --- a/site/e2e/tests/workspaces/startWorkspace.spec.ts +++ b/site/e2e/tests/workspaces/startWorkspace.spec.ts @@ -7,10 +7,10 @@ import { stopWorkspace, verifyParameters, } from "../../helpers"; +import { login } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; import { firstBuildOption, secondBuildOption } from "../../parameters"; import type { RichParameter } from "../../provisionerGenerated"; -import { beforeCoderTest } from "../../hooks"; -import { login } from "../../helpers"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); diff --git a/site/e2e/tests/workspaces/updateWorkspace.spec.ts b/site/e2e/tests/workspaces/updateWorkspace.spec.ts index 11223c6744995..1db623164699c 100644 --- a/site/e2e/tests/workspaces/updateWorkspace.spec.ts +++ b/site/e2e/tests/workspaces/updateWorkspace.spec.ts @@ -8,6 +8,8 @@ import { updateWorkspaceParameters, verifyParameters, } from "../../helpers"; +import { login } from "../../helpers"; +import { beforeCoderTest } from "../../hooks"; import { fifthParameter, firstParameter, @@ -16,8 +18,6 @@ import { sixthParameter, } from "../../parameters"; import type { RichParameter } from "../../provisionerGenerated"; -import { beforeCoderTest } from "../../hooks"; -import { login } from "../../helpers"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); From 924e7dcde70af778b4551a964be960909a7fb718 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Wed, 18 Dec 2024 20:55:25 +0000 Subject: [PATCH 04/11] yay --- site/e2e/tests/auditLogs.spec.ts | 2 +- site/e2e/tests/updateTemplate.spec.ts | 2 ++ site/e2e/tests/workspaces/autoCreateWorkspace.spec.ts | 2 ++ site/e2e/tests/workspaces/createWorkspace.spec.ts | 2 ++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/site/e2e/tests/auditLogs.spec.ts b/site/e2e/tests/auditLogs.spec.ts index f8fb0704bb9d9..e2a473fff70df 100644 --- a/site/e2e/tests/auditLogs.spec.ts +++ b/site/e2e/tests/auditLogs.spec.ts @@ -12,7 +12,7 @@ test.beforeEach(async ({ page }) => { await login(page); }); -test("inspecting and filtering audit logs", async ({ page }) => { +test.fixme("inspecting and filtering audit logs", async ({ page }) => { requiresLicense(); const userName = "admin"; diff --git a/site/e2e/tests/updateTemplate.spec.ts b/site/e2e/tests/updateTemplate.spec.ts index 4e4e311798aab..bfc50eea389dd 100644 --- a/site/e2e/tests/updateTemplate.spec.ts +++ b/site/e2e/tests/updateTemplate.spec.ts @@ -10,6 +10,8 @@ import { import { login } from "../helpers"; import { beforeCoderTest } from "../hooks"; +test.describe.configure({ mode: "parallel" }); + test.beforeEach(async ({ page }) => { beforeCoderTest(page); await login(page); diff --git a/site/e2e/tests/workspaces/autoCreateWorkspace.spec.ts b/site/e2e/tests/workspaces/autoCreateWorkspace.spec.ts index bdf19f7ce0b8a..02a918930a1d1 100644 --- a/site/e2e/tests/workspaces/autoCreateWorkspace.spec.ts +++ b/site/e2e/tests/workspaces/autoCreateWorkspace.spec.ts @@ -10,6 +10,8 @@ import { beforeCoderTest } from "../../hooks"; import { emptyParameter } from "../../parameters"; import type { RichParameter } from "../../provisionerGenerated"; +test.describe.configure({ mode: "parallel" }); + test.beforeEach(async ({ page }) => { beforeCoderTest(page); await login(page); diff --git a/site/e2e/tests/workspaces/createWorkspace.spec.ts b/site/e2e/tests/workspaces/createWorkspace.spec.ts index 3da239edcfa9a..aaafcbcd3a1af 100644 --- a/site/e2e/tests/workspaces/createWorkspace.spec.ts +++ b/site/e2e/tests/workspaces/createWorkspace.spec.ts @@ -22,6 +22,8 @@ import { } from "../../parameters"; import type { RichParameter } from "../../provisionerGenerated"; +test.describe.configure({ mode: "parallel" }); + test.beforeEach(async ({ page }) => { beforeCoderTest(page); await login(page); From a4d778eed50f2de2948682fc13d6d96c2639f535 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 19 Dec 2024 20:43:52 +0000 Subject: [PATCH 05/11] yaaay --- site/e2e/api.ts | 9 +- site/e2e/constants.ts | 28 +++++- site/e2e/helpers.ts | 89 +++++++++++++++---- ...eFirstUser.spec.ts => createUsers.spec.ts} | 32 ++++--- site/e2e/tests/auditLogs.oldspec.ts | 81 +++++++++++++++++ site/e2e/tests/auditLogs.spec.ts | 37 ++++---- site/e2e/tests/externalAuth.spec.ts | 2 +- site/e2e/tests/updateTemplate.spec.ts | 2 +- .../workspaces/autoCreateWorkspace.spec.ts | 40 ++++----- .../tests/workspaces/createWorkspace.spec.ts | 12 +-- 10 files changed, 239 insertions(+), 93 deletions(-) rename site/e2e/setup/{createFirstUser.spec.ts => createUsers.spec.ts} (57%) create mode 100644 site/e2e/tests/auditLogs.oldspec.ts diff --git a/site/e2e/api.ts b/site/e2e/api.ts index 201a899df5a26..96a2e37260767 100644 --- a/site/e2e/api.ts +++ b/site/e2e/api.ts @@ -9,14 +9,9 @@ import { findSessionToken, randomName } from "./helpers"; let currentOrgId: string; export const setupApiCalls = async (page: Page) => { - try { - const token = await findSessionToken(page); - API.setSessionToken(token); - } catch { - // If this fails, we have an unauthenticated client. - } - API.setHost(`http://127.0.0.1:${coderPort}`); + const token = await findSessionToken(page); + API.setSessionToken(token); }; export const getCurrentOrgId = async (): Promise => { diff --git a/site/e2e/constants.ts b/site/e2e/constants.ts index 9418735e22fa1..4377ebe21dc71 100644 --- a/site/e2e/constants.ts +++ b/site/e2e/constants.ts @@ -1,4 +1,5 @@ import * as path from "node:path"; +import { string } from "yup"; export const coderMain = path.join(__dirname, "../../enterprise/cmd/coder"); @@ -15,11 +16,30 @@ export const coderdPProfPort = 6062; // The name of the organization that should be used by default when needed. export const defaultOrganizationName = "coder"; +export const defaultPassword = "SomeSecurePassword!"; -// Credentials for the first user -export const username = "admin"; -export const password = "SomeSecurePassword!"; -export const email = "admin@coder.com"; +// Credentials for users +export const users = { + admin: { + username: "admin", + password: defaultPassword, + email: "admin@coder.com", + }, + auditor: { + username: "auditor", + password: defaultPassword, + email: "auditor@coder.com", + roles: ["Template Admin", "Auditor"], + }, + user: { + username: "user", + password: defaultPassword, + email: "user@coder.com", + }, +} satisfies Record< + string, + { username: string; password: string; email: string; roles?: string[] } +>; export const gitAuth = { deviceProvider: "device", diff --git a/site/e2e/helpers.ts b/site/e2e/helpers.ts index a7b214c5b174d..360f1f792fb03 100644 --- a/site/e2e/helpers.ts +++ b/site/e2e/helpers.ts @@ -18,12 +18,12 @@ import { coderMain, coderPort, defaultOrganizationName, - email, + users, license, - password, premiumTestsRequired, prometheusPort, requireTerraformTests, + defaultPassword, } from "./constants"; import { expectUrl } from "./expectUrl"; import { @@ -62,40 +62,74 @@ export function requireTerraformProvisioner() { } type LoginOptions = { + username: string; email: string; password: string; }; -export async function login(page: Page, options?: LoginOptions) { +export async function login(page: Page, options: LoginOptions = users.admin) { + const ctx = page.context(); + // biome-ignore lint/suspicious/noExplicitAny: shenanigans to make life easier + (ctx as any)[Symbol.for("currentUser")] = undefined; + await ctx.clearCookies(); await page.goto("/login"); - await page.getByLabel("Email").fill(options?.email || email); - await page.getByLabel("Password").fill(options?.password || password); + await page.getByLabel("Email").fill(options.email); + await page.getByLabel("Password").fill(options.password); await page.getByRole("button", { name: "Sign In" }).click(); await expectUrl(page).toHavePathName("/workspaces"); + // biome-ignore lint/suspicious/noExplicitAny: shenanigans to make life easier + (ctx as any)[Symbol.for("currentUser")] = options; } +export function currentUser(page: Page): LoginOptions { + const ctx = page.context(); + // biome-ignore lint/suspicious/noExplicitAny: shenanigans to make life easier + const user = (ctx as any)[Symbol.for("currentUser")]; + + if (!user) { + throw new Error("page context does not have a user. did you call `login`?"); + } + + return user; +} + +type CreateWorkspaceOptions = { + richParameters?: RichParameter[]; + buildParameters?: WorkspaceBuildParameter[]; + useExternalAuth?: boolean; +}; + /** * createWorkspace creates a workspace for a template. It does not wait for it * to be running, but it does navigate to the page. */ export const createWorkspace = async ( page: Page, - templateName: string, - richParameters: RichParameter[] = [], - buildParameters: WorkspaceBuildParameter[] = [], - useExternalAuthProvider: string | undefined = undefined, + template: string | { organization: string; name: string }, + options: CreateWorkspaceOptions = {}, ): Promise => { - await page.goto(`/templates/${templateName}/workspace`, { + const { + richParameters = [], + buildParameters = [], + useExternalAuth, + } = options; + + const templatePath = + typeof template === "string" + ? template + : `${template.organization}/${template.name}`; + + await page.goto(`/templates/${templatePath}/workspace`, { waitUntil: "domcontentloaded", }); - await expectUrl(page).toHavePathName(`/templates/${templateName}/workspace`); + await expectUrl(page).toHavePathName(`/templates/${templatePath}/workspace`); const name = randomName(); await page.getByLabel("name").fill(name); await fillParameters(page, richParameters, buildParameters); - if (useExternalAuthProvider !== undefined) { + if (useExternalAuth) { // Create a new context for the popup which will be created when clicking the button const popupPromise = page.waitForEvent("popup"); @@ -115,7 +149,9 @@ export const createWorkspace = async ( await page.getByTestId("form-submit").click(); - await expectUrl(page).toHavePathName(`/@admin/${name}`); + const user = currentUser(page); + + await expectUrl(page).toHavePathName(`/@${user.username}/${name}`); await page.waitForSelector("[data-testid='build-status'] >> text=Running", { state: "visible", @@ -228,6 +264,12 @@ export const createTemplate = async ( const orgPicker = page.getByLabel("Belongs to *"); const organizationsEnabled = await orgPicker.isVisible(); if (organizationsEnabled) { + if (orgName !== defaultOrganizationName) { + throw new Error( + `No provisioners registered for ${orgName}, creating this template will fail`, + ); + } + await orgPicker.click(); await page.getByText(orgName, { exact: true }).click(); } @@ -673,8 +715,9 @@ const createTemplateVersionTar = async ( ); }; -export const randomName = () => { - return randomUUID().slice(0, 8); +export const randomName = (annotation?: string) => { + const base = randomUUID().slice(0, 8); + return annotation ? `${annotation}-${base}` : base; }; /** @@ -1016,6 +1059,7 @@ type UserValues = { username: string; email: string; password: string; + roles: string[]; }; export async function createUser( @@ -1033,7 +1077,8 @@ export async function createUser( const username = userValues.username ?? randomName(); const name = userValues.name ?? username; const email = userValues.email ?? `${username}@coder.com`; - const password = userValues.password || "s3cure&password!"; + const password = userValues.password || defaultPassword; + const roles = userValues.roles ?? []; await page.getByLabel("Username").fill(username); if (name) { @@ -1050,10 +1095,18 @@ export async function createUser( await expect(page.getByText("Successfully created user.")).toBeVisible(); await expect(page).toHaveTitle("Users - Coder"); - await expect(page.locator("tr", { hasText: email })).toBeVisible(); + const addedRow = page.locator("tr", { hasText: email }); + await expect(addedRow).toBeVisible(); + + // Give them a role + await addedRow.getByLabel("Edit user roles").click(); + for (const role of roles) { + await page.getByText(role, { exact: true }).click(); + } + await page.mouse.click(10, 10); // close the popover by clicking outside of it await page.goto(returnTo, { waitUntil: "domcontentloaded" }); - return { name, username, email, password }; + return { name, username, email, password, roles }; } export async function createOrganization(page: Page): Promise<{ diff --git a/site/e2e/setup/createFirstUser.spec.ts b/site/e2e/setup/createUsers.spec.ts similarity index 57% rename from site/e2e/setup/createFirstUser.spec.ts rename to site/e2e/setup/createUsers.spec.ts index 07e798ab1c36a..f6817e0fd423d 100644 --- a/site/e2e/setup/createFirstUser.spec.ts +++ b/site/e2e/setup/createUsers.spec.ts @@ -1,13 +1,13 @@ import { expect, test } from "@playwright/test"; import { API } from "api/api"; import { Language } from "pages/CreateUserPage/CreateUserForm"; -import { setupApiCalls } from "../api"; -import * as constants from "../constants"; +import { coderPort, license, premiumTestsRequired, users } from "../constants"; import { expectUrl } from "../expectUrl"; +import { createUser } from "../helpers"; test("setup deployment", async ({ page }) => { await page.goto("/", { waitUntil: "domcontentloaded" }); - await setupApiCalls(page); + API.setHost(`http://127.0.0.1:${coderPort}`); const exists = await API.hasFirstUser(); // First user already exists, abort early. All tests execute this as a dependency, // if you run multiple tests in the UI, this will fail unless we check this. @@ -16,27 +16,35 @@ test("setup deployment", async ({ page }) => { } // Setup first user - await page.getByLabel(Language.usernameLabel).fill(constants.username); - await page.getByLabel(Language.emailLabel).fill(constants.email); - await page.getByLabel(Language.passwordLabel).fill(constants.password); + await page.getByLabel(Language.usernameLabel).fill(users.admin.username); + await page.getByLabel(Language.emailLabel).fill(users.admin.email); + await page.getByLabel(Language.passwordLabel).fill(users.admin.password); await page.getByTestId("create").click(); await expectUrl(page).toHavePathName("/workspaces"); - await page.getByTestId("button-select-template").isVisible(); + for (const user of Object.values(users)) { + // Already created as first user + if (user.username === "admin") { + continue; + } + + await createUser(page, user); + } + // Setup license - if (constants.premiumTestsRequired || constants.license) { + if (premiumTestsRequired || license) { // Make sure that we have something that looks like a real license - expect(constants.license).toBeTruthy(); - expect(constants.license.length).toBeGreaterThan(92); // the signature alone should be this long - expect(constants.license.split(".").length).toBe(3); // otherwise it's invalid + expect(license).toBeTruthy(); + expect(license.length).toBeGreaterThan(92); // the signature alone should be this long + expect(license.split(".").length).toBe(3); // otherwise it's invalid await page.goto("/deployment/licenses", { waitUntil: "domcontentloaded" }); await expect(page).toHaveTitle("License Settings - Coder"); await page.getByText("Add a license").click(); - await page.getByRole("textbox").fill(constants.license); + await page.getByRole("textbox").fill(license); await page.getByText("Upload License").click(); await expect( diff --git a/site/e2e/tests/auditLogs.oldspec.ts b/site/e2e/tests/auditLogs.oldspec.ts new file mode 100644 index 0000000000000..f8fb0704bb9d9 --- /dev/null +++ b/site/e2e/tests/auditLogs.oldspec.ts @@ -0,0 +1,81 @@ +import { expect, test } from "@playwright/test"; +import { + createTemplate, + createWorkspace, + login, + requiresLicense, +} from "../helpers"; +import { beforeCoderTest } from "../hooks"; + +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page); +}); + +test("inspecting and filtering audit logs", async ({ page }) => { + requiresLicense(); + + const userName = "admin"; + // Do some stuff that should show up in the audit logs + const templateName = await createTemplate(page); + const workspaceName = await createWorkspace(page, templateName); + + // Go to the audit history + await page.goto("/audit"); + + const loginMessage = `${userName} logged in`; + const startedWorkspaceMessage = `${userName} started workspace ${workspaceName}`; + + // Make sure those things we did all actually show up + await expect(page.getByText(loginMessage).first()).toBeVisible(); + + await page.getByText("All actions").click(); + await page.getByText("Create", { exact: true }).click(); + + await expect( + page.getByText(`${userName} created template ${templateName}`), + ).toBeVisible(); + await expect( + page.getByText(`${userName} created workspace ${workspaceName}`), + ).toBeVisible(); + + // Make sure we can inspect the details of the log item + const createdWorkspace = page.locator(".MuiTableRow-root", { + hasText: `${userName} created workspace ${workspaceName}`, + }); + await createdWorkspace.getByLabel("open-dropdown").click(); + await expect( + createdWorkspace.getByText(`automatic_updates: "never"`), + ).toBeVisible(); + await expect( + createdWorkspace.getByText(`name: "${workspaceName}"`), + ).toBeVisible(); + await page.getByLabel("Clear search").click(); + await expect(page.getByText("All actions")).toBeVisible(); + + await page.getByText("All actions").click(); + await page.getByText("Start", { exact: true }).click(); + await expect(page.getByText(startedWorkspaceMessage)).toBeVisible(); + await page.getByLabel("Clear search").click(); + await expect(page.getByText("All actions")).toBeVisible(); + + // Filter by resource type + await page.getByText("All resource types").click(); + const workspaceBuildsOption = page.getByText("Workspace Build"); + await workspaceBuildsOption.scrollIntoViewIfNeeded({ timeout: 5000 }); + await workspaceBuildsOption.click(); + // Our workspace build should be visible + await expect(page.getByText(startedWorkspaceMessage)).toBeVisible(); + // Logins should no longer be visible + await expect(page.getByText(loginMessage)).not.toBeVisible(); + await page.getByLabel("Clear search").click(); + await expect(page.getByText("All resource types")).toBeVisible(); + + // Filter by action type + await page.getByText("All actions").click(); + await page.getByText("Login").click(); + // Logins should be visible + await expect(page.getByText(loginMessage).first()).toBeVisible(); + // Our workspace build should no longer be visible + await expect(page.getByText(startedWorkspaceMessage)).not.toBeVisible(); +}); diff --git a/site/e2e/tests/auditLogs.spec.ts b/site/e2e/tests/auditLogs.spec.ts index e2a473fff70df..1f0e67df1e3bf 100644 --- a/site/e2e/tests/auditLogs.spec.ts +++ b/site/e2e/tests/auditLogs.spec.ts @@ -6,13 +6,14 @@ import { requiresLicense, } from "../helpers"; import { beforeCoderTest } from "../hooks"; +import { users } from "../constants"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); - await login(page); + await login(page, users.auditor); }); -test.fixme("inspecting and filtering audit logs", async ({ page }) => { +test.skip("inspecting and filtering audit logs", async ({ page }) => { requiresLicense(); const userName = "admin"; @@ -23,21 +24,17 @@ test.fixme("inspecting and filtering audit logs", async ({ page }) => { // Go to the audit history await page.goto("/audit"); - const loginMessage = `${userName} logged in`; - const startedWorkspaceMessage = `${userName} started workspace ${workspaceName}`; - // Make sure those things we did all actually show up - await expect(page.getByText(loginMessage).first()).toBeVisible(); - - await page.getByText("All actions").click(); - await page.getByText("Create", { exact: true }).click(); - + await expect(page.getByText(`${userName} logged in`)).toBeVisible(); await expect( page.getByText(`${userName} created template ${templateName}`), ).toBeVisible(); await expect( page.getByText(`${userName} created workspace ${workspaceName}`), ).toBeVisible(); + await expect( + page.getByText(`${userName} started workspace ${workspaceName}`), + ).toBeVisible(); // Make sure we can inspect the details of the log item const createdWorkspace = page.locator(".MuiTableRow-root", { @@ -50,14 +47,9 @@ test.fixme("inspecting and filtering audit logs", async ({ page }) => { await expect( createdWorkspace.getByText(`name: "${workspaceName}"`), ).toBeVisible(); - await page.getByLabel("Clear search").click(); - await expect(page.getByText("All actions")).toBeVisible(); - await page.getByText("All actions").click(); - await page.getByText("Start", { exact: true }).click(); - await expect(page.getByText(startedWorkspaceMessage)).toBeVisible(); - await page.getByLabel("Clear search").click(); - await expect(page.getByText("All actions")).toBeVisible(); + const startedWorkspaceMessage = `${userName} started workspace ${workspaceName}`; + const loginMessage = `${userName} logged in`; // Filter by resource type await page.getByText("All resource types").click(); @@ -68,14 +60,19 @@ test.fixme("inspecting and filtering audit logs", async ({ page }) => { await expect(page.getByText(startedWorkspaceMessage)).toBeVisible(); // Logins should no longer be visible await expect(page.getByText(loginMessage)).not.toBeVisible(); + + // Clear filters, everything should be visible again await page.getByLabel("Clear search").click(); - await expect(page.getByText("All resource types")).toBeVisible(); + await expect(page.getByText(startedWorkspaceMessage)).toBeVisible(); + await expect(page.getByText(loginMessage)).toBeVisible(); // Filter by action type await page.getByText("All actions").click(); - await page.getByText("Login").click(); + const loginOption = page.getByText("Login"); + await loginOption.scrollIntoViewIfNeeded({ timeout: 5000 }); + await loginOption.click(); // Logins should be visible - await expect(page.getByText(loginMessage).first()).toBeVisible(); + await expect(page.getByText(loginMessage)).toBeVisible(); // Our workspace build should no longer be visible await expect(page.getByText(startedWorkspaceMessage)).not.toBeVisible(); }); diff --git a/site/e2e/tests/externalAuth.spec.ts b/site/e2e/tests/externalAuth.spec.ts index 5cfc874028125..be86c0757286b 100644 --- a/site/e2e/tests/externalAuth.spec.ts +++ b/site/e2e/tests/externalAuth.spec.ts @@ -104,7 +104,7 @@ test("successful external auth from workspace", async ({ page }) => { ]), ); - await createWorkspace(page, templateName, [], [], gitAuth.webProvider); + await createWorkspace(page, templateName, { useExternalAuth: true }); }); const ghUser: Endpoints["GET /user"]["response"]["data"] = { diff --git a/site/e2e/tests/updateTemplate.spec.ts b/site/e2e/tests/updateTemplate.spec.ts index bfc50eea389dd..87fc7e5a104cf 100644 --- a/site/e2e/tests/updateTemplate.spec.ts +++ b/site/e2e/tests/updateTemplate.spec.ts @@ -30,7 +30,7 @@ test("add and remove a group", async ({ page }) => { requiresLicense(); const orgName = defaultOrganizationName; - const templateName = await createTemplate(page, undefined, orgName); + const templateName = await createTemplate(page); const groupName = await createGroup(page); await page.goto( diff --git a/site/e2e/tests/workspaces/autoCreateWorkspace.spec.ts b/site/e2e/tests/workspaces/autoCreateWorkspace.spec.ts index 02a918930a1d1..4bf9b26bb205e 100644 --- a/site/e2e/tests/workspaces/autoCreateWorkspace.spec.ts +++ b/site/e2e/tests/workspaces/autoCreateWorkspace.spec.ts @@ -1,5 +1,5 @@ import { expect, test } from "@playwright/test"; -import { username } from "../../constants"; +import { users } from "../../constants"; import { createTemplate, createWorkspace, @@ -12,19 +12,27 @@ import type { RichParameter } from "../../provisionerGenerated"; test.describe.configure({ mode: "parallel" }); -test.beforeEach(async ({ page }) => { - beforeCoderTest(page); +let template!: string; + +test.beforeAll(async ({ browser }) => { + const page = await (await browser.newContext()).newPage(); await login(page); -}); -test("create workspace in auto mode", async ({ page }) => { const richParameters: RichParameter[] = [ { ...emptyParameter, name: "repo", type: "string" }, ]; - const template = await createTemplate( + template = await createTemplate( page, echoResponsesWithParameters(richParameters), ); +}); + +test.beforeEach(async ({ page }) => { + beforeCoderTest(page); + await login(page, users.user); +}); + +test("create workspace in auto mode", async ({ page }) => { const name = "test-workspace"; await page.goto( `/templates/${template}/workspace?mode=auto¶m.repo=example&name=${name}`, @@ -32,19 +40,12 @@ test("create workspace in auto mode", async ({ page }) => { waitUntil: "domcontentloaded", }, ); - await expect(page).toHaveTitle(`${username}/${name} - Coder`); + await expect(page).toHaveTitle(`${users.user.username}/${name} - Coder`); }); test("use an existing workspace that matches the `match` parameter instead of creating a new one", async ({ page, }) => { - const richParameters: RichParameter[] = [ - { ...emptyParameter, name: "repo", type: "string" }, - ]; - const template = await createTemplate( - page, - echoResponsesWithParameters(richParameters), - ); const prevWorkspace = await createWorkspace(page, template); await page.goto( `/templates/${template}/workspace?mode=auto¶m.repo=example&name=new-name&match=name:${prevWorkspace}`, @@ -52,17 +53,12 @@ test("use an existing workspace that matches the `match` parameter instead of cr waitUntil: "domcontentloaded", }, ); - await expect(page).toHaveTitle(`${username}/${prevWorkspace} - Coder`); + await expect(page).toHaveTitle( + `${users.user.username}/${prevWorkspace} - Coder`, + ); }); test("show error if `match` parameter is invalid", async ({ page }) => { - const richParameters: RichParameter[] = [ - { ...emptyParameter, name: "repo", type: "string" }, - ]; - const template = await createTemplate( - page, - echoResponsesWithParameters(richParameters), - ); const prevWorkspace = await createWorkspace(page, template); await page.goto( `/templates/${template}/workspace?mode=auto¶m.repo=example&name=new-name&match=not-valid-query:${prevWorkspace}`, diff --git a/site/e2e/tests/workspaces/createWorkspace.spec.ts b/site/e2e/tests/workspaces/createWorkspace.spec.ts index aaafcbcd3a1af..4a87930c309b1 100644 --- a/site/e2e/tests/workspaces/createWorkspace.spec.ts +++ b/site/e2e/tests/workspaces/createWorkspace.spec.ts @@ -94,12 +94,10 @@ test("create workspace with default and required parameters", async ({ page, echoResponsesWithParameters(richParameters), ); - const workspaceName = await createWorkspace( - page, - template, + const workspaceName = await createWorkspace(page, template, { richParameters, buildParameters, - ); + }); await verifyParameters(page, workspaceName, richParameters, [ // user values: ...buildParameters, @@ -126,12 +124,10 @@ test("create workspace and overwrite default parameters", async ({ page }) => { echoResponsesWithParameters(richParameters), ); - const workspaceName = await createWorkspace( - page, - template, + const workspaceName = await createWorkspace(page, template, { richParameters, buildParameters, - ); + }); await verifyParameters(page, workspaceName, richParameters, buildParameters); }); From d69b6236416255a0ded5f2c86643d27cc26c9719 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 19 Dec 2024 20:55:48 +0000 Subject: [PATCH 06/11] =?UTF-8?q?=F0=9F=99=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- site/e2e/helpers.ts | 4 ++-- site/e2e/tests/auditLogs.spec.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/site/e2e/helpers.ts b/site/e2e/helpers.ts index 360f1f792fb03..3c9c42ab648ba 100644 --- a/site/e2e/helpers.ts +++ b/site/e2e/helpers.ts @@ -18,12 +18,12 @@ import { coderMain, coderPort, defaultOrganizationName, - users, + defaultPassword, license, premiumTestsRequired, prometheusPort, requireTerraformTests, - defaultPassword, + users, } from "./constants"; import { expectUrl } from "./expectUrl"; import { diff --git a/site/e2e/tests/auditLogs.spec.ts b/site/e2e/tests/auditLogs.spec.ts index 1f0e67df1e3bf..4fafe109e6e71 100644 --- a/site/e2e/tests/auditLogs.spec.ts +++ b/site/e2e/tests/auditLogs.spec.ts @@ -1,4 +1,5 @@ import { expect, test } from "@playwright/test"; +import { users } from "../constants"; import { createTemplate, createWorkspace, @@ -6,7 +7,6 @@ import { requiresLicense, } from "../helpers"; import { beforeCoderTest } from "../hooks"; -import { users } from "../constants"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); From bc1108e0058cfedb2b0ac522c53e6e48e9c6916b Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 19 Dec 2024 21:24:15 +0000 Subject: [PATCH 07/11] better comments --- site/e2e/helpers.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/site/e2e/helpers.ts b/site/e2e/helpers.ts index 3c9c42ab648ba..38a00134800f4 100644 --- a/site/e2e/helpers.ts +++ b/site/e2e/helpers.ts @@ -69,7 +69,7 @@ type LoginOptions = { export async function login(page: Page, options: LoginOptions = users.admin) { const ctx = page.context(); - // biome-ignore lint/suspicious/noExplicitAny: shenanigans to make life easier + // biome-ignore lint/suspicious/noExplicitAny: reset the current user (ctx as any)[Symbol.for("currentUser")] = undefined; await ctx.clearCookies(); await page.goto("/login"); @@ -77,13 +77,13 @@ export async function login(page: Page, options: LoginOptions = users.admin) { await page.getByLabel("Password").fill(options.password); await page.getByRole("button", { name: "Sign In" }).click(); await expectUrl(page).toHavePathName("/workspaces"); - // biome-ignore lint/suspicious/noExplicitAny: shenanigans to make life easier + // biome-ignore lint/suspicious/noExplicitAny: update once logged in (ctx as any)[Symbol.for("currentUser")] = options; } export function currentUser(page: Page): LoginOptions { const ctx = page.context(); - // biome-ignore lint/suspicious/noExplicitAny: shenanigans to make life easier + // biome-ignore lint/suspicious/noExplicitAny: get the current user const user = (ctx as any)[Symbol.for("currentUser")]; if (!user) { From de7c1dbbd97aa2da29c021b8df7cac97d2a02340 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 19 Dec 2024 22:39:39 +0000 Subject: [PATCH 08/11] real good audit logs tests --- site/e2e/playwright.config.ts | 1 + site/e2e/tests/auditLogs.oldspec.ts | 81 ------------------- site/e2e/tests/auditLogs.spec.ts | 51 +++++++----- .../tests/workspaces/createWorkspace.spec.ts | 8 +- 4 files changed, 35 insertions(+), 106 deletions(-) delete mode 100644 site/e2e/tests/auditLogs.oldspec.ts diff --git a/site/e2e/playwright.config.ts b/site/e2e/playwright.config.ts index a840cabd6b993..457d1eed745ca 100644 --- a/site/e2e/playwright.config.ts +++ b/site/e2e/playwright.config.ts @@ -64,6 +64,7 @@ export default defineConfig({ timeout: 30_000, }, ], + reporter: [["./reporter.ts"]], use: { actionTimeout: 5000, baseURL: `http://localhost:${coderPort}`, diff --git a/site/e2e/tests/auditLogs.oldspec.ts b/site/e2e/tests/auditLogs.oldspec.ts deleted file mode 100644 index f8fb0704bb9d9..0000000000000 --- a/site/e2e/tests/auditLogs.oldspec.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { expect, test } from "@playwright/test"; -import { - createTemplate, - createWorkspace, - login, - requiresLicense, -} from "../helpers"; -import { beforeCoderTest } from "../hooks"; - -test.beforeEach(async ({ page }) => { - beforeCoderTest(page); - await login(page); -}); - -test("inspecting and filtering audit logs", async ({ page }) => { - requiresLicense(); - - const userName = "admin"; - // Do some stuff that should show up in the audit logs - const templateName = await createTemplate(page); - const workspaceName = await createWorkspace(page, templateName); - - // Go to the audit history - await page.goto("/audit"); - - const loginMessage = `${userName} logged in`; - const startedWorkspaceMessage = `${userName} started workspace ${workspaceName}`; - - // Make sure those things we did all actually show up - await expect(page.getByText(loginMessage).first()).toBeVisible(); - - await page.getByText("All actions").click(); - await page.getByText("Create", { exact: true }).click(); - - await expect( - page.getByText(`${userName} created template ${templateName}`), - ).toBeVisible(); - await expect( - page.getByText(`${userName} created workspace ${workspaceName}`), - ).toBeVisible(); - - // Make sure we can inspect the details of the log item - const createdWorkspace = page.locator(".MuiTableRow-root", { - hasText: `${userName} created workspace ${workspaceName}`, - }); - await createdWorkspace.getByLabel("open-dropdown").click(); - await expect( - createdWorkspace.getByText(`automatic_updates: "never"`), - ).toBeVisible(); - await expect( - createdWorkspace.getByText(`name: "${workspaceName}"`), - ).toBeVisible(); - await page.getByLabel("Clear search").click(); - await expect(page.getByText("All actions")).toBeVisible(); - - await page.getByText("All actions").click(); - await page.getByText("Start", { exact: true }).click(); - await expect(page.getByText(startedWorkspaceMessage)).toBeVisible(); - await page.getByLabel("Clear search").click(); - await expect(page.getByText("All actions")).toBeVisible(); - - // Filter by resource type - await page.getByText("All resource types").click(); - const workspaceBuildsOption = page.getByText("Workspace Build"); - await workspaceBuildsOption.scrollIntoViewIfNeeded({ timeout: 5000 }); - await workspaceBuildsOption.click(); - // Our workspace build should be visible - await expect(page.getByText(startedWorkspaceMessage)).toBeVisible(); - // Logins should no longer be visible - await expect(page.getByText(loginMessage)).not.toBeVisible(); - await page.getByLabel("Clear search").click(); - await expect(page.getByText("All resource types")).toBeVisible(); - - // Filter by action type - await page.getByText("All actions").click(); - await page.getByText("Login").click(); - // Logins should be visible - await expect(page.getByText(loginMessage).first()).toBeVisible(); - // Our workspace build should no longer be visible - await expect(page.getByText(startedWorkspaceMessage)).not.toBeVisible(); -}); diff --git a/site/e2e/tests/auditLogs.spec.ts b/site/e2e/tests/auditLogs.spec.ts index 4fafe109e6e71..d44a0180d6e63 100644 --- a/site/e2e/tests/auditLogs.spec.ts +++ b/site/e2e/tests/auditLogs.spec.ts @@ -1,8 +1,9 @@ -import { expect, test } from "@playwright/test"; +import { expect, type Page, test } from "@playwright/test"; import { users } from "../constants"; import { createTemplate, createWorkspace, + currentUser, login, requiresLicense, } from "../helpers"; @@ -13,10 +14,22 @@ test.beforeEach(async ({ page }) => { await login(page, users.auditor); }); -test.skip("inspecting and filtering audit logs", async ({ page }) => { +async function resetSearch(page: Page) { + const clearButton = page.getByLabel("Clear search"); + if (await clearButton.isVisible()) { + await clearButton.click(); + } + + // Filter by the auditor test user to prevent race conditions + const user = currentUser(page); + await expect(page.getByText("All users")).toBeVisible(); + await page.getByPlaceholder("Search...").fill(`username:${user.username}`); + await expect(page.getByText("All users")).not.toBeVisible(); +} + +test("inspecting and filtering audit logs", async ({ page }) => { requiresLicense(); - const userName = "admin"; // Do some stuff that should show up in the audit logs const templateName = await createTemplate(page); const workspaceName = await createWorkspace(page, templateName); @@ -24,21 +37,23 @@ test.skip("inspecting and filtering audit logs", async ({ page }) => { // Go to the audit history await page.goto("/audit"); + const user = currentUser(page); + const loginMessage = `${user.username} logged in`; + const startedWorkspaceMessage = `${user.username} started workspace ${workspaceName}`; + // Make sure those things we did all actually show up - await expect(page.getByText(`${userName} logged in`)).toBeVisible(); - await expect( - page.getByText(`${userName} created template ${templateName}`), - ).toBeVisible(); + await resetSearch(page); + await expect(page.getByText(loginMessage).first()).toBeVisible(); await expect( - page.getByText(`${userName} created workspace ${workspaceName}`), + page.getByText(`${user.username} created template ${templateName}`), ).toBeVisible(); await expect( - page.getByText(`${userName} started workspace ${workspaceName}`), + page.getByText(`${user.username} created workspace ${workspaceName}`), ).toBeVisible(); // Make sure we can inspect the details of the log item const createdWorkspace = page.locator(".MuiTableRow-root", { - hasText: `${userName} created workspace ${workspaceName}`, + hasText: `${user.username} created workspace ${workspaceName}`, }); await createdWorkspace.getByLabel("open-dropdown").click(); await expect( @@ -48,10 +63,10 @@ test.skip("inspecting and filtering audit logs", async ({ page }) => { createdWorkspace.getByText(`name: "${workspaceName}"`), ).toBeVisible(); - const startedWorkspaceMessage = `${userName} started workspace ${workspaceName}`; - const loginMessage = `${userName} logged in`; + await expect(page.getByText(startedWorkspaceMessage)).toBeVisible(); // Filter by resource type + await resetSearch(page); await page.getByText("All resource types").click(); const workspaceBuildsOption = page.getByText("Workspace Build"); await workspaceBuildsOption.scrollIntoViewIfNeeded({ timeout: 5000 }); @@ -60,19 +75,15 @@ test.skip("inspecting and filtering audit logs", async ({ page }) => { await expect(page.getByText(startedWorkspaceMessage)).toBeVisible(); // Logins should no longer be visible await expect(page.getByText(loginMessage)).not.toBeVisible(); - - // Clear filters, everything should be visible again await page.getByLabel("Clear search").click(); - await expect(page.getByText(startedWorkspaceMessage)).toBeVisible(); - await expect(page.getByText(loginMessage)).toBeVisible(); + await expect(page.getByText("All resource types")).toBeVisible(); // Filter by action type + await resetSearch(page); await page.getByText("All actions").click(); - const loginOption = page.getByText("Login"); - await loginOption.scrollIntoViewIfNeeded({ timeout: 5000 }); - await loginOption.click(); + await page.getByText("Login", { exact: true }).click(); // Logins should be visible - await expect(page.getByText(loginMessage)).toBeVisible(); + await expect(page.getByText(loginMessage).first()).toBeVisible(); // Our workspace build should no longer be visible await expect(page.getByText(startedWorkspaceMessage)).not.toBeVisible(); }); diff --git a/site/e2e/tests/workspaces/createWorkspace.spec.ts b/site/e2e/tests/workspaces/createWorkspace.spec.ts index 4a87930c309b1..ce1898a31049a 100644 --- a/site/e2e/tests/workspaces/createWorkspace.spec.ts +++ b/site/e2e/tests/workspaces/createWorkspace.spec.ts @@ -153,11 +153,9 @@ test("create workspace with disable_param search params", async ({ page }) => { await expect(page.getByLabel(/Second parameter/i)).toBeDisabled(); }); -test("create docker workspace", async ({ context, page }) => { - test.skip( - true, - "creating docker containers is currently leaky. They are not cleaned up when the tests are over.", - ); +// Creating docker containers is currently leaky. They are not cleaned up when +// the tests are over. +test.skip("create docker workspace", async ({ context, page }) => { requireTerraformProvisioner(); const template = await createTemplate(page, StarterTemplates.STARTER_DOCKER); From e7dd67b1ca8ff660e17cb785c3a7dc6792b559d4 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 19 Dec 2024 22:47:09 +0000 Subject: [PATCH 09/11] split up tests --- site/e2e/tests/auditLogs.spec.ts | 38 +++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/site/e2e/tests/auditLogs.spec.ts b/site/e2e/tests/auditLogs.spec.ts index d44a0180d6e63..68a44c9e17231 100644 --- a/site/e2e/tests/auditLogs.spec.ts +++ b/site/e2e/tests/auditLogs.spec.ts @@ -9,6 +9,8 @@ import { } from "../helpers"; import { beforeCoderTest } from "../hooks"; +test.describe.configure({ mode: "parallel" }); + test.beforeEach(async ({ page }) => { beforeCoderTest(page); await login(page, users.auditor); @@ -27,7 +29,20 @@ async function resetSearch(page: Page) { await expect(page.getByText("All users")).not.toBeVisible(); } -test("inspecting and filtering audit logs", async ({ page }) => { +test("logins are logged", async ({ page }) => { + requiresLicense(); + + // Go to the audit history + await page.goto("/audit"); + + const user = currentUser(page); + const loginMessage = `${user.username} logged in`; + // Make sure those things we did all actually show up + await resetSearch(page); + await expect(page.getByText(loginMessage).first()).toBeVisible(); +}); + +test("creating templates and workspaces is logged", async ({ page }) => { requiresLicense(); // Do some stuff that should show up in the audit logs @@ -38,18 +53,18 @@ test("inspecting and filtering audit logs", async ({ page }) => { await page.goto("/audit"); const user = currentUser(page); - const loginMessage = `${user.username} logged in`; - const startedWorkspaceMessage = `${user.username} started workspace ${workspaceName}`; // Make sure those things we did all actually show up await resetSearch(page); - await expect(page.getByText(loginMessage).first()).toBeVisible(); await expect( page.getByText(`${user.username} created template ${templateName}`), ).toBeVisible(); await expect( page.getByText(`${user.username} created workspace ${workspaceName}`), ).toBeVisible(); + await expect( + page.getByText(`${user.username} started workspace ${workspaceName}`), + ).toBeVisible(); // Make sure we can inspect the details of the log item const createdWorkspace = page.locator(".MuiTableRow-root", { @@ -62,8 +77,21 @@ test("inspecting and filtering audit logs", async ({ page }) => { await expect( createdWorkspace.getByText(`name: "${workspaceName}"`), ).toBeVisible(); +}); - await expect(page.getByText(startedWorkspaceMessage)).toBeVisible(); +test("inspecting and filtering audit logs", async ({ page }) => { + requiresLicense(); + + // Do some stuff that should show up in the audit logs + const templateName = await createTemplate(page); + const workspaceName = await createWorkspace(page, templateName); + + // Go to the audit history + await page.goto("/audit"); + + const user = currentUser(page); + const loginMessage = `${user.username} logged in`; + const startedWorkspaceMessage = `${user.username} started workspace ${workspaceName}`; // Filter by resource type await resetSearch(page); From 2c008e0813cecc5d2ab1d965a78584db660587ac Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 19 Dec 2024 22:50:58 +0000 Subject: [PATCH 10/11] =?UTF-8?q?=F0=9F=A7=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- site/e2e/tests/auditLogs.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/e2e/tests/auditLogs.spec.ts b/site/e2e/tests/auditLogs.spec.ts index 68a44c9e17231..cd12f7507c1ac 100644 --- a/site/e2e/tests/auditLogs.spec.ts +++ b/site/e2e/tests/auditLogs.spec.ts @@ -1,4 +1,4 @@ -import { expect, type Page, test } from "@playwright/test"; +import { type Page, expect, test } from "@playwright/test"; import { users } from "../constants"; import { createTemplate, From c4173ea5826384740be2b774e404fdbf81409680 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 19 Dec 2024 23:07:56 +0000 Subject: [PATCH 11/11] =?UTF-8?q?=F0=9F=A7=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- site/e2e/constants.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/site/e2e/constants.ts b/site/e2e/constants.ts index 4377ebe21dc71..488ccfec58fb5 100644 --- a/site/e2e/constants.ts +++ b/site/e2e/constants.ts @@ -1,5 +1,4 @@ import * as path from "node:path"; -import { string } from "yup"; export const coderMain = path.join(__dirname, "../../enterprise/cmd/coder");