import { expect, test } from "@playwright/test"; const liveE2E = process.env.LIVE_BACKEND_E2E === "1"; const oidcAuthority = "https://sso.hmac.kr/oidc"; const clientId = "adminfront"; test.describe("Tenants CSV live E2E", () => { test.skip(!liveE2E, "Set LIVE_BACKEND_E2E=1 to run against a live backend."); test.beforeEach(async ({ page, baseURL }) => { await page.addInitScript( ({ authority, client_id }) => { window.localStorage.setItem("locale", "ko"); window.localStorage.setItem("X-Mock-Role-Enabled", "true"); window.localStorage.setItem("X-Mock-Role", "super_admin"); ( window as Window & typeof globalThis & { _IS_TEST_MODE?: boolean } )._IS_TEST_MODE = true; const key = `oidc.user:${authority}:${client_id}`; window.localStorage.setItem( key, JSON.stringify({ access_token: "live-e2e-placeholder-token", token_type: "Bearer", profile: { sub: "live-e2e-admin", name: "Live E2E Admin", role: "super_admin", }, expires_at: Math.floor(Date.now() / 1000) + 3600, }), ); }, { authority: oidcAuthority, client_id: clientId }, ); await page.route("**/api/v1/**", async (route) => { const requestUrl = new URL(route.request().url()); const liveUrl = `${baseURL}${requestUrl.pathname}${requestUrl.search}`; const { authorization: _authorization, ...headers } = route .request() .headers(); headers["x-test-role"] = "super_admin"; const response = await route.fetch({ url: liveUrl, headers }); await route.fulfill({ response }); }); await page.route("**/oidc/**", async (route) => { await route.fulfill({ json: { issuer: oidcAuthority, authorization_endpoint: `${oidcAuthority}/auth`, token_endpoint: `${oidcAuthority}/token`, jwks_uri: `${oidcAuthority}/jwks`, userinfo_endpoint: `${oidcAuthority}/userinfo`, end_session_endpoint: `${oidcAuthority}/session/end`, }, }); }); }); test("exports and imports tenant CSV through the admin UI", async ({ page, baseURL, }) => { const slug = `csv-live-${Date.now()}`; let tenantId = ""; await page.goto("/tenants"); await expect(page.locator("h2").last()).toContainText( /테넌트 목록|Tenants/i, ); await expect(page.getByTestId("tenant-export-btn")).toBeVisible(); await expect(page.getByTestId("tenant-import-btn")).toBeVisible(); const download = page.waitForEvent("download"); await page.getByTestId("tenant-export-btn").click(); const exported = await download; expect(exported.suggestedFilename()).toContain("tenants"); await page.getByTestId("tenant-import-input").setInputFiles({ name: "tenants.csv", mimeType: "text/csv", buffer: Buffer.from( `tenant_id,name,type,parent_tenant_id,slug,memo,email_domain\n,Live CSV Tenant,COMPANY,,${slug},Live E2E import,${slug}.example.com\n`, ), }); await expect(page.getByRole("dialog")).toContainText("CSV 가져오기 확인"); await page.getByTestId("tenant-import-confirm-btn").click(); await expect(page.getByTestId("tenant-import-result")).toContainText( /생성 1|Created 1/i, ); const listResponse = await page.request.get( `${baseURL}/api/v1/admin/tenants?limit=1000&offset=0`, { headers: { "X-Test-Role": "super_admin" } }, ); expect(listResponse.ok()).toBeTruthy(); const list = await listResponse.json(); const imported = list.items.find( (tenant: { slug: string }) => tenant.slug === slug, ); expect(imported).toMatchObject({ name: "Live CSV Tenant", slug, description: "Live E2E import", domains: [`${slug}.example.com`], }); tenantId = imported.id; const deleteResponse = await page.request.delete( `${baseURL}/api/v1/admin/tenants/${tenantId}`, { headers: { "X-Test-Role": "super_admin" } }, ); expect(deleteResponse.status()).toBe(204); }); });