test: align remaining action tests with Drizzle mocks
EOF Co-authored-by: Cursor <[email protected]>
This commit is contained in:
1 parent
ed9c23c702
commit
096f55b394
4 files changed
+156
-112
No files matched your search
@@ -2,64 +2,83 @@
|
|||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
import { auth } from "@/lib/auth";
|
import { auth } from "@/lib/auth";
|
||||||
import { prisma } from "@/lib/prisma";
|
|
||||||
import { clientIp, rateLimit } from "@/lib/rate-limit";
|
import { clientIp, rateLimit } from "@/lib/rate-limit";
|
||||||
import { applyStaff, applyTeam } from "./applications";
|
import { applyStaff, applyTeam } from "./applications";
|
||||||
|
|
||||||
|
const { selectLimit, insertValues } = vi.hoisted(() => {
|
||||||
|
const selectLimit = vi.fn();
|
||||||
|
const insertValues = vi.fn().mockResolvedValue([{ insertId: 1 }]);
|
||||||
|
return { selectLimit, insertValues };
|
||||||
|
});
|
||||||
|
|
||||||
vi.mock("@/lib/auth", () => ({ auth: vi.fn() }));
|
vi.mock("@/lib/auth", () => ({ auth: vi.fn() }));
|
||||||
vi.mock("@/lib/prisma", () => ({
|
vi.mock("@/lib/db", () => ({
|
||||||
prisma: { websiteStaffApplications: { findFirst: vi.fn(), create: vi.fn() } },
|
db: {
|
||||||
|
select: vi.fn(() => ({
|
||||||
|
from: vi.fn(() => ({
|
||||||
|
where: vi.fn(() => ({
|
||||||
|
limit: selectLimit,
|
||||||
|
})),
|
||||||
|
})),
|
||||||
|
})),
|
||||||
|
insert: vi.fn(() => ({ values: insertValues })),
|
||||||
|
},
|
||||||
|
WebsiteStaffApplications: {
|
||||||
|
id: "id",
|
||||||
|
userId: "userId",
|
||||||
|
rankId: "rankId",
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
vi.mock("@/lib/rate-limit", () => ({ clientIp: vi.fn(), rateLimit: vi.fn() }));
|
vi.mock("@/lib/rate-limit", () => ({ clientIp: vi.fn(), rateLimit: vi.fn() }));
|
||||||
vi.mock("next/cache", () => ({ revalidatePath: vi.fn() }));
|
vi.mock("next/cache", () => ({ revalidatePath: vi.fn() }));
|
||||||
vi.mock("next/navigation", () => ({ redirect: vi.fn() }));
|
vi.mock("next/navigation", () => ({ redirect: vi.fn() }));
|
||||||
|
|
||||||
const fakeForm = (data: Record<string, string>) => ({
|
const fakeForm = (data) => ({
|
||||||
get: (key: string) => data[key] ?? null,
|
get: (key) => data[key] ?? null,
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
vi.mocked(auth).mockResolvedValue({ user: { id: "42" } } as never);
|
vi.mocked(auth).mockResolvedValue({ user: { id: "42" } });
|
||||||
vi.mocked(clientIp).mockResolvedValue("127.0.0.1");
|
vi.mocked(clientIp).mockResolvedValue("127.0.0.1");
|
||||||
vi.mocked(rateLimit).mockResolvedValue({ ok: true });
|
vi.mocked(rateLimit).mockResolvedValue({ ok: true });
|
||||||
|
selectLimit.mockResolvedValue([]);
|
||||||
|
insertValues.mockResolvedValue([{ insertId: 1 }]);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("applyStaff", () => {
|
describe("applyStaff", () => {
|
||||||
it("submits staff application", async () => {
|
it("submits staff application", async () => {
|
||||||
vi.mocked(prisma.websiteStaffApplications.findFirst).mockResolvedValue(
|
|
||||||
null,
|
|
||||||
);
|
|
||||||
vi.mocked(prisma.websiteStaffApplications.create).mockResolvedValue(
|
|
||||||
{} as never,
|
|
||||||
);
|
|
||||||
await applyStaff(
|
await applyStaff(
|
||||||
fakeForm({
|
fakeForm({
|
||||||
rankId: "3",
|
rankId: "3",
|
||||||
content: "I want to help!",
|
content: "I want to help!",
|
||||||
}) as unknown as FormData,
|
}),
|
||||||
|
);
|
||||||
|
expect(insertValues).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
userId: 42,
|
||||||
|
rankId: 3,
|
||||||
|
content: "I want to help!",
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
expect(prisma.websiteStaffApplications.create).toHaveBeenCalled();
|
|
||||||
expect(redirect).toHaveBeenCalledWith("/apply/staff?submitted=1");
|
expect(redirect).toHaveBeenCalledWith("/apply/staff?submitted=1");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("redirects to login when not authenticated", async () => {
|
it("redirects to login when not authenticated", async () => {
|
||||||
vi.mocked(auth).mockResolvedValue(null);
|
vi.mocked(auth).mockResolvedValue(null);
|
||||||
await applyStaff(fakeForm({}) as unknown as FormData);
|
await applyStaff(fakeForm({}));
|
||||||
expect(redirect).toHaveBeenCalledWith("/login");
|
expect(redirect).toHaveBeenCalledWith("/login");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("returns duplicate status when application exists", async () => {
|
it("returns duplicate status when application exists", async () => {
|
||||||
vi.mocked(prisma.websiteStaffApplications.findFirst).mockResolvedValue({
|
selectLimit.mockResolvedValue([{ id: 1 }]);
|
||||||
id: 1,
|
|
||||||
} as never);
|
|
||||||
await applyStaff(
|
await applyStaff(
|
||||||
fakeForm({
|
fakeForm({
|
||||||
rankId: "3",
|
rankId: "3",
|
||||||
content: "I want to help!",
|
content: "I want to help!",
|
||||||
}) as unknown as FormData,
|
}),
|
||||||
);
|
);
|
||||||
expect(prisma.websiteStaffApplications.create).not.toHaveBeenCalled();
|
expect(insertValues).not.toHaveBeenCalled();
|
||||||
expect(redirect).toHaveBeenCalledWith("/apply/staff?error=duplicate");
|
expect(redirect).toHaveBeenCalledWith("/apply/staff?error=duplicate");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -69,7 +88,7 @@ describe("applyStaff", () => {
|
|||||||
fakeForm({
|
fakeForm({
|
||||||
rankId: "3",
|
rankId: "3",
|
||||||
content: "I want to help!",
|
content: "I want to help!",
|
||||||
}) as unknown as FormData,
|
}),
|
||||||
);
|
);
|
||||||
expect(redirect).toHaveBeenCalledWith("/apply/staff?error=ratelimit");
|
expect(redirect).toHaveBeenCalledWith("/apply/staff?error=ratelimit");
|
||||||
});
|
});
|
||||||
@@ -77,25 +96,25 @@ describe("applyStaff", () => {
|
|||||||
|
|
||||||
describe("applyTeam", () => {
|
describe("applyTeam", () => {
|
||||||
it("submits team application", async () => {
|
it("submits team application", async () => {
|
||||||
vi.mocked(prisma.websiteStaffApplications.findFirst).mockResolvedValue(
|
|
||||||
null,
|
|
||||||
);
|
|
||||||
vi.mocked(prisma.websiteStaffApplications.create).mockResolvedValue(
|
|
||||||
{} as never,
|
|
||||||
);
|
|
||||||
await applyTeam(
|
await applyTeam(
|
||||||
fakeForm({
|
fakeForm({
|
||||||
teamId: "2",
|
teamId: "2",
|
||||||
content: "I want to join team!",
|
content: "I want to join team!",
|
||||||
}) as unknown as FormData,
|
}),
|
||||||
|
);
|
||||||
|
expect(insertValues).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
userId: 42,
|
||||||
|
rankId: 2,
|
||||||
|
content: "I want to join team!",
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
expect(prisma.websiteStaffApplications.create).toHaveBeenCalled();
|
|
||||||
expect(redirect).toHaveBeenCalledWith("/apply/team?submitted=1");
|
expect(redirect).toHaveBeenCalledWith("/apply/team?submitted=1");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("redirects to login when not authenticated", async () => {
|
it("redirects to login when not authenticated", async () => {
|
||||||
vi.mocked(auth).mockResolvedValue(null);
|
vi.mocked(auth).mockResolvedValue(null);
|
||||||
await applyTeam(fakeForm({}) as unknown as FormData);
|
await applyTeam(fakeForm({}));
|
||||||
expect(redirect).toHaveBeenCalledWith("/login");
|
expect(redirect).toHaveBeenCalledWith("/login");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1,15 +1,36 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
import { checkLogin } from "@/lib/auth/password";
|
import { checkLogin } from "@/lib/auth/password";
|
||||||
import { prisma } from "@/lib/prisma";
|
|
||||||
import { clientIp, rateLimit } from "@/lib/rate-limit";
|
import { clientIp, rateLimit } from "@/lib/rate-limit";
|
||||||
import { captchaConfig, verifyCaptcha } from "@/lib/services/captcha";
|
import { captchaConfig, verifyCaptcha } from "@/lib/services/captcha";
|
||||||
import { siteSettings } from "@/lib/services/site-settings";
|
import { siteSettings } from "@/lib/services/site-settings";
|
||||||
import { precheckLogin } from "./auth-precheck";
|
import { precheckLogin } from "./auth-precheck";
|
||||||
|
|
||||||
|
const { selectLimit } = vi.hoisted(() => {
|
||||||
|
const selectLimit = vi.fn().mockResolvedValue([]);
|
||||||
|
return { selectLimit };
|
||||||
|
});
|
||||||
|
|
||||||
vi.mock("@/env", () => ({ env: { CONVERT_PASSWORDS: false } }));
|
vi.mock("@/env", () => ({ env: { CONVERT_PASSWORDS: false } }));
|
||||||
vi.mock("@/lib/auth/password", () => ({ checkLogin: vi.fn() }));
|
vi.mock("@/lib/auth/password", () => ({ checkLogin: vi.fn() }));
|
||||||
vi.mock("@/lib/prisma", () => ({ prisma: { user: { findUnique: vi.fn() } } }));
|
vi.mock("@/lib/db", () => ({
|
||||||
|
db: {
|
||||||
|
select: vi.fn(() => ({
|
||||||
|
from: vi.fn(() => ({
|
||||||
|
where: vi.fn(() => ({
|
||||||
|
limit: selectLimit,
|
||||||
|
})),
|
||||||
|
})),
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
User: {
|
||||||
|
password: "password",
|
||||||
|
twoFactorConfirmedAt: "twoFactorConfirmedAt",
|
||||||
|
mail: "mail",
|
||||||
|
mailVerified: "mailVerified",
|
||||||
|
username: "username",
|
||||||
|
},
|
||||||
|
}));
|
||||||
vi.mock("@/lib/rate-limit", () => ({ clientIp: vi.fn(), rateLimit: vi.fn() }));
|
vi.mock("@/lib/rate-limit", () => ({ clientIp: vi.fn(), rateLimit: vi.fn() }));
|
||||||
vi.mock("@/lib/services/captcha", () => ({
|
vi.mock("@/lib/services/captcha", () => ({
|
||||||
captchaConfig: vi.fn(),
|
captchaConfig: vi.fn(),
|
||||||
@@ -25,26 +46,31 @@ beforeEach(() => {
|
|||||||
vi.mocked(rateLimit).mockResolvedValue({ ok: true });
|
vi.mocked(rateLimit).mockResolvedValue({ ok: true });
|
||||||
vi.mocked(checkLogin).mockResolvedValue({ valid: true } as never);
|
vi.mocked(checkLogin).mockResolvedValue({ valid: true } as never);
|
||||||
vi.mocked(captchaConfig).mockResolvedValue({ provider: "none" } as never);
|
vi.mocked(captchaConfig).mockResolvedValue({ provider: "none" } as never);
|
||||||
|
selectLimit.mockResolvedValue([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("precheckLogin", () => {
|
describe("precheckLogin", () => {
|
||||||
it("returns ok for valid login without 2FA", async () => {
|
it("returns ok for valid login without 2FA", async () => {
|
||||||
vi.mocked(prisma.user.findUnique).mockResolvedValue({
|
selectLimit.mockResolvedValue([
|
||||||
password: "hash",
|
{
|
||||||
twoFactorConfirmedAt: null,
|
password: "hash",
|
||||||
mail: null,
|
twoFactorConfirmedAt: null,
|
||||||
mailVerified: "0",
|
mail: null,
|
||||||
} as never);
|
mailVerified: "0",
|
||||||
|
},
|
||||||
|
]);
|
||||||
expect(await precheckLogin("user", "pass")).toBe("ok");
|
expect(await precheckLogin("user", "pass")).toBe("ok");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("returns twofactor when 2FA is set up", async () => {
|
it("returns twofactor when 2FA is set up", async () => {
|
||||||
vi.mocked(prisma.user.findUnique).mockResolvedValue({
|
selectLimit.mockResolvedValue([
|
||||||
password: "hash",
|
{
|
||||||
twoFactorConfirmedAt: new Date(),
|
password: "hash",
|
||||||
mail: null,
|
twoFactorConfirmedAt: new Date(),
|
||||||
mailVerified: "0",
|
mail: null,
|
||||||
} as never);
|
mailVerified: "0",
|
||||||
|
},
|
||||||
|
]);
|
||||||
expect(await precheckLogin("user", "pass")).toBe("twofactor");
|
expect(await precheckLogin("user", "pass")).toBe("twofactor");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -57,29 +83,33 @@ describe("precheckLogin", () => {
|
|||||||
provider: "hcaptcha",
|
provider: "hcaptcha",
|
||||||
} as never);
|
} as never);
|
||||||
vi.mocked(verifyCaptcha).mockResolvedValue(false);
|
vi.mocked(verifyCaptcha).mockResolvedValue(false);
|
||||||
vi.mocked(prisma.user.findUnique).mockResolvedValue({
|
selectLimit.mockResolvedValue([
|
||||||
password: "hash",
|
{
|
||||||
twoFactorConfirmedAt: null,
|
password: "hash",
|
||||||
mail: null,
|
twoFactorConfirmedAt: null,
|
||||||
mailVerified: "0",
|
mail: null,
|
||||||
} as never);
|
mailVerified: "0",
|
||||||
|
},
|
||||||
|
]);
|
||||||
expect(await precheckLogin("user", "pass", "bad-token")).toBe("captcha");
|
expect(await precheckLogin("user", "pass", "bad-token")).toBe("captcha");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("returns invalid when user not found (dummy hash check)", async () => {
|
it("returns invalid when user not found (dummy hash check)", async () => {
|
||||||
vi.mocked(prisma.user.findUnique).mockResolvedValue(null);
|
selectLimit.mockResolvedValue([]);
|
||||||
const result = await precheckLogin("nonexistent", "pass");
|
const result = await precheckLogin("nonexistent", "pass");
|
||||||
expect(result).toBe("invalid");
|
expect(result).toBe("invalid");
|
||||||
expect(checkLogin).toHaveBeenCalled();
|
expect(checkLogin).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("returns unverified when email verification required", async () => {
|
it("returns unverified when email verification required", async () => {
|
||||||
vi.mocked(prisma.user.findUnique).mockResolvedValue({
|
selectLimit.mockResolvedValue([
|
||||||
password: "hash",
|
{
|
||||||
twoFactorConfirmedAt: null,
|
password: "hash",
|
||||||
mail: "[email protected]",
|
twoFactorConfirmedAt: null,
|
||||||
mailVerified: "0",
|
mail: "[email protected]",
|
||||||
} as never);
|
mailVerified: "0",
|
||||||
|
},
|
||||||
|
]);
|
||||||
vi.mocked(siteSettings.getBool).mockResolvedValue(true);
|
vi.mocked(siteSettings.getBool).mockResolvedValue(true);
|
||||||
expect(await precheckLogin("user", "pass")).toBe("unverified");
|
expect(await precheckLogin("user", "pass")).toBe("unverified");
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,39 +1,38 @@
|
|||||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
const {
|
const { selectLimit, insertOnDup, mockSendMail, mockRedirect } = vi.hoisted(
|
||||||
mockFindFirst,
|
() => ({
|
||||||
mockUpsert,
|
selectLimit: vi.fn(),
|
||||||
mockFindUnique,
|
insertOnDup: vi.fn().mockResolvedValue({}),
|
||||||
mockUpdate,
|
mockSendMail: vi.fn(),
|
||||||
mockDelete,
|
mockRedirect: vi.fn(),
|
||||||
mockSendMail,
|
}),
|
||||||
mockRedirect,
|
);
|
||||||
} = vi.hoisted(() => ({
|
|
||||||
mockFindFirst: vi.fn(),
|
|
||||||
mockUpsert: vi.fn(),
|
|
||||||
mockFindUnique: vi.fn(),
|
|
||||||
mockUpdate: vi.fn(),
|
|
||||||
mockDelete: vi.fn(),
|
|
||||||
mockSendMail: vi.fn(),
|
|
||||||
mockRedirect: vi.fn(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
vi.mock("next/navigation", () => ({
|
vi.mock("next/navigation", () => ({
|
||||||
redirect: (...args: unknown[]) => {
|
redirect: (...args) => {
|
||||||
mockRedirect(...args);
|
mockRedirect(...args);
|
||||||
throw new Error("redirect");
|
throw new Error("redirect");
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock("@/lib/prisma", () => ({
|
vi.mock("@/lib/db", () => ({
|
||||||
prisma: {
|
db: {
|
||||||
user: { findFirst: mockFindFirst, update: mockUpdate },
|
select: vi.fn(() => ({
|
||||||
passwordReset: {
|
from: vi.fn(() => ({
|
||||||
upsert: mockUpsert,
|
where: vi.fn(() => ({
|
||||||
findUnique: mockFindUnique,
|
limit: selectLimit,
|
||||||
delete: mockDelete,
|
})),
|
||||||
},
|
})),
|
||||||
|
})),
|
||||||
|
insert: vi.fn(() => ({
|
||||||
|
values: vi.fn(() => ({
|
||||||
|
onDuplicateKeyUpdate: insertOnDup,
|
||||||
|
})),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
|
User: { id: "id", mail: "mail" },
|
||||||
|
PasswordReset: { email: "email", token: "token", createdAt: "createdAt" },
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock("@/lib/services/email", () => ({
|
vi.mock("@/lib/services/email", () => ({
|
||||||
@@ -62,22 +61,20 @@ import { requestReset } from "./password-reset";
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
|
insertOnDup.mockResolvedValue({});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("requestReset", () => {
|
describe("requestReset", () => {
|
||||||
it("sends a reset email when the user exists", async () => {
|
it("sends a reset email when the user exists", async () => {
|
||||||
mockFindFirst.mockResolvedValue({ id: 1 });
|
selectLimit.mockResolvedValue([{ id: 1 }]);
|
||||||
mockUpsert.mockResolvedValue({});
|
|
||||||
|
|
||||||
const fd = new FormData();
|
const fd = new FormData();
|
||||||
fd.set("email", "[email protected]");
|
fd.set("email", "[email protected]");
|
||||||
|
|
||||||
await expect(requestReset(fd)).rejects.toThrow("redirect");
|
await expect(requestReset(fd)).rejects.toThrow("redirect");
|
||||||
|
|
||||||
expect(mockFindFirst).toHaveBeenCalledWith(
|
expect(selectLimit).toHaveBeenCalled();
|
||||||
expect.objectContaining({ where: { mail: "[email protected]" } }),
|
expect(insertOnDup).toHaveBeenCalled();
|
||||||
);
|
|
||||||
expect(mockUpsert).toHaveBeenCalled();
|
|
||||||
expect(mockSendMail).toHaveBeenCalledWith(
|
expect(mockSendMail).toHaveBeenCalledWith(
|
||||||
"[email protected]",
|
"[email protected]",
|
||||||
expect.stringContaining("password reset"),
|
expect.stringContaining("password reset"),
|
||||||
@@ -86,7 +83,7 @@ describe("requestReset", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("does not send email when user is not found", async () => {
|
it("does not send email when user is not found", async () => {
|
||||||
mockFindFirst.mockResolvedValue(null);
|
selectLimit.mockResolvedValue([]);
|
||||||
|
|
||||||
const fd = new FormData();
|
const fd = new FormData();
|
||||||
fd.set("email", "[email protected]");
|
fd.set("email", "[email protected]");
|
||||||
@@ -100,6 +97,6 @@ describe("requestReset", () => {
|
|||||||
fd.set("email", "not-an-email");
|
fd.set("email", "not-an-email");
|
||||||
|
|
||||||
await expect(requestReset(fd)).rejects.toThrow("redirect");
|
await expect(requestReset(fd)).rejects.toThrow("redirect");
|
||||||
expect(mockFindFirst).not.toHaveBeenCalled();
|
expect(selectLimit).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
const create = vi.hoisted(() => vi.fn());
|
const insertValues = vi.hoisted(() => vi.fn());
|
||||||
|
|
||||||
vi.mock("@/lib/prisma", () => ({
|
vi.mock("@/lib/db", () => ({
|
||||||
prisma: { staffActivities: { create } },
|
db: {
|
||||||
|
insert: vi.fn(() => ({ values: insertValues })),
|
||||||
|
},
|
||||||
|
StaffActivities: {},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock("@/env", () => ({ env: {} }));
|
vi.mock("@/env", () => ({ env: {} }));
|
||||||
@@ -12,8 +15,7 @@ vi.mock("next/headers", () => ({
|
|||||||
headers: () =>
|
headers: () =>
|
||||||
new Promise((resolve) =>
|
new Promise((resolve) =>
|
||||||
resolve({
|
resolve({
|
||||||
get: (key: string) =>
|
get: (key) => (key === "x-real-client-ip" ? "192.168.1.1" : null),
|
||||||
key === "x-real-client-ip" ? "192.168.1.1" : null,
|
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
}));
|
}));
|
||||||
@@ -22,43 +24,39 @@ import { logStaffActivity } from "./staff-activity";
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
|
insertValues.mockResolvedValue([{ insertId: 1 }]);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("logStaffActivity", () => {
|
describe("logStaffActivity", () => {
|
||||||
it("creates a staff activity entry with ip", async () => {
|
it("creates a staff activity entry with ip", async () => {
|
||||||
create.mockResolvedValue({ id: 1 });
|
|
||||||
await logStaffActivity({
|
await logStaffActivity({
|
||||||
staffId: 1,
|
staffId: 1,
|
||||||
action: "test_action",
|
action: "test_action",
|
||||||
description: "Test action performed",
|
description: "Test action performed",
|
||||||
});
|
});
|
||||||
expect(create).toHaveBeenCalledWith(
|
expect(insertValues).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
data: expect.objectContaining({
|
userId: BigInt(1),
|
||||||
userId: BigInt(1),
|
action: "test_action",
|
||||||
action: "test_action",
|
description: "Test action performed",
|
||||||
description: "Test action performed",
|
ipAddress: "192.168.1.1",
|
||||||
ipAddress: "192.168.1.1",
|
|
||||||
}),
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("truncates action to 50 chars", async () => {
|
it("truncates action to 50 chars", async () => {
|
||||||
create.mockResolvedValue({ id: 1 });
|
|
||||||
const longAction = "a".repeat(100);
|
const longAction = "a".repeat(100);
|
||||||
await logStaffActivity({
|
await logStaffActivity({
|
||||||
staffId: 1,
|
staffId: 1,
|
||||||
action: longAction,
|
action: longAction,
|
||||||
description: "test",
|
description: "test",
|
||||||
});
|
});
|
||||||
const call = create.mock.calls[0][0];
|
const call = insertValues.mock.calls[0][0];
|
||||||
expect(call.data.action.length).toBe(50);
|
expect(call.action.length).toBe(50);
|
||||||
expect(call.data.action).toBe("a".repeat(50));
|
expect(call.action).toBe("a".repeat(50));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("includes target type and target id when provided", async () => {
|
it("includes target type and target id when provided", async () => {
|
||||||
create.mockResolvedValue({ id: 1 });
|
|
||||||
await logStaffActivity({
|
await logStaffActivity({
|
||||||
staffId: 1,
|
staffId: 1,
|
||||||
action: "ban",
|
action: "ban",
|
||||||
@@ -66,13 +64,13 @@ describe("logStaffActivity", () => {
|
|||||||
targetType: "user",
|
targetType: "user",
|
||||||
targetId: 42,
|
targetId: 42,
|
||||||
});
|
});
|
||||||
const data = create.mock.calls[0][0].data;
|
const data = insertValues.mock.calls[0][0];
|
||||||
expect(data.targetType).toBe("user");
|
expect(data.targetType).toBe("user");
|
||||||
expect(data.targetId).toBe(BigInt(42));
|
expect(data.targetId).toBe(BigInt(42));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("does not throw on prisma error", async () => {
|
it("does not throw on db error", async () => {
|
||||||
create.mockRejectedValue(new Error("DB down"));
|
insertValues.mockRejectedValue(new Error("DB down"));
|
||||||
await expect(
|
await expect(
|
||||||
logStaffActivity({
|
logStaffActivity({
|
||||||
staffId: 1,
|
staffId: 1,
|
||||||
|
|||||||
Reference in new issue
Block a user