mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-30 18:30:32 -06:00
258 lines
7.7 KiB
TypeScript
258 lines
7.7 KiB
TypeScript
import { IdentityProvider, Prisma } from "@prisma/client";
|
|
import { afterEach, describe, expect, test, vi } from "vitest";
|
|
import { prisma } from "@formbricks/database";
|
|
import { PrismaErrorType } from "@formbricks/database/types/error";
|
|
import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors";
|
|
import { TOrganization } from "@formbricks/types/organizations";
|
|
import { TUserLocale, TUserUpdateInput } from "@formbricks/types/user";
|
|
import { deleteOrganization, getOrganizationsWhereUserIsSingleOwner } from "@/lib/organization/service";
|
|
import { deleteUser, getUser, getUserByEmail, getUsersWithOrganization, updateUser } from "./service";
|
|
|
|
vi.mock("@formbricks/database", () => ({
|
|
prisma: {
|
|
user: {
|
|
findUnique: vi.fn(),
|
|
findFirst: vi.fn(),
|
|
update: vi.fn(),
|
|
delete: vi.fn(),
|
|
findMany: vi.fn(),
|
|
},
|
|
},
|
|
}));
|
|
|
|
vi.mock("@/lib/organization/service", () => ({
|
|
getOrganizationsWhereUserIsSingleOwner: vi.fn(),
|
|
deleteOrganization: vi.fn(),
|
|
}));
|
|
|
|
describe("User Service", () => {
|
|
afterEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
const mockPrismaUser = {
|
|
id: "user1",
|
|
name: "Test User",
|
|
email: "test@example.com",
|
|
emailVerified: new Date(),
|
|
createdAt: new Date(),
|
|
updatedAt: new Date(),
|
|
twoFactorEnabled: false,
|
|
identityProvider: IdentityProvider.email,
|
|
notificationSettings: {
|
|
alert: {},
|
|
|
|
unsubscribedOrganizationIds: [],
|
|
},
|
|
locale: "en-US" as TUserLocale,
|
|
lastLoginAt: new Date(),
|
|
isActive: true,
|
|
twoFactorSecret: null,
|
|
backupCodes: null,
|
|
password: null,
|
|
identityProviderAccountId: null,
|
|
groupId: null,
|
|
};
|
|
|
|
const mockOrganizations: TOrganization[] = [
|
|
{
|
|
id: "org1",
|
|
name: "Organization 1",
|
|
createdAt: new Date(),
|
|
updatedAt: new Date(),
|
|
billing: {
|
|
stripeCustomerId: null,
|
|
plan: "free",
|
|
period: "monthly",
|
|
limits: {
|
|
projects: 3,
|
|
monthly: {
|
|
responses: 1500,
|
|
miu: 2000,
|
|
},
|
|
},
|
|
periodStart: new Date(),
|
|
},
|
|
isAIEnabled: false,
|
|
},
|
|
{
|
|
id: "org2",
|
|
name: "Organization 2",
|
|
createdAt: new Date(),
|
|
updatedAt: new Date(),
|
|
billing: {
|
|
stripeCustomerId: null,
|
|
plan: "free",
|
|
period: "monthly",
|
|
limits: {
|
|
projects: 3,
|
|
monthly: {
|
|
responses: 1500,
|
|
miu: 2000,
|
|
},
|
|
},
|
|
periodStart: new Date(),
|
|
},
|
|
isAIEnabled: false,
|
|
},
|
|
];
|
|
|
|
describe("getUser", () => {
|
|
test("should return user when found", async () => {
|
|
vi.mocked(prisma.user.findUnique).mockResolvedValue(mockPrismaUser);
|
|
|
|
const result = await getUser("user1");
|
|
|
|
expect(result).toEqual(mockPrismaUser);
|
|
expect(prisma.user.findUnique).toHaveBeenCalledWith({
|
|
where: { id: "user1" },
|
|
select: expect.any(Object),
|
|
});
|
|
});
|
|
|
|
test("should return null when user not found", async () => {
|
|
vi.mocked(prisma.user.findUnique).mockResolvedValue(null);
|
|
|
|
const result = await getUser("nonexistent");
|
|
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
test("should throw DatabaseError when prisma throws", async () => {
|
|
const prismaError = new Prisma.PrismaClientKnownRequestError("Database error", {
|
|
code: "P2002",
|
|
clientVersion: "5.0.0",
|
|
});
|
|
vi.mocked(prisma.user.findUnique).mockRejectedValue(prismaError);
|
|
|
|
await expect(getUser("user1")).rejects.toThrow(DatabaseError);
|
|
});
|
|
});
|
|
|
|
describe("getUserByEmail", () => {
|
|
test("should return user when found by email", async () => {
|
|
vi.mocked(prisma.user.findFirst).mockResolvedValue(mockPrismaUser);
|
|
|
|
const result = await getUserByEmail("test@example.com");
|
|
|
|
expect(result).toEqual(mockPrismaUser);
|
|
expect(prisma.user.findFirst).toHaveBeenCalledWith({
|
|
where: { email: "test@example.com" },
|
|
select: expect.any(Object),
|
|
});
|
|
});
|
|
|
|
test("should return null when user not found by email", async () => {
|
|
vi.mocked(prisma.user.findFirst).mockResolvedValue(null);
|
|
|
|
const result = await getUserByEmail("nonexistent@example.com");
|
|
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
test("should throw DatabaseError when prisma throws", async () => {
|
|
const prismaError = new Prisma.PrismaClientKnownRequestError("Database error", {
|
|
code: "P2002",
|
|
clientVersion: "5.0.0",
|
|
});
|
|
vi.mocked(prisma.user.findFirst).mockRejectedValue(prismaError);
|
|
|
|
await expect(getUserByEmail("test@example.com")).rejects.toThrow(DatabaseError);
|
|
});
|
|
});
|
|
|
|
describe("updateUser", () => {
|
|
test("should update user successfully", async () => {
|
|
const updatedPrismaUser = {
|
|
...mockPrismaUser,
|
|
name: "Updated User",
|
|
};
|
|
|
|
const updateData: TUserUpdateInput = {
|
|
name: "Updated User",
|
|
};
|
|
|
|
vi.mocked(prisma.user.update).mockResolvedValue(updatedPrismaUser);
|
|
|
|
const result = await updateUser("user1", updateData);
|
|
|
|
expect(result).toEqual(updatedPrismaUser);
|
|
expect(prisma.user.update).toHaveBeenCalledWith({
|
|
where: { id: "user1" },
|
|
data: updateData,
|
|
select: expect.any(Object),
|
|
});
|
|
});
|
|
|
|
test("should throw ResourceNotFoundError when user not found", async () => {
|
|
const prismaError = new Prisma.PrismaClientKnownRequestError("Record not found", {
|
|
code: PrismaErrorType.RecordDoesNotExist,
|
|
clientVersion: "5.0.0",
|
|
});
|
|
vi.mocked(prisma.user.update).mockRejectedValue(prismaError);
|
|
|
|
await expect(updateUser("nonexistent", { name: "New Name" })).rejects.toThrow(ResourceNotFoundError);
|
|
});
|
|
});
|
|
|
|
describe("deleteUser", () => {
|
|
test("should delete user and their organizations when they are single owner", async () => {
|
|
vi.mocked(prisma.user.delete).mockResolvedValue(mockPrismaUser);
|
|
vi.mocked(getOrganizationsWhereUserIsSingleOwner).mockResolvedValue(mockOrganizations);
|
|
vi.mocked(deleteOrganization).mockResolvedValue();
|
|
|
|
const result = await deleteUser("user1");
|
|
|
|
expect(result).toEqual(mockPrismaUser);
|
|
expect(getOrganizationsWhereUserIsSingleOwner).toHaveBeenCalledWith("user1");
|
|
expect(deleteOrganization).toHaveBeenCalledWith("org1");
|
|
expect(prisma.user.delete).toHaveBeenCalledWith({
|
|
where: { id: "user1" },
|
|
select: expect.any(Object),
|
|
});
|
|
});
|
|
|
|
test("should throw DatabaseError when prisma throws", async () => {
|
|
const prismaError = new Prisma.PrismaClientKnownRequestError("Database error", {
|
|
code: "P2002",
|
|
clientVersion: "5.0.0",
|
|
});
|
|
vi.mocked(getOrganizationsWhereUserIsSingleOwner).mockResolvedValue([]);
|
|
vi.mocked(prisma.user.delete).mockRejectedValue(prismaError);
|
|
|
|
await expect(deleteUser("user1")).rejects.toThrow(DatabaseError);
|
|
});
|
|
});
|
|
|
|
describe("getUsersWithOrganization", () => {
|
|
test("should return users in an organization", async () => {
|
|
const mockUsers = [mockPrismaUser];
|
|
vi.mocked(prisma.user.findMany).mockResolvedValue(mockUsers);
|
|
|
|
const result = await getUsersWithOrganization("org1");
|
|
|
|
expect(result).toEqual(mockUsers);
|
|
expect(prisma.user.findMany).toHaveBeenCalledWith({
|
|
where: {
|
|
memberships: {
|
|
some: {
|
|
organizationId: "org1",
|
|
},
|
|
},
|
|
},
|
|
select: expect.any(Object),
|
|
});
|
|
});
|
|
|
|
test("should throw DatabaseError when prisma throws", async () => {
|
|
const prismaError = new Prisma.PrismaClientKnownRequestError("Database error", {
|
|
code: "P2002",
|
|
clientVersion: "5.0.0",
|
|
});
|
|
vi.mocked(prisma.user.findMany).mockRejectedValue(prismaError);
|
|
|
|
await expect(getUsersWithOrganization("org1")).rejects.toThrow(DatabaseError);
|
|
});
|
|
});
|
|
});
|