From 71ccd3a40bea30b9b54c9beb87e0676de830a82e Mon Sep 17 00:00:00 2001 From: Harish-Naruto Date: Fri, 17 Oct 2025 00:42:47 +0530 Subject: [PATCH 1/4] get all achievement route changed to return with member data --- src/services/achievement.service.ts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/services/achievement.service.ts b/src/services/achievement.service.ts index 46e5d1d..e63ce83 100644 --- a/src/services/achievement.service.ts +++ b/src/services/achievement.service.ts @@ -2,6 +2,34 @@ import { prisma } from "../db/client"; export const getAchievements = async () => { return await prisma.achievement.findMany({ + include: { + + members: { + select: { + member: { + select: { + id: true, + name: true, + email: true, + profilePhoto: true, + }, + }, + }, + }, + + createdBy: { + select: { + id: true, + name: true, + }, + }, + updatedBy: { + select: { + id: true, + name: true, + }, + }, + }, orderBy: { achievedAt: "desc", }, From e6169a5318c94d86ba7a9a8569e467f3ddf90b0b Mon Sep 17 00:00:00 2001 From: Harish-Naruto Date: Fri, 17 Oct 2025 00:44:15 +0530 Subject: [PATCH 2/4] date of birth added to member table --- .../20251016191132_birth_date_added_to_member/migration.sql | 2 ++ prisma/schema.prisma | 1 + 2 files changed, 3 insertions(+) create mode 100644 prisma/migrations/20251016191132_birth_date_added_to_member/migration.sql diff --git a/prisma/migrations/20251016191132_birth_date_added_to_member/migration.sql b/prisma/migrations/20251016191132_birth_date_added_to_member/migration.sql new file mode 100644 index 0000000..c9d6408 --- /dev/null +++ b/prisma/migrations/20251016191132_birth_date_added_to_member/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Member" ADD COLUMN "birth_date" TEXT; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 31e93fa..4046b17 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -16,6 +16,7 @@ model Member { id String @id @default(uuid()) name String email String @unique + birth_date String? phone String? // Single phone number bio String? profilePhoto String? // URL to profile photo From 579cc530accae735fcc9bf0a4a8606ee78863281 Mon Sep 17 00:00:00 2001 From: Harish-Naruto Date: Fri, 17 Oct 2025 01:00:00 +0530 Subject: [PATCH 3/4] test changed for achievement and member --- tests/Achievement.test.ts | 454 ++++++++++++++++++++++---------------- tests/Member.test.ts | 3 + 2 files changed, 270 insertions(+), 187 deletions(-) diff --git a/tests/Achievement.test.ts b/tests/Achievement.test.ts index 726a2ed..620a32e 100644 --- a/tests/Achievement.test.ts +++ b/tests/Achievement.test.ts @@ -1,49 +1,56 @@ -import { createAchievement, getAchievements, getAchievementById, updateAchievementById, deleteAchievementById, removeMemberFromAchievement } from '../src/controllers/achievement.controller'; -import * as achievementService from '../src/services/achievement.service'; -import { uploadImage, deleteImage } from '../src/utils/imageUtils'; -import { ApiError } from '../src/utils/apiError'; - -jest.mock('../src/app', () => ({ +import { + createAchievement, + getAchievements, + getAchievementById, + updateAchievementById, + deleteAchievementById, + removeMemberFromAchievement, +} from "../src/controllers/achievement.controller"; +import * as achievementService from "../src/services/achievement.service"; +import { uploadImage, deleteImage } from "../src/utils/imageUtils"; +import { ApiError } from "../src/utils/apiError"; + +jest.mock("../src/app", () => ({ supabase: { storage: { from: jest.fn(() => ({ - upload: jest.fn().mockResolvedValue({ data: { path: 'fake-path' }, error: null }), + upload: jest + .fn() + .mockResolvedValue({ data: { path: "fake-path" }, error: null }), remove: jest.fn().mockResolvedValue({ data: null, error: null }), })), }, }, })); - -jest.mock('../src/routes/achievements', () => { +jest.mock("../src/routes/achievements", () => { return { __esModule: true, - default: jest.fn(() => require('express').Router()), + default: jest.fn(() => require("express").Router()), }; }); -jest.mock('../src/utils/imageUtils', () => ({ +jest.mock("../src/utils/imageUtils", () => ({ uploadImage: jest.fn(), deleteImage: jest.fn(), })); - const mockedUploadImage = uploadImage as jest.Mock; -describe('createAchievement (with image upload)', () => { - it('should return 201 and created achievement with uploaded image URL', async () => { +describe("createAchievement (with image upload)", () => { + it("should return 201 and created achievement with uploaded image URL", async () => { const req: any = { file: { - originalname: 'maze.png', - buffer: Buffer.from('test'), + originalname: "maze.png", + buffer: Buffer.from("test"), }, body: { achievementData: { - title: 'Maze Master', - description: 'Completed the final maze', - achievedAt: '2025-07-19T10:00:00.000Z', - createdById: 'admin_123', - memberIds: ['user_1', 'user_2'], + title: "Maze Master", + description: "Completed the final maze", + achievedAt: "2025-07-19T10:00:00.000Z", + createdById: "admin_123", + memberIds: ["user_1", "user_2"], }, }, }; @@ -53,26 +60,25 @@ describe('createAchievement (with image upload)', () => { json: jest.fn(), }; - const imageUrl = 'https://example.com/uploaded/maze.png'; + const imageUrl = "https://example.com/uploaded/maze.png"; const mockAchievement = { id: 1, - title: 'Maze Master', - description: 'Completed the final maze', - achievedAt: new Date('2025-07-19T10:00:00.000Z'), - createdById: 'admin_123', + title: "Maze Master", + description: "Completed the final maze", + achievedAt: new Date("2025-07-19T10:00:00.000Z"), + createdById: "admin_123", imageUrl, createdAt: new Date(), updatedAt: new Date(), updatedById: null, - members: [ - { memberId: 'user_1' }, - { memberId: 'user_2' }, - ], + members: [{ memberId: "user_1" }, { memberId: "user_2" }], }; mockedUploadImage.mockResolvedValue(imageUrl); - jest.spyOn(achievementService, 'createAchievement').mockResolvedValue(mockAchievement); + jest + .spyOn(achievementService, "createAchievement") + .mockResolvedValue(mockAchievement); await createAchievement(req, res); @@ -84,16 +90,16 @@ describe('createAchievement (with image upload)', () => { }); }); - it('should throw 400 if file is missing', async () => { + it("should throw 400 if file is missing", async () => { const req: any = { file: undefined, body: { achievementData: { - title: 'Maze Master', - description: 'Completed the final maze', - achievedAt: '2025-07-19T10:00:00.000Z', - createdById: 'admin_123', - memberIds: ['user_1', 'user_2'], + title: "Maze Master", + description: "Completed the final maze", + achievedAt: "2025-07-19T10:00:00.000Z", + createdById: "admin_123", + memberIds: ["user_1", "user_2"], }, }, }; @@ -102,54 +108,53 @@ describe('createAchievement (with image upload)', () => { await expect(createAchievement(req, res)).rejects.toThrow(ApiError); }); - it('should throw 400 if required fields are missing', async () => { + it("should throw 400 if required fields are missing", async () => { const req: any = { file: { - originalname: 'maze.png', - buffer: Buffer.from('test'), + originalname: "maze.png", + buffer: Buffer.from("test"), }, body: { achievementData: { - title: '', - description: '', - achievedAt: '', - createdById: '', - memberIds: ['user_1'], + title: "", + description: "", + achievedAt: "", + createdById: "", + memberIds: ["user_1"], }, }, }; const res: any = {}; - mockedUploadImage.mockResolvedValue('https://example.com/maze.png'); + mockedUploadImage.mockResolvedValue("https://example.com/maze.png"); await expect(createAchievement(req, res)).rejects.toThrow(ApiError); }); - it('should throw 400 if memberIds is not an array', async () => { + it("should throw 400 if memberIds is not an array", async () => { const req: any = { file: { - originalname: 'maze.png', - buffer: Buffer.from('test'), + originalname: "maze.png", + buffer: Buffer.from("test"), }, body: { achievementData: { - title: 'Maze Master', - description: 'Completed the final maze', - achievedAt: '2025-07-19T10:00:00.000Z', - createdById: 'admin_123', - memberIds: 'not-an-array', + title: "Maze Master", + description: "Completed the final maze", + achievedAt: "2025-07-19T10:00:00.000Z", + createdById: "admin_123", + memberIds: "not-an-array", }, }, }; const res: any = {}; - mockedUploadImage.mockResolvedValue('https://example.com/maze.png'); + mockedUploadImage.mockResolvedValue("https://example.com/maze.png"); await expect(createAchievement(req, res)).rejects.toThrow(ApiError); }); }); - -describe('getAchievements', () => { - it('should return 200 and all achievements', async () => { +describe("getAchievements", () => { + it("should return 200 and all achievements", async () => { const req: any = {}; const res: any = { @@ -160,22 +165,43 @@ describe('getAchievements', () => { const mockAchievements = [ { id: 1, - title: 'Maze Master', - description: 'Completed the final maze', - achievedAt: new Date('2025-07-19T10:00:00.000Z'), - imageUrl: 'https://example.com/maze.png', - createdById: 'admin_123', + title: "Maze Master", + description: "Completed the final maze", + achievedAt: new Date("2025-07-19T10:00:00.000Z"), + imageUrl: "https://example.com/maze.png", + createdById: "admin_123", + createdBy: { + id: "admin_123", + name: "Admin", + }, createdAt: new Date(), updatedById: null, + updatedBy: null, updatedAt: new Date(), members: [ - { memberId: 'user_1' }, - { memberId: 'user_2' }, + { + member: { + id: "user_1", + name: "User One", + email: "user1@example.com", + profilePhoto: null, + }, + }, + { + member: { + id: "user_2", + name: "User Two", + email: "user2@example.com", + profilePhoto: null, + }, + }, ], }, ]; - jest.spyOn(achievementService, 'getAchievements').mockResolvedValue(mockAchievements); + jest + .spyOn(achievementService, "getAchievements") + .mockResolvedValue(mockAchievements); await getAchievements(req, res); @@ -188,12 +214,11 @@ describe('getAchievements', () => { }); }); - -describe('getAchievementById', () => { - it('should return 200 and the achievement with given ID', async () => { +describe("getAchievementById", () => { + it("should return 200 and the achievement with given ID", async () => { const req: any = { params: { - achievementId: '1', + achievementId: "1", }, }; @@ -204,33 +229,33 @@ describe('getAchievementById', () => { const mockAchievement = { id: 1, - title: 'Maze Master', - description: 'Completed the final maze', - achievedAt: new Date('2025-07-19T10:00:00.000Z'), - imageUrl: 'https://example.com/maze.png', - createdById: 'admin_123', + title: "Maze Master", + description: "Completed the final maze", + achievedAt: new Date("2025-07-19T10:00:00.000Z"), + imageUrl: "https://example.com/maze.png", + createdById: "admin_123", createdAt: new Date(), updatedById: null, updatedAt: new Date(), createdBy: { - id: 'admin_123', - name: 'Admin', + id: "admin_123", + name: "Admin", }, updatedBy: null, members: [ { member: { - id: 'user_1', - name: 'User One', - email: 'user1@example.com', + id: "user_1", + name: "User One", + email: "user1@example.com", profilePhoto: null, }, }, { member: { - id: 'user_2', - name: 'User Two', - email: 'user2@example.com', + id: "user_2", + name: "User Two", + email: "user2@example.com", profilePhoto: null, }, }, @@ -238,7 +263,7 @@ describe('getAchievementById', () => { }; jest - .spyOn(achievementService, 'getAchievementById') + .spyOn(achievementService, "getAchievementById") .mockResolvedValue(mockAchievement); await getAchievementById(req, res); @@ -250,10 +275,10 @@ describe('getAchievementById', () => { }); }); - it('should throw 400 for invalid ID', async () => { + it("should throw 400 for invalid ID", async () => { const req: any = { params: { - achievementId: 'abc', + achievementId: "abc", }, }; @@ -262,35 +287,35 @@ describe('getAchievementById', () => { await expect(getAchievementById(req, res)).rejects.toThrow(ApiError); }); - it('should throw 404 if achievement not found', async () => { + it("should throw 404 if achievement not found", async () => { const req: any = { params: { - achievementId: '999', + achievementId: "999", }, }; const res: any = {}; jest - .spyOn(achievementService, 'getAchievementById') + .spyOn(achievementService, "getAchievementById") .mockResolvedValue(null); await expect(getAchievementById(req, res)).rejects.toThrow(ApiError); }); }); -describe('updateAchievementById', () => { +describe("updateAchievementById", () => { const baseAchievement = { id: 1, - title: 'Old Title', - description: 'Old Description', - achievedAt: new Date('2025-07-10T00:00:00.000Z'), - imageUrl: 'https://example.com/old-image.png', - createdById: 'admin_123', + title: "Old Title", + description: "Old Description", + achievedAt: new Date("2025-07-10T00:00:00.000Z"), + imageUrl: "https://example.com/old-image.png", + createdById: "admin_123", updatedById: null, createdAt: new Date(), updatedAt: new Date(), - createdBy: { id: 'admin_123', name: 'Admin' }, + createdBy: { id: "admin_123", name: "Admin" }, updatedBy: null, members: [], }; @@ -304,24 +329,34 @@ describe('updateAchievementById', () => { jest.clearAllMocks(); }); - it('should update all fields successfully (200)', async () => { - const updatedAchievement = { ...baseAchievement, title: 'Updated', updatedById: 'admin_456' }; + it("should update all fields successfully (200)", async () => { + const updatedAchievement = { + ...baseAchievement, + title: "Updated", + updatedById: "admin_456", + }; const mockReq: any = { - params: { achievementId: '1' }, - file: { originalname: 'img.png', buffer: Buffer.from('123') }, + params: { achievementId: "1" }, + file: { originalname: "img.png", buffer: Buffer.from("123") }, body: { achievementData: JSON.stringify({ - title: 'Updated', - updatedById: 'admin_456', - memberIds: ['user_2'], + title: "Updated", + updatedById: "admin_456", + memberIds: ["user_2"], }), }, }; - mockedUploadImage.mockResolvedValue('https://updated.com/img.png'); - jest.spyOn(achievementService, 'getAchievementById').mockResolvedValue(baseAchievement); - jest.spyOn(achievementService, 'updateAchievementById').mockResolvedValue(updatedAchievement); - jest.spyOn(achievementService, 'addMembersToAchievement').mockResolvedValue(undefined); + mockedUploadImage.mockResolvedValue("https://updated.com/img.png"); + jest + .spyOn(achievementService, "getAchievementById") + .mockResolvedValue(baseAchievement); + jest + .spyOn(achievementService, "updateAchievementById") + .mockResolvedValue(updatedAchievement); + jest + .spyOn(achievementService, "addMembersToAchievement") + .mockResolvedValue(undefined); await updateAchievementById(mockReq, mockRes); @@ -333,134 +368,173 @@ describe('updateAchievementById', () => { }); }); - it('should update only title', async () => { + it("should update only title", async () => { const mockReq: any = { - params: { achievementId: '1' }, + params: { achievementId: "1" }, body: { - achievementData: JSON.stringify({ title: 'New Title', updatedById: 'admin_456' }), + achievementData: JSON.stringify({ + title: "New Title", + updatedById: "admin_456", + }), }, }; - jest.spyOn(achievementService, 'getAchievementById').mockResolvedValue(baseAchievement); - jest.spyOn(achievementService, 'updateAchievementById').mockResolvedValue({ + jest + .spyOn(achievementService, "getAchievementById") + .mockResolvedValue(baseAchievement); + jest.spyOn(achievementService, "updateAchievementById").mockResolvedValue({ ...baseAchievement, - title: 'New Title', + title: "New Title", }); await updateAchievementById(mockReq, mockRes); - expect(achievementService.updateAchievementById).toHaveBeenCalledWith(1, expect.objectContaining({ - title: 'New Title', - updatedById: 'admin_456', - })); + expect(achievementService.updateAchievementById).toHaveBeenCalledWith( + 1, + expect.objectContaining({ + title: "New Title", + updatedById: "admin_456", + }) + ); }); - it('should update only image', async () => { + it("should update only image", async () => { const mockReq: any = { - params: { achievementId: '1' }, - file: { originalname: 'img.png', buffer: Buffer.from('abc') }, + params: { achievementId: "1" }, + file: { originalname: "img.png", buffer: Buffer.from("abc") }, body: { - achievementData: JSON.stringify({ updatedById: 'admin_456' }), + achievementData: JSON.stringify({ updatedById: "admin_456" }), }, }; - mockedUploadImage.mockResolvedValue('https://updated.com/img.png'); - jest.spyOn(achievementService, 'getAchievementById').mockResolvedValue(baseAchievement); - jest.spyOn(achievementService, 'updateAchievementById').mockResolvedValue({ + mockedUploadImage.mockResolvedValue("https://updated.com/img.png"); + jest + .spyOn(achievementService, "getAchievementById") + .mockResolvedValue(baseAchievement); + jest.spyOn(achievementService, "updateAchievementById").mockResolvedValue({ ...baseAchievement, - imageUrl: 'https://updated.com/img.png', - updatedById: 'admin_456', + imageUrl: "https://updated.com/img.png", + updatedById: "admin_456", }); await updateAchievementById(mockReq, mockRes); expect(mockedUploadImage).toHaveBeenCalled(); }); - it('should update only memberIds', async () => { + it("should update only memberIds", async () => { const mockReq: any = { - params: { achievementId: '1' }, + params: { achievementId: "1" }, body: { - achievementData: JSON.stringify({ updatedById: 'admin_456', memberIds: ['user_3'] }), + achievementData: JSON.stringify({ + updatedById: "admin_456", + memberIds: ["user_3"], + }), }, }; - jest.spyOn(achievementService, 'getAchievementById').mockResolvedValue(baseAchievement); - jest.spyOn(achievementService, 'updateAchievementById').mockResolvedValue({ + jest + .spyOn(achievementService, "getAchievementById") + .mockResolvedValue(baseAchievement); + jest.spyOn(achievementService, "updateAchievementById").mockResolvedValue({ ...baseAchievement, - updatedById: 'admin_456', + updatedById: "admin_456", }); - jest.spyOn(achievementService, 'addMembersToAchievement').mockResolvedValue(undefined); + jest + .spyOn(achievementService, "addMembersToAchievement") + .mockResolvedValue(undefined); await updateAchievementById(mockReq, mockRes); - expect(achievementService.addMembersToAchievement).toHaveBeenCalledWith(1, ['user_3']); + expect(achievementService.addMembersToAchievement).toHaveBeenCalledWith(1, [ + "user_3", + ]); }); - it('should return 400 if updatedById is missing', async () => { + it("should return 400 if updatedById is missing", async () => { const mockReq: any = { - params: { achievementId: '1' }, + params: { achievementId: "1" }, body: { - achievementData: JSON.stringify({ title: 'No Updater' }), + achievementData: JSON.stringify({ title: "No Updater" }), }, }; - await expect(updateAchievementById(mockReq, mockRes)).rejects.toThrow(ApiError); + await expect(updateAchievementById(mockReq, mockRes)).rejects.toThrow( + ApiError + ); }); - it('should return 400 if achievementId is invalid', async () => { + it("should return 400 if achievementId is invalid", async () => { const mockReq: any = { - params: { achievementId: 'abc' }, + params: { achievementId: "abc" }, body: { - achievementData: JSON.stringify({ title: 'Updated', updatedById: 'admin_456' }), + achievementData: JSON.stringify({ + title: "Updated", + updatedById: "admin_456", + }), }, }; - await expect(updateAchievementById(mockReq, mockRes)).rejects.toThrow(ApiError); + await expect(updateAchievementById(mockReq, mockRes)).rejects.toThrow( + ApiError + ); }); - it('should return 404 if achievement not found', async () => { + it("should return 404 if achievement not found", async () => { const mockReq: any = { - params: { achievementId: '999' }, + params: { achievementId: "999" }, body: { - achievementData: JSON.stringify({ title: 'Missing', updatedById: 'admin_456' }), + achievementData: JSON.stringify({ + title: "Missing", + updatedById: "admin_456", + }), }, }; - jest.spyOn(achievementService, 'getAchievementById').mockResolvedValue(null); + jest + .spyOn(achievementService, "getAchievementById") + .mockResolvedValue(null); - await expect(updateAchievementById(mockReq, mockRes)).rejects.toThrow(ApiError); + await expect(updateAchievementById(mockReq, mockRes)).rejects.toThrow( + ApiError + ); }); - it('should return 400 if no fields are provided for update', async () => { + it("should return 400 if no fields are provided for update", async () => { const mockReq: any = { - params: { achievementId: '1' }, + params: { achievementId: "1" }, body: { - achievementData: JSON.stringify({ updatedById: 'admin_456' }), + achievementData: JSON.stringify({ updatedById: "admin_456" }), }, }; - jest.spyOn(achievementService, 'getAchievementById').mockResolvedValue(baseAchievement); + jest + .spyOn(achievementService, "getAchievementById") + .mockResolvedValue(baseAchievement); - await expect(updateAchievementById(mockReq, mockRes)).rejects.toThrow(ApiError); + await expect(updateAchievementById(mockReq, mockRes)).rejects.toThrow( + ApiError + ); }); - it('should return 400 if achievementData is invalid JSON', async () => { + it("should return 400 if achievementData is invalid JSON", async () => { const mockReq: any = { - params: { achievementId: '1' }, + params: { achievementId: "1" }, body: { - achievementData: '{ invalid JSON }', + achievementData: "{ invalid JSON }", }, }; - await expect(updateAchievementById(mockReq, mockRes)).rejects.toThrow(ApiError); + await expect(updateAchievementById(mockReq, mockRes)).rejects.toThrow( + ApiError + ); }); }); const mockedDeleteImage = deleteImage as jest.Mock; -describe('deleteAchievementById', () => { - it('should delete the achievement and return 200 success message', async () => { +describe("deleteAchievementById", () => { + it("should delete the achievement and return 200 success message", async () => { const req: any = { params: { - achievementId: '1', + achievementId: "1", }, }; @@ -471,26 +545,26 @@ describe('deleteAchievementById', () => { const mockDeletedAchievement = { id: 1, - title: 'Maze Master', - description: 'Completed the final maze', - achievedAt: new Date('2025-07-19T10:00:00.000Z'), - imageUrl: 'https://example.com/maze.png', - createdById: 'admin_123', + title: "Maze Master", + description: "Completed the final maze", + achievedAt: new Date("2025-07-19T10:00:00.000Z"), + imageUrl: "https://example.com/maze.png", + createdById: "admin_123", createdAt: new Date(), updatedById: null, updatedAt: new Date(), - createdBy: { id: 'admin_123', name: 'Admin' }, + createdBy: { id: "admin_123", name: "Admin" }, updatedBy: null, members: [], }; jest - .spyOn(achievementService, 'getAchievementById') + .spyOn(achievementService, "getAchievementById") .mockResolvedValue(mockDeletedAchievement); jest - .spyOn(achievementService, 'deleteAchievementById') + .spyOn(achievementService, "deleteAchievementById") .mockResolvedValue(mockDeletedAchievement); mockedDeleteImage.mockResolvedValue(undefined); @@ -498,19 +572,22 @@ describe('deleteAchievementById', () => { await deleteAchievementById(req, res); expect(achievementService.getAchievementById).toHaveBeenCalledWith(1); - expect(mockedDeleteImage).toHaveBeenCalledWith(expect.anything(), mockDeletedAchievement.imageUrl); + expect(mockedDeleteImage).toHaveBeenCalledWith( + expect.anything(), + mockDeletedAchievement.imageUrl + ); expect(achievementService.deleteAchievementById).toHaveBeenCalledWith(1); expect(res.status).toHaveBeenCalledWith(200); expect(res.json).toHaveBeenCalledWith({ success: true, - message: 'Achievement deleted successfully', + message: "Achievement deleted successfully", }); }); - it('should throw 400 if achievementId is invalid', async () => { + it("should throw 400 if achievementId is invalid", async () => { const req: any = { params: { - achievementId: 'invalid', + achievementId: "invalid", }, }; const res: any = {}; @@ -519,13 +596,12 @@ describe('deleteAchievementById', () => { }); }); - -describe('removeMemberFromAchievement', () => { - it('should remove a member from achievement and return 200', async () => { +describe("removeMemberFromAchievement", () => { + it("should remove a member from achievement and return 200", async () => { const req: any = { params: { - achievementId: '1', - memberId: 'user_1', + achievementId: "1", + memberId: "user_1", }, }; @@ -535,9 +611,9 @@ describe('removeMemberFromAchievement', () => { }; jest - .spyOn(achievementService, 'removeMemberFromAchievement') + .spyOn(achievementService, "removeMemberFromAchievement") .mockResolvedValue({ - memberId: 'user_1', + memberId: "user_1", achievementId: 1, }); @@ -546,33 +622,37 @@ describe('removeMemberFromAchievement', () => { expect(res.status).toHaveBeenCalledWith(200); expect(res.json).toHaveBeenCalledWith({ success: true, - message: 'Member removed from achievement successfully', + message: "Member removed from achievement successfully", }); }); - it('should throw 400 for invalid achievement ID', async () => { + it("should throw 400 for invalid achievement ID", async () => { const req: any = { params: { - achievementId: 'invalid', - memberId: 'user_1', + achievementId: "invalid", + memberId: "user_1", }, }; const res: any = {}; - await expect(removeMemberFromAchievement(req, res)).rejects.toThrow(ApiError); + await expect(removeMemberFromAchievement(req, res)).rejects.toThrow( + ApiError + ); }); - it('should throw 400 if member ID is missing', async () => { + it("should throw 400 if member ID is missing", async () => { const req: any = { params: { - achievementId: '1', - memberId: '', + achievementId: "1", + memberId: "", }, }; const res: any = {}; - await expect(removeMemberFromAchievement(req, res)).rejects.toThrow(ApiError); + await expect(removeMemberFromAchievement(req, res)).rejects.toThrow( + ApiError + ); }); }); diff --git a/tests/Member.test.ts b/tests/Member.test.ts index b82e244..9774144 100644 --- a/tests/Member.test.ts +++ b/tests/Member.test.ts @@ -88,6 +88,7 @@ describe('Member Controller - updateAMember', () => { name: 'Test User', email: 'test@example.com', github: 'https://github.com/shrutii', + birth_date: null, profilePhoto: null, phone: null, bio: null, @@ -135,6 +136,7 @@ describe('Member Controller - updateAMember', () => { name: 'Old User', email: 'old@example.com', phone: null, + birth_date: null, bio: null, profilePhoto: 'https://old.url/image.png', github: null, @@ -201,6 +203,7 @@ describe('Member Controller - updateAMember', () => { name: 'Updated User', email: 'updated@example.com', profilePhoto: null, + birth_date: null, github: null, phone: null, bio: null, From 593591ec4c625adf9f2f8b349288ccd818b7e781 Mon Sep 17 00:00:00 2001 From: Harish-Naruto Date: Fri, 17 Oct 2025 01:09:04 +0530 Subject: [PATCH 4/4] birth date type fix to datetime --- .../20251016193811_birth_date_type_fix/migration.sql | 9 +++++++++ prisma/schema.prisma | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 prisma/migrations/20251016193811_birth_date_type_fix/migration.sql diff --git a/prisma/migrations/20251016193811_birth_date_type_fix/migration.sql b/prisma/migrations/20251016193811_birth_date_type_fix/migration.sql new file mode 100644 index 0000000..1fc278c --- /dev/null +++ b/prisma/migrations/20251016193811_birth_date_type_fix/migration.sql @@ -0,0 +1,9 @@ +/* + Warnings: + + - The `birth_date` column on the `Member` table would be dropped and recreated. This will lead to data loss if there is data in the column. + +*/ +-- AlterTable +ALTER TABLE "Member" DROP COLUMN "birth_date", +ADD COLUMN "birth_date" DATE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 4046b17..55b3b5b 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -16,7 +16,7 @@ model Member { id String @id @default(uuid()) name String email String @unique - birth_date String? + birth_date DateTime? @db.Date phone String? // Single phone number bio String? profilePhoto String? // URL to profile photo