mirror of https://github.com/coder/coder.git
Merge 6ae522927f
into f2dd0a8e5d
This commit is contained in:
commit
40406f538b
|
@ -482,6 +482,15 @@ jobs:
|
|||
# tests are failing.
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload Chromatic archive
|
||||
# TODO: We really want this to catch the enterprise snapshots, once those tests
|
||||
# pass consistently. ie. remove the `!` from `matrix.variant.enterprise` here.
|
||||
if: ${{ !matrix.variant.enterprise && github.repository_owner == 'coder' }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: playwright-e2e-chromatic-archive
|
||||
path: ./site/test-results/chromatic-archives/
|
||||
|
||||
- name: Upload Playwright Failed Tests
|
||||
if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' && !github.event.pull_request.head.repo.fork
|
||||
uses: actions/upload-artifact@v4
|
||||
|
@ -499,9 +508,8 @@ jobs:
|
|||
retention-days: 7
|
||||
|
||||
chromatic:
|
||||
# REMARK: this is only used to build storybook and deploy it to Chromatic.
|
||||
runs-on: ubuntu-latest
|
||||
needs: changes
|
||||
needs: [changes, test-e2e]
|
||||
if: needs.changes.outputs.ts == 'true' || needs.changes.outputs.ci == 'true'
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
@ -514,12 +522,17 @@ jobs:
|
|||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node
|
||||
|
||||
- name: Get Playwright results archive
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: playwright-e2e-chromatic-archive
|
||||
path: ./site/test-results/chromatic-archives/
|
||||
# This step is not meant for mainline because any detected changes to
|
||||
# storybook snapshots will require manual approval/review in order for
|
||||
# the check to pass. This is desired in PRs, but not in mainline.
|
||||
- name: Publish to Chromatic (non-mainline)
|
||||
if: github.ref != 'refs/heads/main' && github.repository_owner == 'coder'
|
||||
uses: chromaui/action@v10
|
||||
uses: chromaui/action@v11
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
STORYBOOK: true
|
||||
|
@ -541,6 +554,7 @@ jobs:
|
|||
onlyChanged: true
|
||||
# Avoid uploading single files, because that's very slow
|
||||
zip: true
|
||||
playwright: true
|
||||
|
||||
# This is a separate step for mainline only that auto accepts and changes
|
||||
# instead of holding CI up. Since we squash/merge, this is defensive to
|
||||
|
@ -550,7 +564,7 @@ jobs:
|
|||
# infinitely "in progress" in mainline unless we re-review each build.
|
||||
- name: Publish to Chromatic (mainline)
|
||||
if: github.ref == 'refs/heads/main' && github.repository_owner == 'coder'
|
||||
uses: chromaui/action@v10
|
||||
uses: chromaui/action@v11
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
STORYBOOK: true
|
||||
|
@ -568,6 +582,7 @@ jobs:
|
|||
onlyChanged: true
|
||||
# Avoid uploading single files, because that's very slow
|
||||
zip: true
|
||||
playwright: true
|
||||
|
||||
offlinedocs:
|
||||
name: offlinedocs
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import { test, expect as chromaticExpect } from "@chromatic/test";
|
||||
import { mergeExpects } from "@playwright/test";
|
||||
import { expectUrl } from "./expectUrl";
|
||||
|
||||
const mergedExpect = mergeExpects(chromaticExpect, expectUrl);
|
||||
export { mergedExpect as expect };
|
||||
export { test };
|
||||
|
||||
export { chromium, firefox, type Page, webkit } from "@playwright/test";
|
|
@ -1,4 +1,3 @@
|
|||
import { test } from "@playwright/test";
|
||||
import { randomUUID } from "crypto";
|
||||
import * as http from "http";
|
||||
import {
|
||||
|
@ -9,10 +8,11 @@ import {
|
|||
stopWorkspace,
|
||||
} from "../helpers";
|
||||
import { beforeCoderTest } from "../hooks";
|
||||
import { test } from "../testing";
|
||||
|
||||
test.beforeEach(({ page }) => beforeCoderTest(page));
|
||||
|
||||
test("app", async ({ context, page }) => {
|
||||
test.skip("app", async ({ context, page }) => {
|
||||
const appContent = "Hello World";
|
||||
const token = randomUUID();
|
||||
const srv = http
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import {
|
||||
createTemplate,
|
||||
createWorkspace,
|
||||
requiresEnterpriseLicense,
|
||||
} from "../helpers";
|
||||
import { beforeCoderTest } from "../hooks";
|
||||
import { expect, test } from "../testing";
|
||||
|
||||
test.beforeEach(({ page }) => beforeCoderTest(page));
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { test, expect } from "@playwright/test";
|
||||
import {
|
||||
createTemplate,
|
||||
createWorkspace,
|
||||
|
@ -17,6 +16,7 @@ import {
|
|||
randParamName,
|
||||
} from "../parameters";
|
||||
import type { RichParameter } from "../provisionerGenerated";
|
||||
import { expect, test } from "../testing";
|
||||
|
||||
test.beforeEach(({ page }) => beforeCoderTest(page));
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { chromium, expect, test } from "@playwright/test";
|
||||
import { expectUrl } from "../../expectUrl";
|
||||
import { randomName, requiresEnterpriseLicense } from "../../helpers";
|
||||
import { chromium, expect, test } from "../../testing";
|
||||
|
||||
test("set application name", async ({ page }) => {
|
||||
requiresEnterpriseLicense();
|
||||
|
@ -75,7 +74,7 @@ test("set service banner", async ({ page }) => {
|
|||
|
||||
// Verify service banner
|
||||
await page.goto("/workspaces", { waitUntil: "domcontentloaded" });
|
||||
await expectUrl(page).toHavePathName("/workspaces");
|
||||
await expect(page).toHavePathName("/workspaces");
|
||||
|
||||
const bar = page.locator("div.service-banner", { hasText: message });
|
||||
await expect(bar).toBeVisible();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import * as API from "api/api";
|
||||
import { setupApiCalls } from "../../api";
|
||||
import { e2eFakeExperiment1, e2eFakeExperiment2 } from "../../constants";
|
||||
import { expect, test } from "../../testing";
|
||||
|
||||
test("experiments", async ({ page }) => {
|
||||
await setupApiCalls(page);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import { requiresEnterpriseLicense } from "../../helpers";
|
||||
import { expect, test } from "../../testing";
|
||||
|
||||
test("license was added successfully", async ({ page }) => {
|
||||
requiresEnterpriseLicense();
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { test } from "@playwright/test";
|
||||
import { getDeploymentConfig } from "api/api";
|
||||
import {
|
||||
setupApiCalls,
|
||||
|
@ -8,6 +7,7 @@ import {
|
|||
verifyConfigFlagNumber,
|
||||
verifyConfigFlagString,
|
||||
} from "../../api";
|
||||
import { test } from "../../testing";
|
||||
|
||||
test("enabled network settings", async ({ page }) => {
|
||||
await setupApiCalls(page);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { test } from "@playwright/test";
|
||||
import { getDeploymentConfig } from "api/api";
|
||||
import {
|
||||
setupApiCalls,
|
||||
|
@ -8,6 +7,7 @@ import {
|
|||
verifyConfigFlagEmpty,
|
||||
verifyConfigFlagString,
|
||||
} from "../../api";
|
||||
import { test } from "../../testing";
|
||||
|
||||
test("enabled observability settings", async ({ page }) => {
|
||||
await setupApiCalls(page);
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import type { Page } from "@playwright/test";
|
||||
import { expect, test } from "@playwright/test";
|
||||
import type * as API from "api/api";
|
||||
import { getDeploymentConfig } from "api/api";
|
||||
import {
|
||||
|
@ -9,6 +7,7 @@ import {
|
|||
verifyConfigFlagNumber,
|
||||
verifyConfigFlagString,
|
||||
} from "../../api";
|
||||
import { expect, type Page, test } from "../../testing";
|
||||
|
||||
test("enabled security settings", async ({ page }) => {
|
||||
await setupApiCalls(page);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { test } from "@playwright/test";
|
||||
import { getDeploymentConfig } from "api/api";
|
||||
import {
|
||||
setupApiCalls,
|
||||
|
@ -7,6 +6,7 @@ import {
|
|||
verifyConfigFlagEntries,
|
||||
verifyConfigFlagString,
|
||||
} from "../../api";
|
||||
import { test } from "../../testing";
|
||||
|
||||
test("login with OIDC", async ({ page }) => {
|
||||
await setupApiCalls(page);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { test, expect, type Page } from "@playwright/test";
|
||||
import { createWorkspaceProxy } from "api/api";
|
||||
import { setupApiCalls } from "../../api";
|
||||
import { coderPort, workspaceProxyPort } from "../../constants";
|
||||
import { randomName, requiresEnterpriseLicense } from "../../helpers";
|
||||
import { startWorkspaceProxy, stopWorkspaceProxy } from "../../proxy";
|
||||
import { expect, type Page, test } from "../../testing";
|
||||
|
||||
test("default proxy is online", async ({ page }) => {
|
||||
requiresEnterpriseLicense();
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import type { Endpoints } from "@octokit/types";
|
||||
import { test } from "@playwright/test";
|
||||
import type { ExternalAuthDevice } from "api/typesGenerated";
|
||||
import { gitAuth } from "../constants";
|
||||
import {
|
||||
|
@ -10,6 +9,7 @@ import {
|
|||
echoResponsesWithExternalAuth,
|
||||
} from "../helpers";
|
||||
import { beforeCoderTest, resetExternalAuthKey } from "../hooks";
|
||||
import { test } from "../testing";
|
||||
|
||||
test.beforeAll(async ({ baseURL }) => {
|
||||
const srv = await createServer(gitAuth.webPort);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { test, expect } from "@playwright/test";
|
||||
import {
|
||||
createGroup,
|
||||
createUser,
|
||||
|
@ -7,6 +6,7 @@ import {
|
|||
} from "../../api";
|
||||
import { requiresEnterpriseLicense } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
import { expect, test } from "../../testing";
|
||||
|
||||
test.beforeEach(async ({ page }) => await beforeCoderTest(page));
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { test, expect } from "@playwright/test";
|
||||
import { createUser, getCurrentOrgId, setupApiCalls } from "../../api";
|
||||
import { requiresEnterpriseLicense } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
import { expect, test } from "../../testing";
|
||||
|
||||
test.beforeEach(async ({ page }) => await beforeCoderTest(page));
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { test, expect } from "@playwright/test";
|
||||
import { randomName, requiresEnterpriseLicense } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
import { expect, test } from "../../testing";
|
||||
|
||||
test.beforeEach(async ({ page }) => await beforeCoderTest(page));
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { test, expect } from "@playwright/test";
|
||||
import { createGroup, getCurrentOrgId, setupApiCalls } from "../../api";
|
||||
import { requiresEnterpriseLicense } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
import { expect, test } from "../../testing";
|
||||
|
||||
test.beforeEach(async ({ page }) => await beforeCoderTest(page));
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { test, expect } from "@playwright/test";
|
||||
import { createGroup, getCurrentOrgId, setupApiCalls } from "../../api";
|
||||
import { requiresEnterpriseLicense } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
import { expect, test } from "../../testing";
|
||||
|
||||
test.beforeEach(async ({ page }) => await beforeCoderTest(page));
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { test, expect } from "@playwright/test";
|
||||
import * as API from "api/api";
|
||||
import {
|
||||
createGroup,
|
||||
|
@ -8,6 +7,7 @@ import {
|
|||
} from "../../api";
|
||||
import { requiresEnterpriseLicense } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
import { expect, test } from "../../testing";
|
||||
|
||||
test.beforeEach(async ({ page }) => await beforeCoderTest(page));
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { test, expect } from "@playwright/test";
|
||||
import { beforeCoderTest } from "../hooks";
|
||||
import { expect, test } from "../testing";
|
||||
|
||||
test.beforeEach(({ page }) => beforeCoderTest(page));
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { test } from "@playwright/test";
|
||||
import { randomUUID } from "crypto";
|
||||
import {
|
||||
createTemplate,
|
||||
|
@ -10,13 +9,14 @@ import {
|
|||
stopWorkspace,
|
||||
} from "../helpers";
|
||||
import { beforeCoderTest } from "../hooks";
|
||||
import { test } from "../testing";
|
||||
|
||||
// we no longer support versions prior to single tailnet: https://github.com/coder/coder/commit/d7cbdbd9c64ad26821e6b35834c59ecf85dcd9d4
|
||||
const agentVersion = "v0.27.0";
|
||||
|
||||
test.beforeEach(({ page }) => beforeCoderTest(page));
|
||||
|
||||
test("ssh with agent " + agentVersion, async ({ page }) => {
|
||||
test.skip("ssh with agent " + agentVersion, async ({ page }) => {
|
||||
test.setTimeout(40_000); // This is a slow test, 20s may not be enough on Mac.
|
||||
|
||||
const token = randomUUID();
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { test } from "@playwright/test";
|
||||
import { randomUUID } from "crypto";
|
||||
import {
|
||||
createTemplate,
|
||||
|
@ -10,13 +9,14 @@ import {
|
|||
stopWorkspace,
|
||||
} from "../helpers";
|
||||
import { beforeCoderTest } from "../hooks";
|
||||
import { test } from "../testing";
|
||||
|
||||
// we no longer support versions prior to single tailnet: https://github.com/coder/coder/commit/d7cbdbd9c64ad26821e6b35834c59ecf85dcd9d4
|
||||
const clientVersion = "v0.27.0";
|
||||
|
||||
test.beforeEach(({ page }) => beforeCoderTest(page));
|
||||
|
||||
test("ssh with client " + clientVersion, async ({ page }) => {
|
||||
test.skip("ssh with client " + clientVersion, async ({ page }) => {
|
||||
const token = randomUUID();
|
||||
const template = await createTemplate(page, {
|
||||
apply: [
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { test } from "@playwright/test";
|
||||
import {
|
||||
buildWorkspaceWithParameters,
|
||||
createTemplate,
|
||||
|
@ -9,6 +8,7 @@ import {
|
|||
import { beforeCoderTest } from "../hooks";
|
||||
import { firstBuildOption, secondBuildOption } from "../parameters";
|
||||
import type { RichParameter } from "../provisionerGenerated";
|
||||
import { test } from "../testing";
|
||||
|
||||
test.beforeEach(({ page }) => beforeCoderTest(page));
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { test } from "@playwright/test";
|
||||
import {
|
||||
buildWorkspaceWithParameters,
|
||||
createTemplate,
|
||||
|
@ -10,10 +9,11 @@ import {
|
|||
import { beforeCoderTest } from "../hooks";
|
||||
import { firstBuildOption, secondBuildOption } from "../parameters";
|
||||
import type { RichParameter } from "../provisionerGenerated";
|
||||
import { test } from "../testing";
|
||||
|
||||
test.beforeEach(({ page }) => beforeCoderTest(page));
|
||||
|
||||
test("start workspace with ephemeral parameters", async ({ page }) => {
|
||||
test.skip("start workspace with ephemeral parameters", async ({ page }) => {
|
||||
const richParameters: RichParameter[] = [firstBuildOption, secondBuildOption];
|
||||
const template = await createTemplate(
|
||||
page,
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import { expectUrl } from "../expectUrl";
|
||||
import {
|
||||
createGroup,
|
||||
createTemplate,
|
||||
|
@ -7,6 +5,7 @@ import {
|
|||
updateTemplateSettings,
|
||||
} from "../helpers";
|
||||
import { beforeCoderTest } from "../hooks";
|
||||
import { expect, test } from "../testing";
|
||||
|
||||
test.beforeEach(({ page }) => beforeCoderTest(page));
|
||||
|
||||
|
@ -29,7 +28,7 @@ test("add and remove a group", async ({ page }) => {
|
|||
await page.goto(`/templates/${templateName}/settings/permissions`, {
|
||||
waitUntil: "domcontentloaded",
|
||||
});
|
||||
await expectUrl(page).toHavePathName(
|
||||
await expect(page).toHavePathName(
|
||||
`/templates/${templateName}/settings/permissions`,
|
||||
);
|
||||
|
||||
|
@ -59,7 +58,7 @@ test("require latest version", async ({ page }) => {
|
|||
await page.goto(`/templates/${templateName}/settings`, {
|
||||
waitUntil: "domcontentloaded",
|
||||
});
|
||||
await expectUrl(page).toHavePathName(`/templates/${templateName}/settings`);
|
||||
await expect(page).toHavePathName(`/templates/${templateName}/settings`);
|
||||
let checkbox = await page.waitForSelector("#require_active_version");
|
||||
await checkbox.click();
|
||||
await page.getByTestId("form-submit").click();
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { test } from "@playwright/test";
|
||||
import {
|
||||
createTemplate,
|
||||
createWorkspace,
|
||||
|
@ -17,6 +16,7 @@ import {
|
|||
secondBuildOption,
|
||||
} from "../parameters";
|
||||
import type { RichParameter } from "../provisionerGenerated";
|
||||
import { test } from "../testing";
|
||||
|
||||
test.beforeEach(({ page }) => beforeCoderTest(page));
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { test, expect } from "@playwright/test";
|
||||
import { randomName } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
import { expect, test } from "../../testing";
|
||||
|
||||
test.beforeEach(async ({ page }) => await beforeCoderTest(page));
|
||||
test.beforeEach(({ page }) => beforeCoderTest(page));
|
||||
|
||||
test("create user with password", async ({ page, baseURL }) => {
|
||||
await page.goto(`${baseURL}/users`, { waitUntil: "domcontentloaded" });
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { test, expect } from "@playwright/test";
|
||||
import { createUser, getCurrentOrgId, setupApiCalls } from "../../api";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
import { expect, test } from "../../testing";
|
||||
|
||||
test.beforeEach(async ({ page }) => await beforeCoderTest(page));
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { test } from "@playwright/test";
|
||||
import { randomUUID } from "crypto";
|
||||
import {
|
||||
createTemplate,
|
||||
|
@ -8,10 +7,11 @@ import {
|
|||
stopAgent,
|
||||
} from "../helpers";
|
||||
import { beforeCoderTest } from "../hooks";
|
||||
import { test } from "../testing";
|
||||
|
||||
test.beforeEach(({ page }) => beforeCoderTest(page));
|
||||
|
||||
test("web terminal", async ({ context, page }) => {
|
||||
test.skip("web terminal", async ({ context, page }) => {
|
||||
const token = randomUUID();
|
||||
const template = await createTemplate(page, {
|
||||
apply: [
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
"yup": "1.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@chromatic/test": "npm:@chromatic-com/playwright@0.6.6",
|
||||
"@octokit/types": "12.3.0",
|
||||
"@playwright/test": "1.40.1",
|
||||
"@storybook/addon-actions": "8.0.5",
|
||||
|
@ -158,6 +159,7 @@
|
|||
"jest-websocket-mock": "2.5.0",
|
||||
"jest_workaround": "0.1.14",
|
||||
"msw": "2.2.3",
|
||||
"playwright": "1.40.1",
|
||||
"prettier": "3.1.0",
|
||||
"protobufjs": "7.2.4",
|
||||
"rxjs": "7.8.1",
|
||||
|
|
1313
site/pnpm-lock.yaml
1313
site/pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue