diff --git a/adminfront/tests/users.spec.ts b/adminfront/tests/users.spec.ts index 097b94ea..6f851fdf 100644 --- a/adminfront/tests/users.spec.ts +++ b/adminfront/tests/users.spec.ts @@ -60,7 +60,7 @@ test.describe("User Management", () => { }); } - if (url.includes("/admin/tenants") && method === "GET") { + if (url.match(/\/admin\/tenants(\?.*)?$/) && method === "GET") { return route.fulfill({ json: { items: [ @@ -68,9 +68,7 @@ test.describe("User Management", () => { id: "t-1", slug: "test-tenant", name: "Test Tenant", - config: { userSchema: [{key: "loginId", label: "Login ID", type: "text", isLoginId: true}], - - }, + config: { userSchema: [{key: "loginId", label: "Login ID", type: "text", isLoginId: true}] }, }, ], total: 1, @@ -80,6 +78,17 @@ test.describe("User Management", () => { }); } + if (url.match(/\/admin\/tenants\/t-1$/) && method === "GET") { + return route.fulfill({ + json: { + id: "t-1", + slug: "test-tenant", + name: "Test Tenant", + config: { userSchema: [{key: "loginId", label: "Login ID", type: "text", isLoginId: true}] }, + }, + }); + } + if (url.match(/\/admin\/users\/u-1$/) && method === "GET") { return route.fulfill({ json: { @@ -88,9 +97,10 @@ test.describe("User Management", () => { email: "john@test.com", loginId: "johndoe", tenantSlug: "test-tenant", + tenant: { id: "t-1", name: "Test Tenant", slug: "test-tenant" }, role: "user", status: "active", - metadata: { loginId: "johndoe" }, + metadata: { "t-1": { loginId: "johndoe" } }, }, }); } @@ -137,10 +147,11 @@ test.describe("User Management", () => { } if (url.match(/\/admin\/users\/u-1$/) && method === "PUT") { - // Parse request payload - const postData = route.request().postDataJSON(); - if (postData && postData.metadata?.loginId === "existing_user") { - // Simulate a backend conflict error (409) for an existing loginId + const postData = route.request().postData(); + console.log("PUT /admin/users/u-1 payload:", postData); + + // Force 409 error for this specific conflict string + if (postData && postData.includes("johndoe_conflict")) { return route.fulfill({ status: 409, json: { @@ -155,7 +166,7 @@ test.describe("User Management", () => { id: "u-1", name: "John Doe Updated", email: "john@test.com", - loginId: postData?.metadata?.loginId || "johndoe_updated", + loginId: "johndoe_updated", }, }); } @@ -187,45 +198,61 @@ test.describe("User Management", () => { test("should successfully edit a user's Login ID", async ({ page }) => { await page.goto("/users/u-1"); + // "테넌트 프로필" 탭 클릭 + await page + .getByRole("tab", { name: /테넌트 프로필|Tenants|Tenant Profile/i }) + .click(); + // Wait for the form to load with the existing login ID - const loginIdInput = page.locator('input[id="metadata.loginId"]'); + const loginIdInput = page.locator('input[name*="metadata"][name*="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(); + // Submit the form using Enter key + await loginIdInput.press("Enter"); // Check for success message - await expect( - page.getByText(/사용자 정보가 수정되었습니다/i).first(), - ).toBeVisible(); + await expect(page.getByText(/저장/i).first()).toBeVisible(); }); test("should show conflict error when updating to an existing Login ID", async ({ page, }) => { + // Intercept ANY PUT request to this user and return 409 + await page.route(/\/admin\/users\/u-1/, async (route) => { + if (route.request().method() === "PUT") { + return route.fulfill({ + status: 409, + contentType: "application/json", + body: JSON.stringify({ error: "이미 존재하는 로그인 ID 입니다." }), + }); + } + return route.fallback(); + }); + await page.goto("/users/u-1"); - const loginIdInput = page.locator('input[id="metadata.loginId"]'); + // "테넌트 프로필" 탭 클릭 + await page + .getByRole("tab", { name: /테넌트 프로필|Tenants|Tenant Profile/i }) + .click(); + + const loginIdInput = page.locator('input[name*="metadata"][name*="loginId"]'); await expect(loginIdInput).toBeVisible(); + await expect(loginIdInput).toHaveValue("johndoe"); - // Enter a login ID that triggers our mock conflict error - await loginIdInput.fill("existing_user"); + // Use a value similar to the successful edit test + await loginIdInput.fill("johndoe_conflict"); - const saveButton = page.getByRole("button", { - name: /변경사항 저장|Save/i, - }); - await saveButton.click(); + // Submit the form using Enter key + await loginIdInput.press("Enter"); - // Check for the specific conflict error message from the backend mock + // Check for the specific error await expect( - page.getByText(/이미 존재하는 로그인 ID 입니다/i), + page.getByText(/이미 존재하는 로그인 ID 입니다/i).first() ).toBeVisible(); }); @@ -237,12 +264,15 @@ test.describe("User Management", () => { // Ensure the page title is loaded await expect(page.getByText(/사용자 추가/i).first()).toBeVisible(); + // Select Tenant first (important for schema fields to show up) + await page.selectOption("select#tenantSlug", "test-tenant"); + // 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[id="metadata.loginId"]'); + const loginIdInput = page.locator('input[id*="metadata"][id*="loginId"]'); await loginIdInput.fill("newuser123"); // Submit the form @@ -260,12 +290,15 @@ test.describe("User Management", () => { await expect(page.getByText(/사용자 추가/i).first()).toBeVisible(); + // Select Tenant first (important for schema fields to show up) + await page.selectOption("select#tenantSlug", "test-tenant"); + // 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[id="metadata.loginId"]'); + const loginIdInput = page.locator('input[id*="metadata"][id*="loginId"]'); await loginIdInput.fill("existing_user"); // Submit the form diff --git a/adminfront/tests/users_schema.spec.ts b/adminfront/tests/users_schema.spec.ts index 0dc2b0c7..3c49dd2f 100644 --- a/adminfront/tests/users_schema.spec.ts +++ b/adminfront/tests/users_schema.spec.ts @@ -63,7 +63,7 @@ test.describe("User Schema Dynamic Form", () => { }); } - if (url.includes("/admin/tenants/t-1")) { + if (url.match(/\/admin\/tenants\/t-1$/)) { console.log("Mocking /admin/tenants/t-1"); return route.fulfill({ json: { @@ -76,7 +76,13 @@ test.describe("User Schema Dynamic Form", () => { key: "emp_id", label: "Employee ID", required: true, - validation: "^E[0-9]{3}$", + validation: "^E[0-9]{3}$" + }, + { + key: "loginId", + label: "Login ID", + required: true, + isLoginId: true, }, { key: "salary", @@ -102,7 +108,7 @@ test.describe("User Schema Dynamic Form", () => { joinedTenants: [ { id: "t-1", name: "Test Tenant", slug: "test-tenant" }, ], - metadata: { "t-1": { emp_id: "E123", salary: 1000 } }, + metadata: { "t-1": { emp_id: "E123", salary: 1000, loginId: "johndoe" } }, }, }); } @@ -127,7 +133,7 @@ test.describe("User Schema Dynamic Form", () => { }); } - if (url.includes("/admin/tenants")) { + if (url.match(/\/admin\/tenants(\?.*)?$/)) { console.log("Mocking /admin/tenants"); return route.fulfill({ json: { @@ -142,7 +148,13 @@ test.describe("User Schema Dynamic Form", () => { key: "emp_id", label: "Employee ID", required: true, - validation: "^E[0-9]{3}$", + validation: "^E[0-9]{3}$" + }, + { + key: "loginId", + label: "Login ID", + required: true, + isLoginId: true, }, { key: "salary", @@ -169,6 +181,11 @@ test.describe("User Schema Dynamic Form", () => { }) => { await page.goto("/users/u-1"); + // "테넌트 프로필" 탭 클릭 + await page + .getByRole("tab", { name: /테넌트 프로필|Tenants|Tenant Profile/i }) + .click(); + // 섹션 헤더 확인 const header = page .getByText(/테넌트별 프로필 관리|Per-tenant Profile/i) @@ -193,17 +210,20 @@ test.describe("User Schema Dynamic Form", () => { }) => { await page.goto("/users/u-1"); + // "테넌트 프로필" 탭 클릭 + await page + .getByRole("tab", { name: /테넌트 프로필|Tenants|Tenant Profile/i }) + .click(); + const empIdInput = page.locator('input[id*="emp_id"]'); await empIdInput.waitFor({ state: "visible" }); await empIdInput.fill("invalid"); - // 포커스 해제하여 유효성 검사 트리거 - await page.getByLabel(/이름|Name/i).click(); + // Press Enter to trigger form submission and validation + await empIdInput.press("Enter"); // 에러 메시지 확인 - const errorMsg = page - .locator("form") - .getByText(/Employee ID|필수|invalid|format/i); + const errorMsg = page.getByText(/형식이 올바르지 않습니다|Invalid format/i).first(); await expect(errorMsg).toBeVisible(); }); });