import { expect, test } from "@playwright/test"; test.describe("User Management", () => { test.beforeEach(async ({ page }) => { await page.addInitScript(() => { const authority = "http://localhost:5000/oidc"; const client_id = "adminfront"; const key = `oidc.user:${authority}:${client_id}`; const authData = { id_token: "fake-id-token", access_token: "fake-token", token_type: "Bearer", scope: "openid profile email", profile: { sub: "admin-user", name: "Admin", email: "admin@test.com", role: "super_admin", }, expires_at: Math.floor(Date.now() / 1000) + 36000, }; window.localStorage.setItem(key, JSON.stringify(authData)); window.localStorage.setItem("admin_session", "fake-token"); window.localStorage.setItem("locale", "ko"); window.localStorage.setItem("oidc.state", "dummy"); ( window as Window & typeof globalThis & { _IS_TEST_MODE?: boolean } )._IS_TEST_MODE = true; }); await page.route("**/oidc/**", async (route) => { if (route.request().url().includes("/.well-known/openid-configuration")) { return route.fulfill({ json: { issuer: "http://localhost:5000/oidc", authorization_endpoint: "http://localhost:5000/oidc/auth", token_endpoint: "http://localhost:5000/oidc/token", userinfo_endpoint: "http://localhost:5000/oidc/userinfo", jwks_uri: "http://localhost:5000/oidc/jwks", }, }); } await route.fulfill({ json: { issuer: "http://localhost:5000/oidc" } }); }); await page.route(/.*\/api\/v1\/.*/, async (route) => { const url = route.request().url(); const method = route.request().method(); if (url.includes("/user/me")) { return route.fulfill({ json: { id: "admin-user", name: "Admin", email: "admin@test.com", role: "super_admin", manageableTenants: [], }, }); } if (url.includes("/admin/tenants") && method === "GET") { return route.fulfill({ json: { items: [ { id: "t-1", slug: "test-tenant", name: "Test Tenant", config: { userSchema: [], }, }, ], total: 1, limit: 100, offset: 0, }, }); } if (url.includes("/admin/users/u-1") && method === "GET") { return route.fulfill({ json: { id: "u-1", name: "John Doe", email: "john@test.com", loginId: "johndoe", tenantSlug: "test-tenant", role: "user", status: "active", }, }); } if (url.includes("/admin/users") && method === "POST") { // Parse request payload to simulate validation checks const postData = route.request().postDataJSON(); if (postData && postData.loginId === "existing_user") { // Simulate a backend conflict error (409) for an existing loginId return route.fulfill({ status: 409, json: { error: "이미 존재하는 로그인 ID 입니다.", }, }); } // Mock successful user creation return route.fulfill({ json: { id: "new-user-id", name: "New User", email: "newuser@test.com", loginId: postData?.loginId || "newuser123", }, }); } if (url.includes("/admin/users/u-1") && method === "PUT") { // Parse request payload const postData = route.request().postDataJSON(); if (postData && postData.loginId === "existing_user") { // Simulate a backend conflict error (409) for an existing loginId return route.fulfill({ status: 409, json: { error: "이미 존재하는 로그인 ID 입니다.", }, }); } // Mock successful user update return route.fulfill({ json: { id: "u-1", name: "John Doe Updated", email: "john@test.com", loginId: postData?.loginId || "johndoe_updated", }, }); } if (url.includes("/admin/users") && method === "GET") { return route.fulfill({ json: { items: [ { id: "u-1", name: "John Doe", email: "john@test.com", loginId: "johndoe", role: "user", status: "active", }, ], total: 1, limit: 50, offset: 0, }, }); } return route.fulfill({ json: { items: [], total: 0 } }); }); }); test("should successfully edit a user's Login ID", async ({ page }) => { await page.goto("/users/u-1"); // Wait for the form to load with the existing login ID const loginIdInput = page.locator('input[id="loginId"]'); await expect(loginIdInput).toBeVisible(); await expect(loginIdInput).toHaveValue("johndoe"); // Change the Login ID await loginIdInput.fill("johndoe_updated"); // Submit the form const saveButton = page.getByRole("button", { name: /변경사항 저장|Save/i, }); await saveButton.click(); // Check for success message await expect( page.getByText(/사용자 정보가 수정되었습니다/i).first(), ).toBeVisible(); }); test("should show conflict error when updating to an existing Login ID", async ({ page, }) => { await page.goto("/users/u-1"); const loginIdInput = page.locator('input[id="loginId"]'); await expect(loginIdInput).toBeVisible(); // Enter a login ID that triggers our mock conflict error await loginIdInput.fill("existing_user"); const saveButton = page.getByRole("button", { name: /변경사항 저장|Save/i, }); await saveButton.click(); // Check for the specific conflict error message from the backend mock await expect( page.getByText(/이미 존재하는 로그인 ID 입니다/i), ).toBeVisible(); }); test("should successfully create a new user with a Login ID", async ({ page, }) => { await page.goto("/users/new"); // Ensure the page title is loaded await expect(page.getByText(/사용자 추가/i).first()).toBeVisible(); // Fill required fields await page.locator('input[name="name"]').fill("New User"); await page.locator('input[name="email"]').fill("newuser@test.com"); // Fill Login ID const loginIdInput = page.locator('input[name="loginId"]'); await loginIdInput.fill("newuser123"); // Submit the form const createButton = page.getByRole("button", { name: /생성/i }); await createButton.click(); // Assuming successful creation redirects back to the user list await expect(page).toHaveURL(/.*\/users$/, { timeout: 10000 }); }); test("should show conflict error when creating with an existing Login ID", async ({ page, }) => { await page.goto("/users/new"); await expect(page.getByText(/사용자 추가/i).first()).toBeVisible(); // Fill required fields await page.locator('input[name="name"]').fill("New User"); await page.locator('input[name="email"]').fill("newuser@test.com"); // Fill Login ID that triggers the mock conflict error const loginIdInput = page.locator('input[name="loginId"]'); await loginIdInput.fill("existing_user"); // Submit the form const createButton = page.getByRole("button", { name: /생성/i }); await createButton.click(); // Check for the specific conflict error message from the backend mock await expect( page.getByText(/이미 존재하는 로그인 ID 입니다/i), ).toBeVisible(); }); });