Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 39 additions & 81 deletions web/tests/e2e/organization-settings-profile.spec.ts
Original file line number Diff line number Diff line change
@@ -1,61 +1,11 @@
import { execFileSync } from "node:child_process";
import { expect, type Page, test } from "@playwright/test";

const databaseUrl = process.env.TEST_DATABASE_URL ?? process.env.DATABASE_URL;

type SeededOrganizationProfile = {
cookieName: string;
cookieValue: string;
organizationProfileHref: string;
};

function seedOrganizationProfile(): SeededOrganizationProfile {
if (!databaseUrl) {
throw new Error("TEST_DATABASE_URL or DATABASE_URL is required");
}

const output = execFileSync(
"cargo",
[
"run",
"--quiet",
"-p",
"opengithub-api",
"--example",
"dashboard_e2e_seed",
],
{
cwd: "..",
env: {
...process.env,
ORG_PROFILE_E2E: "1",
SESSION_COOKIE_NAME: "og_session",
},
},
).toString();
return JSON.parse(output) as SeededOrganizationProfile;
}

async function signIn(page: Page, seeded: SeededOrganizationProfile) {
await page.context().addCookies([
{
domain: "localhost",
httpOnly: true,
name: seeded.cookieName,
path: "/",
sameSite: "Lax",
secure: false,
value: seeded.cookieValue,
},
]);
}

async function expectNoDeadControls(page: Page) {
await expect(page.locator('a[href="#"], a:not([href])')).toHaveCount(0);
for (const button of await page.locator("button:visible").all()) {
await expect(button).toHaveAccessibleName(/.+/);
}
}
import {
expect,
expectNoDeadControls,
expectNoHorizontalOverflow,
screenshotPath,
skipWithoutTestDb,
test,
} from "./_fixtures/auth";

function slugFromProfileHref(href: string) {
const parts = href.split("/").filter(Boolean);
Expand All @@ -73,15 +23,19 @@ function slugFromProfileHref(href: string) {
}

test.skip(
!databaseUrl,
skipWithoutTestDb(),
"organization settings profile E2E needs a test database",
);
test.setTimeout(60_000);

test("owner opens organization profile settings shell", async ({ page }) => {
const seeded = seedOrganizationProfile();
test("owner opens organization profile settings shell", async ({
page,
seed,
signIn,
}, testInfo) => {
const seeded = await seed({ scenes: ["orgProfile"] });
await signIn(page, seeded);
const slug = slugFromProfileHref(seeded.organizationProfileHref);
const slug = slugFromProfileHref(seeded.hrefs.organizationProfile);

await page.goto(`/organizations/${slug}/settings/profile`);
await expect(
Expand Down Expand Up @@ -117,13 +71,14 @@ test("owner opens organization profile settings shell", async ({ page }) => {
"true",
);
await expectNoDeadControls(page);
await expectNoHorizontalOverflow(page);
await page.screenshot({
fullPage: true,
path: "../ralph/screenshots/build/org-admin-002-phase2-settings-shell.jpg",
path: screenshotPath(testInfo, "org-admin-002-phase2-settings-shell"),
});
await page.screenshot({
fullPage: true,
path: "../ralph/screenshots/build/org-admin-002-final-desktop-shell.jpg",
path: screenshotPath(testInfo, "org-admin-002-final-desktop-shell"),
});

await page.goto(`/orgs/${slug}/settings`);
Expand All @@ -132,10 +87,12 @@ test("owner opens organization profile settings shell", async ({ page }) => {

test("owner saves organization profile, contact, and social sections", async ({
page,
}) => {
const seeded = seedOrganizationProfile();
seed,
signIn,
}, testInfo) => {
const seeded = await seed({ scenes: ["orgProfile"] });
await signIn(page, seeded);
const slug = slugFromProfileHref(seeded.organizationProfileHref);
const slug = slugFromProfileHref(seeded.hrefs.organizationProfile);

await page.goto(`/organizations/${slug}/settings/profile`);
await page
Expand Down Expand Up @@ -164,13 +121,14 @@ test("owner saves organization profile, contact, and social sections", async ({
await page.getByRole("button", { name: "Save social accounts" }).click();
await expect(page.getByText("Social accounts updated")).toBeVisible();
await expectNoDeadControls(page);
await expectNoHorizontalOverflow(page);
await page.screenshot({
fullPage: true,
path: "../ralph/screenshots/build/org-admin-002-phase3-profile-save.jpg",
path: screenshotPath(testInfo, "org-admin-002-phase3-profile-save"),
});
await page.screenshot({
fullPage: true,
path: "../ralph/screenshots/build/org-admin-002-final-profile-form.jpg",
path: screenshotPath(testInfo, "org-admin-002-final-profile-form"),
});

await page.reload();
Expand All @@ -191,14 +149,18 @@ test("owner saves organization profile, contact, and social sections", async ({
).toBeVisible();
await page.screenshot({
fullPage: true,
path: "../ralph/screenshots/build/org-admin-002-final-validation-error.jpg",
path: screenshotPath(testInfo, "org-admin-002-final-validation-error"),
});
});

test("owner validates rename and typed danger guardrails", async ({ page }) => {
const seeded = seedOrganizationProfile();
test("owner validates rename and typed danger guardrails", async ({
page,
seed,
signIn,
}, testInfo) => {
const seeded = await seed({ scenes: ["orgProfile"] });
await signIn(page, seeded);
const slug = slugFromProfileHref(seeded.organizationProfileHref);
const slug = slugFromProfileHref(seeded.hrefs.organizationProfile);
const nextSlug = `${slug}-renamed`;

await page.goto(`/organizations/${slug}/settings/profile`);
Expand Down Expand Up @@ -241,21 +203,17 @@ test("owner validates rename and typed danger guardrails", async ({ page }) => {
await expectNoDeadControls(page);

await page.setViewportSize({ width: 390, height: 900 });
const bodyWidths = await page.locator("body").evaluate((body) => ({
clientWidth: body.clientWidth,
scrollWidth: body.scrollWidth,
}));
expect(bodyWidths.scrollWidth).toBeLessThanOrEqual(bodyWidths.clientWidth);
await expectNoHorizontalOverflow(page);
await page.screenshot({
fullPage: true,
path: "../ralph/screenshots/build/org-admin-002-phase4-danger-zone.jpg",
path: screenshotPath(testInfo, "org-admin-002-phase4-danger-zone"),
});
await page.screenshot({
fullPage: true,
path: "../ralph/screenshots/build/org-admin-002-final-danger-zone.jpg",
path: screenshotPath(testInfo, "org-admin-002-final-danger-zone"),
});
await page.screenshot({
fullPage: true,
path: "../ralph/screenshots/build/org-admin-002-final-mobile.jpg",
path: screenshotPath(testInfo, "org-admin-002-final-mobile"),
});
});