tests/team-settings.spec.ts
Rama main · réplica de lectura del repositorio original.
import { expect } from "@playwright/test";
import { TeamUser } from "../apps/backend/src/database/models";
import { createUserAccount } from "../apps/backend/src/database/seeds";
import { loggedTest } from "./logged-test";
import { ensureTeamOwner, getUniqueTestIdentifier, screenshot } from "./util";
loggedTest.beforeEach(async ({ auth, team }) => {
await ensureTeamOwner({ team: team.team, user: auth.user });
});
loggedTest("team settings - general", async ({ page, team }) => {
await page.goto(`/${team.account.slug}/settings`);
await expect(
page.getByRole("heading", { name: "Team Settings" }),
).toBeVisible();
await expect(page.getByText("Team Name")).toBeVisible();
await page.getByLabel("URL namespace").fill("acme");
await screenshot(page, "team-settings-general");
});
loggedTest("team settings - billing", async ({ page, team }) => {
await page.goto(`/${team.account.slug}/settings/billing`);
await expect(page.getByRole("heading", { name: "Plan" })).toBeVisible();
await expect(page.getByText("Current period")).toBeVisible();
await screenshot(page, "team-settings-billing");
});
loggedTest("team settings - members", async ({ page, team, auth }) => {
await page.goto(`/${team.account.slug}/settings/members`);
await expect(page.getByRole("heading", { name: "Members" })).toBeVisible();
await expect(
page.getByRole("heading", { name: "Default access role" }),
).toBeVisible();
if (!auth.account.name) {
throw new Error("Account name not found");
}
await expect(page.getByText(auth.account.name)).toBeVisible();
await screenshot(page, "team-settings-members", {
replacements: {
[auth.account.slug]: "john-doe",
[auth.account.name]: "John Doe",
},
});
});
loggedTest("team settings - integrations", async ({ page, team }) => {
await page.goto(`/${team.account.slug}/settings/integrations`);
await expect(page.getByRole("heading", { name: "Slack" })).toBeVisible();
await expect(page.getByRole("heading", { name: "GitLab" })).toBeVisible();
await screenshot(page, "team-settings-integrations");
});
loggedTest("team settings - authentication", async ({ page, team }) => {
await page.goto(`/${team.account.slug}/settings/authentication`);
await expect(
page.getByRole("heading", { name: "Team domains" }),
).toBeVisible();
await expect(
page.getByRole("heading", { name: "SAML Single Sign-On" }),
).toBeVisible();
await expect(
page.getByRole("heading").filter({
hasText: /^(Team domains|GitHub Single Sign-On|SAML Single Sign-On)$/,
}),
).toHaveText([
"Team domains",
"GitHub Single Sign-On",
"SAML Single Sign-On",
]);
await screenshot(page, "team-settings-authentication");
});
loggedTest(
"team settings - provision members with SCIM",
async ({ page, team }, testInfo) => {
const id = getUniqueTestIdentifier(testInfo);
await page.goto(`/${team.account.slug}/settings/authentication`);
await expect(
page.getByRole("heading", { name: "SCIM Provisioning" }),
).toBeVisible();
await page.getByRole("button", { name: "Generate token" }).click();
const generateDialog = page.getByRole("dialog", {
name: "Generate SCIM Token",
});
await generateDialog
.getByRole("button", { name: "Generate token" })
.click();
const createdDialog = page.getByRole("dialog", {
name: "SCIM Token Generated",
});
const token = await createdDialog.locator("code").textContent();
expect(token).toMatch(/^argos_scim_/);
await createdDialog.getByRole("button", { name: "Close" }).click();
await expect(createdDialog).toBeHidden();
await expect(page.getByText("never used")).toBeVisible();
await expect(page.getByText("Your team has a single owner.")).toBeVisible();
await screenshot(page, "team-settings-scim");
// What the Identity Provider does with it.
const headers = {
Authorization: `Bearer ${token}`,
"Content-Type": "application/scim+json",
};
const provisioned = await page.request.post("/scim/v2/Users", {
headers,
data: {
schemas: ["urn:ietf:params:scim:schemas:core:2.0:User"],
userName: `fox-${id}@acme.com`,
displayName: "Fox Mulder",
emails: [{ value: `fox-${id}@acme.com`, primary: true }],
active: true,
},
});
expect(provisioned.status()).toBe(201);
// This server is single-domain, where the app's own routes come first.
const filter = encodeURIComponent(`userName eq "fox-${id}@acme.com"`);
const lookup = await page.request.get(`/scim/v2/Users?filter=${filter}`, {
headers,
});
expect(lookup.headers()["content-type"]).toContain("application/scim+json");
expect((await lookup.json()).totalResults).toBe(1);
await page.goto(`/${team.account.slug}/settings/members`);
await expect(
page.getByRole("row").filter({ hasText: "Fox Mulder" }),
).toBeVisible();
await page.goto(`/${team.account.slug}/settings/authentication`);
await page.getByRole("button", { name: "Revoke", exact: true }).click();
const revokeDialog = page.getByRole("alertdialog", {
name: "Revoke SCIM Token",
});
await revokeDialog.getByRole("button", { name: "Revoke token" }).click();
await expect(revokeDialog).toBeHidden();
await expect(page.getByText("No SCIM token")).toBeVisible();
const rejected = await page.request.patch(
`/scim/v2/Users/${(await provisioned.json()).id}`,
{
headers,
data: {
schemas: ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
Operations: [{ op: "replace", value: { active: false } }],
},
},
);
expect(rejected.status()).toBe(401);
},
);
loggedTest(
"team settings - remove a member from the team",
async ({ page, team }, testInfo) => {
const id = getUniqueTestIdentifier(testInfo);
const member = await createUserAccount({
email: `dana-${id}@acme.com`,
name: "Dana Scully",
slug: `dana-${id}`,
});
await TeamUser.query().insert({
teamId: team.team.id,
userId: member.user.id,
userLevel: "member",
});
await page.goto(`/${team.account.slug}/settings/members`);
const row = page.getByRole("row").filter({ hasText: "Dana Scully" });
await expect(row).toBeVisible();
await row.locator("button:has(.lucide-ellipsis-vertical)").click();
await page.getByRole("option", { name: "Remove from Team" }).click();
// The whole point of the guard: the dialog is driven by a controlled
// `Modal`, and a mismatched prop left it permanently closed — the menu
// item worked, and nothing happened.
const dialog = page.getByRole("alertdialog");
await expect(
dialog.getByRole("heading", { name: "Remove Team Member" }),
).toBeVisible();
await dialog.getByRole("button", { name: "Remove from Team" }).click();
await expect(dialog).toBeHidden();
await expect(row).toBeHidden();
expect(
await TeamUser.query().findOne({
teamId: team.team.id,
userId: member.user.id,
}),
).toBeUndefined();
},
);