From 19b99ae6990603c43b08bb9a530ec5ea1164e0df Mon Sep 17 00:00:00 2001 From: Bernt Christian Egeland Date: Mon, 11 Dec 2023 19:03:42 +0100 Subject: [PATCH 1/2] api tests --- src/pages/api/__tests__/v1/user/user.test.ts | 64 ++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/pages/api/__tests__/v1/user/user.test.ts diff --git a/src/pages/api/__tests__/v1/user/user.test.ts b/src/pages/api/__tests__/v1/user/user.test.ts new file mode 100644 index 00000000..c78b940b --- /dev/null +++ b/src/pages/api/__tests__/v1/user/user.test.ts @@ -0,0 +1,64 @@ +import { NextApiRequest, NextApiResponse } from "next"; +import createUserHandler from "~/pages/api/v1/user"; +import { prisma } from "~/server/db"; +import * as encryptionModule from "~/utils/encryption"; +import { appRouter } from "~/server/api/root"; + +jest.mock("~/server/api/root", () => ({ + appRouter: { + createCaller: jest.fn(() => ({ + auth: { + // Mock the mutation method used in your authRouter + register: jest.fn().mockImplementation(() => ({ + mutation: jest.fn().mockResolvedValue({}), + })), + }, + })), + }, +})); + +jest.mock("~/utils/encryption"); +jest.mock("~/server/api/trpc"); + +jest.mock("~/server/db", () => ({ + prisma: { + user: { + count: jest.fn(), + create: jest.fn(), + }, + }, +})); + +describe("createUserHandler", () => { + it("should create a user successfully", async () => { + prisma.user.count = jest.fn().mockResolvedValue(0); + + // Mock the decryption to fail + (encryptionModule.decryptAndVerifyToken as jest.Mock).mockResolvedValue({ + userId: "userId", + }); + + const mockRegister = jest.fn().mockResolvedValue({ id: "newUserId" }); + appRouter.createCaller = jest + .fn() + .mockReturnValue({ auth: { register: mockRegister } }); + + const req = { + method: "POST", + headers: { "x-ztnet-auth": "validApiKey" }, + body: { email: "test@example.com", password: "password123", name: "Test User" }, + } as unknown as NextApiRequest; + + const res = { + status: jest.fn().mockReturnThis(), + json: jest.fn(), + end: jest.fn(), + setHeader: jest.fn(), + } as unknown as NextApiResponse; + + await createUserHandler(req, res); + + expect(res.status).toHaveBeenCalledWith(200); + expect(res.json).toHaveBeenCalledWith({ id: "newUserId" }); + }); +}); From 2bf7f263cfd471b2c94c25636b297741ae6eaa14 Mon Sep 17 00:00:00 2001 From: Bernt Christian Egeland Date: Mon, 11 Dec 2023 19:28:30 +0100 Subject: [PATCH 2/2] more tests --- src/pages/api/__tests__/v1/user/user.test.ts | 55 ++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/pages/api/__tests__/v1/user/user.test.ts b/src/pages/api/__tests__/v1/user/user.test.ts index c78b940b..7bd68978 100644 --- a/src/pages/api/__tests__/v1/user/user.test.ts +++ b/src/pages/api/__tests__/v1/user/user.test.ts @@ -30,6 +30,20 @@ jest.mock("~/server/db", () => ({ })); describe("createUserHandler", () => { + afterEach(() => { + // Restores all mocks back to their original value. + // only works when the mock was created with jest.spyOn; + jest.restoreAllMocks(); + }); + // Helper function to create a mock response object + const createMockRes = () => + ({ + status: jest.fn().mockReturnThis(), + json: jest.fn(), + end: jest.fn(), + setHeader: jest.fn(), + }) as unknown as NextApiResponse; + it("should create a user successfully", async () => { prisma.user.count = jest.fn().mockResolvedValue(0); @@ -61,4 +75,45 @@ describe("createUserHandler", () => { expect(res.status).toHaveBeenCalledWith(200); expect(res.json).toHaveBeenCalledWith({ id: "newUserId" }); }); + + it("should respond 401 when decryptAndVerifyToken fails", async () => { + prisma.user.count = jest.fn().mockResolvedValue(1); + + // Mock the decryption to fail + (encryptionModule.decryptAndVerifyToken as jest.Mock).mockRejectedValue( + new Error("Invalid token"), + ); + + const req = { + method: "POST", + headers: { "x-ztnet-auth": "invalidApiKey" }, + query: { id: "networkId" }, + } as unknown as NextApiRequest; + + const res = { + status: jest.fn().mockReturnThis(), + json: jest.fn(), + end: jest.fn(), + setHeader: jest.fn(), // Mock `setHeader` if rate limiter uses it + } as unknown as NextApiResponse; + + await createUserHandler(req, res); + + expect(res.status).toHaveBeenCalledWith(401); + expect(res.json).toHaveBeenCalledWith({ error: "Invalid token" }); + }); + + it("should allow only POST method", async () => { + const methods = ["GET", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"]; + const req = {} as NextApiRequest; + const res = createMockRes(); + + for (const method of methods) { + req.method = method; + await createUserHandler(req, res); + + expect(res.status).toHaveBeenCalledWith(405); + expect(res.end).toHaveBeenCalled(); + } + }); });