From 37f2a41050fb47b4029dd116de3ea840cf6a0437 Mon Sep 17 00:00:00 2001 From: Adwaith2207 Date: Fri, 6 Feb 2026 19:04:19 +0530 Subject: [PATCH 1/4] add unit tests for forms --- src/test/forms.test.ts | 156 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 src/test/forms.test.ts diff --git a/src/test/forms.test.ts b/src/test/forms.test.ts new file mode 100644 index 0000000..942d940 --- /dev/null +++ b/src/test/forms.test.ts @@ -0,0 +1,156 @@ +import { describe, it, expect, mock, beforeEach } from "bun:test"; + +// ---------- MOCK PRISMA ---------- +const findManyMock = mock(); +const createMock = mock(); +const findFirstMock = mock(); + +mock.module("../db/prisma", () => ({ + prisma: { + form: { + findMany: findManyMock, + create: createMock, + findFirst: findFirstMock, + }, + }, +})); + +// ---------- MOCK LOGGER ---------- +const mockInfo = mock(); +const mockWarn = mock(); + +mock.module("../logger", () => ({ + logger: { + info: mockInfo, + warn: mockWarn, + error: mock(), + }, +})); + +// IMPORT AFTER MOCKS +// IMPORT AFTER MOCKS +const { + getAllForms, + createForm, + getFormById, +} = await import("../api/forms/controller"); + +describe("Forms Controller Tests", () => { + + beforeEach(() => { + findManyMock.mockReset(); + createMock.mockReset(); + findFirstMock.mockReset(); + mockInfo.mockReset(); + mockWarn.mockReset(); + }); + + const user = { id: "user1" }; + + // ===== getAllForms ===== + + it("getAllForms → success", async () => { + findManyMock.mockResolvedValue([ + { id: "1", title: "A", isPublished: true, createdAt: new Date() }, + ]); + + const res = await getAllForms({ user } as any); + + expect(res.success).toBe(true); + expect(res.data.length).toBe(1); + }); + + it("getAllForms → empty", async () => { + findManyMock.mockResolvedValue([]); + + const res = await getAllForms({ user } as any); + + expect(res.message).toBe("No forms found"); + expect(res.data).toEqual([]); + }); + + it("getAllForms → DB error", async () => { + findManyMock.mockRejectedValue(new Error("DB fail")); + + expect(getAllForms({ user } as any)).rejects.toThrow(); + }); + + // ===== createForm ===== + + it("createForm → success", async () => { + createMock.mockResolvedValue({ id: "1", title: "New" }); + + const res = await createForm({ + user, + body: { title: "New", description: "desc" }, + } as any); + + expect(res.success).toBe(true); + }); + + it("createForm → called", async () => { + createMock.mockResolvedValue({ id: "1" }); + + await createForm({ + user, + body: { title: "T", description: "D" }, + } as any); + + expect(createMock).toHaveBeenCalled(); + }); + + it("createForm → DB error", async () => { + createMock.mockRejectedValue(new Error("DB crash")); + + expect( + createForm({ + user, + body: { title: "X", description: "Y" }, + } as any) + ).rejects.toThrow(); + }); + + // ===== getFormById ===== + + it("getFormById → found", async () => { + findFirstMock.mockResolvedValue({ id: "1" }); + + const set: any = {}; + const res = await getFormById({ + user, + params: { id: "1" }, + set, + } as any); + + expect(res.success).toBe(true); + }); + + it("getFormById → not found", async () => { + findFirstMock.mockResolvedValue(null); + + const set: any = {}; + const res = await getFormById({ + user, + params: { id: "2" }, + set, + } as any); + + expect(res.success).toBe(false); + expect(set.status).toBe(404); + }); + + it("getFormById → DB error", async () => { + findFirstMock.mockRejectedValue(new Error("DB error")); + + const set: any = {}; + + expect( + getFormById({ + user, + params: { id: "1" }, + set, + } as any) + ).rejects.toThrow(); + }); + +}); From e370bb8ae1e8db382077d3d71c1dbb62c64a5183 Mon Sep 17 00:00:00 2001 From: Adwaith2207 Date: Fri, 6 Feb 2026 21:10:54 +0530 Subject: [PATCH 2/4] add unit test for forms --- bunfig.toml | 13 +++++ src/test/forms.test.ts | 107 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 bunfig.toml diff --git a/bunfig.toml b/bunfig.toml new file mode 100644 index 0000000..5bff54a --- /dev/null +++ b/bunfig.toml @@ -0,0 +1,13 @@ +[test] +# Enable coverage by default when running 'bun test' +coverage = true + +# Exclude test files from coverage reports to get more accurate metrics +coverageSkipTestFiles = true + +# Set a coverage threshold (0.0 to 1.0) +# This will cause 'bun test' to exit with a non-zero code if coverage is below this value +coverageThreshold = 0.5 + +# Specify reporters. "text" is for CLI, "lcov" generates an lcov.info file +coverageReporter = ["text", "lcov"] diff --git a/src/test/forms.test.ts b/src/test/forms.test.ts index 942d940..108fb5f 100644 --- a/src/test/forms.test.ts +++ b/src/test/forms.test.ts @@ -4,6 +4,8 @@ import { describe, it, expect, mock, beforeEach } from "bun:test"; const findManyMock = mock(); const createMock = mock(); const findFirstMock = mock(); +const updateMock = mock(); +const deleteManyMock = mock(); mock.module("../db/prisma", () => ({ prisma: { @@ -11,6 +13,8 @@ mock.module("../db/prisma", () => ({ findMany: findManyMock, create: createMock, findFirst: findFirstMock, + update: updateMock, + deleteMany: deleteManyMock, }, }, })); @@ -27,12 +31,13 @@ mock.module("../logger", () => ({ }, })); -// IMPORT AFTER MOCKS // IMPORT AFTER MOCKS const { getAllForms, createForm, getFormById, + updateForm, + deleteForm, } = await import("../api/forms/controller"); describe("Forms Controller Tests", () => { @@ -41,6 +46,8 @@ describe("Forms Controller Tests", () => { findManyMock.mockReset(); createMock.mockReset(); findFirstMock.mockReset(); + updateMock.mockReset(); + deleteManyMock.mockReset(); mockInfo.mockReset(); mockWarn.mockReset(); }); @@ -153,4 +160,102 @@ describe("Forms Controller Tests", () => { ).rejects.toThrow(); }); + // ===== updateForm ===== + + it("updateForm → success", async () => { + findFirstMock.mockResolvedValue({ id: "1" }); + + updateMock.mockResolvedValue({ + id: "1", + title: "Updated", + }); + + const set: any = {}; + + const res = await updateForm({ + user, + params: { id: "1" }, + body: { title: "Updated", description: "D" }, + set, + } as any); + + expect(res.success).toBe(true); + }); + + it("updateForm → not found", async () => { + findFirstMock.mockResolvedValue(null); + + const set: any = {}; + + const res = await updateForm({ + user, + params: { id: "1" }, + body: { title: "T", description: "D" }, + set, + } as any); + + expect(res.success).toBe(false); + expect(set.status).toBe(404); + }); + + it("updateForm → DB error", async () => { + findFirstMock.mockRejectedValue(new Error("DB fail")); + + const set: any = {}; + + expect( + updateForm({ + user, + params: { id: "1" }, + body: { title: "T", description: "D" }, + set, + } as any) + ).rejects.toThrow(); + }); + + // ===== deleteForm ===== + + it("deleteForm → success", async () => { + deleteManyMock.mockResolvedValue({ count: 1 }); + + const set: any = {}; + + const res = await deleteForm({ + user, + params: { id: "1" }, + set, + } as any); + + expect(res.success).toBe(true); + }); + + it("deleteForm → not found", async () => { + deleteManyMock.mockResolvedValue({ count: 0 }); + + const set: any = {}; + + const res = await deleteForm({ + user, + params: { id: "1" }, + set, + } as any); + + expect(res.success).toBe(false); + expect(set.status).toBe(404); + }); + + it("deleteForm → DB error", async () => { + deleteManyMock.mockRejectedValue(new Error("DB crash")); + + const set: any = {}; + + expect( + deleteForm({ + user, + params: { id: "1" }, + set, + } as any) + ).rejects.toThrow(); + }); + }); From f8de3a960a934ae97c3ee99f5e8d6fa14cb53fce Mon Sep 17 00:00:00 2001 From: Nandgopal-R Date: Fri, 6 Feb 2026 21:41:15 +0530 Subject: [PATCH 3/4] fix: change parseInt funtion to Number --- src/api/auth/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/auth/index.ts b/src/api/auth/index.ts index 8ef68ce..46eec3f 100644 --- a/src/api/auth/index.ts +++ b/src/api/auth/index.ts @@ -5,7 +5,7 @@ import { prisma } from "../../db/prisma"; const transporter = nodemailer.createTransport({ host: process.env.SMTP_HOST, - port: parseInt(process.env.SMTP_PORT || "587"), + port: Number(process.env.SMTP_PORT || "587"), secure: false, // true for 465, false for other ports auth: { user: process.env.SMTP_USER, From dc25869c070279bfb75d0b9a9bd47dce95558b81 Mon Sep 17 00:00:00 2001 From: Nandgopal-R Date: Fri, 6 Feb 2026 23:33:08 +0530 Subject: [PATCH 4/4] chore: run linter --- .husky/pre-commit | 1 + package.json | 1 + src/test/forms.test.ts | 21 +++++++-------------- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index ec6aa55..5f6006b 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,2 +1,3 @@ #!/usr/bin/env sh npx --no -- lint-staged +bun run test diff --git a/package.json b/package.json index f679ab8..c81e3cb 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "dev": "bun --watch src/index.ts", "check": "biome check .", "typecheck": "tsc --noEmit", + "test": "bun test", "build": "bun build src/index.ts --outdir dist --target bun --minify", "prepare": "husky" }, diff --git a/src/test/forms.test.ts b/src/test/forms.test.ts index 108fb5f..9b25b34 100644 --- a/src/test/forms.test.ts +++ b/src/test/forms.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, mock, beforeEach } from "bun:test"; +import { beforeEach, describe, expect, it, mock } from "bun:test"; // ---------- MOCK PRISMA ---------- const findManyMock = mock(); @@ -32,16 +32,10 @@ mock.module("../logger", () => ({ })); // IMPORT AFTER MOCKS -const { - getAllForms, - createForm, - getFormById, - updateForm, - deleteForm, -} = await import("../api/forms/controller"); +const { getAllForms, createForm, getFormById, updateForm, deleteForm } = + await import("../api/forms/controller"); describe("Forms Controller Tests", () => { - beforeEach(() => { findManyMock.mockReset(); createMock.mockReset(); @@ -113,7 +107,7 @@ describe("Forms Controller Tests", () => { createForm({ user, body: { title: "X", description: "Y" }, - } as any) + } as any), ).rejects.toThrow(); }); @@ -156,7 +150,7 @@ describe("Forms Controller Tests", () => { user, params: { id: "1" }, set, - } as any) + } as any), ).rejects.toThrow(); }); @@ -209,7 +203,7 @@ describe("Forms Controller Tests", () => { params: { id: "1" }, body: { title: "T", description: "D" }, set, - } as any) + } as any), ).rejects.toThrow(); }); @@ -254,8 +248,7 @@ describe("Forms Controller Tests", () => { user, params: { id: "1" }, set, - } as any) + } as any), ).rejects.toThrow(); }); - });