diff --git a/src/entity/NoticeEntity.ts b/src/entity/NoticeEntity.ts index d0fedc0..b286048 100644 --- a/src/entity/NoticeEntity.ts +++ b/src/entity/NoticeEntity.ts @@ -13,7 +13,7 @@ export default class Notice { @PrimaryGeneratedColumn('uuid', { name: 'ID' }) id!: string; - @Column('varchar', { name: 'TITLE', length: 500 }) + @Column('varchar', { name: 'TITLE', length: 40 }) title!: string; @Column('varchar', { name: 'ABOUT', length: 500 }) diff --git a/src/entity/StudyEntity.ts b/src/entity/StudyEntity.ts index bbeeeb7..3714c97 100644 --- a/src/entity/StudyEntity.ts +++ b/src/entity/StudyEntity.ts @@ -43,7 +43,7 @@ export default class Study { @CreateDateColumn({ name: 'CREATED_AT' }) createdAt!: Date; - @Column('varchar', { name: 'TITLE', length: 500 }) + @Column('varchar', { name: 'TITLE', length: 40 }) title!: string; @Column('varchar', { name: 'STUDY_ABOUT', length: 500 }) diff --git a/src/routes/notice/notice.controller.ts b/src/routes/notice/notice.controller.ts index 02f0258..20697ff 100644 --- a/src/routes/notice/notice.controller.ts +++ b/src/routes/notice/notice.controller.ts @@ -3,7 +3,6 @@ import { createNotice, deleteNotice, findAllNotice, - findAllUser, findNoticeById, findNoticeCount, updateNoticeById, @@ -12,7 +11,7 @@ import { import { UserRoleEnum } from '../../entity/UserEntity'; import { createNoticeNoti, NotiTypeEnum } from '../../services/notification'; import { temp_findUserProfileById } from '../../services/user/profile'; -import { findOnlyUserRoleById } from '../../services/user'; +import { findAllUser, findOnlyUserRoleById } from '../../services/user'; export default { async findAllNotice(req: Request, res: Response) { @@ -90,10 +89,10 @@ export default { if (process.env.NODE_ENV !== 'test') { const users = await findAllUser(); if (users.length !== 0) { - for (const u of users) { + for (const user of users) { await createNoticeNoti({ id, - userId: u.id, + userId: user.id, title: '새로운 공지', about: '중대본으로부터 새로운 공지글이 등록되었어요.', type: NotiTypeEnum.NEW_NOTICE, diff --git a/src/routes/study/index.ts b/src/routes/study/index.ts index 1fb268e..2374750 100644 --- a/src/routes/study/index.ts +++ b/src/routes/study/index.ts @@ -11,7 +11,11 @@ router.get('/', controller.getAllStudy); router.post('/', checkToken, controller.createStudy); router.get('/search', controller.searchStudy); -router.get('/:studyid', controller.getStudybyId); +router.get( + '/:studyid', + controller.getStudybyIdWithLogIn, + controller.getStudybyId +); router.patch('/:studyid', checkToken, controller.updateStudy); router.delete('/:studyid', checkToken, controller.deleteStudy); diff --git a/src/routes/study/study.controller.ts b/src/routes/study/study.controller.ts index bda696f..3545fa0 100644 --- a/src/routes/study/study.controller.ts +++ b/src/routes/study/study.controller.ts @@ -1,4 +1,4 @@ -import { Request, Response } from 'express'; +import { NextFunction, Request, Response } from 'express'; import jwt from 'jsonwebtoken'; import cron from 'node-cron'; import Study, { @@ -11,7 +11,7 @@ import studyService from '../../services/study'; import { checkApplied, findAcceptedByStudyId, - findAllByStudyId, + findAllStudyUserByStudyId, findNotAcceptedApplicantsByStudyId, } from '../../services/studyUser'; import { temp_findUserProfileById } from '../../services/user/profile'; @@ -20,6 +20,7 @@ import bookmarkService from '../../services/study/bookmark'; import { getRepository } from 'typeorm'; import User from '../../entity/UserEntity'; import { generateToken } from '../../middlewares/auth'; +import { logoutUserById } from '../../services/user'; export const schedules: { [key: string]: cron.ScheduledTask } = {}; export const closedschedules: string[] = []; @@ -38,29 +39,23 @@ if (process.env.NODE_ENV !== 'test') { const scheduleJob = async (study: Study) => { await studyService.updateIsOpen(study); const members = await findAcceptedByStudyId(study.id); - members.map((record: Record) => ({ - userId: record.StudyUser_USER_ID, - })); if (members.length !== 0) { for (const member of members) { await createStudyNoti({ id: study.id, - userId: member.userId, + userId: member.USER_ID, title: '모집 종료', - about: `모집이 종료되었어요. 스터디를 응원합니다!`, + about: `모집이 종료되었어요. ${member.USER_NAME}님의 스터디를 응원합니다!`, type: NotiTypeEnum.CLOSED, }); } } const applicants = await findNotAcceptedApplicantsByStudyId(study.id); - applicants.map((record: Record) => ({ - userId: record.StudyUser_USER_ID, - })); if (applicants.length !== 0) { for (const user of applicants) { await createStudyNoti({ id: study.id, - userId: user.userId, + userId: user.USER_ID, title: '모집 종료', about: '스터디의 모집이 마감되었어요.', type: NotiTypeEnum.CLOSED, @@ -226,85 +221,82 @@ const createStudy = async (req: Request, res: Response) => { } }; -const getStudybyId = async (req: Request, res: Response) => { - const NOT_FOUND = '데이터베이스에 일치하는 요청값이 없습니다'; +const getStudybyIdWithLogIn = async ( + req: Request, + res: Response, + next: NextFunction +) => { const FORBIDDEN = '접근 권한이 없습니다'; + const NOT_FOUND = '데이터베이스에 일치하는 요청값이 없습니다'; try { const { studyid } = req.params; const study = await studyService.findStudyById(studyid); + if (!study) throw new Error(NOT_FOUND); - if (!study) { - throw new Error(NOT_FOUND); - } - await studyService.updateStudyViews(study); + const { accessToken, refreshToken } = req.cookies; + let decoded; - if (req.cookies) { - const { accessToken, refreshToken } = req.cookies; + if (!accessToken && !refreshToken) { + next(); + } else if (!accessToken && refreshToken) { + try { + decoded = jwt.verify( + refreshToken, + process.env.SIGNUP_TOKEN_SECRET as string + ) as { id: string; email: string }; - if (!accessToken && !refreshToken) { - return res.status(200).json({ - ...study, - bookmarked: false, - applied: false, - isLogIn: false, - }); - } - if (!accessToken && refreshToken) { - try { - const decoded = jwt.verify( - refreshToken, - process.env.SIGNUP_TOKEN_SECRET as string - ) as { id: string; email: string }; - const user = await getRepository(User).findOne({ id: decoded.id }); - if (user?.id !== decoded.id) throw new Error(FORBIDDEN); - if (user?.isLogout) throw new Error(FORBIDDEN); - - const newAccessToken = generateToken({ id: decoded.id }); - const bookmarkFlag = await bookmarkService.checkBookmarked( - decoded.id, - studyid - ); - const appliedFlag = await checkApplied(studyid, decoded.id); - return res - .cookie('accessToken', newAccessToken, { - expires: new Date(Date.now() + 3 * 3600 * 1000), - domain: 'caustudy.com', - sameSite: 'none', - secure: true, - }) - .status(200) - .json({ - ...study, - bookmarked: bookmarkFlag ? true : false, - applied: appliedFlag ? true : false, - isLogIn: true, - }); - } catch (e) { - if ((e as Error).message === FORBIDDEN) { - return res.status(403).json({ message: FORBIDDEN }); - } else { - // logout - return res.status(200).json({ - ...study, - bookmarked: false, - applied: false, - isLogIn: false, - }); - } + const user = await getRepository(User).findOne({ id: decoded.id }); + if (user?.id !== decoded.id) throw new Error(FORBIDDEN); + if (user?.isLogout) throw new Error(FORBIDDEN); + + const newAccessToken = generateToken({ id: decoded.id }); + req.user = { id: decoded.id }; + + const bookmarkFlag = await bookmarkService.checkBookmarked( + decoded.id, + studyid + ); + const appliedFlag = await checkApplied(studyid, decoded.id); + await studyService.updateStudyViews(study); + + return res + .cookie('accessToken', newAccessToken, { + expires: new Date(Date.now() + 3 * 3600 * 1000), + domain: 'caustudy.com', + sameSite: 'none', + secure: true, + }) + .status(200) + .json({ + ...study, + bookmarked: bookmarkFlag ? true : false, + applied: appliedFlag ? true : false, + isLogIn: true, + }); + } catch (e) { + if ((e as Error).message === FORBIDDEN) { + return res.status(403).json({ message: (e as Error).message }); + } else { + if (decoded?.id) await logoutUserById(decoded.id); + next(); } } + } else { try { - const decoded = jwt.verify( + decoded = jwt.verify( accessToken, process.env.SIGNUP_TOKEN_SECRET as string ) as { id: string }; + req.user = { id: decoded.id }; const bookmarkFlag = await bookmarkService.checkBookmarked( decoded.id, studyid ); const appliedFlag = await checkApplied(studyid, decoded.id); + await studyService.updateStudyViews(study); + return res.status(200).json({ ...study, bookmarked: bookmarkFlag ? true : false, @@ -312,18 +304,35 @@ const getStudybyId = async (req: Request, res: Response) => { isLogIn: true, }); } catch (e) { - // logout - return res.status(200).json({ - ...study, - bookmarked: false, - applied: false, - isLogIn: false, - }); + if (decoded?.id) await logoutUserById(decoded.id); + next(); } } - return res - .status(200) - .json({ ...study, bookmarked: false, applied: false, isLogIn: false }); + } catch (e) { + if ((e as Error).message === NOT_FOUND) { + return res.status(404).json({ message: NOT_FOUND }); + } else { + return res.status(500).json({ message: (e as Error).message }); + } + } +}; + +const getStudybyId = async (req: Request, res: Response) => { + const NOT_FOUND = '데이터베이스에 일치하는 요청값이 없습니다'; + + try { + const { studyid } = req.params; + const study = await studyService.findStudyById(studyid); + if (!study) throw new Error(NOT_FOUND); + + await studyService.updateStudyViews(study); + + return res.status(200).json({ + ...study, + bookmarked: false, + applied: false, + isLogIn: false, + }); } catch (e) { if ((e as Error).message === NOT_FOUND) { return res.status(404).json({ message: NOT_FOUND }); @@ -335,6 +344,7 @@ const getStudybyId = async (req: Request, res: Response) => { const updateStudy = async (req: Request, res: Response) => { const BAD_REQUEST = '요청값이 유효하지 않음'; + const FORBIDDEN = '접근 권한이 없습니다'; const NOT_FOUND = '데이터베이스에 일치하는 요청값이 없습니다'; try { @@ -353,37 +363,55 @@ const updateStudy = async (req: Request, res: Response) => { Object.keys(req.body).forEach((key) => { if (!allowedFields.includes(key)) throw new Error(BAD_REQUEST); }); - if (!req.body.weekday.length || !req.body.location.length) - throw new Error(BAD_REQUEST); - req.body.weekday.forEach((value: string) => { - if (!(Object.values(WeekDayEnum) as string[]).includes(value)) - throw new Error(BAD_REQUEST); - }); - if ( - !(Object.values(FrequencyEnum) as string[]).includes(req.body.frequency) - ) - throw new Error(BAD_REQUEST); - req.body.location.forEach((value: string) => { - if (!(Object.values(LocationEnum) as string[]).includes(value)) + if (req.body.weekday) { + if (!req.body.weekday.length) throw new Error(BAD_REQUEST); + req.body.weekday.forEach((value: string) => { + if (!(Object.values(WeekDayEnum) as string[]).includes(value)) + throw new Error(BAD_REQUEST); + }); + } + if (req.body.frequency) { + if ( + !(Object.values(FrequencyEnum) as string[]).includes(req.body.frequency) + ) throw new Error(BAD_REQUEST); - }); + } + if (req.body.location) { + if (!req.body.location.length) throw new Error(BAD_REQUEST); + req.body.location.forEach((value: string) => { + if (!(Object.values(LocationEnum) as string[]).includes(value)) + throw new Error(BAD_REQUEST); + }); + } if (req.body.dueDate) { const due = new Date(req.body.dueDate); const now = new Date(); - - if (due.toISOString().split('T')[0] < now.toISOString().split('T')[0]) { + if (due.toISOString().split('T')[0] < now.toISOString().split('T')[0]) throw new Error(BAD_REQUEST); - } } const study = await studyService.findStudyById(studyid); - if (!study) { - throw new Error(NOT_FOUND); - } - await studyService.updateStudy(req.body, study); + if (!study) throw new Error(NOT_FOUND); + + const userId = (req.user as { id: string }).id; + if (study.HOST_ID !== userId) throw new Error(FORBIDDEN); + + await studyService.updateStudy( + { + title: req.body.title ?? study.title, + studyAbout: req.body.studyAbout ?? study.studyAbout, + weekday: req.body.weekday ?? study.weekday, + frequency: req.body.frequency ?? study.frequency, + location: req.body.location ?? study.location, + capacity: req.body.capacity ?? study.capacity, + categoryCode: req.body.categoryCode ?? study.categoryCode, + dueDate: req.body.dueDate ?? study.dueDate, + }, + studyid + ); if (process.env.NODE_ENV !== 'test') { - const users = await findAllByStudyId(studyid); + const users = await findAllStudyUserByStudyId(studyid); if (users.length !== 0) { for (const user of users) { await createStudyNoti({ @@ -395,7 +423,6 @@ const updateStudy = async (req: Request, res: Response) => { }); } } - if (req.body.dueDate) { const due = new Date(req.body.dueDate); schedules[`${study.id}`].stop(); @@ -409,6 +436,8 @@ const updateStudy = async (req: Request, res: Response) => { } catch (e) { if ((e as Error).message === BAD_REQUEST) { return res.status(400).json({ message: BAD_REQUEST }); + } else if ((e as Error).message === FORBIDDEN) { + return res.status(403).json({ message: FORBIDDEN }); } else if ((e as Error).message === NOT_FOUND) { return res.status(404).json({ message: NOT_FOUND }); } else { @@ -418,19 +447,38 @@ const updateStudy = async (req: Request, res: Response) => { }; const deleteStudy = async (req: Request, res: Response) => { + const FORBIDDEN = '접근 권한이 없습니다'; const NOT_FOUND = '데이터베이스에 일치하는 요청값이 없습니다'; try { const { studyid } = req.params; const study = await studyService.findStudyById(studyid); + if (!study) throw new Error(NOT_FOUND); - if (!study) { - throw new Error(NOT_FOUND); + const userId = (req.user as { id: string }).id; + if (study.HOST_ID !== userId) throw new Error(FORBIDDEN); + + await studyService.deleteStudy(studyid); + + if (process.env.NODE_ENV !== 'test') { + const users = await findAllStudyUserByStudyId(studyid); + if (users.length !== 0) { + for (const user of users) { + await createStudyNoti({ + id: studyid, + userId: user.USER_ID, + title: '모집 취소', + about: '스터디가 삭제되었어요:(', + type: NotiTypeEnum.DELETED, + }); + } + } } - await studyService.deleteStudy(study); return res.status(200).json({ message: '스터디 삭제 성공' }); } catch (e) { - if ((e as Error).message === NOT_FOUND) { + if ((e as Error).message === FORBIDDEN) { + return res.status(403).json({ message: FORBIDDEN }); + } else if ((e as Error).message === NOT_FOUND) { return res.status(404).json({ message: NOT_FOUND }); } else { return res.status(500).json({ message: (e as Error).message }); @@ -496,13 +544,17 @@ const searchStudy = async (req: Request, res: Response) => { const closeStudy = async (req: Request, res: Response) => { const BAD_REQUEST = '잘못된 요청입니다'; + const FORBIDDEN = '접근 권한이 없습니다'; const NOT_FOUND = '데이터베이스에 일치하는 요청값이 없습니다'; try { const { studyid } = req.params; const study = await studyService.findStudyById(studyid); - if (!study) throw new Error(NOT_FOUND); + + const userId = (req.user as { id: string }).id; + if (study.HOST_ID !== userId) throw new Error(FORBIDDEN); + if (study.isOpen) { if (process.env.NODE_ENV !== 'test') { await scheduleJob(study); @@ -517,6 +569,8 @@ const closeStudy = async (req: Request, res: Response) => { } catch (e) { if ((e as Error).message === BAD_REQUEST) { return res.status(400).json({ message: BAD_REQUEST }); + } else if ((e as Error).message === FORBIDDEN) { + return res.status(403).json({ message: FORBIDDEN }); } else if ((e as Error).message === NOT_FOUND) { return res.status(404).json({ message: NOT_FOUND }); } else { @@ -528,6 +582,7 @@ const closeStudy = async (req: Request, res: Response) => { export default { getAllStudy, createStudy, + getStudybyIdWithLogIn, getStudybyId, updateStudy, deleteStudy, @@ -713,6 +768,14 @@ export default { * isLogIn: * type: boolean * description: "유저가 현재 로그인 상태인지 아닌지에 대한 여부" + * 403: + * description: "접근 권한이 없는 경우입니다" + * schema: + * type: object + * properties: + * message: + * type: string + * example: "접근 권한이 없습니다" * 404: * description: "전달한 studyid가 데이터베이스에 없는 경우입니다" * schema: @@ -809,6 +872,14 @@ export default { * message: * type: string * example: "로그인 필요" + * 403: + * description: "스터디의 호스트(작성자)가 아닌 경우입니다" + * schema: + * type: object + * properties: + * message: + * type: string + * example: "접근 권한이 없습니다" * 404: * description: "전달한 studyid가 데이터베이스에 없는 경우입니다" * schema: @@ -847,6 +918,14 @@ export default { * message: * type: string * example: "로그인 필요" + * 403: + * description: "스터디의 호스트(작성자)가 아닌 경우입니다" + * schema: + * type: object + * properties: + * message: + * type: string + * example: "접근 권한이 없습니다" * 404: * description: "전달한 studyid가 데이터베이스에 없는 경우입니다" * schema: @@ -894,6 +973,14 @@ export default { * message: * type: string * example: "로그인 필요" + * 403: + * description: "스터디의 호스트(작성자)가 아닌 경우입니다" + * schema: + * type: object + * properties: + * message: + * type: string + * example: "접근 권한이 없습니다" * 404: * description: "전달한 studyid가 데이터베이스에 없는 경우입니다" * schema: diff --git a/src/routes/study/studyUser/studyUser.controller.ts b/src/routes/study/studyUser/studyUser.controller.ts index 7853bc3..8b766f9 100644 --- a/src/routes/study/studyUser/studyUser.controller.ts +++ b/src/routes/study/studyUser/studyUser.controller.ts @@ -113,7 +113,7 @@ export default { id: studyid, userId: study.HOST_ID, title: '새로운 신청자', - about: `[${profile?.userName}]님이 신청수락을 요청했어요.`, + about: `[${profile[0].userProfile_USER_NAME}]님이 신청수락을 요청했어요.`, type: NotiTypeEnum.NEW_APPLY, }); } @@ -159,13 +159,15 @@ export default { await studyService.increaseMemberCount(studyId); if (process.env.NODE_ENV !== 'test') { - await createStudyNoti({ - id: studyId, - userId: targetUserId, - title: '참가완료', - about: '스터디의 참가신청이 수락되었어요:)', - type: NotiTypeEnum.ACCEPT, - }); + if (accept) { + await createStudyNoti({ + id: studyId, + userId: targetUserId, + title: '참가신청 수락', + about: '스터디의 참가신청이 수락되었어요:)', + type: NotiTypeEnum.ACCEPT, + }); + } } res.json({ message: OK }); @@ -237,13 +239,15 @@ export default { /* 호스트가 참가신청 취소해버린 경우 */ if (process.env.NODE_ENV !== 'test') { - await createStudyNoti({ - id: studyid, - userId: userId, - title: '참가 취소', - about: '스터디의 참가신청이 취소되었어요:(', - type: NotiTypeEnum.REJECT, - }); + if (isDeletedByHost) { + await createStudyNoti({ + id: studyid, + userId: targetUserId, + title: '참가신청 취소', + about: '스터디의 참가신청이 취소되었어요:(', + type: NotiTypeEnum.REJECT, + }); + } } } catch (e) { const err = e as Error; diff --git a/src/services/notice/index.ts b/src/services/notice/index.ts index 8569340..6123a99 100644 --- a/src/services/notice/index.ts +++ b/src/services/notice/index.ts @@ -1,13 +1,8 @@ import { randomUUID } from 'crypto'; import { getRepository } from 'typeorm'; import Notice from '../../entity/NoticeEntity'; -import User from '../../entity/UserEntity'; import UserProfile from '../../entity/UserProfileEntity'; -export const findAllUser = async () => { - return await getRepository(User).createQueryBuilder().select('id').getMany(); -}; - export const findNoticeCount = async () => { return await getRepository(Notice).createQueryBuilder().select().getCount(); }; diff --git a/src/services/notification/index.ts b/src/services/notification/index.ts index 56e5619..9812afe 100644 --- a/src/services/notification/index.ts +++ b/src/services/notification/index.ts @@ -10,6 +10,7 @@ export enum NotiTypeEnum { ACCEPT, REJECT, CLOSED, + DELETED, NEW_NOTICE = 201, } diff --git a/src/services/study/index.ts b/src/services/study/index.ts index 4f4206a..c3adc59 100644 --- a/src/services/study/index.ts +++ b/src/services/study/index.ts @@ -177,34 +177,21 @@ const createStudy = async (studyDTO: studyDTO, user: UserProfile) => { return await getRepository(Study).save(study); }; -const updateStudy = async (studyDTO: studyDTO, study: Study) => { - const { - title, - studyAbout, - weekday, - frequency, - location, - capacity, - categoryCode, - dueDate, - } = studyDTO; - - if (title) study.title = title; - if (studyAbout) study.studyAbout = studyAbout; - if (weekday) study.weekday = weekday; - if (frequency) study.frequency = frequency; - if (location) study.location = location; - if (capacity) study.capacity = capacity; - if (categoryCode) study.categoryCode = categoryCode; - if (dueDate) { - const due = new Date(dueDate); - study.dueDate = due; - } - return await getRepository(Study).save(study); +const updateStudy = async (studyDTO: studyDTO, studyId: string) => { + return await getRepository(Study) + .createQueryBuilder() + .update() + .set(studyDTO) + .where('id = :studyId', { studyId }) + .execute(); }; -const deleteStudy = async (study: Study) => { - return await getRepository(Study).remove(study); +const deleteStudy = async (studyId: string) => { + return await getRepository(Study) + .createQueryBuilder() + .delete() + .where('id = :studyId', { studyId }) + .execute(); }; const searchStudy = async (searchStudyDTO: searchStudyDTO) => { diff --git a/src/services/studyUser/index.ts b/src/services/studyUser/index.ts index b12e0a9..c6eed6d 100644 --- a/src/services/studyUser/index.ts +++ b/src/services/studyUser/index.ts @@ -24,12 +24,12 @@ export const saveStudyUserRecord = async ({ .execute(); }; -export const findAllByStudyId = async (studyId: string) => { +export const findAllStudyUserByStudyId = async (studyId: string) => { return await getRepository(StudyUser) - .createQueryBuilder() - .select() - .where('STUDY_ID = :id', { id: studyId }) - .execute(); + .createQueryBuilder('studyUser') + .select('studyUser.USER_ID') + .where('studyUser.STUDY_ID = :studyId', { studyId }) + .getMany(); }; export const findAllIfParticipatedByUserId = async (userId: string) => { diff --git a/src/services/user/index.ts b/src/services/user/index.ts index 4d0743a..1f52b80 100644 --- a/src/services/user/index.ts +++ b/src/services/user/index.ts @@ -126,3 +126,7 @@ const _setLogoutStatusById = (logoutStatus: boolean) => async (id: string) => { export const logoutUserById = _setLogoutStatusById(true); export const loginUserById = _setLogoutStatusById(false); + +export const findAllUser = async () => { + return await getRepository(User).createQueryBuilder().getMany(); +}; diff --git a/test/study.test.ts b/test/study.test.ts index 6717b55..c546ef1 100644 --- a/test/study.test.ts +++ b/test/study.test.ts @@ -20,6 +20,7 @@ import StudyUser from '../src/entity/StudyUserEntity'; let conn: Connection; let userid: string; +let userid2: string; let studyid: string; beforeAll(async () => { @@ -56,6 +57,34 @@ beforeAll(async () => { profile.link3 = 'user_link3'; profile.image = 'image'; await getRepository(UserProfile).save(profile); + + const user2 = new User(); + userid2 = randomUUID(); + user2.id = userid2; + user2.email = 'user@gmail.com'; + user2.password = bcrypt.hashSync('user', 10); + user2.isLogout = false; + user2.token = ''; + user2.role = UserRoleEnum.USER; + await getRepository(User).save(user2); + + const profile2 = new UserProfile(); + profile2.id = user2; + profile2.email = user2.email; + profile2.userName = 'user2'; + profile2.dept = 'dept2'; + profile2.grade = 2; + profile2.bio = 'bio2'; + profile2.userAbout = 'about2'; + profile2.showDept = false; + profile2.showGrade = false; + profile2.onBreak = false; + profile2.categories = ['102']; + profile2.link1 = 'user_link1'; + profile2.link2 = 'user_link2'; + profile2.link3 = 'user_link3'; + profile2.image = 'image2'; + await getRepository(UserProfile).save(profile2); }); afterAll(async () => { @@ -322,11 +351,13 @@ describe('GET /api/study/:studyid', () => { beforeEach(async () => { // login const res = await request(app).post('/api/user/login').send({ - email: 'test@gmail.com', - password: 'test', + email: 'user@gmail.com', + password: 'user', }); cookies = res.headers['set-cookie']; + }); + it('각 studyid에 따라 모든 스터디 상세 정보 반환 (로그인O)', async () => { // bookmark await request(app) .post(`/api/study/${studyid}/bookmark`) @@ -334,13 +365,14 @@ describe('GET /api/study/:studyid', () => { .send(); // apply - await request(app) - .post(`/api/study/${studyid}/user`) - .set('Cookie', cookies) - .send({ tempBio: 'hello' }); - }); + const studyUser = new StudyUser(); + studyUser.STUDY_ID = studyid; + studyUser.USER_ID = userid2; + studyUser.createdAt = new Date(); + studyUser.isAccepted = false; + studyUser.tempBio = 'hello'; + await getRepository(StudyUser).save(studyUser); - it('각 studyid에 따라 모든 스터디 상세 정보 반환 (로그인O)', async () => { const res = await request(app) .get(`/api/study/${studyid}`) .set('Cookie', cookies); @@ -362,14 +394,18 @@ describe('GET /api/study/:studyid', () => { expect(res.body.applied).toBeFalsy(); }); - it('요청된 studyid가 데이터베이스에 존재하지 않으면 404 응답', async () => { - const res = await request(app).get('/api/study/wrong'); + it('요청된 studyid가 데이터베이스에 존재하지 않으면 404 응답 (로그인O)', async () => { + const res = await request(app) + .get('/api/study/wrong') + .set('Cookie', cookies); expect(res.status).toBe(404); }); - afterEach(async () => { - await getRepository(StudyUser).createQueryBuilder().delete().execute(); + it('요청된 studyid가 데이터베이스에 존재하지 않으면 404 응답 (로그인X)', async () => { + const res = await request(app).get('/api/study/wrong'); + + expect(res.status).toBe(404); }); }); @@ -395,12 +431,30 @@ describe('PATCH /api/study/:studyid', () => { weekday: [WeekDayEnum.WED, WeekDayEnum.THU], frequency: FrequencyEnum.MORE, location: [LocationEnum.LIBRARY, LocationEnum.NO_CONTACT], - capacity: 10, - categoryCode: 102, dueDate: new Date(date.getTime() + 60 * 60 * 7), }); expect(res.status).toBe(200); + + const study = await getRepository(Study) + .createQueryBuilder('study') + .addSelect('study.dueDate') + .leftJoinAndSelect('study.hostId', 'UserProfile') + .where('study.id = :id', { id: studyid }) + .getOne(); + + expect(study?.title).toEqual('STUDY TITLE'); + expect(study?.studyAbout).toEqual('STUDY ABOUT'); + expect(study?.weekday).toEqual( + expect.arrayContaining([WeekDayEnum.WED, WeekDayEnum.THU]) + ); + expect(study?.frequency).toEqual(FrequencyEnum.MORE); + expect(study?.location).toEqual( + expect.arrayContaining([LocationEnum.LIBRARY, LocationEnum.NO_CONTACT]) + ); + + expect(study?.capacity).toEqual(8); + expect(study?.categoryCode).toEqual(101); }); it('유효하지 않은 body를 포함한 요청을 받으면 400 응답', async () => { @@ -431,8 +485,6 @@ describe('PATCH /api/study/:studyid', () => { weekday: [WeekDayEnum.WED, WeekDayEnum.THU], frequency: FrequencyEnum.MORE, location: [LocationEnum.LIBRARY, LocationEnum.NO_CONTACT], - capacity: 10, - categoryCode: 102, dueDate: new Date(date.getTime() + 60 * 60 * 7), }); @@ -450,8 +502,6 @@ describe('PATCH /api/study/:studyid', () => { weekday: [WeekDayEnum.WED, WeekDayEnum.THU], frequency: FrequencyEnum.MORE, location: [LocationEnum.LIBRARY, LocationEnum.NO_CONTACT], - capacity: 10, - categoryCode: 102, dueDate: new Date(date.getTime() + 60 * 60 * 7), });