mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: allow signing in as non-admin users in e2e tests (#15892)
Closes coder/internal#168 Gets rid of the "global state" authentication, and adds a `login` helper which should be called at the beginning of each test. This means that not every test needs to authenticated as admin, and we can even have tests that encompass multiple permission levels. We also now create more than just the single admin user during setup, so that we can have a set of users to pick from as appropriate.
This commit is contained in:
+2
-7
@@ -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<string> => {
|
||||
|
||||
+23
-4
@@ -15,11 +15,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",
|
||||
|
||||
+81
-14
@@ -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,10 +18,12 @@ import {
|
||||
coderMain,
|
||||
coderPort,
|
||||
defaultOrganizationName,
|
||||
defaultPassword,
|
||||
license,
|
||||
premiumTestsRequired,
|
||||
prometheusPort,
|
||||
requireTerraformTests,
|
||||
users,
|
||||
} from "./constants";
|
||||
import { expectUrl } from "./expectUrl";
|
||||
import {
|
||||
@@ -60,28 +61,75 @@ export function requireTerraformProvisioner() {
|
||||
test.skip(!requireTerraformTests);
|
||||
}
|
||||
|
||||
type LoginOptions = {
|
||||
username: string;
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
|
||||
export async function login(page: Page, options: LoginOptions = users.admin) {
|
||||
const ctx = page.context();
|
||||
// biome-ignore lint/suspicious/noExplicitAny: reset the current user
|
||||
(ctx as any)[Symbol.for("currentUser")] = undefined;
|
||||
await ctx.clearCookies();
|
||||
await page.goto("/login");
|
||||
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: 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: get the current user
|
||||
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<string> => {
|
||||
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");
|
||||
|
||||
@@ -101,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",
|
||||
@@ -214,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();
|
||||
}
|
||||
@@ -659,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;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1002,6 +1059,7 @@ type UserValues = {
|
||||
username: string;
|
||||
email: string;
|
||||
password: string;
|
||||
roles: string[];
|
||||
};
|
||||
|
||||
export async function createUser(
|
||||
@@ -1019,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) {
|
||||
@@ -1036,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<{
|
||||
|
||||
+1
-1
@@ -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) => {
|
||||
|
||||
@@ -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,13 +55,12 @@ 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,
|
||||
},
|
||||
],
|
||||
|
||||
@@ -1,14 +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 { expectUrl } from "./expectUrl";
|
||||
import { storageState } from "./playwright.config";
|
||||
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.
|
||||
@@ -17,28 +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.context().storageState({ path: storageState });
|
||||
|
||||
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(
|
||||
@@ -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);
|
||||
|
||||
@@ -1,13 +1,50 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { createTemplate, createWorkspace, requiresLicense } from "../helpers";
|
||||
import { type Page, expect, test } from "@playwright/test";
|
||||
import { users } from "../constants";
|
||||
import {
|
||||
createTemplate,
|
||||
createWorkspace,
|
||||
currentUser,
|
||||
login,
|
||||
requiresLicense,
|
||||
} from "../helpers";
|
||||
import { beforeCoderTest } from "../hooks";
|
||||
|
||||
test.beforeEach(({ page }) => beforeCoderTest(page));
|
||||
test.describe.configure({ mode: "parallel" });
|
||||
|
||||
test("inspecting and filtering audit logs", async ({ page }) => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
beforeCoderTest(page);
|
||||
await login(page, users.auditor);
|
||||
});
|
||||
|
||||
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("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();
|
||||
|
||||
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);
|
||||
@@ -15,21 +52,23 @@ test("inspecting and filtering audit logs", async ({ page }) => {
|
||||
// Go to the audit history
|
||||
await page.goto("/audit");
|
||||
|
||||
const user = currentUser(page);
|
||||
|
||||
// Make sure those things we did all actually show up
|
||||
await expect(page.getByText(`${userName} logged in`)).toBeVisible();
|
||||
await resetSearch(page);
|
||||
await expect(
|
||||
page.getByText(`${userName} created template ${templateName}`),
|
||||
page.getByText(`${user.username} created template ${templateName}`),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByText(`${userName} created workspace ${workspaceName}`),
|
||||
page.getByText(`${user.username} created workspace ${workspaceName}`),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByText(`${userName} started workspace ${workspaceName}`),
|
||||
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", {
|
||||
hasText: `${userName} created workspace ${workspaceName}`,
|
||||
hasText: `${user.username} created workspace ${workspaceName}`,
|
||||
});
|
||||
await createdWorkspace.getByLabel("open-dropdown").click();
|
||||
await expect(
|
||||
@@ -38,11 +77,24 @@ test("inspecting and filtering audit logs", async ({ page }) => {
|
||||
await expect(
|
||||
createdWorkspace.getByText(`name: "${workspaceName}"`),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
const startedWorkspaceMessage = `${userName} started workspace ${workspaceName}`;
|
||||
const loginMessage = `${userName} logged in`;
|
||||
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);
|
||||
await page.getByText("All resource types").click();
|
||||
const workspaceBuildsOption = page.getByText("Workspace Build");
|
||||
await workspaceBuildsOption.scrollIntoViewIfNeeded({ timeout: 5000 });
|
||||
@@ -51,19 +103,15 @@ 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 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();
|
||||
});
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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.beforeEach(async ({ page }) => {
|
||||
beforeCoderTest(page);
|
||||
await login(page);
|
||||
await setupApiCalls(page);
|
||||
});
|
||||
|
||||
test("experiments", async ({ page }) => {
|
||||
await setupApiCalls(page);
|
||||
|
||||
// Load experiments from backend API
|
||||
const availableExperiments = await API.getAvailableExperiments();
|
||||
|
||||
|
||||
@@ -6,14 +6,18 @@ import {
|
||||
setupApiCalls,
|
||||
} from "../../api";
|
||||
import { randomName, requiresLicense } from "../../helpers";
|
||||
import { login } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
|
||||
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();
|
||||
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { requiresLicense } from "../../helpers";
|
||||
import { login, requiresLicense } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
beforeCoderTest(page);
|
||||
await login(page);
|
||||
});
|
||||
|
||||
test("license was added successfully", async ({ page }) => {
|
||||
requiresLicense();
|
||||
|
||||
@@ -8,9 +8,16 @@ import {
|
||||
verifyConfigFlagNumber,
|
||||
verifyConfigFlagString,
|
||||
} from "../../api";
|
||||
import { login } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
beforeCoderTest(page);
|
||||
await login(page);
|
||||
await setupApiCalls(page);
|
||||
});
|
||||
|
||||
test("enabled network settings", async ({ page }) => {
|
||||
await setupApiCalls(page);
|
||||
const config = await API.getDeploymentConfig();
|
||||
|
||||
await page.goto("/deployment/network", { waitUntil: "domcontentloaded" });
|
||||
|
||||
@@ -8,9 +8,16 @@ import {
|
||||
verifyConfigFlagEmpty,
|
||||
verifyConfigFlagString,
|
||||
} from "../../api";
|
||||
import { login } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
beforeCoderTest(page);
|
||||
await login(page);
|
||||
await setupApiCalls(page);
|
||||
});
|
||||
|
||||
test("enabled observability settings", async ({ page }) => {
|
||||
await setupApiCalls(page);
|
||||
const config = await API.getDeploymentConfig();
|
||||
|
||||
await page.goto("/deployment/observability", {
|
||||
|
||||
@@ -8,9 +8,16 @@ import {
|
||||
verifyConfigFlagNumber,
|
||||
verifyConfigFlagString,
|
||||
} from "../../api";
|
||||
import { login } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
beforeCoderTest(page);
|
||||
await login(page);
|
||||
await setupApiCalls(page);
|
||||
});
|
||||
|
||||
test("enabled security settings", async ({ page }) => {
|
||||
await setupApiCalls(page);
|
||||
const config = await API.getDeploymentConfig();
|
||||
|
||||
await page.goto("/deployment/security", { waitUntil: "domcontentloaded" });
|
||||
|
||||
@@ -7,9 +7,16 @@ import {
|
||||
verifyConfigFlagEntries,
|
||||
verifyConfigFlagString,
|
||||
} from "../../api";
|
||||
import { login } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
beforeCoderTest(page);
|
||||
await login(page);
|
||||
await setupApiCalls(page);
|
||||
});
|
||||
|
||||
test("login with OIDC", async ({ page }) => {
|
||||
await setupApiCalls(page);
|
||||
const config = await API.getDeploymentConfig();
|
||||
|
||||
await page.goto("/deployment/userauth", { waitUntil: "domcontentloaded" });
|
||||
|
||||
@@ -3,8 +3,15 @@ import { API } from "api/api";
|
||||
import { setupApiCalls } from "../../api";
|
||||
import { coderPort, workspaceProxyPort } from "../../constants";
|
||||
import { randomName, requiresLicense } from "../../helpers";
|
||||
import { login } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
import { startWorkspaceProxy, stopWorkspaceProxy } from "../../proxy";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
beforeCoderTest(page);
|
||||
await login(page);
|
||||
});
|
||||
|
||||
test("default proxy is online", async ({ page }) => {
|
||||
requiresLicense();
|
||||
await setupApiCalls(page);
|
||||
|
||||
@@ -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 }) => {
|
||||
@@ -101,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"] = {
|
||||
|
||||
@@ -6,13 +6,18 @@ import {
|
||||
setupApiCalls,
|
||||
} from "../../api";
|
||||
import { requiresLicense } from "../../helpers";
|
||||
import { login } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
|
||||
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;
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { createUser, getCurrentOrgId, setupApiCalls } from "../../api";
|
||||
import { requiresLicense } from "../../helpers";
|
||||
import { login } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
|
||||
test.beforeEach(async ({ page }) => await beforeCoderTest(page));
|
||||
test.beforeEach(async ({ page }) => {
|
||||
beforeCoderTest(page);
|
||||
await login(page);
|
||||
});
|
||||
|
||||
const DEFAULT_GROUP_NAME = "Everyone";
|
||||
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { randomName, requiresLicense } from "../../helpers";
|
||||
import { login } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
|
||||
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");
|
||||
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { createGroup, getCurrentOrgId, setupApiCalls } from "../../api";
|
||||
import { requiresLicense } from "../../helpers";
|
||||
import { login } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@@ -7,13 +7,18 @@ import {
|
||||
setupApiCalls,
|
||||
} from "../../api";
|
||||
import { requiresLicense } from "../../helpers";
|
||||
import { login } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
|
||||
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),
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
|
||||
@@ -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 }) => {
|
||||
await beforeCoderTest(page);
|
||||
beforeCoderTest(page);
|
||||
await login(page);
|
||||
await setupApiCalls(page);
|
||||
});
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
createTemplate,
|
||||
createWorkspace,
|
||||
downloadCoderVersion,
|
||||
login,
|
||||
sshIntoWorkspace,
|
||||
startAgentWithCommand,
|
||||
stopAgent,
|
||||
@@ -14,7 +15,10 @@ 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);
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
createTemplate,
|
||||
createWorkspace,
|
||||
downloadCoderVersion,
|
||||
login,
|
||||
sshIntoWorkspace,
|
||||
startAgent,
|
||||
stopAgent,
|
||||
@@ -14,7 +15,10 @@ 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);
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { login } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
|
||||
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" });
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { API } from "api/api";
|
||||
import { getCurrentOrgId, setupApiCalls } from "../../api";
|
||||
import { login } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
|
||||
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,
|
||||
|
||||
@@ -7,9 +7,15 @@ import {
|
||||
requiresLicense,
|
||||
updateTemplateSettings,
|
||||
} from "../helpers";
|
||||
import { login } from "../helpers";
|
||||
import { beforeCoderTest } from "../hooks";
|
||||
|
||||
test.beforeEach(({ page }) => beforeCoderTest(page));
|
||||
test.describe.configure({ mode: "parallel" });
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
beforeCoderTest(page);
|
||||
await login(page);
|
||||
});
|
||||
|
||||
test("template update with new name redirects on successful submit", async ({
|
||||
page,
|
||||
@@ -24,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(
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import { test } from "@playwright/test";
|
||||
import { createUser } from "../../helpers";
|
||||
import { login } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
|
||||
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);
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { createUser, getCurrentOrgId, setupApiCalls } from "../../api";
|
||||
import { login } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@@ -7,9 +7,13 @@ import {
|
||||
startAgent,
|
||||
stopAgent,
|
||||
} from "../helpers";
|
||||
import { login } from "../helpers";
|
||||
import { beforeCoderTest } from "../hooks";
|
||||
|
||||
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,
|
||||
},
|
||||
],
|
||||
|
||||
@@ -1,21 +1,38 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { username } from "../../constants";
|
||||
import { users } from "../../constants";
|
||||
import {
|
||||
createTemplate,
|
||||
createWorkspace,
|
||||
echoResponsesWithParameters,
|
||||
} from "../../helpers";
|
||||
import { login } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
import { emptyParameter } from "../../parameters";
|
||||
import type { RichParameter } from "../../provisionerGenerated";
|
||||
|
||||
test("create workspace in auto mode", async ({ page }) => {
|
||||
test.describe.configure({ mode: "parallel" });
|
||||
|
||||
let template!: string;
|
||||
|
||||
test.beforeAll(async ({ browser }) => {
|
||||
const page = await (await browser.newContext()).newPage();
|
||||
await login(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}`,
|
||||
@@ -23,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}`,
|
||||
@@ -43,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}`,
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
requireTerraformProvisioner,
|
||||
verifyParameters,
|
||||
} from "../../helpers";
|
||||
import { login } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
import {
|
||||
fifthParameter,
|
||||
@@ -21,7 +22,12 @@ import {
|
||||
} from "../../parameters";
|
||||
import type { RichParameter } from "../../provisionerGenerated";
|
||||
|
||||
test.beforeEach(({ page }) => beforeCoderTest(page));
|
||||
test.describe.configure({ mode: "parallel" });
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
beforeCoderTest(page);
|
||||
await login(page);
|
||||
});
|
||||
|
||||
test("create workspace", async ({ page }) => {
|
||||
const template = await createTemplate(page, {
|
||||
@@ -88,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,
|
||||
@@ -120,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);
|
||||
});
|
||||
|
||||
@@ -151,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);
|
||||
|
||||
|
||||
@@ -6,11 +6,15 @@ import {
|
||||
echoResponsesWithParameters,
|
||||
verifyParameters,
|
||||
} from "../../helpers";
|
||||
import { login } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
import { firstBuildOption, secondBuildOption } from "../../parameters";
|
||||
import type { RichParameter } from "../../provisionerGenerated";
|
||||
|
||||
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];
|
||||
|
||||
@@ -7,11 +7,15 @@ import {
|
||||
stopWorkspace,
|
||||
verifyParameters,
|
||||
} from "../../helpers";
|
||||
import { login } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
import { firstBuildOption, secondBuildOption } from "../../parameters";
|
||||
import type { RichParameter } from "../../provisionerGenerated";
|
||||
|
||||
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];
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
updateWorkspaceParameters,
|
||||
verifyParameters,
|
||||
} from "../../helpers";
|
||||
import { login } from "../../helpers";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
import {
|
||||
fifthParameter,
|
||||
@@ -18,7 +19,10 @@ import {
|
||||
} from "../../parameters";
|
||||
import type { RichParameter } from "../../provisionerGenerated";
|
||||
|
||||
test.beforeEach(({ page }) => beforeCoderTest(page));
|
||||
test.beforeEach(async ({ page }) => {
|
||||
beforeCoderTest(page);
|
||||
await login(page);
|
||||
});
|
||||
|
||||
test("update workspace, new optional, immutable parameter added", async ({
|
||||
page,
|
||||
|
||||
Reference in New Issue
Block a user