forked from baron/baron-sso
124 lines
3.7 KiB
TypeScript
124 lines
3.7 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
import {
|
|
installDevApiMock,
|
|
makeClient,
|
|
seedAuth,
|
|
} from "./helpers/devfront-fixtures";
|
|
import { captureEvidence } from "./helpers/evidence";
|
|
|
|
test.describe("DevFront tenant switch", () => {
|
|
test.afterEach(async ({ page }, testInfo) => {
|
|
if (testInfo.status === "passed") {
|
|
await captureEvidence(page, testInfo, testInfo.title);
|
|
}
|
|
});
|
|
|
|
const MOCK_STATE = {
|
|
clients: [makeClient("client-a", { name: "Tenant A App" })],
|
|
consents: [],
|
|
auditLogs: [],
|
|
};
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.route("**/api/v1/user/me", async (route) => {
|
|
if (route.request().method() === "GET") {
|
|
await route.fulfill({
|
|
status: 200,
|
|
contentType: "application/json",
|
|
body: JSON.stringify({
|
|
id: "playwright-user",
|
|
email: "playwright@example.com",
|
|
name: "Playwright User",
|
|
role: "tenant_admin",
|
|
tenantId: "tenant-a",
|
|
}),
|
|
});
|
|
} else {
|
|
await route.continue();
|
|
}
|
|
});
|
|
});
|
|
|
|
test("multiple tenants: user can switch tenant context", async ({ page }) => {
|
|
// Seed an admin user
|
|
await seedAuth(page, "tenant_admin");
|
|
|
|
await installDevApiMock(page, MOCK_STATE);
|
|
|
|
// Mock API to return multiple tenants
|
|
await page.route("**/api/v1/dev/my-tenants", async (route) => {
|
|
await route.fulfill({
|
|
status: 200,
|
|
contentType: "application/json",
|
|
body: JSON.stringify([
|
|
{ id: "tenant-a", name: "Tenant A", slug: "tenant-a" },
|
|
{ id: "tenant-b", name: "Tenant B", slug: "tenant-b" },
|
|
]),
|
|
});
|
|
});
|
|
|
|
// Navigate to profile page
|
|
await page.goto("/profile");
|
|
|
|
// Wait for the switcher to load
|
|
const switcherHeading = page.getByText("작업 테넌트 (컨텍스트)");
|
|
await expect(switcherHeading).toBeVisible();
|
|
|
|
// Verify initial state is selected (tenant-a comes from seedAuth)
|
|
const select = page.getByRole("combobox", { name: /테넌트/i });
|
|
await expect(select).toHaveValue("tenant-a");
|
|
|
|
// Change to Tenant B
|
|
await select.selectOption("tenant-b");
|
|
|
|
// Click Save
|
|
await page.getByRole("button", { name: /저장|Save/i }).click();
|
|
|
|
// Verify success toast
|
|
await expect(page.getByText("테넌트 전환 완료").first()).toBeVisible();
|
|
|
|
// Verify localStorage was updated
|
|
const savedTenantId = await page.evaluate(() =>
|
|
window.localStorage.getItem("dev_tenant_id"),
|
|
);
|
|
expect(savedTenantId).toBe("tenant-b");
|
|
});
|
|
|
|
test("single tenant: switcher is disabled with a notice", async ({
|
|
page,
|
|
}) => {
|
|
await seedAuth(page, "tenant_admin");
|
|
|
|
// Mock API to return only ONE tenant
|
|
await page.route("**/api/v1/dev/my-tenants", async (route) => {
|
|
await route.fulfill({
|
|
status: 200,
|
|
contentType: "application/json",
|
|
body: JSON.stringify([
|
|
{ id: "tenant-a", name: "Tenant A", slug: "tenant-a" },
|
|
]),
|
|
});
|
|
});
|
|
|
|
await installDevApiMock(page, MOCK_STATE);
|
|
|
|
await page.goto("/profile");
|
|
|
|
// Wait for the switcher to load
|
|
await expect(page.getByText("작업 테넌트 (컨텍스트)")).toBeVisible();
|
|
|
|
// Verify the select is disabled
|
|
const select = page.getByRole("combobox", { name: /테넌트/i });
|
|
await expect(select).toBeDisabled();
|
|
|
|
// Verify the save button is disabled
|
|
const saveButton = page.getByRole("button", { name: /저장|Save/i });
|
|
await expect(saveButton).toBeDisabled();
|
|
|
|
// Verify the notice message
|
|
await expect(
|
|
page.getByText("단일 테넌트에 소속되어 전환할 필요가 없습니다."),
|
|
).toBeVisible();
|
|
});
|
|
});
|