diff --git a/controllers/friendController.js b/controllers/friendController.js index 6dc37400fcfea24164af27d46070059b70cd3784..a8411e34c4f0fde9e7970bc8841a0446833e2290 100644 --- a/controllers/friendController.js +++ b/controllers/friendController.js @@ -1,6 +1,10 @@ const FriendService = require('../services/friendService'); class friendController { + + + + class FriendController { /** * 친구 요청 보내기 * 클라이언트는 userId와 요청을 보낼 사용자의 email을 전송 @@ -33,11 +37,12 @@ class friendController { if (error.message === 'Friend request already exists') { return res.status(409).json({ message: error.message }); } - // 일반 오류 처리 return res.status(500).json({ message: '서버 오류가 발생했습니다.', error: error.message }); } } + } + /** * 받은 친구 요청 목록 조회 * GET /api/friend/requests/received @@ -190,6 +195,7 @@ class friendController { }); } } + } module.exports = new friendController(); \ No newline at end of file diff --git a/middlewares/auth.js b/middleware/auth.js similarity index 100% rename from middlewares/auth.js rename to middleware/auth.js diff --git a/package-lock.json b/package-lock.json index cb3d8d14cd5330564553ceb4b9126c365d62f17a..ea44223a36312ef0197fb5fc7195747f86c21694 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,6 @@ "morgan": "^1.10.0", "multer": "^1.4.5-lts.1", "mysql2": "^3.11.4", - "node-cron": "^3.0.3", "passport": "^0.7.0", "passport-google-oauth20": "^2.0.0", "sequelize": "^6.37.5", @@ -11803,18 +11802,6 @@ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", "license": "ISC" }, - "node_modules/node-cron": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.3.tgz", - "integrity": "sha512-dOal67//nohNgYWb+nWmg5dkFdIwDm8EpeGYMekPMrngV3637lqnX0lbUcCtgibHTz6SEz7DAIjKvKDFYCnO1A==", - "license": "ISC", - "dependencies": { - "uuid": "8.3.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/node-gyp": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.2.0.tgz", diff --git a/package.json b/package.json index 2151becb800731c9f2b5bb635082d01be0301abc..48d1fb66671a2e13a190a34237941ad8de30ffbb 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,6 @@ "morgan": "^1.10.0", "multer": "^1.4.5-lts.1", "mysql2": "^3.11.4", - "node-cron": "^3.0.3", "passport": "^0.7.0", "passport-google-oauth20": "^2.0.0", "sequelize": "^6.37.5", diff --git a/routes/friend.js b/routes/friend.js index 53145a9930403881d542d7fad15a27d9d485edbc..782540b23a393a1d00e4b74ceb5db371c542088d 100644 --- a/routes/friend.js +++ b/routes/friend.js @@ -9,7 +9,7 @@ router.use(isLoggedIn); * 친구 요청 보내기 * POST /api/friend/request/:friendId */ -router.post('/request/:friendId', FriendController.sendFriendRequest); +router.post('/request/:friendId', FriendController.sendRequest); /** * 받은 친구 요청 목록 조회 diff --git a/routes/index.js b/routes/index.js new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/routes/schedule.js b/routes/schedule.js index 35da45e5004555891dc1baf16e8cd53d7982d6fb..045bc48e689f139cd72f111ecb76ff3bbe71f508 100644 --- a/routes/schedule.js +++ b/routes/schedule.js @@ -1,6 +1,6 @@ const express = require('express'); const router = express.Router(); -const { isLoggedIn } = require('../middlewares/auth'); +const { isLoggedIn } = require('../middleware/auth'); const ScheduleController = require('../controllers/scheduleController'); /** diff --git a/test/friendService.test.js b/test/friendService.test.js deleted file mode 100644 index ca18666c14fb343a97b406a618e1b481595a09a8..0000000000000000000000000000000000000000 --- a/test/friendService.test.js +++ /dev/null @@ -1,220 +0,0 @@ -// test/friendService.test.js - -const sequelize = require('../config/sequelize'); // Sequelize 인스턴스 임포트 -const User = require('../models/User'); -const Friend = require('../models/Friend'); -const friendService = require('../services/friendService'); // FriendService 임포트 - -// Sequelize의 Op를 가져오기 위해 추가 -const { Op } = require('sequelize'); - -beforeAll(async () => { - // 테스트 전에 데이터베이스를 동기화하고 테이블을 생성합니다. - await sequelize.sync({ force: true }); -}); - -beforeEach(async () => { - // 각 테스트 전에 데이터베이스를 초기화하여 독립성을 보장합니다. - await sequelize.sync({ force: true }); - - // 더미 사용자 생성 - await User.bulkCreate([ - { id: 1, name: 'Alice', email: 'alice@example.com' }, - { id: 2, name: 'Bob', email: 'bob@example.com' }, - { id: 3, name: 'Charlie', email: 'charlie@example.com' }, - ]); -}); - -afterAll(async () => { - // 모든 테스트가 끝난 후 데이터베이스 연결을 종료합니다. - await sequelize.close(); -}); - -describe('Friend Service', () => { - describe('validUser', () => { - test('should return user when user exists', async () => { - const user = await friendService.validUser(1); - expect(user).toBeDefined(); - expect(user.name).toBe('Alice'); - }); - - test('should throw error when user does not exist', async () => { - await expect(friendService.validUser(999)).rejects.toThrow('User not found'); - }); - }); - - describe('sendFriendRequest', () => { - test('should send a friend request successfully', async () => { - const friendRequest = await friendService.sendFriendRequest(1, 3); // Alice sends request to Charlie - expect(friendRequest).toBeDefined(); - expect(friendRequest.requester_id).toBe(1); - expect(friendRequest.receiver_id).toBe(3); - expect(friendRequest.status).toBe('PENDING'); - }); - - test('should throw error when sending friend request to self', async () => { - await expect(friendService.sendFriendRequest(1, 1)).rejects.toThrow('Cannot send friend request to yourself'); - }); - - test('should throw error when sending duplicate friend request', async () => { - - await friendService.sendFriendRequest(1, 2); - - - await friendService.acceptFriendRequest(2, 1); - - await expect(friendService.sendFriendRequest(1, 2)).rejects.toThrow('Friend request already exists'); - }); - - test('should throw error when user does not exist', async () => { - await expect(friendService.sendFriendRequest(1, 999)).rejects.toThrow('User not found'); - await expect(friendService.sendFriendRequest(999, 1)).rejects.toThrow('User not found'); - }); - }); - - describe('getReceivedRequests', () => { - test('friend requests', async () => { - await friendService.sendFriendRequest(3, 1); - - const receivedRequests = await friendService.getReceivedRequests(1); - expect(receivedRequests.length).toBe(1); - expect(receivedRequests[0].requester.name).toBe('Charlie'); - }); - - test('not send request', async () => { - const receivedRequests = await friendService.getReceivedRequests(2); - expect(receivedRequests.length).toBe(0); - }); - }); - - describe('getSentRequests', () => { - test('should retrieve sent friend requests', async () => { - - await friendService.sendFriendRequest(1, 3); - - const sentRequests = await friendService.getSentRequests(1); - expect(sentRequests.length).toBe(1); - expect(sentRequests[0].receiver.name).toBe('Charlie'); - }); - - test('should return empty array when no sent requests', async () => { - const sentRequests = await friendService.getSentRequests(3); // Charlie has not sent any PENDING requests - expect(sentRequests.length).toBe(0); - }); - }); - - describe('acceptFriendRequest', () => { - test('should accept a pending friend request successfully', async () => { - - await friendService.sendFriendRequest(3, 1); - - const updatedRequest = await friendService.acceptFriendRequest(1, 3); - expect(updatedRequest).toBeDefined(); - expect(updatedRequest.status).toBe('ACCEPTED'); - - //Db상태 확인 - const request = await Friend.findOne({ - where: { - requester_id: 3, - receiver_id: 1, - }, - }); - expect(request.status).toBe('ACCEPTED'); - }); - - test('없는 요청수락', async () => { - await expect(friendService.acceptFriendRequest(1, 999)).rejects.toThrow('Friend request not found'); - }); - }); - - describe('rejectFriendRequest', () => { - test('should reject a pending friend request successfully', async () => { - - await friendService.sendFriendRequest(2, 3); - - - const result = await friendService.rejectFriendRequest(3, 2); - expect(result).toBe(1); - - const request = await Friend.findOne({ - where: { - requester_id: 2, - receiver_id: 3, - }, - }); - expect(request).toBeNull(); - }); - - test('should throw error when rejecting non-existing friend request', async () => { - await expect(friendService.rejectFriendRequest(1, 999)).rejects.toThrow('Friend request not found'); - }); - }); - - describe('getFriendList', () => { - test('should retrieve friend list with correct pagination', async () => { - await friendService.sendFriendRequest(1, 2); - await friendService.acceptFriendRequest(2, 1); - - await friendService.sendFriendRequest(1, 3); - await friendService.acceptFriendRequest(3, 1); - - // 추가 더미데이터 생성 - for (let i = 4; i <= 23; i++) { - // Create dummy users - await User.create({ - id: i, - name: `User${i}`, - email: `user${i}@example.com`, - }); - - //Alice랑 친구맺기 - await friendService.sendFriendRequest(1, i); - await friendService.acceptFriendRequest(i, 1); - } - - // Alice 친구: Bob (2), Charlie (3),User4 to User23 (20 friends) - const limit = 5; - const offset = 0; - const friendsPage1 = await friendService.getFriendList(1, limit, offset); - expect(friendsPage1.length).toBe(limit); - expect(['Bob', 'Charlie', 'User4', 'User5', 'User6']).toContain(friendsPage1[0].friendInfo.name); - - const friendsPage2 = await friendService.getFriendList(1, limit, limit); - expect(friendsPage2.length).toBe(limit); - expect(['User7', 'User8', 'User9', 'User10', 'User11']).toContain(friendsPage2[0].friendInfo.name); - }); - - test('should return empty array when user has no friends', async () => { - const friends = await friendService.getFriendList(999); // Non-existing user - expect(friends.length).toBe(0); - }); - }); - - describe('deleteFriend', () => { - test('should delete an existing friend relationship successfully', async () => { - - await friendService.sendFriendRequest(1, 2); - await friendService.acceptFriendRequest(2, 1); - - - const result = await friendService.deleteFriend(1, 2); - expect(result).toBe(1); - - - const relationship = await Friend.findOne({ - where: { - [Op.or]: [ - { requester_id: 1, receiver_id: 2 }, - { requester_id: 2, receiver_id: 1 }, - ], - status: 'ACCEPTED', - }, - }); - expect(relationship).toBeNull(); - }); - - test('should throw error when deleting a non-existing friend relationship', async () => { - await expect(friendService.deleteFriend(1, 999)).rejects.toThrow('Friend relationship not found'); - }); - }); -}); diff --git a/test/friendrelation.test.js b/test/friendrelation.test.js deleted file mode 100644 index 04a2601b50d9554dcdeba6065b3673a6fd5c3205..0000000000000000000000000000000000000000 --- a/test/friendrelation.test.js +++ /dev/null @@ -1,133 +0,0 @@ -// test/friend.test.js - -const sequelize = require('../config/sequelize'); // 환경 변수에 따라 다른 인스턴스 사용 -const User = require('../models/User'); -const Friend = require('../models/Friend'); - -beforeAll(async () => { - // 데이터베이스 동기화 - await sequelize.sync({ force: true }); - - // 더미 사용자 생성 - await User.bulkCreate([ - { id: 1, name: 'Alice', email: 'alice@example.com' }, - { id: 2, name: 'Bob', email: 'bob@example.com' }, - ]); - - // 더미 친구 관계 생성 - await Friend.create({ - id: 1, - requester_id: 1, - receiver_id: 2, - status: 'ACCEPTED', - }); -}); - -afterAll(async () => { - // 데이터베이스 연결 종료 - await sequelize.close();//sequelize.close(): 테스트가 끝난 후 데이터베이스 연결을 종료하여 리소스를 해제 -}); - -describe('User and Friend Relationships', () => { - test('relation mapping test ', async () => { - // 사용자 Alice의 보낸 친구 요청 조회 - const alice = await User.findByPk(1, { - include: { - model: Friend, - as: 'sentRequests', - include: { - model: User, - as: 'receiver', - attributes: ['id', 'name', 'email'], - }, - }, - }); - - expect(alice.sentRequests.length).toBe(1); - expect(alice.sentRequests[0].receiver.name).toBe('Bob'); - - // 사용자 Bob의 받은 친구 요청 조회 - const bob = await User.findByPk(2, { - include: { - model: Friend, - as: 'receivedRequests', - include: { - model: User, - as: 'requester', - attributes: ['id', 'name', 'email'], - }, - }, - }); - - expect(bob.receivedRequests.length).toBe(1); - expect(bob.receivedRequests[0].requester.name).toBe('Alice'); - }); - - test('create friend', async () => { - // 새로운 친구 요청 생성 - const newFriendRequest = await Friend.create({ - id: 2, - requester_id: 2, - receiver_id: 1, - status: 'PENDING', - }); - - expect(newFriendRequest.requester_id).toBe(2); - expect(newFriendRequest.receiver_id).toBe(1); - expect(newFriendRequest.status).toBe('PENDING'); - - // 사용자 Bob의 보낸 친구 요청 조회 - const bob = await User.findByPk(2, { - include: { - model: Friend, - as: 'sentRequests', - where: { id: 2 }, - include: { - model: User, - as: 'receiver', - attributes: ['id', 'name', 'email'], - }, - }, - }); - - expect(bob.sentRequests.length).toBe(1); - expect(bob.sentRequests[0].receiver.name).toBe('Alice'); - }); - - test('self friend reqeust', async () => { - await expect( - Friend.create({ - id: 3, - requester_id: 1, - receiver_id: 1, // 자신에게 요청 - status: 'PENDING', - }) - ).rejects.toThrow(); - }); - - test('already request test', async () => { - // Alice가 Bob에게 이미 친구 요청을 보냈으므로, 다시 보내면 에러 발생 - await expect( - Friend.create({ - id: 4, - requester_id: 1, - receiver_id: 2, - status: 'PENDING', - }) - ).rejects.toThrow(); - }); - - test('should accept a pending friend request correctly', async () => { - // Bob이 Alice에게 보낸 친구 요청을 'ACCEPTED' 상태로 변경 - const friendRequest = await Friend.findOne({ where: { id: 2 } }); - expect(friendRequest.status).toBe('PENDING'); - - friendRequest.status = 'ACCEPTED'; - await friendRequest.save(); - - const updatedRequest = await Friend.findOne({ where: { id: 2 } }); - expect(updatedRequest.status).toBe('ACCEPTED'); - }); - - -}); diff --git a/test/schedule.test.js b/test/schedule.test.js deleted file mode 100644 index a82562bf124a1f5044e3ecf54990531527bff78d..0000000000000000000000000000000000000000 --- a/test/schedule.test.js +++ /dev/null @@ -1,233 +0,0 @@ -// test/schedule.test.js - -const sequelize = require('../config/sequelize'); -const User = require('../models/User'); -const Friend = require('../models/Friend'); -const Schedule = require('../models/Schedule'); -const scheduleService = require('../services/scheduleService'); // scheduleService 임포트 - -beforeAll(async () => { - await sequelize.sync({ force: true }); - // 더미 사용자 생성 - await User.bulkCreate([ - { id: 1, name: 'Alice', email: 'alice@example.com' }, - { id: 2, name: 'Bob', email: 'bob@example.com' }, - ]); - - // 더미 친구 관계 생성 - await Friend.create({ - id: 1, - requester_id: 1, - receiver_id: 2, - status: 'ACCEPTED', - }); - - // 더미 스케줄 생성 - await Schedule.create({ - id: 1, - user_id: 1, - title: 'Alice\'s Fixed Schedule', - start_time: new Date('2024-05-01T09:00:00Z'), - end_time: new Date('2024-05-01T10:00:00Z'), - is_fixed: true, - expiry_date: null, - }); - - await Schedule.create({ - id: 2, - user_id: 1, - title: 'Alice\'s Flexible Schedule', - start_time: new Date('2024-05-02T11:00:00Z'), - end_time: new Date('2024-05-02T12:00:00Z'), - is_fixed: false, - expiry_date: new Date('2024-05-08T00:00:00Z'), // 다음 월요일 - }); -}); - -afterAll(async () => { - // 데이터베이스 연결 종료 - await sequelize.close(); -}); - -describe('Schedule Service', () => { - describe('createSchedule', () => { - test('should create a new fixed schedule successfully', async () => { - const scheduleData = { - userId: 2, - title: 'Bob\'s Fixed Schedule', - start_time: new Date('2024-05-03T14:00:00Z'), - end_time: new Date('2024-05-03T15:00:00Z'), - is_fixed: true, - }; - - const schedule = await scheduleService.createSchedule(scheduleData); - - expect(schedule).toBeDefined(); - expect(schedule.user_id).toBe(2); - expect(schedule.title).toBe('Bob\'s Fixed Schedule'); - expect(schedule.is_fixed).toBe(true); - expect(schedule.expiry_date).toBeNull(); - }); - - test('should create a new flexible schedule with expiry date', async () => { - const scheduleData = { - userId: 2, - title: 'Bob\'s Flexible Schedule', - start_time: new Date('2024-05-04T16:00:00Z'), - end_time: new Date('2024-05-04T17:00:00Z'), - is_fixed: false, - }; - - const schedule = await scheduleService.createSchedule(scheduleData); - - expect(schedule).toBeDefined(); - expect(schedule.user_id).toBe(2); - expect(schedule.title).toBe('Bob\'s Flexible Schedule'); - expect(schedule.is_fixed).toBe(false); - expect(schedule.expiry_date).toBeInstanceOf(Date); - - // expiry_date가 다음 월요일로 설정되었는지 확인 - const expectedExpiryDate = new Date('2024-05-06T00:00:00Z'); // 2024-05-06은 다음 월요일 - expect(schedule.expiry_date.toISOString()).toBe(expectedExpiryDate.toISOString()); - }); - - test('should throw error when schedule times overlap with existing schedule', async () => { - const scheduleData = { - userId: 1, - title: 'Alice\'s Overlapping Schedule', - start_time: new Date('2024-05-01T09:30:00Z'), // 기존 스케줄과 겹침 - end_time: new Date('2024-05-01T10:30:00Z'), - is_fixed: false, - }; - - await expect(scheduleService.createSchedule(scheduleData)).rejects.toThrow('Schedule overlaps with existing schedule'); - }); - - test('should throw error when start_time is after end_time', async () => { - const scheduleData = { - userId: 1, - title: 'Invalid Schedule', - start_time: new Date('2024-05-05T18:00:00Z'), - end_time: new Date('2024-05-05T17:00:00Z'), // start_time이 더 나중 - is_fixed: false, - }; - - await expect(scheduleService.createSchedule(scheduleData)).rejects.toThrow('Start time must be before end time'); - }); - }); - - describe('updateSchedule', () => { - test('should update an existing schedule successfully', async () => { - const updateData = { - title: 'Alice\'s Updated Flexible Schedule', - start_time: new Date('2024-05-02T11:30:00Z'), - end_time: new Date('2024-05-02T12:30:00Z'), - }; - - const updatedSchedule = await scheduleService.updateSchedule(2, 1, updateData); - - expect(updatedSchedule).toBeDefined(); - expect(updatedSchedule.title).toBe('Alice\'s Updated Flexible Schedule'); - expect(updatedSchedule.start_time.toISOString()).toBe(new Date('2024-05-02T11:30:00Z').toISOString()); - expect(updatedSchedule.end_time.toISOString()).toBe(new Date('2024-05-02T12:30:00Z').toISOString()); - expect(updatedSchedule.expiry_date).toBeInstanceOf(Date); - }); - - test('should throw error when updating a non-existing schedule', async () => { - const updateData = { - title: 'Non-existing Schedule', - start_time: new Date('2024-05-06T10:00:00Z'), - end_time: new Date('2024-05-06T11:00:00Z'), - }; - - await expect(scheduleService.updateSchedule(999, 1, updateData)).rejects.toThrow('Schedule not found'); - }); - - test('should throw error when updated schedule overlaps with existing schedule', async () => { - const updateData = { - title: 'Alice\'s Overlapping Update', - start_time: new Date('2024-05-01T09:30:00Z'), // 기존 스케줄과 겹침 - end_time: new Date('2024-05-01T10:30:00Z'), - }; - - await expect(scheduleService.updateSchedule(2, 1, updateData)).rejects.toThrow('Schedule overlaps with existing schedule'); - }); - }); - - describe('deleteSchedule', () => { - test('should delete an existing schedule successfully', async () => { - const result = await scheduleService.deleteSchedule(2, 1); - - expect(result).toBe(true); - - // 삭제된 스케줄이 실제로 삭제되었는지 확인 - const schedule = await Schedule.findByPk(2); - expect(schedule).toBeNull(); - }); - - test('should throw error when deleting a non-existing schedule', async () => { - await expect(scheduleService.deleteSchedule(999, 1)).rejects.toThrow('Schedule not found'); - }); - }); - - describe('getAllSchedules', () => { - test('should retrieve all valid schedules for a user', async () => { - // 사용자 Alice의 모든 스케줄 조회 - const schedules = await scheduleService.getAllSchedules(1); - - expect(schedules.length).toBe(1); // id=1 스케줄은 is_fixed=true - expect(schedules[0].title).toBe('Alice\'s Fixed Schedule'); - }); - }); - - describe('getScheduleById', () => { - test('should retrieve a specific schedule by ID', async () => { - const schedule = await scheduleService.getScheduleById(1, 1); - - expect(schedule).toBeDefined(); - expect(schedule.title).toBe('Alice\'s Fixed Schedule'); - }); - - test('should throw error when retrieving a non-existing schedule', async () => { - await expect(scheduleService.getScheduleById(999, 1)).rejects.toThrow('Schedule not found'); - }); - }); - - describe('cleanExpiredSchedules', () => { - test('should delete expired flexible schedules', async () => { - // 만료된 유동 스케줄 생성 - await Schedule.create({ - id: 3, - user_id: 1, - title: 'Expired Flexible Schedule', - start_time: new Date('2024-04-25T10:00:00Z'), - end_time: new Date('2024-04-25T11:00:00Z'), - is_fixed: false, - expiry_date: new Date('2024-04-30T00:00:00Z'), // 이미 만료됨 - }); - - // 만료되지 않은 유동 스케줄 생성 - await Schedule.create({ - id: 4, - user_id: 1, - title: 'Valid Flexible Schedule', - start_time: new Date('2024-05-07T10:00:00Z'), - end_time: new Date('2024-05-07T11:00:00Z'), - is_fixed: false, - expiry_date: new Date('2024-05-14T00:00:00Z'), // 아직 만료되지 않음 - }); - - // 만료된 스케줄 정리 - await scheduleService.cleanExpiredSchedules(); - - // 만료된 스케줄이 삭제되었는지 확인 - const expiredSchedule = await Schedule.findByPk(3); - expect(expiredSchedule).toBeNull(); - - // 만료되지 않은 스케줄은 남아있는지 확인 - const validSchedule = await Schedule.findByPk(4); - expect(validSchedule).toBeDefined(); - expect(validSchedule.title).toBe('Valid Flexible Schedule'); - }); - }); -});