From 48df8df00510d27947720cb620f296f9b6410892 Mon Sep 17 00:00:00 2001 From: tmddus2 Date: Thu, 14 Mar 2024 01:48:33 +0900 Subject: [PATCH 1/5] =?UTF-8?q?refactor:=20Controller=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=97=AC=EB=9F=AC=20Service=20=EC=9D=98=EC=A1=B4=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/lecture/lecture.controller.ts | 11 ++++------- backend/src/lecture/lecture.module.ts | 5 ++--- backend/src/lecture/lecture.service.ts | 18 ++++++++++++++--- backend/src/user/user.module.ts | 16 +++++---------- backend/src/user/user.service.ts | 24 ++++++++++------------- 5 files changed, 36 insertions(+), 38 deletions(-) diff --git a/backend/src/lecture/lecture.controller.ts b/backend/src/lecture/lecture.controller.ts index 10fe023..806dc24 100644 --- a/backend/src/lecture/lecture.controller.ts +++ b/backend/src/lecture/lecture.controller.ts @@ -14,7 +14,6 @@ import { } from '@nestjs/common'; import { ApiBody, ApiHeader, ApiOperation, ApiParam, ApiQuery, ApiResponse, ApiTags } from '@nestjs/swagger'; import { Response } from 'express'; -import { UserService } from 'src/user/user.service'; import { CreateLectureDto } from './dto/create-lecture.dto'; import { LectureInfoDto } from './dto/response/response-lecture-info.dto'; import { UpdateLectureDto } from './dto/update-lecture.dto'; @@ -28,8 +27,7 @@ import { Types } from 'mongoose'; @Controller('lecture') export class LectureController { constructor( - private readonly lectureService: LectureService, - private readonly userService: UserService + private readonly lectureService: LectureService ) {} @UseGuards(CustomAuthGuard) @@ -43,8 +41,7 @@ export class LectureController { if (!req.user) { throw new HttpException('로그인 되지 않은 사용자입니다.', HttpStatus.UNAUTHORIZED); } - const user = await this.userService.findOneByEmail(req.user.email); - const code = await this.lectureService.createLecture(createLecture, user._id); + const code = await this.lectureService.createLecture(createLecture, req.user.email); res.status(HttpStatus.CREATED).send({ code: code }); } @@ -73,7 +70,7 @@ export class LectureController { throw new HttpException('유효하지 않은 강의 참여코드입니다.', HttpStatus.NOT_FOUND); } - await this.userService.updateLecture(req.user.email, enterCodeDocument); + await this.lectureService.updateLecture(req.user.email, enterCodeDocument); res.status(HttpStatus.OK).send(); } @@ -140,7 +137,7 @@ export class LectureController { throw new HttpException('로그인 되지 않은 사용자입니다.', HttpStatus.UNAUTHORIZED); } - const result = await this.userService.findLectureList(req.user.email); + const result = await this.lectureService.findLectureList(req.user.email); return res.status(HttpStatus.OK).send(result); } } diff --git a/backend/src/lecture/lecture.module.ts b/backend/src/lecture/lecture.module.ts index 02d7895..7b1f923 100644 --- a/backend/src/lecture/lecture.module.ts +++ b/backend/src/lecture/lecture.module.ts @@ -19,10 +19,9 @@ import { JwtModule } from '@nestjs/jwt'; { name: WhiteboardLog.name, schema: WhiteboardLogSchema }, { name: LectureSubtitle.name, schema: LectureSubtitleSchema } ]), - JwtModule + JwtModule, ], controllers: [LectureController], - providers: [LectureService, UserService], - exports: [LectureService, MongooseModule] + providers: [LectureService, UserService] }) export class LectureModule {} diff --git a/backend/src/lecture/lecture.service.ts b/backend/src/lecture/lecture.service.ts index 00a2389..ace0337 100644 --- a/backend/src/lecture/lecture.service.ts +++ b/backend/src/lecture/lecture.service.ts @@ -10,6 +10,7 @@ import { Lecture } from './schema/lecture.schema'; import { EnterCode } from './schema/lecture-code.schema'; import { generateRandomNumber } from 'src/utils/GenerateUtils'; import { LectureRecordDto } from './dto/response/response-lecture-record.dto'; +import { UserService } from 'src/user/user.service'; @Injectable() export class LectureService { @@ -21,14 +22,16 @@ export class LectureService { @InjectModel(WhiteboardLog.name) private whiteboardLogModel: Model, @InjectModel(LectureSubtitle.name) - private lectureSubtitleModel: Model + private lectureSubtitleModel: Model, + private readonly userService: UserService ) {} - async createLecture(createLectureDto: CreateLectureDto, id: Types.ObjectId) { + async createLecture(createLectureDto: CreateLectureDto, email: string) { + const user = await this.userService.findOneByEmail(email); const lecture = new this.lectureModel({ title: createLectureDto.title, description: createLectureDto.description, - presenter_id: id + presenter_id: user._id }); const lectureCode = new this.enterCodeModel({ code: await this.generateRoomCode(), @@ -103,4 +106,13 @@ export class LectureService { const audioFile = lecture.audio_file; return new LectureRecordDto(logs, subtitles, audioFile); } + + async updateLecture(email: string, enterCode: EnterCode) { + const lecture = await this.findLectureInfo(enterCode); + return await this.userService.updateLectureList(email, lecture.id); + } + + async findLectureList(email: string) { + return await this.userService.findLectureList(email); + } } diff --git a/backend/src/user/user.module.ts b/backend/src/user/user.module.ts index 8bbc303..0f4ce8a 100644 --- a/backend/src/user/user.module.ts +++ b/backend/src/user/user.module.ts @@ -4,24 +4,18 @@ import { User, UserSchema } from './user.schema'; import { UserController } from './user.controller'; import { UserService } from './user.service'; import { JwtModule } from '@nestjs/jwt'; -import { LectureService } from 'src/lecture/lecture.service'; -import { Lecture, LectureSchema } from 'src/lecture/schema/lecture.schema'; -import { EnterCode, EnterCodeSchema } from 'src/lecture/schema/lecture-code.schema'; -import { WhiteboardLog, WhiteboardLogSchema } from 'src/lecture/schema/whiteboard-log.schema'; -import { LectureSubtitle, LectureSubtitleSchema } from 'src/lecture/lecture-subtitle.schema'; +import { LectureModule } from 'src/lecture/lecture.module'; @Module({ imports: [ MongooseModule.forFeature([ { name: User.name, schema: UserSchema }, - { name: Lecture.name, schema: LectureSchema }, - { name: EnterCode.name, schema: EnterCodeSchema }, - { name: WhiteboardLog.name, schema: WhiteboardLogSchema }, - { name: LectureSubtitle.name, schema: LectureSubtitleSchema } ]), - JwtModule + JwtModule, + LectureModule ], controllers: [UserController], - providers: [UserService, LectureService] + providers: [UserService], + exports: [UserModule] }) export class UserModule {} diff --git a/backend/src/user/user.service.ts b/backend/src/user/user.service.ts index 3960fa8..9fd9def 100644 --- a/backend/src/user/user.service.ts +++ b/backend/src/user/user.service.ts @@ -1,15 +1,12 @@ import { Injectable } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; import { User, UserDocument } from './user.schema'; -import { Model } from 'mongoose'; -import { LectureService } from 'src/lecture/lecture.service'; -import { EnterCode } from 'src/lecture/schema/lecture-code.schema'; +import { Model, Types } from 'mongoose'; @Injectable() export class UserService { constructor( - @InjectModel(User.name) private userModel: Model, - private lectureService: LectureService + @InjectModel(User.name) private userModel: Model ) {} async findOneByEmail(email: string): Promise { @@ -20,15 +17,6 @@ export class UserService { return await this.userModel.findOneAndUpdate({ email: email }, { username: username }, { new: true }); } - async updateLecture(email: string, enterCode: EnterCode) { - const lecture = await this.lectureService.findLectureInfo(enterCode); - return await this.userModel.findOneAndUpdate( - { email: email }, - { $push: { lecture_id: lecture.id } }, - { new: true } - ); - } - async findLectureList(email: string) { return ( await ( @@ -41,4 +29,12 @@ export class UserService { }) ).lecture_id; } + + async updateLectureList(email: string, id: Types.ObjectId) { + return await this.userModel.findOneAndUpdate( + { email: email }, + { $push: { lecture_id: id } }, + { new: true } + ); + } } From 57ab619ddbfabc450ea4bd7c7843fd4a657a42ec Mon Sep 17 00:00:00 2001 From: tmddus2 Date: Fri, 15 Mar 2024 01:02:03 +0900 Subject: [PATCH 2/5] =?UTF-8?q?refactor:=20service=EB=8B=A8=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/user/user.controller.ts | 8 -------- backend/src/user/user.service.ts | 10 +++++++++- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/backend/src/user/user.controller.ts b/backend/src/user/user.controller.ts index e66fe70..d14cb22 100644 --- a/backend/src/user/user.controller.ts +++ b/backend/src/user/user.controller.ts @@ -20,10 +20,6 @@ export class UserController { throw new HttpException('로그인 되지 않은 사용자입니다.', HttpStatus.UNAUTHORIZED); } const userInfo = await this.userService.findOneByEmail(req.user.email); - - if (!userInfo) { - throw new HttpException('사용자 정보가 존재하지 않습니다.', HttpStatus.NOT_FOUND); - } res.status(HttpStatus.OK).send(new UserInfoDto(userInfo)); } @@ -39,10 +35,6 @@ export class UserController { throw new HttpException('로그인 되지 않은 사용자입니다.', HttpStatus.UNAUTHORIZED); } const result = await this.userService.updateUsername(req.user.email, userUpdateDto.username); - if (!result) { - res.status(HttpStatus.NOT_FOUND).send(); - throw new HttpException('업데이트에 실패했습니다.', HttpStatus.NOT_FOUND); - } res.status(HttpStatus.OK).send(new UserInfoDto(result)); } } diff --git a/backend/src/user/user.service.ts b/backend/src/user/user.service.ts index 9fd9def..f130694 100644 --- a/backend/src/user/user.service.ts +++ b/backend/src/user/user.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, NotFoundException } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; import { User, UserDocument } from './user.schema'; import { Model, Types } from 'mongoose'; @@ -10,10 +10,18 @@ export class UserService { ) {} async findOneByEmail(email: string): Promise { + const user = await this.userModel.findOne({ email: email }); + if (!user) { + throw new NotFoundException(' ʽϴ.'); + } return await this.userModel.findOne({ email: email }); } async updateUsername(email: string, username: string) { + const user = await this.userModel.findOneAndUpdate({ email: email }, { username: username }, { new: true }); + if (!user) { + throw new NotFoundException('Ʈ ߽ϴ.'); + } return await this.userModel.findOneAndUpdate({ email: email }, { username: username }, { new: true }); } From 6d3668138a0858cc1aa09986bdbbb1911521ddd4 Mon Sep 17 00:00:00 2001 From: tmddus2 Date: Fri, 15 Mar 2024 03:19:45 +0900 Subject: [PATCH 3/5] =?UTF-8?q?test:=20UserService=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EB=B0=9C=EC=83=9D=ED=95=98=EB=8A=94=20=EC=97=90=EB=9F=AC?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EB=B6=80=EB=B6=84=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/user/user.service.spec.ts | 70 +++++++++++++++++++++++++++ backend/src/user/user.service.ts | 28 ++++++----- 2 files changed, 85 insertions(+), 13 deletions(-) create mode 100644 backend/src/user/user.service.spec.ts diff --git a/backend/src/user/user.service.spec.ts b/backend/src/user/user.service.spec.ts new file mode 100644 index 0000000..86287fd --- /dev/null +++ b/backend/src/user/user.service.spec.ts @@ -0,0 +1,70 @@ +import { Test } from '@nestjs/testing'; +import { UserService } from './user.service'; +import { getModelToken } from '@nestjs/mongoose'; +import { User } from './user.schema'; +import { Model, Types } from 'mongoose'; +import { NotFoundException } from '@nestjs/common'; + + +describe('UserModule', () => { + let service: UserService; + let model: Model; + beforeAll(async () => { + const module = await Test.createTestingModule({ + providers: [UserService, + { + provide: getModelToken(User.name), + useValue: Model + } + ] + }).compile(); + + service = module.get(UserService); + model = module.get>(getModelToken(User.name)); + }); + + it('should have UserService', () => { + expect(service).toBeDefined(); + }); + + describe('findOneByEmail', () => { + const email = "test@gmail.com"; + + it('should throw NotFoundException', async () => { + jest.spyOn(model, 'findOne').mockResolvedValue(null); + await expect(service.findOneByEmail(email)).rejects.toThrow(NotFoundException); + }) + + it('should find user', async () => { + jest.spyOn(model, 'findOne').mockResolvedValue({ + email: email + }); + const user = await service.findOneByEmail(email); + await expect(service.findOneByEmail(email)).resolves.toEqual({email: email}); + }) + }); + + describe('updateUsername', () => { + const email = "test@gmail.com"; + const username = "testname"; + + it('should throw NotFoundException', async () => { + jest.spyOn(model, 'findOneAndUpdate').mockResolvedValue(null); + await expect(service.updateUsername(email, username)).rejects.toThrow(NotFoundException); + }) + }); + + describe('findLectureList', () => { + + }); + + describe('updateLectureList', () => { + const email = 'test@gmail.com'; + const id = new Types.ObjectId(); + + it('should throw NotFoundException', async () => { + jest.spyOn(model, 'findOneAndUpdate').mockResolvedValue(null); + await expect(service.updateLectureList(email, id)).rejects.toThrow(NotFoundException); + }) + }); +}); \ No newline at end of file diff --git a/backend/src/user/user.service.ts b/backend/src/user/user.service.ts index f130694..e61b441 100644 --- a/backend/src/user/user.service.ts +++ b/backend/src/user/user.service.ts @@ -20,29 +20,31 @@ export class UserService { async updateUsername(email: string, username: string) { const user = await this.userModel.findOneAndUpdate({ email: email }, { username: username }, { new: true }); if (!user) { - throw new NotFoundException('Ʈ ߽ϴ.'); + throw new NotFoundException(' ʽϴ.'); } - return await this.userModel.findOneAndUpdate({ email: email }, { username: username }, { new: true }); + return user; } async findLectureList(email: string) { - return ( - await ( - await this.findOneByEmail(email) - ).populate({ - path: 'lecture_id', - select: '-__v', - match: { is_end: true }, - populate: { path: 'presenter_id', select: '-_id username' } - }) - ).lecture_id; + let user = await this.findOneByEmail(email); + user = await user.populate({ + path: 'lecture_id', + select: '-__v', + match: { is_end: true }, + populate: { path: 'presenter_id', select: '-_id username' } + }); + return user.lecture_id; } async updateLectureList(email: string, id: Types.ObjectId) { - return await this.userModel.findOneAndUpdate( + const user = await this.userModel.findOneAndUpdate( { email: email }, { $push: { lecture_id: id } }, { new: true } ); + if (!user) { + throw new NotFoundException(' ʽϴ.'); + } + return user; } } From 4395cf336fab8739671344edfb10613890d61dad Mon Sep 17 00:00:00 2001 From: tmddus2 Date: Tue, 19 Mar 2024 00:15:44 +0900 Subject: [PATCH 4/5] =?UTF-8?q?test:=20UserService=20=EB=8B=A8=EC=9C=84?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/package-lock.json | 14 +++++------ backend/package.json | 5 +++- backend/src/user/user.service.spec.ts | 34 ++++++++++++++++++++++++++- backend/src/user/user.service.ts | 2 +- 4 files changed, 45 insertions(+), 10 deletions(-) diff --git a/backend/package-lock.json b/backend/package-lock.json index 3ab43fd..f5f008b 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -33,7 +33,7 @@ "devDependencies": { "@nestjs/cli": "^10.0.0", "@nestjs/schematics": "^10.0.0", - "@nestjs/testing": "^10.0.0", + "@nestjs/testing": "^10.3.3", "@types/cookie-parser": "^1.4.6", "@types/express": "^4.17.17", "@types/jest": "^29.5.2", @@ -1893,9 +1893,9 @@ } }, "node_modules/@nestjs/testing": { - "version": "10.2.8", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.2.8.tgz", - "integrity": "sha512-9Kj5IQhM67/nj/MT6Wi2OmWr5YQnCMptwKVFrX1TDaikpY12196v7frk0jVjdT7wms7rV07GZle9I2z0aSjqtQ==", + "version": "10.3.3", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.3.3.tgz", + "integrity": "sha512-kX20GfjAImL5grd/i69uD/x7sc00BaqGcP2dRG3ilqshQUuy5DOmspLCr3a2C8xmVU7kzK4spT0oTxhe6WcCAA==", "dev": true, "dependencies": { "tslib": "2.6.2" @@ -12661,9 +12661,9 @@ } }, "@nestjs/testing": { - "version": "10.2.8", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.2.8.tgz", - "integrity": "sha512-9Kj5IQhM67/nj/MT6Wi2OmWr5YQnCMptwKVFrX1TDaikpY12196v7frk0jVjdT7wms7rV07GZle9I2z0aSjqtQ==", + "version": "10.3.3", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.3.3.tgz", + "integrity": "sha512-kX20GfjAImL5grd/i69uD/x7sc00BaqGcP2dRG3ilqshQUuy5DOmspLCr3a2C8xmVU7kzK4spT0oTxhe6WcCAA==", "dev": true, "requires": { "tslib": "2.6.2" diff --git a/backend/package.json b/backend/package.json index f35aa3c..05bd60e 100644 --- a/backend/package.json +++ b/backend/package.json @@ -44,7 +44,7 @@ "devDependencies": { "@nestjs/cli": "^10.0.0", "@nestjs/schematics": "^10.0.0", - "@nestjs/testing": "^10.0.0", + "@nestjs/testing": "^10.3.3", "@types/cookie-parser": "^1.4.6", "@types/express": "^4.17.17", "@types/jest": "^29.5.2", @@ -74,6 +74,9 @@ "ts" ], "rootDir": "src", + "modulePaths": [ + "/.." + ], "testRegex": ".*\\.spec\\.ts$", "transform": { "^.+\\.(t|j)s$": "ts-jest" diff --git a/backend/src/user/user.service.spec.ts b/backend/src/user/user.service.spec.ts index 86287fd..c45ca61 100644 --- a/backend/src/user/user.service.spec.ts +++ b/backend/src/user/user.service.spec.ts @@ -28,6 +28,7 @@ describe('UserModule', () => { }); describe('findOneByEmail', () => { + const id = new Types.ObjectId(); const email = "test@gmail.com"; it('should throw NotFoundException', async () => { @@ -37,14 +38,17 @@ describe('UserModule', () => { it('should find user', async () => { jest.spyOn(model, 'findOne').mockResolvedValue({ + _id: id, email: email }); const user = await service.findOneByEmail(email); - await expect(service.findOneByEmail(email)).resolves.toEqual({email: email}); + expect(user._id).toEqual(id); + expect(user.email).toEqual(email); }) }); describe('updateUsername', () => { + const id = new Types.ObjectId(); const email = "test@gmail.com"; const username = "testname"; @@ -52,10 +56,27 @@ describe('UserModule', () => { jest.spyOn(model, 'findOneAndUpdate').mockResolvedValue(null); await expect(service.updateUsername(email, username)).rejects.toThrow(NotFoundException); }) + + it('should update username', async () => { + jest.spyOn(model, 'findOneAndUpdate').mockResolvedValue({ + _id: id, + email: email, + username: username + }); + + const user = await service.updateUsername(email, username); + expect(user.username).toEqual(username); + }) }); + describe('findLectureList', () => { + const email = "test@gmail.com"; + it('should throw NotFoundException', async () => { + jest.spyOn(model, 'findOne').mockResolvedValue(null); + await expect(service.findLectureList(email)).rejects.toThrow(NotFoundException); + }) }); describe('updateLectureList', () => { @@ -66,5 +87,16 @@ describe('UserModule', () => { jest.spyOn(model, 'findOneAndUpdate').mockResolvedValue(null); await expect(service.updateLectureList(email, id)).rejects.toThrow(NotFoundException); }) + + it('should call with', async () => { + const findOneAndUpdateMock = jest.spyOn(model, 'findOneAndUpdate').mockResolvedValue({}); + + await service.updateLectureList(email, id); + expect(findOneAndUpdateMock).toHaveBeenCalledWith( + { email: email }, + { $push: { lecture_id: id } }, + { new: true } + ); + }) }); }); \ No newline at end of file diff --git a/backend/src/user/user.service.ts b/backend/src/user/user.service.ts index e61b441..022ad42 100644 --- a/backend/src/user/user.service.ts +++ b/backend/src/user/user.service.ts @@ -14,7 +14,7 @@ export class UserService { if (!user) { throw new NotFoundException(' ʽϴ.'); } - return await this.userModel.findOne({ email: email }); + return user; } async updateUsername(email: string, username: string) { From 5f0edd7fec9ab5f22a2e074f9c3b18e2e08de499 Mon Sep 17 00:00:00 2001 From: tmddus2 Date: Tue, 19 Mar 2024 22:39:56 +0900 Subject: [PATCH 5/5] =?UTF-8?q?chore:=20=EC=97=90=EB=9F=AC=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=80=20=EC=98=81=EC=96=B4=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/user/user.service.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/user/user.service.ts b/backend/src/user/user.service.ts index 022ad42..1d4c761 100644 --- a/backend/src/user/user.service.ts +++ b/backend/src/user/user.service.ts @@ -12,7 +12,7 @@ export class UserService { async findOneByEmail(email: string): Promise { const user = await this.userModel.findOne({ email: email }); if (!user) { - throw new NotFoundException(' ʽϴ.'); + throw new NotFoundException('user not found'); } return user; } @@ -20,7 +20,7 @@ export class UserService { async updateUsername(email: string, username: string) { const user = await this.userModel.findOneAndUpdate({ email: email }, { username: username }, { new: true }); if (!user) { - throw new NotFoundException(' ʽϴ.'); + throw new NotFoundException('user not found'); } return user; } @@ -43,7 +43,7 @@ export class UserService { { new: true } ); if (!user) { - throw new NotFoundException(' ʽϴ.'); + throw new NotFoundException('user not found'); } return user; }