import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { fireEvent, render, screen, waitFor } from "@testing-library/react"; import type React from "react"; import { MemoryRouter, Route, Routes } from "react-router-dom"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { createI18nMock } from "../../test/i18nMock"; import { TenantAdminsAndOwnersTab } from "../tenants/routes/TenantAdminsAndOwnersTab"; import TenantUserGroupsTab from "../user-groups/routes/TenantUserGroupsTab"; const exportUsersCSVMock = vi.hoisted(() => vi.fn(async () => ({ blob: new Blob(["email,name\nmember@example.com,Member User\n"], { type: "text/csv", }), filename: "users_export_20260609.csv", })), ); const tenants = [ { id: "tenant-root", type: "COMPANY_GROUP", name: "한맥 가족", slug: "hanmac-family", description: "", status: "active", memberCount: 0, createdAt: "2026-05-01T00:00:00Z", updatedAt: "2026-05-01T00:00:00Z", }, { id: "tenant-company", type: "COMPANY", parentId: "tenant-root", name: "GPDTDC", slug: "gpdtdc", description: "", status: "active", memberCount: 2, createdAt: "2026-05-01T00:00:00Z", updatedAt: "2026-05-01T00:00:00Z", }, { id: "tenant-leaf", type: "ORGANIZATION", parentId: "tenant-company", name: "기술연구팀", slug: "gpdtdc-rnd", description: "", status: "active", memberCount: 1, createdAt: "2026-05-01T00:00:00Z", updatedAt: "2026-05-01T00:00:00Z", }, ]; const users = [ { id: "user-owner", name: "Owner User", email: "owner@example.com", role: "tenant_admin", status: "active", }, { id: "user-admin", name: "Admin User", email: "admin@example.com", role: "tenant_admin", status: "active", }, { id: "user-member", name: "Member User", email: "member@example.com", role: "user", status: "active", tenantSlug: "gpdtdc-rnd", tenant: tenants[2], }, ]; vi.mock("../../lib/i18n", () => createI18nMock()); vi.mock("react-oidc-context", () => ({ useAuth: () => ({ user: { profile: { sub: "admin-1", }, }, }), })); vi.mock("../../lib/adminApi", () => ({ fetchTenantOwners: vi.fn(async () => [users[0]]), fetchTenantAdmins: vi.fn(async () => [users[1]]), addTenantOwner: vi.fn(async () => undefined), addTenantAdmin: vi.fn(async () => undefined), removeTenantOwner: vi.fn(async () => undefined), removeTenantAdmin: vi.fn(async () => undefined), fetchUsers: vi.fn(async () => ({ items: users, total: users.length, })), fetchAllTenants: vi.fn(async () => ({ items: tenants, total: tenants.length, })), updateTenant: vi.fn(async () => tenants[2]), updateUser: vi.fn(async () => users[2]), exportTenantsCSV: vi.fn(async () => ({ blob: new Blob(["name,slug"]), filename: "tenants.csv", })), exportUsersCSV: exportUsersCSVMock, })); function renderWithProviders(ui: React.ReactElement, entry: string) { const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false }, mutations: { retry: false }, }, }); return render( {ui} , ); } describe("admin tenant tab coverage smoke", () => { beforeEach(() => { vi.clearAllMocks(); vi.spyOn(window, "confirm").mockReturnValue(true); vi.spyOn(window.URL, "createObjectURL").mockReturnValue( "blob:tenant-users-export", ); vi.spyOn(window.URL, "revokeObjectURL").mockImplementation(() => {}); }); it("renders tenant owners and admins lists", async () => { renderWithProviders( } /> , "/tenants/tenant-company/permissions", ); expect(await screen.findByText("Owner User")).toBeInTheDocument(); expect(screen.getByText("Admin User")).toBeInTheDocument(); expect(screen.getByText("owner@example.com")).toBeInTheDocument(); expect(screen.getByText("admin@example.com")).toBeInTheDocument(); }); it("renders tenant hierarchy and selected organization members", async () => { renderWithProviders( } /> , "/tenants/tenant-company/organization", ); expect((await screen.findAllByText("GPDTDC")).length).toBeGreaterThan(0); expect(screen.getAllByText("기술연구팀").length).toBeGreaterThan(0); expect(await screen.findByText("Member User")).toBeInTheDocument(); }); it("exports selected organization users by tenant slug", async () => { renderWithProviders( } /> , "/tenants/tenant-company/organization", ); expect(await screen.findByText("Member User")).toBeInTheDocument(); fireEvent.click(screen.getByTestId("tenant-current-users-export-btn")); await waitFor(() => { expect(exportUsersCSVMock).toHaveBeenCalledWith("", "gpdtdc", false); }); }); });