diff --git a/site/e2e/helpers.ts b/site/e2e/helpers.ts index 3ab726f245c54..e99de6e97e1bc 100644 --- a/site/e2e/helpers.ts +++ b/site/e2e/helpers.ts @@ -267,9 +267,8 @@ export const createTemplate = async ( ); } - // picker is disabled if only one org is available + // The organization picker will be disabled if there is only one option. const pickerIsDisabled = await orgPicker.isDisabled(); - if (!pickerIsDisabled) { await orgPicker.click(); await page.getByText(orgName, { exact: true }).click(); @@ -1094,8 +1093,12 @@ export async function createUser( const orgPicker = page.getByLabel("Organization *"); const organizationsEnabled = await orgPicker.isVisible(); if (organizationsEnabled) { - await orgPicker.click(); - await page.getByText(orgName, { exact: true }).click(); + // The organization picker will be disabled if there is only one option. + const pickerIsDisabled = await orgPicker.isDisabled(); + if (!pickerIsDisabled) { + await orgPicker.click(); + await page.getByText(orgName, { exact: true }).click(); + } } await page.getByLabel("Login Type").click(); diff --git a/site/e2e/tests/auditLogs.spec.ts b/site/e2e/tests/auditLogs.spec.ts index 31d3208c636fa..c25a828eedb64 100644 --- a/site/e2e/tests/auditLogs.spec.ts +++ b/site/e2e/tests/auditLogs.spec.ts @@ -1,10 +1,11 @@ import { type Page, expect, test } from "@playwright/test"; -import { users } from "../constants"; +import { defaultPassword, users } from "../constants"; import { createTemplate, + createUser, createWorkspace, - currentUser, login, + randomName, requiresLicense, } from "../helpers"; import { beforeCoderTest } from "../hooks"; @@ -15,6 +16,14 @@ test.beforeEach(async ({ page }) => { beforeCoderTest(page); }); +const name = randomName(); +const userToAudit = { + username: `peep-${name}`, + password: defaultPassword, + email: `peep-${name}@coder.com`, + roles: ["Template Admin", "User Admin"], +}; + async function resetSearch(page: Page, username: string) { const clearButton = page.getByLabel("Clear search"); if (await clearButton.isVisible()) { @@ -27,92 +36,96 @@ async function resetSearch(page: Page, username: string) { await expect(page.getByText("All users")).not.toBeVisible(); } -test("logins are logged", async ({ page }) => { +test.describe("audit logs", () => { requiresLicense(); - // Go to the audit history - await login(page, users.auditor); - await page.goto("/audit"); - const username = users.auditor.username; - - const loginMessage = `${username} logged in`; - // Make sure those things we did all actually show up - await resetSearch(page, username); - await expect(page.getByText(loginMessage).first()).toBeVisible(); -}); + test.beforeAll(async ({ browser }) => { + const context = await browser.newContext(); + const page = await context.newPage(); + await login(page); + await createUser(page, userToAudit); + }); -test("creating templates and workspaces is logged", async ({ page }) => { - requiresLicense(); + test("logins are logged", async ({ page }) => { + // Go to the audit history + await login(page, users.auditor); + await page.goto("/audit"); - // Do some stuff that should show up in the audit logs - await login(page, users.templateAdmin); - const username = users.templateAdmin.username; - const templateName = await createTemplate(page); - const workspaceName = await createWorkspace(page, templateName); - - // Go to the audit history - await login(page, users.auditor); - await page.goto("/audit"); - - // Make sure those things we did all actually show up - await resetSearch(page, username); - 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", { - hasText: `${username} created workspace ${workspaceName}`, + // Make sure those things we did all actually show up + await resetSearch(page, users.auditor.username); + const loginMessage = `${users.auditor.username} logged in`; + await expect(page.getByText(loginMessage).first()).toBeVisible(); }); - await createdWorkspace.getByLabel("open-dropdown").click(); - await expect( - createdWorkspace.getByText(`automatic_updates: "never"`), - ).toBeVisible(); - await expect( - createdWorkspace.getByText(`name: "${workspaceName}"`), - ).toBeVisible(); -}); -test("inspecting and filtering audit logs", async ({ page }) => { - requiresLicense(); + test("creating templates and workspaces is logged", async ({ page }) => { + // Do some stuff that should show up in the audit logs + await login(page, userToAudit); + const username = userToAudit.username; + const templateName = await createTemplate(page); + const workspaceName = await createWorkspace(page, templateName); + + // Go to the audit history + await login(page, users.auditor); + await page.goto("/audit"); + + // Make sure those things we did all actually show up + await resetSearch(page, username); + 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", { + 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(); + }); - // Do some stuff that should show up in the audit logs - await login(page, users.templateAdmin); - const username = users.templateAdmin.username; - const templateName = await createTemplate(page); - const workspaceName = await createWorkspace(page, templateName); - - // Go to the audit history - await login(page, users.auditor); - await page.goto("/audit"); - const loginMessage = `${username} logged in`; - const startedWorkspaceMessage = `${username} started workspace ${workspaceName}`; - - // Filter by resource type - await resetSearch(page, username); - 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 resetSearch(page, username); - await page.getByText("All actions").click(); - await page.getByText("Login", { exact: true }).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(); + test("inspecting and filtering audit logs", async ({ page }) => { + // Do some stuff that should show up in the audit logs + await login(page, userToAudit); + const username = userToAudit.username; + const templateName = await createTemplate(page); + const workspaceName = await createWorkspace(page, templateName); + + // Go to the audit history + await login(page, users.auditor); + await page.goto("/audit"); + const loginMessage = `${username} logged in`; + const startedWorkspaceMessage = `${username} started workspace ${workspaceName}`; + + // Filter by resource type + await resetSearch(page, username); + 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 resetSearch(page, username); + await page.getByText("All actions").click(); + await page.getByText("Login", { exact: true }).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/deployment/idpOrgSync.spec.ts b/site/e2e/tests/deployment/idpOrgSync.spec.ts index d77ddb1593fd3..a693e70007d4d 100644 --- a/site/e2e/tests/deployment/idpOrgSync.spec.ts +++ b/site/e2e/tests/deployment/idpOrgSync.spec.ts @@ -5,8 +5,8 @@ import { deleteOrganization, setupApiCalls, } from "../../api"; -import { randomName, requiresLicense } from "../../helpers"; -import { login } from "../../helpers"; +import { users } from "../../constants"; +import { login, randomName, requiresLicense } from "../../helpers"; import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { @@ -15,13 +15,14 @@ test.beforeEach(async ({ page }) => { await setupApiCalls(page); }); -test.describe("IdpOrgSyncPage", () => { +test.describe("IdP organization sync", () => { + requiresLicense(); + test.describe.configure({ retries: 1 }); test("show empty table when no org mappings are present", async ({ page, }) => { - requiresLicense(); await page.goto("/deployment/idp-org-sync", { waitUntil: "domcontentloaded", }); @@ -35,8 +36,6 @@ test.describe("IdpOrgSyncPage", () => { }); test("add new IdP organization mapping with API", async ({ page }) => { - requiresLicense(); - await createOrganizationSyncSettings(); await page.goto("/deployment/idp-org-sync", { @@ -59,7 +58,6 @@ test.describe("IdpOrgSyncPage", () => { }); test("delete a IdP org to coder org mapping row", async ({ page }) => { - requiresLicense(); await createOrganizationSyncSettings(); await page.goto("/deployment/idp-org-sync", { waitUntil: "domcontentloaded", @@ -77,7 +75,6 @@ test.describe("IdpOrgSyncPage", () => { }); test("update sync field", async ({ page }) => { - requiresLicense(); await page.goto("/deployment/idp-org-sync", { waitUntil: "domcontentloaded", }); @@ -100,7 +97,6 @@ test.describe("IdpOrgSyncPage", () => { }); test("toggle off default organization assignment", async ({ page }) => { - requiresLicense(); await page.goto("/deployment/idp-org-sync", { waitUntil: "domcontentloaded", }); @@ -126,8 +122,6 @@ test.describe("IdpOrgSyncPage", () => { test("export policy button is enabled when sync settings are present", async ({ page, }) => { - requiresLicense(); - await page.goto("/deployment/idp-org-sync", { waitUntil: "domcontentloaded", }); @@ -140,10 +134,7 @@ test.describe("IdpOrgSyncPage", () => { }); test("add new IdP organization mapping with UI", async ({ page }) => { - requiresLicense(); - const orgName = randomName(); - await createOrganizationWithName(orgName); await page.goto("/deployment/idp-org-sync", { @@ -172,7 +163,7 @@ test.describe("IdpOrgSyncPage", () => { await orgSelector.click(); await page.waitForTimeout(1000); - const option = await page.getByRole("option", { name: orgName }); + const option = page.getByRole("option", { name: orgName }); await expect(option).toBeAttached({ timeout: 30000 }); await expect(option).toBeVisible(); await option.click(); diff --git a/site/e2e/tests/groups/addMembers.spec.ts b/site/e2e/tests/groups/addMembers.spec.ts index 7f29f4a536385..d48b8e7beee54 100644 --- a/site/e2e/tests/groups/addMembers.spec.ts +++ b/site/e2e/tests/groups/addMembers.spec.ts @@ -5,14 +5,13 @@ import { getCurrentOrgId, setupApiCalls, } from "../../api"; -import { defaultOrganizationName } from "../../constants"; -import { requiresLicense } from "../../helpers"; -import { login } from "../../helpers"; +import { defaultOrganizationName, users } from "../../constants"; +import { login, requiresLicense } from "../../helpers"; import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); - await login(page); + await login(page, users.userAdmin); await setupApiCalls(page); }); diff --git a/site/e2e/tests/groups/addUsersToDefaultGroup.spec.ts b/site/e2e/tests/groups/addUsersToDefaultGroup.spec.ts index b1ece8705e2c6..e28566f57e73e 100644 --- a/site/e2e/tests/groups/addUsersToDefaultGroup.spec.ts +++ b/site/e2e/tests/groups/addUsersToDefaultGroup.spec.ts @@ -1,13 +1,12 @@ import { expect, test } from "@playwright/test"; import { createUser, getCurrentOrgId, setupApiCalls } from "../../api"; -import { defaultOrganizationName } from "../../constants"; -import { requiresLicense } from "../../helpers"; -import { login } from "../../helpers"; +import { defaultOrganizationName, users } from "../../constants"; +import { login, requiresLicense } from "../../helpers"; import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); - await login(page); + await login(page, users.userAdmin); }); const DEFAULT_GROUP_NAME = "Everyone"; diff --git a/site/e2e/tests/groups/createGroup.spec.ts b/site/e2e/tests/groups/createGroup.spec.ts index 8df1cdbdcc9fb..e5e6e059ebe93 100644 --- a/site/e2e/tests/groups/createGroup.spec.ts +++ b/site/e2e/tests/groups/createGroup.spec.ts @@ -1,12 +1,11 @@ import { expect, test } from "@playwright/test"; -import { defaultOrganizationName } from "../../constants"; -import { randomName, requiresLicense } from "../../helpers"; -import { login } from "../../helpers"; +import { defaultOrganizationName, users } from "../../constants"; +import { login, randomName, requiresLicense } from "../../helpers"; import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); - await login(page); + await login(page, users.userAdmin); }); test("create group", async ({ page, baseURL }) => { diff --git a/site/e2e/tests/groups/removeGroup.spec.ts b/site/e2e/tests/groups/removeGroup.spec.ts index 736b86f7d386d..7caec10d6034c 100644 --- a/site/e2e/tests/groups/removeGroup.spec.ts +++ b/site/e2e/tests/groups/removeGroup.spec.ts @@ -1,13 +1,12 @@ import { expect, test } from "@playwright/test"; import { createGroup, getCurrentOrgId, setupApiCalls } from "../../api"; -import { defaultOrganizationName } from "../../constants"; -import { requiresLicense } from "../../helpers"; -import { login } from "../../helpers"; +import { defaultOrganizationName, users } from "../../constants"; +import { login, requiresLicense } from "../../helpers"; import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); - await login(page); + await login(page, users.userAdmin); await setupApiCalls(page); }); diff --git a/site/e2e/tests/groups/removeMember.spec.ts b/site/e2e/tests/groups/removeMember.spec.ts index 81fb5ee4f4117..856ece95c0b02 100644 --- a/site/e2e/tests/groups/removeMember.spec.ts +++ b/site/e2e/tests/groups/removeMember.spec.ts @@ -6,14 +6,13 @@ import { getCurrentOrgId, setupApiCalls, } from "../../api"; -import { defaultOrganizationName } from "../../constants"; -import { requiresLicense } from "../../helpers"; -import { login } from "../../helpers"; +import { defaultOrganizationName, users } from "../../constants"; +import { login, requiresLicense } from "../../helpers"; import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); - await login(page); + await login(page, users.userAdmin); await setupApiCalls(page); }); diff --git a/site/e2e/tests/templates/listTemplates.spec.ts b/site/e2e/tests/templates/listTemplates.spec.ts index 6defbe10f40dd..d844925644881 100644 --- a/site/e2e/tests/templates/listTemplates.spec.ts +++ b/site/e2e/tests/templates/listTemplates.spec.ts @@ -1,10 +1,11 @@ import { expect, test } from "@playwright/test"; +import { users } from "../../constants"; import { login } from "../../helpers"; import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); - await login(page); + await login(page, users.templateAdmin); }); test("list templates", async ({ page, baseURL }) => { diff --git a/site/e2e/tests/templates/updateTemplateSchedule.spec.ts b/site/e2e/tests/templates/updateTemplateSchedule.spec.ts index 8c1f6a87dc2fe..42c758df5db16 100644 --- a/site/e2e/tests/templates/updateTemplateSchedule.spec.ts +++ b/site/e2e/tests/templates/updateTemplateSchedule.spec.ts @@ -1,12 +1,13 @@ import { expect, test } from "@playwright/test"; import { API } from "api/api"; import { getCurrentOrgId, setupApiCalls } from "../../api"; +import { users } from "../../constants"; import { login } from "../../helpers"; import { beforeCoderTest } from "../../hooks"; test.beforeEach(async ({ page }) => { beforeCoderTest(page); - await login(page); + await login(page, users.templateAdmin); await setupApiCalls(page); }); diff --git a/site/e2e/tests/updateTemplate.spec.ts b/site/e2e/tests/updateTemplate.spec.ts index 33e85e40e3b6d..e0bfac03cf036 100644 --- a/site/e2e/tests/updateTemplate.spec.ts +++ b/site/e2e/tests/updateTemplate.spec.ts @@ -1,20 +1,20 @@ import { expect, test } from "@playwright/test"; -import { defaultOrganizationName } from "../constants"; +import { defaultOrganizationName, users } from "../constants"; import { expectUrl } from "../expectUrl"; import { createGroup, createTemplate, + login, requiresLicense, updateTemplateSettings, } from "../helpers"; -import { login } from "../helpers"; import { beforeCoderTest } from "../hooks"; test.describe.configure({ mode: "parallel" }); test.beforeEach(async ({ page }) => { beforeCoderTest(page); - await login(page); + await login(page, users.templateAdmin); }); test("template update with new name redirects on successful submit", async ({ @@ -29,10 +29,13 @@ test("template update with new name redirects on successful submit", async ({ test("add and remove a group", async ({ page }) => { requiresLicense(); + await login(page, users.userAdmin); const orgName = defaultOrganizationName; - const templateName = await createTemplate(page); const groupName = await createGroup(page, orgName); + await login(page, users.templateAdmin); + const templateName = await createTemplate(page); + await page.goto( `/templates/${orgName}/${templateName}/settings/permissions`, { waitUntil: "domcontentloaded" },