From e0c7ec1c699dfb4d329b003e9e5295a55ae0cfa5 Mon Sep 17 00:00:00 2001
From: tpgus2603 <kakaneymar2424@gmail.com>
Date: Sat, 23 Nov 2024 15:57:18 +0900
Subject: [PATCH] =?UTF-8?q?test/refactor=20:=20=EC=84=9C=EB=B9=84=EC=8A=A4?=
 =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EB=A6=AC=ED=8E=99=ED=86=A0=EB=A7=81(#13)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 dtos/MeetingDetailResponseDTO.js |  22 +++---
 dtos/MeetingResponseDTO.js       |  18 +++--
 middlewares/auth.js              |   4 +-
 models/Friend.js                 |   9 +--
 models/index.js                  |   6 +-
 models/meeting.js                |  11 +--
 models/meetingParticipant.js     |  17 +----
 models/schedule.js               |   2 +-
 services/meetingService.js       | 120 +++++++++++++++----------------
 services/meetingService.test.js  |  68 +++++++++++++-----
 10 files changed, 139 insertions(+), 138 deletions(-)

diff --git a/dtos/MeetingDetailResponseDTO.js b/dtos/MeetingDetailResponseDTO.js
index 0c489f0..5d4ac75 100644
--- a/dtos/MeetingDetailResponseDTO.js
+++ b/dtos/MeetingDetailResponseDTO.js
@@ -1,19 +1,21 @@
 // dtos/MeetingResponseDTO.js
-
-class MeetingResponseDTO {
-  constructor(meeting, isParticipant, isScheduleConflict, creatorName) {
+class MeetingDetailResponseDTO {
+  constructor(meeting) {
       this.id = meeting.id;
       this.title = meeting.title;
       this.description = meeting.description;
-      this.timeIdxStart = meeting.time_idx_start; // 변경된 필드
-      this.timeIdxEnd = meeting.time_idx_end;     // 변경된 필드
+      this.timeIdxStart = meeting.time_idx_start; 
+      this.timeIdxEnd = meeting.time_idx_end;     
       this.location = meeting.location;
-      this.deadline = meeting.deadline;
+      this.time_idx_deadline = meeting.time_idx_deadline;
       this.type = meeting.type;
-      this.creatorName = creatorName;
-      this.isParticipant = isParticipant;
-      this.isScheduleConflict = isScheduleConflict;
+      this.creatorName = meeting.creator ? meeting.creator.name : 'Unknown';
+      this.participants = meeting.participants.map(participant => ({
+          userId: participant.user_id,
+          name: participant.participantUser ? participant.participantUser.name : 'Unknown',
+          email: participant.participantUser ? participant.participantUser.email : 'Unknown'
+      }));
   }
 }
 
-module.exports = MeetingResponseDTO;
+module.exports = MeetingDetailResponseDTO;
\ No newline at end of file
diff --git a/dtos/MeetingResponseDTO.js b/dtos/MeetingResponseDTO.js
index f7cc8ef..67c3171 100644
--- a/dtos/MeetingResponseDTO.js
+++ b/dtos/MeetingResponseDTO.js
@@ -1,22 +1,20 @@
 // dtos/MeetingDetailResponseDTO.js
 
-class MeetingDetailResponseDTO {
-  constructor(meeting) {
+
+class MeetingResponseDTO {
+  constructor(meeting, isParticipant, isScheduleConflict, creatorName) {
       this.id = meeting.id;
       this.title = meeting.title;
       this.description = meeting.description;
       this.timeIdxStart = meeting.time_idx_start; 
       this.timeIdxEnd = meeting.time_idx_end;     
       this.location = meeting.location;
-      this.deadline = meeting.deadline;
+      this.time_idx_deadline = meeting.time_idx_deadline;
       this.type = meeting.type;
-      this.creatorName = meeting.creator ? meeting.creator.name : 'Unknown';
-      this.participants = meeting.participants.map(participant => ({
-          userId: participant.user_id,
-          name: participant.participantUser ? participant.participantUser.name : 'Unknown',
-          email: participant.participantUser ? participant.participantUser.email : 'Unknown'
-      }));
+      this.creatorName = creatorName;
+      this.isParticipant = isParticipant;
+      this.isScheduleConflict = isScheduleConflict;
   }
 }
 
-module.exports = MeetingDetailResponseDTO;
+module.exports = MeetingResponseDTO;
\ No newline at end of file
diff --git a/middlewares/auth.js b/middlewares/auth.js
index 8ae9be0..afc74ea 100644
--- a/middlewares/auth.js
+++ b/middlewares/auth.js
@@ -1,13 +1,13 @@
 // middlewares/auth.js
 
-exports.isLoggedIn = (req, res, next) => {
+exports.isLoggedIn = (req, res, next) => { //로그인된 사용자자만 접근허용
   if (req.isAuthenticated()) {
     return next();
   }
   res.redirect('/auth/login');
 };
 
-exports.isNotLoggedIn = (req, res, next) => {
+exports.isNotLoggedIn = (req, res, next) => { //로그인 안되면 리다이렉트 
   if (!req.isAuthenticated()) {
     return next();
   }
diff --git a/models/Friend.js b/models/Friend.js
index add987c..ed09212 100644
--- a/models/Friend.js
+++ b/models/Friend.js
@@ -2,7 +2,7 @@
 
 const { DataTypes } = require('sequelize');
 const sequelize = require('../config/sequelize');
-const User = require('./User');
+const User = require('./user');
 
 const Friend = sequelize.define('Friend', {
     status: {
@@ -25,11 +25,4 @@ const Friend = sequelize.define('Friend', {
     ]
 });
 
-// // 관계 설정
-// Friend.belongsTo(User, { foreignKey: 'requester_id', as: 'requester' }); // 친구 요청을 보낸 사용자
-// Friend.belongsTo(User, { foreignKey: 'receiver_id', as: 'receiver' });   // 친구 요청을 받은 사용자
-
-// User.hasMany(Friend, { foreignKey: 'requester_id', as: 'sentRequests' }); // 친구 요청을 보낸 목록
-// User.hasMany(Friend, { foreignKey: 'receiver_id', as: 'receivedRequests' }); // 친구 요청을 받은 목록
-
 module.exports = Friend;
diff --git a/models/index.js b/models/index.js
index adb731e..a07f247 100644
--- a/models/index.js
+++ b/models/index.js
@@ -1,12 +1,12 @@
 // models/index.js
 
 const sequelize = require('../config/sequelize');
-const User = require('./User');
+const User = require('./user');
 const Friend = require('./Friend');
 const Schedule = require('./Schedule');
 const Meeting = require('./Meeting');
 const MeetingParticipant = require('./MeetingParticipant');
-const ChatRoom = require('./ChatRooms');
+const ChatRooms = require('./ChatRooms');
 
 // 관계 설정
 Friend.belongsTo(User, { foreignKey: 'requester_id', as: 'requester' }); // 친구 요청을 보낸 사용자
@@ -34,5 +34,5 @@ module.exports = {
     Schedule,
     Meeting,
     MeetingParticipant,
-    ChatRoom,
+    ChatRooms,
 };
diff --git a/models/meeting.js b/models/meeting.js
index 3d006a5..0616319 100644
--- a/models/meeting.js
+++ b/models/meeting.js
@@ -1,7 +1,7 @@
 // models/Meeting.js
 const { DataTypes } = require('sequelize');
 const sequelize  = require('../config/sequelize');
-const User = require('./User');
+const User = require('./user');
 
 const Meeting = sequelize.define('Meeting', {
   title: {
@@ -22,7 +22,7 @@ const Meeting = sequelize.define('Meeting', {
   location: {
     type: DataTypes.STRING,
   },
-  deadline: {
+  time_idx_deadline: {
     type: DataTypes.INTEGER,
   },
   type: {
@@ -34,11 +34,4 @@ const Meeting = sequelize.define('Meeting', {
   timestamps: false,
 });
 
-// // 연관 관계 설정
-// Meeting.belongsTo(User, { foreignKey: 'created_by', as: 'creator' });
-// User.hasMany(Meeting, { foreignKey: 'created_by', as: 'meetings' });
-
-// Meeting.belongsTo(ChatRoom, { foreignKey: 'chatRoomId', as: 'chatRoom' });
-// ChatRoom.hasOne(Meeting, { foreignKey: 'chatRoomId', as: 'meeting' });
-
 module.exports = Meeting;
diff --git a/models/meetingParticipant.js b/models/meetingParticipant.js
index 288d3b9..59a2624 100644
--- a/models/meetingParticipant.js
+++ b/models/meetingParticipant.js
@@ -3,28 +3,13 @@
 const { DataTypes } = require('sequelize');
 const sequelize  = require('../config/sequelize');
 const Meeting =require('./Meeting');
-const User = require('./User');
+const User = require('./user');
 
 
 const MeetingParticipant = sequelize.define('MeetingParticipant', {
-  meeting_id: {
-    type: DataTypes.INTEGER,
-    allowNull: false
-  },
-  user_id: {
-    type: DataTypes.INTEGER,
-    allowNull: false
-  }
-}, {
   tableName: 'MeetingParticipants',
   timestamps: false,
 });
 
-// MeetingParticipant.belongsTo(Meeting, { foreignKey: 'meeting_id', as: 'meeting' });
-// Meeting.hasMany(MeetingParticipant, { foreignKey: 'meeting_id', as: 'participants' });
-
-// MeetingParticipant.belongsTo(User, { foreignKey: 'user_id', as: 'user' });
-// User.hasMany(MeetingParticipant, { foreignKey: 'user_id', as: 'meetingParticipations' });
-
 
 module.exports = MeetingParticipant;
diff --git a/models/schedule.js b/models/schedule.js
index a7c4a42..48dcec4 100644
--- a/models/schedule.js
+++ b/models/schedule.js
@@ -1,7 +1,7 @@
 // models/Schedule.js
 const { DataTypes } = require('sequelize');
 const sequelize = require('../config/sequelize');
-const User = require('./User');
+const User = require('./user');
 
 const Schedule = sequelize.define('Schedule', {
   title: {
diff --git a/services/meetingService.js b/services/meetingService.js
index 0d87a0c..3132239 100644
--- a/services/meetingService.js
+++ b/services/meetingService.js
@@ -122,40 +122,37 @@ class MeetingService {
      * @returns {Promise<Array<MeetingResponseDTO>>} - 모임 목록 DTO 배열
      */
     async getMeetings(userId) {
-        const meetings = await Meeting.findAll({
-            attributes: [
-                'id',
-                'title',
-                'description',
-                'time_idx_start',
-                'time_idx_end',
-                'location',
-                'time_idx_deadline',
-                'type',
-            ],
-            include: [
-                {
-                    model: User,
-                    as: 'creator',
-                    attributes: ['name'],
-                },
-                {
-                    model: MeetingParticipant,
-                    as: 'participants',
-                    attributes: ['user_id'],
-                },
-            ],
-        });
-
-        return meetings.map((meeting) => {
-            const creatorName = meeting.creator ? meeting.creator.name : 'Unknown';
-            const isParticipant = meeting.participants.some(
-                (participant) => participant.user_id === parseInt(userId, 10)
-            );
-
-            return new MeetingResponseDTO(meeting, isParticipant, false, creatorName);
-        });
-    }
+      const meetings = await Meeting.findAll({
+          attributes: [
+              'id',
+              'title',
+              'description',
+              'time_idx_start',
+              'time_idx_end',
+              'location',
+              'time_idx_deadline',
+              'type',
+          ],
+          include: [
+              {
+                  model: MeetingParticipant,
+                  as: 'participants',
+                  where: { user_id: userId }, // userId와 매핑된 미팅만 가져옴
+                  attributes: [], // MeetingParticipant 테이블의 데이터는 필요 없으므로 제외
+              },
+              {
+                  model: User,
+                  as: 'creator',
+                  attributes: ['name'], // 미팅 생성자의 이름만 필요
+              },
+          ],
+      });
+  
+      return meetings.map((meeting) => {
+          const creatorName = meeting.creator ? meeting.creator.name : 'Unknown';
+          return new MeetingResponseDTO(meeting, true, false, creatorName);
+      });
+  }
 
     /**
      * 번개 모임 마감
@@ -262,34 +259,35 @@ class MeetingService {
      * @param {number} meetingId - 모임 ID
      * @returns {Promise<MeetingDetailResponseDTO>} - 모임 상세 DTO
      */
-    async getMeetingDetail(meetingId) {
-        const meeting = await Meeting.findByPk(meetingId, {
-            include: [
-                {
-                    model: User,
-                    as: 'creator',
-                    attributes: ['name'],
-                },
-                {
-                    model: MeetingParticipant,
-                    as: 'participants',
-                    include: [
-                        {
-                            model: User,
-                            as: 'participantUser',
-                            attributes: ['name', 'email'],
-                        },
-                    ],
-                },
-            ],
-        });
-
-        if (!meeting) {
-            throw new Error('모임을 찾을 수 없습니다.');
-        }
-
-        return new MeetingDetailResponseDTO(meeting);
+    // services/meetingService.js
+  async getMeetingDetail(meetingId) {
+    const meeting = await Meeting.findByPk(meetingId, {
+      include: [
+        {
+          model: User,
+          as: "creator",
+          attributes: ["name"],
+        },
+        {
+          model: MeetingParticipant,
+          as: "participants",
+          include: [
+            {
+              model: User,
+              as: "user", // 'participantUser'에서 'user'로 수정
+              attributes: ["name", "email"],
+            },
+          ],
+        },
+      ],
+    });
+
+    if (!meeting) {
+      throw new Error("모임을 찾을 수 없습니다.");
     }
+
+    return new MeetingDetailResponseDTO(meeting);
+  }
 }
 
 module.exports = new MeetingService();
diff --git a/services/meetingService.test.js b/services/meetingService.test.js
index 6471bba..2bea20b 100644
--- a/services/meetingService.test.js
+++ b/services/meetingService.test.js
@@ -9,6 +9,14 @@ const CreateMeetingRequestDTO = require('../dtos/CreateMeetingRequestDTO');
 const MeetingResponseDTO = require('../dtos/MeetingResponseDTO');
 const MeetingDetailResponseDTO = require('../dtos/MeetingDetailResponseDTO');
 
+// Jest 설정에서 'node' 환경을 사용하고 있는지 확인
+// jest.config.js 또는 package.json에 다음을 추가하세요:
+// {
+//   "jest": {
+//     "testEnvironment": "node"
+//   }
+// }
+
 // ChatRooms 모듈 전체를 모킹하지 않고, 필요한 메서드만 선택적으로 모킹합니다.
 beforeAll(async () => {
     // 테스트 스위트가 시작되기 전에 데이터베이스를 동기화합니다.
@@ -129,6 +137,11 @@ describe('MeetingService', () => {
                 created_by: 1,
             };
 
+            // 'createSchedules' 메서드에서 'Schedule overlaps with existing schedule at time_idx 50' 오류가 발생해야 함
+            // 이를 위해 'ScheduleService.checkScheduleOverlapByTime'을 모킹합니다.
+
+            jest.spyOn(ScheduleService, 'checkScheduleOverlapByTime').mockResolvedValue(true); // 충돌이 발생한다고 가정
+
             await expect(MeetingService.createMeeting(meetingData)).rejects.toThrow(
                 'Schedule overlaps with existing schedule at time_idx 50'
             );
@@ -160,28 +173,31 @@ describe('MeetingService', () => {
                 created_by: 2,
             };
 
-            await MeetingService.createMeeting(meetingData1);
-            await MeetingService.createMeeting(meetingData2);
+            const result1 = await MeetingService.createMeeting(meetingData1);
+            const result2 = await MeetingService.createMeeting(meetingData2);
 
             const meetings = await MeetingService.getMeetings(1); // Alice의 사용자 ID
-
+            console.log(meetings);
             expect(meetings).toBeDefined();
             expect(Array.isArray(meetings)).toBe(true);
-            expect(meetings.length).toBe(2);
-
-            meetings.forEach(meeting => {
-                expect(meeting).toBeInstanceOf(MeetingResponseDTO);
-                expect(['Meeting 1', 'Meeting 2']).toContain(meeting.title);
-                expect(['OPEN']).toContain(meeting.type);
-                if (meeting.id === 1) {
-                    expect(meeting.creatorName).toBe('Alice');
-                    expect(meeting.isParticipant).toBe(true);
-                } else {
-                    expect(meeting.creatorName).toBe('Bob');
-                    expect(meeting.isParticipant).toBe(false);
-                }
-            });
+            expect(meetings.length).toBe(1);
+
+            // 생성된 미팅의 ID를 기준으로 기대값 설정
+            const meeting1 = meetings.find(meeting => meeting.title === 'Meeting 1');
+            const meeting2 = meetings.find(meeting => meeting.title === 'Meeting 2');
+
+            console.log(meeting1);
+            console.log(meeting2);
+            expect(meeting1).toBeDefined();
+            expect(meeting1.creatorName).toBe('Alice');
+            expect(meeting1.isParticipant).toBe(true);
+
+            expect(meeting2).toBeDefined();
+            expect(meeting2.creatorName).toBe('Bob');
+            expect(meeting2.isParticipant).toBe(false);
         });
+
+        // 추가적인 getMeetings 테스트 케이스 작성 가능
     });
 
     describe('closeMeeting', () => {
@@ -248,6 +264,9 @@ describe('MeetingService', () => {
 
             const { meeting_id } = await MeetingService.createMeeting(meetingData);
 
+            // 'getCurrentTimeIdx'를 고정된 값으로 모킹하여 '참가 신청이 마감되었습니다.' 오류를 방지
+            jest.spyOn(MeetingService, 'getCurrentTimeIdx').mockReturnValue(100); // 100 < 108
+
             // Bob이 참가
             await MeetingService.joinMeeting(meeting_id, 2);
 
@@ -290,6 +309,9 @@ describe('MeetingService', () => {
 
             const { meeting_id } = await MeetingService.createMeeting(meetingData);
 
+            // 'getCurrentTimeIdx'를 고정된 값으로 모킹
+            jest.spyOn(MeetingService, 'getCurrentTimeIdx').mockReturnValue(100); // 100 < 118
+
             await MeetingService.closeMeeting(meeting_id);
 
             await expect(MeetingService.joinMeeting(meeting_id, 2)).rejects.toThrow('이미 마감된 모임입니다.');
@@ -309,6 +331,9 @@ describe('MeetingService', () => {
 
             const { meeting_id } = await MeetingService.createMeeting(meetingData);
 
+            // 'getCurrentTimeIdx'를 고정된 값으로 모킹
+            jest.spyOn(MeetingService, 'getCurrentTimeIdx').mockReturnValue(100); // 100 < 128
+
             await MeetingService.joinMeeting(meeting_id, 2);
 
             await expect(MeetingService.joinMeeting(meeting_id, 2)).rejects.toThrow('이미 참가한 사용자입니다.');
@@ -322,13 +347,19 @@ describe('MeetingService', () => {
                 time_idx_start: 59,
                 time_idx_end: 61, // time_idx 60 포함
                 location: 'Conference Room H',
-                time_idx_deadline: 58,
+                time_idx_deadline: 110, // 참가 신청 마감을 피하기 위해 값 변경
                 type: 'OPEN',
                 created_by: 1,
             };
 
             const { meeting_id } = await MeetingService.createMeeting(meetingData);
 
+            // 'getCurrentTimeIdx'를 고정된 값으로 모킹
+            jest.spyOn(MeetingService, 'getCurrentTimeIdx').mockReturnValue(100); // 100 < 110
+
+            // 'checkScheduleOverlapByTime'을 모킹하여 충돌이 발생하도록 설정
+            jest.spyOn(ScheduleService, 'checkScheduleOverlapByTime').mockResolvedValue(true);
+
             await expect(MeetingService.joinMeeting(meeting_id, 2)).rejects.toThrow(
                 '스케줄이 겹칩니다. 다른 모임에 참가하세요.'
             );
@@ -351,6 +382,7 @@ describe('MeetingService', () => {
             const { meeting_id } = await MeetingService.createMeeting(meetingData);
 
             // Bob과 Charlie 참가
+            jest.spyOn(MeetingService, 'getCurrentTimeIdx').mockReturnValue(100); // 참가 신청 마감 방지
             await MeetingService.joinMeeting(meeting_id, 2);
             await MeetingService.joinMeeting(meeting_id, 3);
 
-- 
GitLab