142 lines
4.0 KiB
TypeScript
142 lines
4.0 KiB
TypeScript
/**
|
|
* Tests for GET /api/social/profile/[userId] — postsCount + followingCount
|
|
*
|
|
* Covers:
|
|
* - postsCount reflects live communityPost.count (not 0 when posts exist)
|
|
* - followingCount reflects live userFollow.count
|
|
* - followersCount passes through from profile row (denormalized)
|
|
*/
|
|
import { describe, expect, it, vi, beforeEach } from "vitest";
|
|
|
|
const mocks = vi.hoisted(() => ({
|
|
communityPost: {
|
|
findMany: vi.fn(),
|
|
count: vi.fn(),
|
|
},
|
|
userFollow: {
|
|
findUnique: vi.fn(),
|
|
count: vi.fn(),
|
|
},
|
|
profile: {
|
|
findUnique: vi.fn(),
|
|
},
|
|
userScore: {
|
|
findUnique: vi.fn(),
|
|
},
|
|
domainSubmission: {
|
|
count: vi.fn(),
|
|
},
|
|
}));
|
|
|
|
vi.mock("../../server/utils/prisma", () => ({
|
|
usePrisma: () => ({
|
|
communityPost: mocks.communityPost,
|
|
userFollow: mocks.userFollow,
|
|
profile: mocks.profile,
|
|
userScore: mocks.userScore,
|
|
domainSubmission: mocks.domainSubmission,
|
|
}),
|
|
}));
|
|
|
|
vi.mock("../../server/utils/auth", () => ({
|
|
requireUser: vi.fn().mockRejectedValue(
|
|
Object.assign(new Error("Unauthorized"), { statusCode: 401 }),
|
|
),
|
|
}));
|
|
|
|
vi.mock("../../server/db/profile", () => ({
|
|
getProfile: vi.fn().mockResolvedValue({
|
|
id: "user-1",
|
|
username: "testuser",
|
|
followersCount: 3,
|
|
createdAt: new Date("2026-01-01T00:00:00Z"),
|
|
}),
|
|
}));
|
|
|
|
vi.mock("../../server/db/scores", () => ({
|
|
getUserScore: vi.fn().mockResolvedValue({ tier: "beginner", totalPoints: 0 }),
|
|
}));
|
|
|
|
vi.mock("../../server/db/social", () => ({
|
|
getFollowRelation: vi.fn().mockResolvedValue(null),
|
|
}));
|
|
|
|
vi.mock("../../server/utils/getUsersMeta", () => ({
|
|
getUsersMeta: vi.fn().mockResolvedValue({
|
|
"user-1": { nickname: "Tester", avatar: null },
|
|
}),
|
|
}));
|
|
|
|
// Stub Nitro globals needed by the endpoint file
|
|
const g = globalThis as Record<string, unknown>;
|
|
if (typeof g.getRouterParam === "undefined") {
|
|
g.getRouterParam = (_event: unknown, key: string) =>
|
|
key === "userId" ? "user-1" : undefined;
|
|
}
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
mocks.communityPost.findMany.mockResolvedValue([]);
|
|
mocks.communityPost.count.mockResolvedValue(0);
|
|
mocks.userFollow.count.mockResolvedValue(0);
|
|
mocks.userFollow.findUnique.mockResolvedValue(null);
|
|
mocks.domainSubmission.count.mockResolvedValue(0);
|
|
});
|
|
|
|
async function callHandler() {
|
|
const mod = await import("../../server/api/social/profile/[userId].get");
|
|
const handler =
|
|
typeof mod.default === "function"
|
|
? mod.default
|
|
: (mod.default as { handler?: unknown }).handler;
|
|
return (handler as (e: unknown) => Promise<unknown>)({ body: null });
|
|
}
|
|
|
|
describe("postsCount", () => {
|
|
it("returns postsCount > 0 when user has unmoderated posts", async () => {
|
|
mocks.communityPost.count.mockResolvedValueOnce(5);
|
|
mocks.userFollow.count.mockResolvedValueOnce(2);
|
|
|
|
const result = (await callHandler()) as Record<string, unknown>;
|
|
|
|
expect(result.postsCount).toBe(5);
|
|
expect(mocks.communityPost.count).toHaveBeenCalledWith({
|
|
where: { userId: "user-1", isModerated: false },
|
|
});
|
|
});
|
|
|
|
it("returns postsCount = 0 when user has no posts", async () => {
|
|
mocks.communityPost.count.mockResolvedValueOnce(0);
|
|
mocks.userFollow.count.mockResolvedValueOnce(0);
|
|
|
|
const result = (await callHandler()) as Record<string, unknown>;
|
|
|
|
expect(result.postsCount).toBe(0);
|
|
});
|
|
});
|
|
|
|
describe("followingCount", () => {
|
|
it("returns followingCount from userFollow.count", async () => {
|
|
mocks.communityPost.count.mockResolvedValueOnce(2);
|
|
mocks.userFollow.count.mockResolvedValueOnce(7);
|
|
|
|
const result = (await callHandler()) as Record<string, unknown>;
|
|
|
|
expect(result.followingCount).toBe(7);
|
|
expect(mocks.userFollow.count).toHaveBeenCalledWith({
|
|
where: { followerId: "user-1" },
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("followersCount", () => {
|
|
it("passes through denormalized followersCount from profile row", async () => {
|
|
mocks.communityPost.count.mockResolvedValueOnce(0);
|
|
mocks.userFollow.count.mockResolvedValueOnce(0);
|
|
|
|
const result = (await callHandler()) as Record<string, unknown>;
|
|
|
|
expect(result.followersCount).toBe(3);
|
|
});
|
|
});
|