diff --git a/scripts/lib.sh b/scripts/lib.sh index 1b4c48c784..689712eb1a 100644 --- a/scripts/lib.sh +++ b/scripts/lib.sh @@ -190,6 +190,8 @@ if [[ "${CODER_LIBSH_NO_CHECK_DEPENDENCIES:-}" != *t* ]]; then if isdarwin; then log "On darwin:" log "- brew install bash" + # shellcheck disable=SC2016 + log '- Add "$(brew --prefix bash)/bin" to your PATH' log "- Restart your terminal" fi log @@ -203,7 +205,7 @@ if [[ "${CODER_LIBSH_NO_CHECK_DEPENDENCIES:-}" != *t* ]]; then log "On darwin:" log "- brew install gnu-getopt" # shellcheck disable=SC2016 - log '- Add "$(brew --prefix)/opt/gnu-getopt/bin" to your PATH' + log '- Add "$(brew --prefix gnu-getopt)/bin" to your PATH' log "- Restart your terminal" fi log @@ -226,7 +228,7 @@ if [[ "${CODER_LIBSH_NO_CHECK_DEPENDENCIES:-}" != *t* ]]; then log "On darwin:" log "- brew install make" # shellcheck disable=SC2016 - log '- Add "$(brew --prefix)/opt/make/libexec/gnubin" to your PATH (you should Google this first)' + log '- Add "$(brew --prefix make)/libexec/gnubin" to your PATH' log "- Restart your terminal" fi log diff --git a/site/e2e/README.md b/site/e2e/README.md index 315de9dd47..72ef360335 100644 --- a/site/e2e/README.md +++ b/site/e2e/README.md @@ -12,6 +12,8 @@ cd site # Build the frontend assets. If you are actively changing # the site to debug an issue, add `--watch`. pnpm build +# Alternatively, build with debug info and source maps: +NODE_ENV=development pnpm vite build --mode=development # Install the browsers to `~/.cache/ms-playwright`. pnpm playwright:install # Run E2E tests. You can see the configuration of the server diff --git a/site/e2e/tests/app.spec.ts b/site/e2e/tests/app.spec.ts index 847ae6a7e0..78b83991a0 100644 --- a/site/e2e/tests/app.spec.ts +++ b/site/e2e/tests/app.spec.ts @@ -10,7 +10,7 @@ import { } from "../helpers"; import { beforeCoderTest } from "../hooks"; -test.beforeEach(async ({ page }) => await beforeCoderTest(page)); +test.beforeEach(({ page }) => beforeCoderTest(page)); test("app", async ({ context, page }) => { const appContent = "Hello World"; diff --git a/site/e2e/tests/auditLogs.spec.ts b/site/e2e/tests/auditLogs.spec.ts new file mode 100644 index 0000000000..d198a957e1 --- /dev/null +++ b/site/e2e/tests/auditLogs.spec.ts @@ -0,0 +1,69 @@ +import { expect, test } from "@playwright/test"; +import { + createTemplate, + createWorkspace, + requiresEnterpriseLicense, +} from "../helpers"; +import { beforeCoderTest } from "../hooks"; + +test.beforeEach(({ page }) => beforeCoderTest(page)); + +test("inspecting and filtering audit logs", async ({ page }) => { + requiresEnterpriseLicense(); + + 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"); + + // 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 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(); + + const startedWorkspaceMessage = `${userName} started workspace ${workspaceName}`; + const loginMessage = `${userName} logged in`; + + // Filter by resource type + await page.getByText("All resource types").click(); + await page.getByRole("menu").getByText("Workspace Build").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(); + + // Clear filters, everything should be visible again + await page.getByLabel("Clear filter").click(); + await expect(page.getByText(startedWorkspaceMessage)).toBeVisible(); + await expect(page.getByText(loginMessage)).toBeVisible(); + + // Filter by action type + await page.getByText("All actions").click(); + await page.getByRole("menu").getByText("Login").click(); + // Logins should be visible + 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/createWorkspace.spec.ts b/site/e2e/tests/createWorkspace.spec.ts index 6a8b4ab7ad..1fa770c5d3 100644 --- a/site/e2e/tests/createWorkspace.spec.ts +++ b/site/e2e/tests/createWorkspace.spec.ts @@ -18,7 +18,7 @@ import { } from "../parameters"; import type { RichParameter } from "../provisionerGenerated"; -test.beforeEach(async ({ page }) => await beforeCoderTest(page)); +test.beforeEach(({ page }) => beforeCoderTest(page)); test("create workspace", async ({ page }) => { const template = await createTemplate(page, { diff --git a/site/e2e/tests/externalAuth.spec.ts b/site/e2e/tests/externalAuth.spec.ts index 941fac9914..2067582ccc 100644 --- a/site/e2e/tests/externalAuth.spec.ts +++ b/site/e2e/tests/externalAuth.spec.ts @@ -5,7 +5,7 @@ import { gitAuth } from "../constants"; import { Awaiter, createServer } from "../helpers"; import { beforeCoderTest } from "../hooks"; -test.beforeEach(async ({ page }) => await beforeCoderTest(page)); +test.beforeEach(({ page }) => beforeCoderTest(page)); // 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/listTemplates.spec.ts b/site/e2e/tests/listTemplates.spec.ts index 922d7215b7..87d87109a8 100644 --- a/site/e2e/tests/listTemplates.spec.ts +++ b/site/e2e/tests/listTemplates.spec.ts @@ -1,7 +1,7 @@ import { test, expect } from "@playwright/test"; import { beforeCoderTest } from "../hooks"; -test.beforeEach(async ({ page }) => await beforeCoderTest(page)); +test.beforeEach(({ page }) => beforeCoderTest(page)); test("list templates", async ({ page, baseURL }) => { await page.goto(`${baseURL}/templates`, { waitUntil: "domcontentloaded" }); diff --git a/site/e2e/tests/outdatedAgent.spec.ts b/site/e2e/tests/outdatedAgent.spec.ts index 56207e9dbc..c6bccba658 100644 --- a/site/e2e/tests/outdatedAgent.spec.ts +++ b/site/e2e/tests/outdatedAgent.spec.ts @@ -14,7 +14,7 @@ import { beforeCoderTest } from "../hooks"; // we no longer support versions prior to single tailnet: https://github.com/coder/coder/commit/d7cbdbd9c64ad26821e6b35834c59ecf85dcd9d4 const agentVersion = "v0.27.0"; -test.beforeEach(async ({ page }) => await beforeCoderTest(page)); +test.beforeEach(({ page }) => beforeCoderTest(page)); test("ssh with agent " + agentVersion, async ({ page }) => { test.setTimeout(40_000); // This is a slow test, 20s may not be enough on Mac. diff --git a/site/e2e/tests/outdatedCLI.spec.ts b/site/e2e/tests/outdatedCLI.spec.ts index ca4957ccee..55afdef7f4 100644 --- a/site/e2e/tests/outdatedCLI.spec.ts +++ b/site/e2e/tests/outdatedCLI.spec.ts @@ -14,7 +14,7 @@ import { beforeCoderTest } from "../hooks"; // we no longer support versions prior to single tailnet: https://github.com/coder/coder/commit/d7cbdbd9c64ad26821e6b35834c59ecf85dcd9d4 const clientVersion = "v0.27.0"; -test.beforeEach(async ({ page }) => await beforeCoderTest(page)); +test.beforeEach(({ page }) => beforeCoderTest(page)); test("ssh with client " + clientVersion, async ({ page }) => { const token = randomUUID(); diff --git a/site/e2e/tests/restartWorkspace.spec.ts b/site/e2e/tests/restartWorkspace.spec.ts index 1e066aea0b..0da42b1257 100644 --- a/site/e2e/tests/restartWorkspace.spec.ts +++ b/site/e2e/tests/restartWorkspace.spec.ts @@ -10,7 +10,7 @@ import { beforeCoderTest } from "../hooks"; import { firstBuildOption, secondBuildOption } from "../parameters"; import type { RichParameter } from "../provisionerGenerated"; -test.beforeEach(async ({ page }) => await beforeCoderTest(page)); +test.beforeEach(({ page }) => beforeCoderTest(page)); test("restart workspace with ephemeral parameters", async ({ page }) => { const richParameters: RichParameter[] = [firstBuildOption, secondBuildOption]; diff --git a/site/e2e/tests/startWorkspace.spec.ts b/site/e2e/tests/startWorkspace.spec.ts index 054bbf1721..eb180c3df4 100644 --- a/site/e2e/tests/startWorkspace.spec.ts +++ b/site/e2e/tests/startWorkspace.spec.ts @@ -7,9 +7,12 @@ import { stopWorkspace, verifyParameters, } from "../helpers"; +import { beforeCoderTest } from "../hooks"; import { firstBuildOption, secondBuildOption } from "../parameters"; import type { RichParameter } from "../provisionerGenerated"; +test.beforeEach(({ page }) => beforeCoderTest(page)); + test("start workspace with ephemeral parameters", async ({ page }) => { const richParameters: RichParameter[] = [firstBuildOption, secondBuildOption]; const template = await createTemplate( diff --git a/site/e2e/tests/updateTemplate.spec.ts b/site/e2e/tests/updateTemplate.spec.ts index 4e967b2947..c35ebcd6d1 100644 --- a/site/e2e/tests/updateTemplate.spec.ts +++ b/site/e2e/tests/updateTemplate.spec.ts @@ -6,6 +6,9 @@ import { requiresEnterpriseLicense, updateTemplateSettings, } from "../helpers"; +import { beforeCoderTest } from "../hooks"; + +test.beforeEach(({ page }) => beforeCoderTest(page)); test("template update with new name redirects on successful submit", async ({ page, diff --git a/site/e2e/tests/updateWorkspace.spec.ts b/site/e2e/tests/updateWorkspace.spec.ts index 5de1c42e01..40b62aa1fc 100644 --- a/site/e2e/tests/updateWorkspace.spec.ts +++ b/site/e2e/tests/updateWorkspace.spec.ts @@ -18,7 +18,7 @@ import { } from "../parameters"; import type { RichParameter } from "../provisionerGenerated"; -test.beforeEach(async ({ page }) => await beforeCoderTest(page)); +test.beforeEach(({ page }) => beforeCoderTest(page)); test("update workspace, new optional, immutable parameter added", async ({ page, diff --git a/site/e2e/tests/webTerminal.spec.ts b/site/e2e/tests/webTerminal.spec.ts index 37ab01d78e..d4221ae036 100644 --- a/site/e2e/tests/webTerminal.spec.ts +++ b/site/e2e/tests/webTerminal.spec.ts @@ -9,7 +9,7 @@ import { } from "../helpers"; import { beforeCoderTest } from "../hooks"; -test.beforeEach(async ({ page }) => await beforeCoderTest(page)); +test.beforeEach(({ page }) => beforeCoderTest(page)); test("web terminal", async ({ context, page }) => { const token = randomUUID();