import { beforeEach, describe, expect, it, vi } from "vitest"; import { deleteUserWithItsTenants } from "./userService"; import { getMyTenants, getTenantWithUsers } from "../db/tenants.db.server"; import { deleteUser } from "../db/users.db.server"; import { deleteAndCancelTenant } from "./tenantService"; vi.mock("../db.server", () => ({ db: {} })); vi.mock("../cache.server", () => ({ clearCacheKey: vi.fn() })); vi.mock("../db/permissions/userRoles.db.server", () => ({ createUserRoles: vi.fn(), deleteAllUserRoles: vi.fn() })); vi.mock("../db/tenants.db.server", () => ({ getMyTenants: vi.fn(), getTenantWithUsers: vi.fn() })); vi.mock("../db/users.db.server", () => ({ deleteUser: vi.fn() })); vi.mock("./tenantService", () => ({ deleteAndCancelTenant: vi.fn() })); const soloTenant = { id: "tenant_solo", name: "Solo" }; const sharedTenant = { id: "tenant_shared", name: "Shared" }; describe("deleteUserWithItsTenants", () => { beforeEach(() => { vi.clearAllMocks(); vi.mocked(getMyTenants).mockResolvedValue([soloTenant, sharedTenant] as never); vi.mocked(getTenantWithUsers).mockImplementation(async (tenantId) => { if (tenantId === soloTenant.id) { return { users: [{ userId: "user_1" }] } as never; } return { users: [{ userId: "user_1" }, { userId: "user_2" }] } as never; }); vi.mocked(deleteAndCancelTenant).mockResolvedValue(soloTenant as never); vi.mocked(deleteUser).mockResolvedValue({ id: "user_1" } as never); }); it("cancels and deletes only tenants where the deleted user is the sole tenant user", async () => { const result = await deleteUserWithItsTenants("user_1"); expect(deleteAndCancelTenant).toHaveBeenCalledTimes(1); expect(deleteAndCancelTenant).toHaveBeenCalledWith({ tenantId: soloTenant.id, userId: "user_1" }); expect(deleteUser).toHaveBeenCalledWith("user_1"); expect(result.deletedTenants).toEqual([soloTenant]); }); it("does not delete shared tenants when another tenant user remains", async () => { await deleteUserWithItsTenants("user_1"); expect(deleteAndCancelTenant).not.toHaveBeenCalledWith({ tenantId: sharedTenant.id, userId: "user_1" }); }); it("does not delete the user if tenant cancellation fails", async () => { vi.mocked(deleteAndCancelTenant).mockRejectedValueOnce(new Error("stripe unavailable") as never); await expect(deleteUserWithItsTenants("user_1")).rejects.toThrow("stripe unavailable"); expect(deleteUser).not.toHaveBeenCalled(); }); });