From 4097d4e64aad6c2793ab40175e415d648d1f06ec Mon Sep 17 00:00:00 2001 From: Conut-1 <1mim1@naver.com> Date: Fri, 20 Dec 2024 18:25:40 +0900 Subject: [PATCH 01/18] =?UTF-8?q?feat:=20=EC=9D=B8=EA=B0=80=20=EA=B3=BC?= =?UTF-8?q?=EC=A0=95=20=EA=B0=80=EB=93=9C=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/src/spaces/spaces.controller.ts | 26 ++++++++++--------- nestjs-BE/server/src/spaces/spaces.service.ts | 12 +-------- 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/nestjs-BE/server/src/spaces/spaces.controller.ts b/nestjs-BE/server/src/spaces/spaces.controller.ts index 1861ef8d..ecb0f3ad 100644 --- a/nestjs-BE/server/src/spaces/spaces.controller.ts +++ b/nestjs-BE/server/src/spaces/spaces.controller.ts @@ -13,14 +13,17 @@ import { Query, BadRequestException, Delete, + UseGuards, } from '@nestjs/common'; import { FileInterceptor } from '@nestjs/platform-express'; -import { ApiTags, ApiResponse, ApiOperation } from '@nestjs/swagger'; +import { ApiTags, ApiResponse, ApiOperation, ApiQuery } from '@nestjs/swagger'; import { SpacesService } from './spaces.service'; import { CreateSpaceRequestDto } from './dto/create-space.dto'; import { UpdateSpaceRequestDto } from './dto/update-space.dto'; import { JoinSpaceRequestDto } from './dto/join-space.dto'; import { User } from '../auth/decorators/user.decorator'; +import { IsProfileInSpaceGuard } from '../auth/guards/is-profile-in-space.guard'; +import { MatchUserProfileGuard } from '../auth/guards/match-user-profile.guard'; @Controller('spaces') @ApiTags('spaces') @@ -73,8 +76,16 @@ export class SpacesController { } @Get(':space_uuid') + @UseGuards(MatchUserProfileGuard) + @UseGuards(IsProfileInSpaceGuard) @Header('Cache-Control', 'no-store') @ApiOperation({ summary: 'Get space by space uuid' }) + @ApiQuery({ + name: 'profile_uuid', + type: String, + description: 'profile uuid', + required: true, + }) @ApiResponse({ status: HttpStatus.OK, description: 'Return the space data.', @@ -95,17 +106,8 @@ export class SpacesController { status: HttpStatus.NOT_FOUND, description: 'Space not found. Profile not found', }) - async findSpace( - @Param('space_uuid') spaceUuid: string, - @Query('profile_uuid') profileUuid: string, - @User('uuid') userUuid: string, - ) { - if (!profileUuid) throw new BadRequestException(); - const space = await this.spacesService.findSpace( - userUuid, - profileUuid, - spaceUuid, - ); + async findSpace(@Param('space_uuid') spaceUuid: string) { + const space = await this.spacesService.findSpace(spaceUuid); return { statusCode: HttpStatus.OK, message: 'OK', data: space }; } diff --git a/nestjs-BE/server/src/spaces/spaces.service.ts b/nestjs-BE/server/src/spaces/spaces.service.ts index 5f48798a..43ca3ac5 100644 --- a/nestjs-BE/server/src/spaces/spaces.service.ts +++ b/nestjs-BE/server/src/spaces/spaces.service.ts @@ -28,19 +28,9 @@ export class SpacesService { return this.prisma.space.findUnique({ where: { uuid: spaceUuid } }); } - async findSpace( - userUuid: string, - profileUuid: string, - spaceUuid: string, - ): Promise { - await this.profilesService.verifyUserProfile(userUuid, profileUuid); + async findSpace(spaceUuid: string): Promise { const space = await this.findSpaceBySpaceUuid(spaceUuid); if (!space) throw new NotFoundException(); - const isProfileInSpace = await this.profileSpaceService.isProfileInSpace( - profileUuid, - spaceUuid, - ); - if (!isProfileInSpace) throw new ForbiddenException(); return space; } From d8bfa7bca2c41e22ba442034d36fe8fb48ac9c61 Mon Sep 17 00:00:00 2001 From: Conut-1 <1mim1@naver.com> Date: Fri, 20 Dec 2024 18:43:02 +0900 Subject: [PATCH 02/18] =?UTF-8?q?fix:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nestjs-BE/server/test/spaces.e2e-spec.ts | 95 ++++++++++++++++-------- 1 file changed, 64 insertions(+), 31 deletions(-) diff --git a/nestjs-BE/server/test/spaces.e2e-spec.ts b/nestjs-BE/server/test/spaces.e2e-spec.ts index 3bb19f31..190c3983 100644 --- a/nestjs-BE/server/test/spaces.e2e-spec.ts +++ b/nestjs-BE/server/test/spaces.e2e-spec.ts @@ -1,7 +1,7 @@ import { HttpStatus, INestApplication } from '@nestjs/common'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { Test, TestingModule } from '@nestjs/testing'; -import { Profile, Space } from '@prisma/client'; +import { Profile, Space, User } from '@prisma/client'; import * as request from 'supertest'; import { sign } from 'jsonwebtoken'; import { v4 as uuid } from 'uuid'; @@ -219,11 +219,39 @@ describe('SpacesController (e2e)', () => { }); describe('/spaces/:space_uuid?profile_uuid={profile_uuid} (GET)', () => { - it('space found', async () => { + let testUser: User; + let testSpace: Space; + let testProfile: Profile; + let testToken: string; + + beforeEach(async () => { + testUser = await prisma.user.create({ data: { uuid: uuid() } }); + testProfile = await prisma.profile.create({ + data: { + uuid: uuid(), + userUuid: testUser.uuid, + image: 'test image', + nickname: 'test nickname', + }, + }); + testSpace = await prisma.space.create({ + data: { + uuid: uuid(), + name: 'test space', + icon: configService.get('APP_ICON_URL'), + }, + }); await prisma.profileSpace.create({ data: { spaceUuid: testSpace.uuid, profileUuid: testProfile.uuid }, }); + testToken = sign( + { sub: testUser.uuid }, + configService.get('JWT_ACCESS_SECRET'), + { expiresIn: '5m' }, + ); + }); + it('respond ok if space found', async () => { return request(app.getHttpServer()) .get(`/spaces/${testSpace.uuid}?profile_uuid=${testProfile.uuid}`) .auth(testToken, { type: 'bearer' }) @@ -235,7 +263,7 @@ describe('SpacesController (e2e)', () => { }); }); - it('query profile_uuid needed', async () => { + it('respond bad request if query profile_uuid needed', async () => { return request(app.getHttpServer()) .get(`/spaces/${testSpace.uuid}`) .auth(testToken, { type: 'bearer' }) @@ -243,11 +271,7 @@ describe('SpacesController (e2e)', () => { .expect({ message: 'Bad Request', statusCode: HttpStatus.BAD_REQUEST }); }); - it('user not logged in', async () => { - await prisma.profileSpace.create({ - data: { spaceUuid: testSpace.uuid, profileUuid: testProfile.uuid }, - }); - + it('respond unauthorized if user is not logged in', async () => { return request(app.getHttpServer()) .get(`/spaces/${testSpace.uuid}?profile_uuid=${testProfile.uuid}`) .expect(HttpStatus.UNAUTHORIZED) @@ -257,49 +281,58 @@ describe('SpacesController (e2e)', () => { }); }); - it("profile user doesn't have", async () => { + it('respond forbidden if user does not have profile', async () => { const newUser = await prisma.user.create({ data: { uuid: uuid() } }); - const newProfile = await prisma.profile.create({ - data: { - uuid: uuid(), - userUuid: newUser.uuid, - image: 'test image', - nickname: 'test nickname', - }, - }); - await prisma.profileSpace.create({ - data: { spaceUuid: testSpace.uuid, profileUuid: newProfile.uuid }, - }); + const newToken = sign( + { sub: newUser.uuid }, + configService.get('JWT_ACCESS_SECRET'), + { expiresIn: '5m' }, + ); return request(app.getHttpServer()) - .get(`/spaces/${testSpace.uuid}?profile_uuid=${newProfile.uuid}`) - .auth(testToken, { type: 'bearer' }) + .get(`/spaces/${testSpace.uuid}?profile_uuid=${testProfile.uuid}`) + .auth(newToken, { type: 'bearer' }) .expect(HttpStatus.FORBIDDEN) .expect({ message: 'Forbidden', statusCode: HttpStatus.FORBIDDEN }); }); - it('profile not existing', async () => { + it('respond forbidden if profile does not exist', async () => { return request(app.getHttpServer()) .get(`/spaces/${testSpace.uuid}?profile_uuid=${uuid()}`) .auth(testToken, { type: 'bearer' }) - .expect(HttpStatus.NOT_FOUND) - .expect({ message: 'Not Found', statusCode: HttpStatus.NOT_FOUND }); + .expect(HttpStatus.FORBIDDEN) + .expect({ message: 'Forbidden', statusCode: HttpStatus.FORBIDDEN }); }); - it('findOne profile not joined space', () => { + it('respond forbidden if profile does not join space', async () => { + const newUser = await prisma.user.create({ data: { uuid: uuid() } }); + const newProfile = await prisma.profile.create({ + data: { + uuid: uuid(), + userUuid: newUser.uuid, + image: 'test image', + nickname: 'test nickname', + }, + }); + const newToken = sign( + { sub: newUser.uuid }, + configService.get('JWT_ACCESS_SECRET'), + { expiresIn: '5m' }, + ); + return request(app.getHttpServer()) - .get(`/spaces/${testSpace.uuid}?profile_uuid=${testProfile.uuid}`) - .auth(testToken, { type: 'bearer' }) + .get(`/spaces/${testSpace.uuid}?profile_uuid=${newProfile.uuid}`) + .auth(newToken, { type: 'bearer' }) .expect(HttpStatus.FORBIDDEN) .expect({ message: 'Forbidden', statusCode: HttpStatus.FORBIDDEN }); }); - it('not existing space', () => { + it('respond forbidden if space does not exist', () => { return request(app.getHttpServer()) .get(`/spaces/${uuid()}?profile_uuid=${testProfile.uuid}`) .auth(testToken, { type: 'bearer' }) - .expect(HttpStatus.NOT_FOUND) - .expect({ message: 'Not Found', statusCode: HttpStatus.NOT_FOUND }); + .expect(HttpStatus.FORBIDDEN) + .expect({ message: 'Forbidden', statusCode: HttpStatus.FORBIDDEN }); }); }); From 32f90505f85bb3ce54091b73dc07b53279f75a47 Mon Sep 17 00:00:00 2001 From: Conut-1 <1mim1@naver.com> Date: Fri, 20 Dec 2024 18:43:29 +0900 Subject: [PATCH 03/18] =?UTF-8?q?fix:=20=EC=BF=BC=EB=A6=AC=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nestjs-BE/server/src/auth/guards/match-user-profile.guard.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nestjs-BE/server/src/auth/guards/match-user-profile.guard.ts b/nestjs-BE/server/src/auth/guards/match-user-profile.guard.ts index 6773a13f..fd7db737 100644 --- a/nestjs-BE/server/src/auth/guards/match-user-profile.guard.ts +++ b/nestjs-BE/server/src/auth/guards/match-user-profile.guard.ts @@ -14,7 +14,7 @@ export class MatchUserProfileGuard implements CanActivate { async canActivate(context: ExecutionContext): Promise { const request = context.switchToHttp().getRequest(); const userUuid = request.user.uuid; - const profileUuid = request.body.profile_uuid || request.query.profileUuid; + const profileUuid = request.body.profile_uuid || request.query.profile_uuid; if (!profileUuid || !userUuid) throw new BadRequestException(); const profile = await this.profilesService.findProfileByProfileUuid(profileUuid); From 877e9e50ef38460c19381a025f3da8f29d993ecc Mon Sep 17 00:00:00 2001 From: Conut-1 <1mim1@naver.com> Date: Sun, 22 Dec 2024 23:11:06 +0900 Subject: [PATCH 04/18] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/spaces/spaces.controller.spec.ts | 56 ++++++++++-------- .../server/src/spaces/spaces.service.spec.ts | 59 +------------------ 2 files changed, 33 insertions(+), 82 deletions(-) diff --git a/nestjs-BE/server/src/spaces/spaces.controller.spec.ts b/nestjs-BE/server/src/spaces/spaces.controller.spec.ts index 17d8c9d9..61e5d9a9 100644 --- a/nestjs-BE/server/src/spaces/spaces.controller.spec.ts +++ b/nestjs-BE/server/src/spaces/spaces.controller.spec.ts @@ -1,10 +1,18 @@ -import { BadRequestException, HttpStatus } from '@nestjs/common'; +import { + BadRequestException, + HttpStatus, + NotFoundException, +} from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; import { Profile, Space } from '@prisma/client'; import { SpacesController } from './spaces.controller'; import { SpacesService } from './spaces.service'; import { UpdateSpaceRequestDto } from './dto/update-space.dto'; import { CreateSpaceRequestDto } from './dto/create-space.dto'; +import { MatchUserProfileGuard } from '../auth/guards/match-user-profile.guard'; +import { IsProfileInSpaceGuard } from '../auth/guards/is-profile-in-space.guard'; +import { ProfilesService } from '../profiles/profiles.service'; +import { ProfileSpaceService } from '../profile-space/profile-space.service'; describe('SpacesController', () => { let controller: SpacesController; @@ -18,13 +26,16 @@ describe('SpacesController', () => { provide: SpacesService, useValue: { createSpace: jest.fn(), - findSpace: jest.fn(), updateSpace: jest.fn(), joinSpace: jest.fn(), leaveSpace: jest.fn(), findProfilesInSpace: jest.fn(), }, }, + { provide: ProfilesService, useValue: {} }, + { provide: ProfileSpaceService, useValue: {} }, + MatchUserProfileGuard, + IsProfileInSpaceGuard, ], }).compile(); @@ -78,37 +89,32 @@ describe('SpacesController', () => { expect(spacesService.createSpace).not.toHaveBeenCalled(); }); - it('findOne found space', async () => { - const profileUuid = 'profile uuid'; + describe('findOne', () => { const spaceMock = { uuid: 'space uuid' } as Space; - const userUuidMock = 'user uuid'; - (spacesService.findSpace as jest.Mock).mockResolvedValue(spaceMock); + beforeEach(() => { + spacesService.findSpace = jest.fn(async () => spaceMock); + }); - const response = controller.findSpace( - spaceMock.uuid, - profileUuid, - userUuidMock, - ); + it('found space', async () => { + const response = controller.findSpace(spaceMock.uuid); - await expect(response).resolves.toEqual({ - statusCode: HttpStatus.OK, - message: 'OK', - data: spaceMock, + await expect(response).resolves.toEqual({ + statusCode: HttpStatus.OK, + message: 'OK', + data: spaceMock, + }); }); - }); - it('findOne profile_uuid missing', async () => { - const spaceMock = { uuid: 'space uuid' } as Space; - const userUuidMock = 'user uuid'; + it('space not found', async () => { + (spacesService.findSpace as jest.Mock).mockRejectedValue( + new NotFoundException(), + ); - const response = controller.findSpace( - spaceMock.uuid, - undefined, - userUuidMock, - ); + const response = controller.findSpace(spaceMock.uuid); - await expect(response).rejects.toThrow(BadRequestException); + await expect(response).rejects.toThrow(NotFoundException); + }); }); it('updateSpace update space', async () => { diff --git a/nestjs-BE/server/src/spaces/spaces.service.spec.ts b/nestjs-BE/server/src/spaces/spaces.service.spec.ts index 40251892..c57f9b3a 100644 --- a/nestjs-BE/server/src/spaces/spaces.service.spec.ts +++ b/nestjs-BE/server/src/spaces/spaces.service.spec.ts @@ -64,8 +64,6 @@ describe('SpacesService', () => { }); describe('findSpace', () => { - const userUuid = 'user uuid'; - const profileUuid = 'profile uuid'; const spaceMock = { uuid: 'space uuid' } as Space; beforeEach(() => { @@ -75,68 +73,15 @@ describe('SpacesService', () => { }); it('found space', async () => { - const space = spacesService.findSpace( - userUuid, - profileUuid, - spaceMock.uuid, - ); + const space = spacesService.findSpace(spaceMock.uuid); await expect(space).resolves.toEqual(spaceMock); }); - it('profile user not own', async () => { - (profilesService.verifyUserProfile as jest.Mock).mockRejectedValue( - new ForbiddenException(), - ); - - const space = spacesService.findSpace( - userUuid, - profileUuid, - spaceMock.uuid, - ); - - await expect(space).rejects.toThrow(ForbiddenException); - expect(spacesService.findSpaceBySpaceUuid).not.toHaveBeenCalled(); - }); - - it('profile not joined space', async () => { - (profileSpaceService.isProfileInSpace as jest.Mock).mockResolvedValue( - false, - ); - - const space = spacesService.findSpace( - userUuid, - profileUuid, - spaceMock.uuid, - ); - - await expect(space).rejects.toThrow(ForbiddenException); - expect(profileSpaceService.isProfileInSpace).toHaveBeenCalled(); - }); - it('space not found', async () => { jest.spyOn(spacesService, 'findSpaceBySpaceUuid').mockResolvedValue(null); - const space = spacesService.findSpace( - userUuid, - profileUuid, - spaceMock.uuid, - ); - - await expect(space).rejects.toThrow(NotFoundException); - expect(profileSpaceService.isProfileInSpace).not.toHaveBeenCalled(); - }); - - it('profile not found', async () => { - (profilesService.verifyUserProfile as jest.Mock).mockRejectedValue( - new NotFoundException(), - ); - - const space = spacesService.findSpace( - userUuid, - profileUuid, - spaceMock.uuid, - ); + const space = spacesService.findSpace(spaceMock.uuid); await expect(space).rejects.toThrow(NotFoundException); }); From 4ad64877ee87d231fc39564385b0b2dec9aee2fd Mon Sep 17 00:00:00 2001 From: Conut-1 <1mim1@naver.com> Date: Sun, 22 Dec 2024 23:48:49 +0900 Subject: [PATCH 05/18] =?UTF-8?q?feat:=20createSpace=EC=97=90=20=EA=B0=80?= =?UTF-8?q?=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 --- .../server/src/spaces/dto/create-space.dto.ts | 13 ++++++------- nestjs-BE/server/src/spaces/spaces.controller.ts | 14 ++++---------- nestjs-BE/server/src/spaces/spaces.service.ts | 12 ++++++------ 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/nestjs-BE/server/src/spaces/dto/create-space.dto.ts b/nestjs-BE/server/src/spaces/dto/create-space.dto.ts index 703bdfdf..0e4fd495 100644 --- a/nestjs-BE/server/src/spaces/dto/create-space.dto.ts +++ b/nestjs-BE/server/src/spaces/dto/create-space.dto.ts @@ -4,7 +4,7 @@ import { Expose } from 'class-transformer'; import { v4 as uuid } from 'uuid'; import { MAX_NAME_LENGTH } from '../../config/constants'; -export class CreateSpaceRequestDto { +export class CreateSpaceDto { @IsString() @IsNotEmpty() @MaxLength(MAX_NAME_LENGTH) @@ -14,7 +14,11 @@ export class CreateSpaceRequestDto { @IsString() @IsNotEmpty() @Expose({ name: 'profile_uuid' }) - @ApiProperty({ example: uuid(), description: 'Profile uuid' }) + @ApiProperty({ + name: 'profile_uuid', + example: uuid(), + description: 'Profile uuid', + }) profileUuid: string; @ApiProperty({ @@ -23,8 +27,3 @@ export class CreateSpaceRequestDto { }) icon: string; } - -export class CreateSpacePrismaDto { - name: string; - icon: string; -} diff --git a/nestjs-BE/server/src/spaces/spaces.controller.ts b/nestjs-BE/server/src/spaces/spaces.controller.ts index ecb0f3ad..9cb0b01d 100644 --- a/nestjs-BE/server/src/spaces/spaces.controller.ts +++ b/nestjs-BE/server/src/spaces/spaces.controller.ts @@ -18,7 +18,7 @@ import { import { FileInterceptor } from '@nestjs/platform-express'; import { ApiTags, ApiResponse, ApiOperation, ApiQuery } from '@nestjs/swagger'; import { SpacesService } from './spaces.service'; -import { CreateSpaceRequestDto } from './dto/create-space.dto'; +import { CreateSpaceDto } from './dto/create-space.dto'; import { UpdateSpaceRequestDto } from './dto/update-space.dto'; import { JoinSpaceRequestDto } from './dto/join-space.dto'; import { User } from '../auth/decorators/user.decorator'; @@ -31,6 +31,7 @@ export class SpacesController { constructor(private readonly spacesService: SpacesService) {} @Post() + @UseGuards(MatchUserProfileGuard) @UseInterceptors(FileInterceptor('icon')) @ApiOperation({ summary: 'Create space' }) @ApiResponse({ @@ -62,16 +63,9 @@ export class SpacesController { disableErrorMessages: true, }), ) - createSpaceDto: CreateSpaceRequestDto, - @User('uuid') userUuid: string, + createSpaceDto: CreateSpaceDto, ) { - if (!createSpaceDto.profileUuid) throw new BadRequestException(); - const space = await this.spacesService.createSpace( - userUuid, - createSpaceDto.profileUuid, - icon, - createSpaceDto, - ); + const space = await this.spacesService.createSpace(icon, createSpaceDto); return { statusCode: HttpStatus.CREATED, message: 'Created', data: space }; } diff --git a/nestjs-BE/server/src/spaces/spaces.service.ts b/nestjs-BE/server/src/spaces/spaces.service.ts index 43ca3ac5..64eeab04 100644 --- a/nestjs-BE/server/src/spaces/spaces.service.ts +++ b/nestjs-BE/server/src/spaces/spaces.service.ts @@ -8,7 +8,7 @@ import { ConfigService } from '@nestjs/config'; import { Prisma, Profile, Space } from '@prisma/client'; import { v4 as uuid } from 'uuid'; import { UpdateSpacePrismaDto } from './dto/update-space.dto'; -import { CreateSpacePrismaDto } from './dto/create-space.dto'; +import { CreateSpaceDto } from './dto/create-space.dto'; import { PrismaService } from '../prisma/prisma.service'; import { ProfileSpaceService } from '../profile-space/profile-space.service'; import { UploadService } from '../upload/upload.service'; @@ -35,12 +35,9 @@ export class SpacesService { } async createSpace( - userUuid: string, - profileUuid: string, icon: Express.Multer.File, - createSpaceDto: CreateSpacePrismaDto, + createSpaceDto: CreateSpaceDto, ): Promise { - await this.profilesService.verifyUserProfile(userUuid, profileUuid); const iconUrl = icon ? await this.uploadService.uploadFile(icon) : this.configService.get('APP_ICON_URL'); @@ -51,7 +48,10 @@ export class SpacesService { icon: iconUrl, }, }); - await this.profileSpaceService.createProfileSpace(profileUuid, space.uuid); + await this.profileSpaceService.createProfileSpace( + createSpaceDto.profileUuid, + space.uuid, + ); return space; } From 3e9c8119cf54456fbc79292063d94b3e72e23aa8 Mon Sep 17 00:00:00 2001 From: Conut-1 <1mim1@naver.com> Date: Mon, 23 Dec 2024 00:47:34 +0900 Subject: [PATCH 06/18] =?UTF-8?q?test:=20createSpace=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/spaces/spaces.controller.spec.ts | 46 +++++-------- .../server/src/spaces/spaces.service.spec.ts | 64 ++----------------- 2 files changed, 20 insertions(+), 90 deletions(-) diff --git a/nestjs-BE/server/src/spaces/spaces.controller.spec.ts b/nestjs-BE/server/src/spaces/spaces.controller.spec.ts index 61e5d9a9..8225c61a 100644 --- a/nestjs-BE/server/src/spaces/spaces.controller.spec.ts +++ b/nestjs-BE/server/src/spaces/spaces.controller.spec.ts @@ -8,7 +8,7 @@ import { Profile, Space } from '@prisma/client'; import { SpacesController } from './spaces.controller'; import { SpacesService } from './spaces.service'; import { UpdateSpaceRequestDto } from './dto/update-space.dto'; -import { CreateSpaceRequestDto } from './dto/create-space.dto'; +import { CreateSpaceDto } from './dto/create-space.dto'; import { MatchUserProfileGuard } from '../auth/guards/match-user-profile.guard'; import { IsProfileInSpaceGuard } from '../auth/guards/is-profile-in-space.guard'; import { ProfilesService } from '../profiles/profiles.service'; @@ -43,7 +43,7 @@ describe('SpacesController', () => { spacesService = module.get(SpacesService); }); - it('create created', async () => { + describe('createSpace', () => { const iconMock = { filename: 'icon' } as Express.Multer.File; const userUuidMock = 'user uuid'; const profileMock = { @@ -53,40 +53,24 @@ describe('SpacesController', () => { const bodyMock = { name: 'new space name', profileUuid: profileMock.uuid, - } as CreateSpaceRequestDto; + } as CreateSpaceDto; const spaceMock = { uuid: 'space uuid' } as Space; - (spacesService.createSpace as jest.Mock).mockResolvedValue(spaceMock); + it('created', async () => { + (spacesService.createSpace as jest.Mock).mockResolvedValue(spaceMock); - const response = controller.createSpace(iconMock, bodyMock, userUuidMock); + const response = controller.createSpace(iconMock, bodyMock); - await expect(response).resolves.toEqual({ - statusCode: HttpStatus.CREATED, - message: 'Created', - data: spaceMock, + await expect(response).resolves.toEqual({ + statusCode: HttpStatus.CREATED, + message: 'Created', + data: spaceMock, + }); + expect(spacesService.createSpace).toHaveBeenCalledWith( + iconMock, + bodyMock, + ); }); - expect(spacesService.createSpace).toHaveBeenCalledWith( - userUuidMock, - bodyMock.profileUuid, - iconMock, - bodyMock, - ); - }); - - it('create profile uuid needed', async () => { - const userUuidMock = 'user uuid'; - const bodyMock = { - name: 'new space name', - } as CreateSpaceRequestDto; - - const response = controller.createSpace( - undefined as Express.Multer.File, - bodyMock, - userUuidMock, - ); - - await expect(response).rejects.toThrow(BadRequestException); - expect(spacesService.createSpace).not.toHaveBeenCalled(); }); describe('findOne', () => { diff --git a/nestjs-BE/server/src/spaces/spaces.service.spec.ts b/nestjs-BE/server/src/spaces/spaces.service.spec.ts index c57f9b3a..2e266942 100644 --- a/nestjs-BE/server/src/spaces/spaces.service.spec.ts +++ b/nestjs-BE/server/src/spaces/spaces.service.spec.ts @@ -8,7 +8,7 @@ import { ConfigModule, ConfigService } from '@nestjs/config'; import { Space } from '@prisma/client'; import { PrismaClientKnownRequestError } from '@prisma/client/runtime/library'; import { SpacesService } from './spaces.service'; -import { CreateSpacePrismaDto } from './dto/create-space.dto'; +import { CreateSpaceDto } from './dto/create-space.dto'; import { UpdateSpacePrismaDto } from './dto/update-space.dto'; import { PrismaService } from '../prisma/prisma.service'; import { ProfileSpaceService } from '../profile-space/profile-space.service'; @@ -88,8 +88,6 @@ describe('SpacesService', () => { }); describe('createSpace', () => { - const userUuid = 'user uuid'; - const profileUuid = 'profile uuid'; const icon = { filename: 'icon' } as Express.Multer.File; const iconUrlMock = 'www.test.com/image'; @@ -107,14 +105,9 @@ describe('SpacesService', () => { it('created', async () => { const createSpaceDto = { name: 'new space name', - } as CreateSpacePrismaDto; + } as CreateSpaceDto; - const space = await spacesService.createSpace( - userUuid, - profileUuid, - icon, - createSpaceDto, - ); + const space = await spacesService.createSpace(icon, createSpaceDto); expect(space.uuid).toMatch( /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/, @@ -125,59 +118,12 @@ describe('SpacesService', () => { expect(prisma.space.create).toHaveBeenCalled(); }); - it('profile not found', async () => { - const createSpaceDto = { - name: 'new space name', - } as CreateSpacePrismaDto; - - (profilesService.verifyUserProfile as jest.Mock).mockRejectedValue( - new NotFoundException(), - ); - - const space = spacesService.createSpace( - userUuid, - profileUuid, - icon, - createSpaceDto, - ); - - await expect(space).rejects.toThrow(NotFoundException); - expect(uploadService.uploadFile).not.toHaveBeenCalled(); - expect(prisma.space.create).not.toHaveBeenCalled(); - }); - - it('profile user not own', async () => { - const createSpaceDto = { - name: 'new space name', - } as CreateSpacePrismaDto; - - (profilesService.verifyUserProfile as jest.Mock).mockRejectedValue( - new ForbiddenException(), - ); - - const space = spacesService.createSpace( - userUuid, - profileUuid, - icon, - createSpaceDto, - ); - - await expect(space).rejects.toThrow(ForbiddenException); - expect(uploadService.uploadFile).not.toHaveBeenCalled(); - expect(prisma.space.create).not.toHaveBeenCalledWith(); - }); - it('icon not requested', async () => { const createSpaceDto = { name: 'new space name', - } as CreateSpacePrismaDto; + } as CreateSpaceDto; - const space = await spacesService.createSpace( - userUuid, - profileUuid, - undefined, - createSpaceDto, - ); + const space = await spacesService.createSpace(undefined, createSpaceDto); expect(space.uuid).toMatch( /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/, From a4ed0e9d1eb26c6732876897a54ec0b3f45191fd Mon Sep 17 00:00:00 2001 From: Conut-1 <1mim1@naver.com> Date: Mon, 23 Dec 2024 15:11:34 +0900 Subject: [PATCH 07/18] =?UTF-8?q?feat:=20omit=20=EC=9C=A0=ED=8B=B8=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 객체에서 필요없는 프로퍼티를 제외하고 복사하는 함수 --- nestjs-BE/server/src/utils/omit.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 nestjs-BE/server/src/utils/omit.ts diff --git a/nestjs-BE/server/src/utils/omit.ts b/nestjs-BE/server/src/utils/omit.ts new file mode 100644 index 00000000..c13f88c1 --- /dev/null +++ b/nestjs-BE/server/src/utils/omit.ts @@ -0,0 +1,12 @@ +export function omit( + object: T, + exclude: K[], +): Omit { + return Object.keys(object).reduce( + (result, key) => { + if (!exclude.includes(key as K)) result[key] = object[key]; + return result; + }, + {} as Omit, + ); +} From 878c27d8121c120cb787361c9ea316d25fc0aa52 Mon Sep 17 00:00:00 2001 From: Conut-1 <1mim1@naver.com> Date: Mon, 23 Dec 2024 15:13:20 +0900 Subject: [PATCH 08/18] =?UTF-8?q?feat:=20updateSpace=EC=97=90=20=EA=B0=80?= =?UTF-8?q?=EB=93=9C=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/src/spaces/dto/update-space.dto.ts | 19 +++++++++++------ .../server/src/spaces/spaces.controller.ts | 19 ++++++++++------- nestjs-BE/server/src/spaces/spaces.service.ts | 21 ++++++++----------- 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/nestjs-BE/server/src/spaces/dto/update-space.dto.ts b/nestjs-BE/server/src/spaces/dto/update-space.dto.ts index e7f8274f..78012568 100644 --- a/nestjs-BE/server/src/spaces/dto/update-space.dto.ts +++ b/nestjs-BE/server/src/spaces/dto/update-space.dto.ts @@ -1,8 +1,20 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsNotEmpty, IsOptional, IsString, MaxLength } from 'class-validator'; +import { Expose } from 'class-transformer'; +import { v4 as uuid } from 'uuid'; import { MAX_NAME_LENGTH } from '../../config/constants'; -export class UpdateSpaceRequestDto { +export class UpdateSpaceDto { + @IsString() + @IsNotEmpty() + @Expose({ name: 'profile_uuid' }) + @ApiProperty({ + name: 'profile_uuid', + example: uuid(), + description: 'Profile uuid', + }) + profileUuid: string; + @IsOptional() @IsString() @IsNotEmpty() @@ -22,8 +34,3 @@ export class UpdateSpaceRequestDto { }) icon: string; } - -export class UpdateSpacePrismaDto { - name: string; - icon: string; -} diff --git a/nestjs-BE/server/src/spaces/spaces.controller.ts b/nestjs-BE/server/src/spaces/spaces.controller.ts index 9cb0b01d..3281a30e 100644 --- a/nestjs-BE/server/src/spaces/spaces.controller.ts +++ b/nestjs-BE/server/src/spaces/spaces.controller.ts @@ -19,7 +19,7 @@ import { FileInterceptor } from '@nestjs/platform-express'; import { ApiTags, ApiResponse, ApiOperation, ApiQuery } from '@nestjs/swagger'; import { SpacesService } from './spaces.service'; import { CreateSpaceDto } from './dto/create-space.dto'; -import { UpdateSpaceRequestDto } from './dto/update-space.dto'; +import { UpdateSpaceDto } from './dto/update-space.dto'; import { JoinSpaceRequestDto } from './dto/join-space.dto'; import { User } from '../auth/decorators/user.decorator'; import { IsProfileInSpaceGuard } from '../auth/guards/is-profile-in-space.guard'; @@ -106,6 +106,8 @@ export class SpacesController { } @Patch(':space_uuid') + @UseGuards(MatchUserProfileGuard) + @UseGuards(IsProfileInSpaceGuard) @UseInterceptors(FileInterceptor('icon')) @ApiOperation({ summary: 'Update space by space_uuid' }) @ApiResponse({ @@ -131,15 +133,16 @@ export class SpacesController { async updateSpace( @UploadedFile() icon: Express.Multer.File, @Param('space_uuid') spaceUuid: string, - @Query('profile_uuid') profileUuid: string, - @Body(new ValidationPipe({ whitelist: true, disableErrorMessages: true })) - updateSpaceDto: UpdateSpaceRequestDto, - @User('uuid') userUuid: string, + @Body( + new ValidationPipe({ + transform: true, + whitelist: true, + disableErrorMessages: true, + }), + ) + updateSpaceDto: UpdateSpaceDto, ) { - if (!profileUuid) throw new BadRequestException(); const space = await this.spacesService.updateSpace( - userUuid, - profileUuid, spaceUuid, icon, updateSpaceDto, diff --git a/nestjs-BE/server/src/spaces/spaces.service.ts b/nestjs-BE/server/src/spaces/spaces.service.ts index 64eeab04..7c398455 100644 --- a/nestjs-BE/server/src/spaces/spaces.service.ts +++ b/nestjs-BE/server/src/spaces/spaces.service.ts @@ -7,12 +7,13 @@ import { import { ConfigService } from '@nestjs/config'; import { Prisma, Profile, Space } from '@prisma/client'; import { v4 as uuid } from 'uuid'; -import { UpdateSpacePrismaDto } from './dto/update-space.dto'; +import { UpdateSpaceDto } from './dto/update-space.dto'; import { CreateSpaceDto } from './dto/create-space.dto'; import { PrismaService } from '../prisma/prisma.service'; import { ProfileSpaceService } from '../profile-space/profile-space.service'; import { UploadService } from '../upload/upload.service'; import { ProfilesService } from '../profiles/profiles.service'; +import { omit } from '../utils/omit'; @Injectable() export class SpacesService { @@ -56,26 +57,22 @@ export class SpacesService { } async updateSpace( - userUuid: string, - profileUuid: string, spaceUuid: string, icon: Express.Multer.File, - updateSpaceDto: UpdateSpacePrismaDto, + updateSpaceDto: UpdateSpaceDto, ): Promise { - await this.profilesService.verifyUserProfile(userUuid, profileUuid); - const isProfileInSpace = await this.profileSpaceService.isProfileInSpace( - profileUuid, - spaceUuid, - ); - if (!isProfileInSpace) throw new ForbiddenException(); + const updateData: Partial = omit(updateSpaceDto, [ + 'icon', + 'profileUuid', + ]); if (icon) { - updateSpaceDto.icon = await this.uploadService.uploadFile(icon); + updateData.icon = await this.uploadService.uploadFile(icon); } let space: Space; try { space = await this.prisma.space.update({ where: { uuid: spaceUuid }, - data: updateSpaceDto, + data: updateData, }); } catch (err) { if (err instanceof Prisma.PrismaClientKnownRequestError) { From ba225fae2a8c9b8aa0a4a429b0bbc404a5f2f8fe Mon Sep 17 00:00:00 2001 From: Conut-1 <1mim1@naver.com> Date: Mon, 23 Dec 2024 15:14:07 +0900 Subject: [PATCH 09/18] =?UTF-8?q?test:=20updateSpace=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/spaces/spaces.controller.spec.ts | 50 +++++------- .../server/src/spaces/spaces.service.spec.ts | 80 ++----------------- 2 files changed, 23 insertions(+), 107 deletions(-) diff --git a/nestjs-BE/server/src/spaces/spaces.controller.spec.ts b/nestjs-BE/server/src/spaces/spaces.controller.spec.ts index 8225c61a..a9c8f91a 100644 --- a/nestjs-BE/server/src/spaces/spaces.controller.spec.ts +++ b/nestjs-BE/server/src/spaces/spaces.controller.spec.ts @@ -7,7 +7,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { Profile, Space } from '@prisma/client'; import { SpacesController } from './spaces.controller'; import { SpacesService } from './spaces.service'; -import { UpdateSpaceRequestDto } from './dto/update-space.dto'; +import { UpdateSpaceDto } from './dto/update-space.dto'; import { CreateSpaceDto } from './dto/create-space.dto'; import { MatchUserProfileGuard } from '../auth/guards/match-user-profile.guard'; import { IsProfileInSpaceGuard } from '../auth/guards/is-profile-in-space.guard'; @@ -101,47 +101,33 @@ describe('SpacesController', () => { }); }); - it('updateSpace update space', async () => { + describe('updateSpace', () => { const spaceUuid = 'space uuid'; - const profileUuid = 'profile uuid'; const iconMock = { filename: 'icon' } as Express.Multer.File; - const bodyMock = { name: 'new space name' } as UpdateSpaceRequestDto; - const userUuidMock = 'user uuid'; + const bodyMock = { name: 'new space name' } as UpdateSpaceDto; const spaceMock = { uuid: spaceUuid } as Space; - (spacesService.updateSpace as jest.Mock).mockResolvedValue(spaceMock); + it('update space', async () => { + (spacesService.updateSpace as jest.Mock).mockResolvedValue(spaceMock); - const response = controller.updateSpace( - iconMock, - spaceUuid, - profileUuid, - bodyMock, - userUuidMock, - ); + const response = controller.updateSpace(iconMock, spaceUuid, bodyMock); - await expect(response).resolves.toEqual({ - statusCode: HttpStatus.OK, - message: 'OK', - data: spaceMock, + await expect(response).resolves.toEqual({ + statusCode: HttpStatus.OK, + message: 'OK', + data: spaceMock, + }); }); - }); - it('updateSpace profile uuid needed', async () => { - const iconMock = { filename: 'icon' } as Express.Multer.File; - const spaceUuid = 'space uuid'; - const bodyMock = { name: 'new space name' } as UpdateSpaceRequestDto; - const userUuidMock = 'user uuid'; + it('space not found', async () => { + (spacesService.updateSpace as jest.Mock).mockRejectedValue( + new NotFoundException(), + ); - const response = controller.updateSpace( - iconMock, - spaceUuid, - undefined, - bodyMock, - userUuidMock, - ); + const response = controller.updateSpace(iconMock, spaceUuid, bodyMock); - await expect(response).rejects.toThrow(BadRequestException); - expect(spacesService.updateSpace).not.toHaveBeenCalled(); + await expect(response).rejects.toThrow(NotFoundException); + }); }); it('joinSpace', async () => { diff --git a/nestjs-BE/server/src/spaces/spaces.service.spec.ts b/nestjs-BE/server/src/spaces/spaces.service.spec.ts index 2e266942..65dddb8d 100644 --- a/nestjs-BE/server/src/spaces/spaces.service.spec.ts +++ b/nestjs-BE/server/src/spaces/spaces.service.spec.ts @@ -9,7 +9,7 @@ import { Space } from '@prisma/client'; import { PrismaClientKnownRequestError } from '@prisma/client/runtime/library'; import { SpacesService } from './spaces.service'; import { CreateSpaceDto } from './dto/create-space.dto'; -import { UpdateSpacePrismaDto } from './dto/update-space.dto'; +import { UpdateSpaceDto } from './dto/update-space.dto'; import { PrismaService } from '../prisma/prisma.service'; import { ProfileSpaceService } from '../profile-space/profile-space.service'; import { UploadService } from '../upload/upload.service'; @@ -136,8 +136,6 @@ describe('SpacesService', () => { }); describe('updateSpace', () => { - const userUuid = 'user uuid'; - const profileUuid = 'profile uuid'; const spaceUuid = 'space uuid'; const iconMock = { filename: 'icon' } as Express.Multer.File; const iconUrlMock = 'www.test.com/image'; @@ -157,11 +155,9 @@ describe('SpacesService', () => { }); it('update space', async () => { - const updateSpaceDto = { name: 'new space name' } as UpdateSpacePrismaDto; + const updateSpaceDto = { name: 'new space name' } as UpdateSpaceDto; const space = spacesService.updateSpace( - userUuid, - profileUuid, spaceUuid, iconMock, updateSpaceDto, @@ -177,11 +173,9 @@ describe('SpacesService', () => { }); it('icon not requested', async () => { - const updateSpaceDto = { name: 'new space name' } as UpdateSpacePrismaDto; + const updateSpaceDto = { name: 'new space name' } as UpdateSpaceDto; const space = spacesService.updateSpace( - userUuid, - profileUuid, spaceUuid, undefined, updateSpaceDto, @@ -197,11 +191,9 @@ describe('SpacesService', () => { }); it('name not requested', async () => { - const updateSpaceDto = {} as UpdateSpacePrismaDto; + const updateSpaceDto = {} as UpdateSpaceDto; const space = spacesService.updateSpace( - userUuid, - profileUuid, spaceUuid, iconMock, updateSpaceDto, @@ -216,68 +208,8 @@ describe('SpacesService', () => { expect(prisma.space.update).toHaveBeenCalled(); }); - it('profile user not own', async () => { - const updateSpaceDto = { name: 'new space name' } as UpdateSpacePrismaDto; - - (profilesService.verifyUserProfile as jest.Mock).mockRejectedValue( - new ForbiddenException(), - ); - - const space = spacesService.updateSpace( - userUuid, - profileUuid, - spaceUuid, - iconMock, - updateSpaceDto, - ); - - await expect(space).rejects.toThrow(ForbiddenException); - expect(uploadService.uploadFile).not.toHaveBeenCalled(); - expect(prisma.space.update).not.toHaveBeenCalled(); - }); - - it('profile not joined space', async () => { - const updateSpaceDto = { name: 'new space name' } as UpdateSpacePrismaDto; - - (profileSpaceService.isProfileInSpace as jest.Mock).mockResolvedValue( - false, - ); - - const space = spacesService.updateSpace( - userUuid, - profileUuid, - spaceUuid, - iconMock, - updateSpaceDto, - ); - - await expect(space).rejects.toThrow(ForbiddenException); - expect(uploadService.uploadFile).not.toHaveBeenCalled(); - expect(prisma.space.update).not.toHaveBeenCalled(); - }); - - it('profile not found', async () => { - const updateSpaceDto = { name: 'new space name' } as UpdateSpacePrismaDto; - - (profilesService.verifyUserProfile as jest.Mock).mockRejectedValue( - new NotFoundException(), - ); - - const space = spacesService.updateSpace( - userUuid, - profileUuid, - spaceUuid, - iconMock, - updateSpaceDto, - ); - - await expect(space).rejects.toThrow(NotFoundException); - expect(uploadService.uploadFile).not.toHaveBeenCalled(); - expect(prisma.space.update).not.toHaveBeenCalled(); - }); - it('update fail', async () => { - const updateSpaceDto = { name: 'new space name' } as UpdateSpacePrismaDto; + const updateSpaceDto = { name: 'new space name' } as UpdateSpaceDto; (prisma.space.update as jest.Mock).mockRejectedValue( new PrismaClientKnownRequestError('', { @@ -287,8 +219,6 @@ describe('SpacesService', () => { ); const space = spacesService.updateSpace( - userUuid, - profileUuid, spaceUuid, iconMock, updateSpaceDto, From ac54f3a94f061d7e5ebfc28ae1664cfb09dd8c9c Mon Sep 17 00:00:00 2001 From: Conut-1 <1mim1@naver.com> Date: Mon, 23 Dec 2024 16:42:44 +0900 Subject: [PATCH 10/18] =?UTF-8?q?feat:=20joinSpace=EC=97=90=20=EA=B0=80?= =?UTF-8?q?=EB=93=9C=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/src/spaces/dto/join-space.dto.ts | 12 ----------- .../server/src/spaces/spaces.controller.ts | 20 ++++--------------- nestjs-BE/server/src/spaces/spaces.service.ts | 7 +------ 3 files changed, 5 insertions(+), 34 deletions(-) delete mode 100644 nestjs-BE/server/src/spaces/dto/join-space.dto.ts diff --git a/nestjs-BE/server/src/spaces/dto/join-space.dto.ts b/nestjs-BE/server/src/spaces/dto/join-space.dto.ts deleted file mode 100644 index 462a053e..00000000 --- a/nestjs-BE/server/src/spaces/dto/join-space.dto.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { Expose } from 'class-transformer'; -import { IsNotEmpty, IsString } from 'class-validator'; -import { v4 as uuid } from 'uuid'; - -export class JoinSpaceRequestDto { - @IsString() - @IsNotEmpty() - @Expose({ name: 'profile_uuid' }) - @ApiProperty({ example: uuid(), description: 'Profile uuid' }) - profileUuid: string; -} diff --git a/nestjs-BE/server/src/spaces/spaces.controller.ts b/nestjs-BE/server/src/spaces/spaces.controller.ts index 3281a30e..86044915 100644 --- a/nestjs-BE/server/src/spaces/spaces.controller.ts +++ b/nestjs-BE/server/src/spaces/spaces.controller.ts @@ -20,7 +20,6 @@ import { ApiTags, ApiResponse, ApiOperation, ApiQuery } from '@nestjs/swagger'; import { SpacesService } from './spaces.service'; import { CreateSpaceDto } from './dto/create-space.dto'; import { UpdateSpaceDto } from './dto/update-space.dto'; -import { JoinSpaceRequestDto } from './dto/join-space.dto'; import { User } from '../auth/decorators/user.decorator'; import { IsProfileInSpaceGuard } from '../auth/guards/is-profile-in-space.guard'; import { MatchUserProfileGuard } from '../auth/guards/match-user-profile.guard'; @@ -150,7 +149,8 @@ export class SpacesController { return { statusCode: HttpStatus.OK, message: 'OK', data: space }; } - @Post(':space_uuid/join') + @Post(':space_uuid/profiles/:profile_uuid') + @UseGuards(MatchUserProfileGuard) @ApiOperation({ summary: 'Join space' }) @ApiResponse({ status: HttpStatus.CREATED, @@ -178,21 +178,9 @@ export class SpacesController { }) async joinSpace( @Param('space_uuid') spaceUuid: string, - @Body( - new ValidationPipe({ - transform: true, - whitelist: true, - disableErrorMessages: true, - }), - ) - joinSpaceDto: JoinSpaceRequestDto, - @User('uuid') userUuid: string, + @Param('profile_uuid') profileUuid: string, ) { - const space = await this.spacesService.joinSpace( - userUuid, - joinSpaceDto.profileUuid, - spaceUuid, - ); + const space = await this.spacesService.joinSpace(profileUuid, spaceUuid); return { statusCode: HttpStatus.CREATED, message: 'Created', data: space }; } diff --git a/nestjs-BE/server/src/spaces/spaces.service.ts b/nestjs-BE/server/src/spaces/spaces.service.ts index 7c398455..602e43b9 100644 --- a/nestjs-BE/server/src/spaces/spaces.service.ts +++ b/nestjs-BE/server/src/spaces/spaces.service.ts @@ -88,12 +88,7 @@ export class SpacesService { return this.prisma.space.delete({ where: { uuid: spaceUuid } }); } - async joinSpace( - userUuid: string, - profileUuid: string, - spaceUuid: string, - ): Promise { - await this.profilesService.verifyUserProfile(userUuid, profileUuid); + async joinSpace(profileUuid: string, spaceUuid: string): Promise { try { await this.profileSpaceService.createProfileSpace(profileUuid, spaceUuid); } catch (err) { From cecbee8e6431709834d93d83639b006c4df9adf6 Mon Sep 17 00:00:00 2001 From: Conut-1 <1mim1@naver.com> Date: Mon, 23 Dec 2024 16:43:13 +0900 Subject: [PATCH 11/18] =?UTF-8?q?test:=20joinSpace=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/spaces/spaces.controller.spec.ts | 25 ++++++++--------- .../server/src/spaces/spaces.service.spec.ts | 27 +++---------------- 2 files changed, 14 insertions(+), 38 deletions(-) diff --git a/nestjs-BE/server/src/spaces/spaces.controller.spec.ts b/nestjs-BE/server/src/spaces/spaces.controller.spec.ts index a9c8f91a..2359047f 100644 --- a/nestjs-BE/server/src/spaces/spaces.controller.spec.ts +++ b/nestjs-BE/server/src/spaces/spaces.controller.spec.ts @@ -130,23 +130,20 @@ describe('SpacesController', () => { }); }); - it('joinSpace', async () => { - const spaceMock = { uuid: 'space uuid' }; - const bodyMock = { profileUuid: 'profile uuid' }; - const userUuidMock = 'user uuid'; + describe('joinSpace', () => { + it('join space', async () => { + const spaceMock = { uuid: 'space uuid' }; + const profileUuidMock = 'profile uuid'; - (spacesService.joinSpace as jest.Mock).mockResolvedValue(spaceMock); + (spacesService.joinSpace as jest.Mock).mockResolvedValue(spaceMock); - const response = controller.joinSpace( - spaceMock.uuid, - bodyMock, - userUuidMock, - ); + const response = controller.joinSpace(spaceMock.uuid, profileUuidMock); - await expect(response).resolves.toEqual({ - statusCode: HttpStatus.CREATED, - message: 'Created', - data: spaceMock, + await expect(response).resolves.toEqual({ + statusCode: HttpStatus.CREATED, + message: 'Created', + data: spaceMock, + }); }); }); diff --git a/nestjs-BE/server/src/spaces/spaces.service.spec.ts b/nestjs-BE/server/src/spaces/spaces.service.spec.ts index 65dddb8d..16510f1b 100644 --- a/nestjs-BE/server/src/spaces/spaces.service.spec.ts +++ b/nestjs-BE/server/src/spaces/spaces.service.spec.ts @@ -229,7 +229,6 @@ describe('SpacesService', () => { }); describe('joinSpace', () => { - const userUuid = 'user uuid'; const profileUuid = 'profile uuid'; const spaceUuid = 'space uuid'; const space = { uuid: spaceUuid } as Space; @@ -241,31 +240,11 @@ describe('SpacesService', () => { }); it('join space', async () => { - const res = spacesService.joinSpace(userUuid, profileUuid, spaceUuid); + const res = spacesService.joinSpace(profileUuid, spaceUuid); await expect(res).resolves.toEqual(space); }); - it('profile not found', async () => { - (profilesService.verifyUserProfile as jest.Mock).mockRejectedValue( - new NotFoundException(), - ); - - const res = spacesService.joinSpace(userUuid, profileUuid, spaceUuid); - - await expect(res).rejects.toThrow(NotFoundException); - }); - - it('profile user not own', async () => { - (profilesService.verifyUserProfile as jest.Mock).mockRejectedValue( - new ForbiddenException(), - ); - - const res = spacesService.joinSpace(userUuid, profileUuid, spaceUuid); - - await expect(res).rejects.toThrow(ForbiddenException); - }); - it('conflict', async () => { (profileSpaceService.createProfileSpace as jest.Mock).mockRejectedValue( new PrismaClientKnownRequestError('', { @@ -274,7 +253,7 @@ describe('SpacesService', () => { }), ); - const res = spacesService.joinSpace(userUuid, profileUuid, spaceUuid); + const res = spacesService.joinSpace(profileUuid, spaceUuid); await expect(res).rejects.toThrow(ConflictException); }); @@ -287,7 +266,7 @@ describe('SpacesService', () => { }), ); - const res = spacesService.joinSpace(userUuid, profileUuid, spaceUuid); + const res = spacesService.joinSpace(profileUuid, spaceUuid); await expect(res).rejects.toThrow(ForbiddenException); }); From 9b16867a208274fd21019e27a96ba5e0e7b070c2 Mon Sep 17 00:00:00 2001 From: Conut-1 <1mim1@naver.com> Date: Mon, 23 Dec 2024 16:55:11 +0900 Subject: [PATCH 12/18] =?UTF-8?q?feat:=20leaveSpace=EC=97=90=20=EA=B0=80?= =?UTF-8?q?=EB=93=9C=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nestjs-BE/server/src/spaces/spaces.controller.ts | 7 ++++--- nestjs-BE/server/src/spaces/spaces.service.ts | 7 +------ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/nestjs-BE/server/src/spaces/spaces.controller.ts b/nestjs-BE/server/src/spaces/spaces.controller.ts index 86044915..6336de2a 100644 --- a/nestjs-BE/server/src/spaces/spaces.controller.ts +++ b/nestjs-BE/server/src/spaces/spaces.controller.ts @@ -185,9 +185,11 @@ export class SpacesController { } @Delete(':space_uuid/profiles/:profile_uuid') + @UseGuards(MatchUserProfileGuard) + @UseGuards(IsProfileInSpaceGuard) @ApiOperation({ summary: 'Leave space' }) @ApiResponse({ - status: HttpStatus.NO_CONTENT, + status: HttpStatus.OK, description: 'Successfully left the space.', }) @ApiResponse({ @@ -205,9 +207,8 @@ export class SpacesController { async leaveSpace( @Param('space_uuid') spaceUuid: string, @Param('profile_uuid') profileUuid: string, - @User('uuid') userUuid: string, ) { - await this.spacesService.leaveSpace(userUuid, profileUuid, spaceUuid); + await this.spacesService.leaveSpace(profileUuid, spaceUuid); return { statusCode: HttpStatus.OK, message: 'OK' }; } diff --git a/nestjs-BE/server/src/spaces/spaces.service.ts b/nestjs-BE/server/src/spaces/spaces.service.ts index 602e43b9..7106ec42 100644 --- a/nestjs-BE/server/src/spaces/spaces.service.ts +++ b/nestjs-BE/server/src/spaces/spaces.service.ts @@ -108,12 +108,7 @@ export class SpacesService { return this.findSpaceBySpaceUuid(spaceUuid); } - async leaveSpace( - userUuid: string, - profileUuid: string, - spaceUuid: string, - ): Promise { - await this.profilesService.verifyUserProfile(userUuid, profileUuid); + async leaveSpace(profileUuid: string, spaceUuid: string): Promise { try { await this.profileSpaceService.deleteProfileSpace(profileUuid, spaceUuid); } catch (err) { From a7a785d032d6164c884ff4711b171973c3ba434b Mon Sep 17 00:00:00 2001 From: Conut-1 <1mim1@naver.com> Date: Mon, 23 Dec 2024 16:55:34 +0900 Subject: [PATCH 13/18] =?UTF-8?q?test:=20leaveSpace=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/spaces/spaces.controller.spec.ts | 23 +++++++-------- .../server/src/spaces/spaces.service.spec.ts | 29 +++---------------- 2 files changed, 14 insertions(+), 38 deletions(-) diff --git a/nestjs-BE/server/src/spaces/spaces.controller.spec.ts b/nestjs-BE/server/src/spaces/spaces.controller.spec.ts index 2359047f..de824a57 100644 --- a/nestjs-BE/server/src/spaces/spaces.controller.spec.ts +++ b/nestjs-BE/server/src/spaces/spaces.controller.spec.ts @@ -147,22 +147,19 @@ describe('SpacesController', () => { }); }); - it('leaveSpace', async () => { - const spaceMock = { uuid: 'space uuid' }; - const profileMock = { uuid: 'profile uuid' }; - const userUuidMock = 'user uuid'; + describe('leaveSpace', () => { + it('leave space', async () => { + const spaceMock = { uuid: 'space uuid' }; + const profileMock = { uuid: 'profile uuid' }; - (spacesService.leaveSpace as jest.Mock).mockResolvedValue(undefined); + (spacesService.leaveSpace as jest.Mock).mockResolvedValue(undefined); - const response = controller.leaveSpace( - spaceMock.uuid, - profileMock.uuid, - userUuidMock, - ); + const response = controller.leaveSpace(spaceMock.uuid, profileMock.uuid); - await expect(response).resolves.toEqual({ - statusCode: HttpStatus.OK, - message: 'OK', + await expect(response).resolves.toEqual({ + statusCode: HttpStatus.OK, + message: 'OK', + }); }); }); diff --git a/nestjs-BE/server/src/spaces/spaces.service.spec.ts b/nestjs-BE/server/src/spaces/spaces.service.spec.ts index 16510f1b..820351c2 100644 --- a/nestjs-BE/server/src/spaces/spaces.service.spec.ts +++ b/nestjs-BE/server/src/spaces/spaces.service.spec.ts @@ -273,7 +273,6 @@ describe('SpacesService', () => { }); describe('leaveSpace', () => { - const userUuid = 'user uuid'; const profileUuid = 'profile uuid'; const spaceUuid = 'space uuid'; @@ -282,14 +281,14 @@ describe('SpacesService', () => { }); it('leave space', async () => { - const res = spacesService.leaveSpace(userUuid, profileUuid, spaceUuid); + const res = spacesService.leaveSpace(profileUuid, spaceUuid); await expect(res).resolves.toBeUndefined(); expect(spacesService.deleteSpace).toHaveBeenCalled(); }); it('leave space, other profile exist', async () => { - const res = spacesService.leaveSpace(userUuid, profileUuid, spaceUuid); + const res = spacesService.leaveSpace(profileUuid, spaceUuid); (profileSpaceService.isSpaceEmpty as jest.Mock).mockResolvedValue(false); @@ -305,31 +304,11 @@ describe('SpacesService', () => { }), ); - const res = spacesService.leaveSpace(userUuid, profileUuid, spaceUuid); + const res = spacesService.leaveSpace(profileUuid, spaceUuid); await expect(res).resolves.toBeUndefined(); }); - it('profile not found', async () => { - (profilesService.verifyUserProfile as jest.Mock).mockRejectedValue( - new NotFoundException(), - ); - - const res = spacesService.leaveSpace(userUuid, profileUuid, spaceUuid); - - await expect(res).rejects.toThrow(NotFoundException); - }); - - it('profile user not own', async () => { - (profilesService.verifyUserProfile as jest.Mock).mockRejectedValue( - new ForbiddenException(), - ); - - const res = spacesService.leaveSpace(userUuid, profileUuid, spaceUuid); - - await expect(res).rejects.toThrow(ForbiddenException); - }); - it('profile not joined space', async () => { (profileSpaceService.deleteProfileSpace as jest.Mock).mockRejectedValue( new PrismaClientKnownRequestError('', { @@ -338,7 +317,7 @@ describe('SpacesService', () => { }), ); - const res = spacesService.leaveSpace(userUuid, profileUuid, spaceUuid); + const res = spacesService.leaveSpace(profileUuid, spaceUuid); await expect(res).rejects.toThrow(NotFoundException); }); From b1bda9505c62a32bae40eba98b8c724bc6ad2492 Mon Sep 17 00:00:00 2001 From: Conut-1 <1mim1@naver.com> Date: Mon, 23 Dec 2024 18:36:50 +0900 Subject: [PATCH 14/18] =?UTF-8?q?feat:=20findProfilesInSpace=EC=97=90=20?= =?UTF-8?q?=EA=B0=80=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 --- .../server/src/spaces/spaces.controller.ts | 24 ++++++++----------- nestjs-BE/server/src/spaces/spaces.service.ts | 14 +---------- 2 files changed, 11 insertions(+), 27 deletions(-) diff --git a/nestjs-BE/server/src/spaces/spaces.controller.ts b/nestjs-BE/server/src/spaces/spaces.controller.ts index 6336de2a..c2e3ae60 100644 --- a/nestjs-BE/server/src/spaces/spaces.controller.ts +++ b/nestjs-BE/server/src/spaces/spaces.controller.ts @@ -10,8 +10,6 @@ import { ValidationPipe, Header, HttpStatus, - Query, - BadRequestException, Delete, UseGuards, } from '@nestjs/common'; @@ -20,7 +18,6 @@ import { ApiTags, ApiResponse, ApiOperation, ApiQuery } from '@nestjs/swagger'; import { SpacesService } from './spaces.service'; import { CreateSpaceDto } from './dto/create-space.dto'; import { UpdateSpaceDto } from './dto/update-space.dto'; -import { User } from '../auth/decorators/user.decorator'; import { IsProfileInSpaceGuard } from '../auth/guards/is-profile-in-space.guard'; import { MatchUserProfileGuard } from '../auth/guards/match-user-profile.guard'; @@ -213,8 +210,16 @@ export class SpacesController { } @Get(':space_uuid/profiles') + @UseGuards(MatchUserProfileGuard) + @UseGuards(IsProfileInSpaceGuard) @Header('Cache-Control', 'no-store') @ApiOperation({ summary: 'Get profiles joined space.' }) + @ApiQuery({ + name: 'profile_uuid', + type: String, + description: 'profile uuid', + required: true, + }) @ApiResponse({ status: HttpStatus.OK, description: 'Successfully get profiles.', @@ -235,17 +240,8 @@ export class SpacesController { status: HttpStatus.NOT_FOUND, description: 'Profile not found.', }) - async findProfilesInSpace( - @Param('space_uuid') spaceUuid: string, - @Query('profile_uuid') profileUuid: string, - @User('uuid') userUuid: string, - ) { - if (!profileUuid) throw new BadRequestException(); - const profiles = await this.spacesService.findProfilesInSpace( - userUuid, - profileUuid, - spaceUuid, - ); + async findProfilesInSpace(@Param('space_uuid') spaceUuid: string) { + const profiles = await this.spacesService.findProfilesInSpace(spaceUuid); return { statusCode: HttpStatus.OK, message: 'OK', data: profiles }; } } diff --git a/nestjs-BE/server/src/spaces/spaces.service.ts b/nestjs-BE/server/src/spaces/spaces.service.ts index 7106ec42..5cc16f00 100644 --- a/nestjs-BE/server/src/spaces/spaces.service.ts +++ b/nestjs-BE/server/src/spaces/spaces.service.ts @@ -12,7 +12,6 @@ import { CreateSpaceDto } from './dto/create-space.dto'; import { PrismaService } from '../prisma/prisma.service'; import { ProfileSpaceService } from '../profile-space/profile-space.service'; import { UploadService } from '../upload/upload.service'; -import { ProfilesService } from '../profiles/profiles.service'; import { omit } from '../utils/omit'; @Injectable() @@ -22,7 +21,6 @@ export class SpacesService { private readonly configService: ConfigService, private readonly profileSpaceService: ProfileSpaceService, private readonly uploadService: UploadService, - private readonly profilesService: ProfilesService, ) {} async findSpaceBySpaceUuid(spaceUuid: string): Promise { @@ -129,17 +127,7 @@ export class SpacesService { } catch (err) {} } - async findProfilesInSpace( - userUuid: string, - profileUuid: string, - spaceUuid: string, - ): Promise { - await this.profilesService.verifyUserProfile(userUuid, profileUuid); - const isProfileInSpace = await this.profileSpaceService.isProfileInSpace( - profileUuid, - spaceUuid, - ); - if (!isProfileInSpace) throw new ForbiddenException(); + async findProfilesInSpace(spaceUuid: string): Promise { return this.prisma.profile.findMany({ where: { spaces: { some: { spaceUuid } } }, }); From 646cebb05f8d747a6194af85e406a5ddec6b1c4c Mon Sep 17 00:00:00 2001 From: Conut-1 <1mim1@naver.com> Date: Mon, 23 Dec 2024 18:38:19 +0900 Subject: [PATCH 15/18] =?UTF-8?q?test:=20findProfilesInSpace=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/spaces/spaces.controller.spec.ts | 53 +++++------------- .../server/src/spaces/spaces.service.spec.ts | 55 +------------------ 2 files changed, 16 insertions(+), 92 deletions(-) diff --git a/nestjs-BE/server/src/spaces/spaces.controller.spec.ts b/nestjs-BE/server/src/spaces/spaces.controller.spec.ts index de824a57..1001f3fd 100644 --- a/nestjs-BE/server/src/spaces/spaces.controller.spec.ts +++ b/nestjs-BE/server/src/spaces/spaces.controller.spec.ts @@ -1,8 +1,4 @@ -import { - BadRequestException, - HttpStatus, - NotFoundException, -} from '@nestjs/common'; +import { HttpStatus, NotFoundException } from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; import { Profile, Space } from '@prisma/client'; import { SpacesController } from './spaces.controller'; @@ -163,41 +159,22 @@ describe('SpacesController', () => { }); }); - it('findProfilesInSpace', async () => { - const spaceMock = { uuid: 'space uuid' }; - const profileMock = { uuid: 'profile uuid' }; - const userUuidMock = 'user uuid'; - const profilesMock = []; - - (spacesService.findProfilesInSpace as jest.Mock).mockResolvedValue( - profilesMock, - ); - - const response = controller.findProfilesInSpace( - spaceMock.uuid, - profileMock.uuid, - userUuidMock, - ); - - await expect(response).resolves.toEqual({ - statusCode: HttpStatus.OK, - message: 'OK', - data: profilesMock, - }); - }); - - it('findProfilesInSpace space uuid needed', async () => { - const spaceMock = { uuid: 'space uuid' }; - const userUuidMock = 'user uuid'; + describe('findProfilesInSpace', () => { + it('get profiles', async () => { + const spaceMock = { uuid: 'space uuid' }; + const profilesMock = []; - (spacesService.findProfilesInSpace as jest.Mock).mockResolvedValue([]); + (spacesService.findProfilesInSpace as jest.Mock).mockResolvedValue( + profilesMock, + ); - const response = controller.findProfilesInSpace( - spaceMock.uuid, - undefined, - userUuidMock, - ); + const response = controller.findProfilesInSpace(spaceMock.uuid); - await expect(response).rejects.toThrow(BadRequestException); + await expect(response).resolves.toEqual({ + statusCode: HttpStatus.OK, + message: 'OK', + data: profilesMock, + }); + }); }); }); diff --git a/nestjs-BE/server/src/spaces/spaces.service.spec.ts b/nestjs-BE/server/src/spaces/spaces.service.spec.ts index 820351c2..cec8a059 100644 --- a/nestjs-BE/server/src/spaces/spaces.service.spec.ts +++ b/nestjs-BE/server/src/spaces/spaces.service.spec.ts @@ -21,7 +21,6 @@ describe('SpacesService', () => { let configService: ConfigService; let profileSpaceService: ProfileSpaceService; let uploadService: UploadService; - let profilesService: ProfilesService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -44,10 +43,7 @@ describe('SpacesService', () => { isProfileInSpace: jest.fn(async () => true), }, }, - { - provide: ProfilesService, - useValue: { verifyUserProfile: jest.fn(async () => true) }, - }, + { provide: ProfilesService, useValue: {} }, { provide: UploadService, useValue: { uploadFile: jest.fn() }, @@ -60,7 +56,6 @@ describe('SpacesService', () => { configService = module.get(ConfigService); profileSpaceService = module.get(ProfileSpaceService); uploadService = module.get(UploadService); - profilesService = module.get(ProfilesService); }); describe('findSpace', () => { @@ -322,52 +317,4 @@ describe('SpacesService', () => { await expect(res).rejects.toThrow(NotFoundException); }); }); - - describe('findProfilesInSpace', () => { - const userUuid = 'user uuid'; - const profileUuid = 'profile uuid'; - const spaceUuid = 'space uuid'; - - it('profile not found', async () => { - (profilesService.verifyUserProfile as jest.Mock).mockRejectedValue( - new NotFoundException(), - ); - - const res = spacesService.findProfilesInSpace( - userUuid, - profileUuid, - spaceUuid, - ); - - await expect(res).rejects.toThrow(NotFoundException); - }); - - it('profile user not own', async () => { - (profilesService.verifyUserProfile as jest.Mock).mockRejectedValue( - new ForbiddenException(), - ); - - const res = spacesService.findProfilesInSpace( - userUuid, - profileUuid, - spaceUuid, - ); - - await expect(res).rejects.toThrow(ForbiddenException); - }); - - it('profile not joined space', async () => { - (profileSpaceService.isProfileInSpace as jest.Mock).mockResolvedValue( - false, - ); - - const res = spacesService.findProfilesInSpace( - userUuid, - profileUuid, - spaceUuid, - ); - - await expect(res).rejects.toThrow(ForbiddenException); - }); - }); }); From abc5bca5dd48e0b77ef1c0170371e165bccd0df6 Mon Sep 17 00:00:00 2001 From: Conut-1 <1mim1@naver.com> Date: Mon, 23 Dec 2024 19:21:43 +0900 Subject: [PATCH 16/18] =?UTF-8?q?refactor:=20=EA=B0=81=20=EB=B8=94?= =?UTF-8?q?=EB=A1=9D=EC=97=90=EC=84=9C=20mocking=20=ED=95=A8=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/src/spaces/spaces.service.spec.ts | 37 ++++++------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/nestjs-BE/server/src/spaces/spaces.service.spec.ts b/nestjs-BE/server/src/spaces/spaces.service.spec.ts index cec8a059..57e431dd 100644 --- a/nestjs-BE/server/src/spaces/spaces.service.spec.ts +++ b/nestjs-BE/server/src/spaces/spaces.service.spec.ts @@ -13,7 +13,6 @@ import { UpdateSpaceDto } from './dto/update-space.dto'; import { PrismaService } from '../prisma/prisma.service'; import { ProfileSpaceService } from '../profile-space/profile-space.service'; import { UploadService } from '../upload/upload.service'; -import { ProfilesService } from '../profiles/profiles.service'; describe('SpacesService', () => { let spacesService: SpacesService; @@ -27,27 +26,9 @@ describe('SpacesService', () => { imports: [ConfigModule], providers: [ SpacesService, - { - provide: PrismaService, - useValue: { - space: { create: jest.fn(), update: jest.fn() }, - profile: { findMany: jest.fn() }, - }, - }, - { - provide: ProfileSpaceService, - useValue: { - createProfileSpace: jest.fn(), - deleteProfileSpace: jest.fn(), - isSpaceEmpty: jest.fn(async () => true), - isProfileInSpace: jest.fn(async () => true), - }, - }, - { provide: ProfilesService, useValue: {} }, - { - provide: UploadService, - useValue: { uploadFile: jest.fn() }, - }, + { provide: PrismaService, useValue: { space: {} } }, + { provide: ProfileSpaceService, useValue: {} }, + { provide: UploadService, useValue: {} }, ], }).compile(); @@ -87,14 +68,15 @@ describe('SpacesService', () => { const iconUrlMock = 'www.test.com/image'; beforeEach(() => { - (uploadService.uploadFile as jest.Mock).mockResolvedValue(iconUrlMock); - (prisma.space.create as jest.Mock).mockImplementation((args) => { + uploadService.uploadFile = jest.fn(async () => iconUrlMock); + (prisma.space.create as jest.Mock) = jest.fn(async (args) => { return { uuid: args.data.uuid, name: args.data.name, icon: args.data.icon, }; }); + profileSpaceService.createProfileSpace = jest.fn(); }); it('created', async () => { @@ -136,8 +118,8 @@ describe('SpacesService', () => { const iconUrlMock = 'www.test.com/image'; beforeEach(() => { - (uploadService.uploadFile as jest.Mock).mockResolvedValue(iconUrlMock); - (prisma.space.update as jest.Mock).mockImplementation(async (args) => { + uploadService.uploadFile = jest.fn(async () => iconUrlMock); + (prisma.space.update as jest.Mock) = jest.fn(async (args) => { const space = { uuid: args.where.uuid, name: args.data.name ? args.data.name : 'test space', @@ -232,6 +214,7 @@ describe('SpacesService', () => { jest .spyOn(spacesService, 'findSpaceBySpaceUuid') .mockResolvedValue(space); + profileSpaceService.createProfileSpace = jest.fn(); }); it('join space', async () => { @@ -272,6 +255,8 @@ describe('SpacesService', () => { const spaceUuid = 'space uuid'; beforeEach(() => { + profileSpaceService.isSpaceEmpty = jest.fn(async () => true); + profileSpaceService.deleteProfileSpace = jest.fn(); jest.spyOn(spacesService, 'deleteSpace').mockResolvedValue(null); }); From 01d821fdaab1abd2bfac28504242affdb2225a7c Mon Sep 17 00:00:00 2001 From: Conut-1 <1mim1@naver.com> Date: Mon, 23 Dec 2024 19:37:12 +0900 Subject: [PATCH 17/18] =?UTF-8?q?refactor:=20=EA=B0=81=20=EB=B8=94?= =?UTF-8?q?=EB=A1=9D=EC=97=90=EC=84=9C=20mocking=20=ED=95=A8=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/spaces/spaces.controller.spec.ts | 51 +++++++++---------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/nestjs-BE/server/src/spaces/spaces.controller.spec.ts b/nestjs-BE/server/src/spaces/spaces.controller.spec.ts index 1001f3fd..1b9d1b04 100644 --- a/nestjs-BE/server/src/spaces/spaces.controller.spec.ts +++ b/nestjs-BE/server/src/spaces/spaces.controller.spec.ts @@ -18,16 +18,7 @@ describe('SpacesController', () => { const module: TestingModule = await Test.createTestingModule({ controllers: [SpacesController], providers: [ - { - provide: SpacesService, - useValue: { - createSpace: jest.fn(), - updateSpace: jest.fn(), - joinSpace: jest.fn(), - leaveSpace: jest.fn(), - findProfilesInSpace: jest.fn(), - }, - }, + { provide: SpacesService, useValue: {} }, { provide: ProfilesService, useValue: {} }, { provide: ProfileSpaceService, useValue: {} }, MatchUserProfileGuard, @@ -53,7 +44,7 @@ describe('SpacesController', () => { const spaceMock = { uuid: 'space uuid' } as Space; it('created', async () => { - (spacesService.createSpace as jest.Mock).mockResolvedValue(spaceMock); + spacesService.createSpace = jest.fn(async () => spaceMock); const response = controller.createSpace(iconMock, bodyMock); @@ -103,9 +94,11 @@ describe('SpacesController', () => { const bodyMock = { name: 'new space name' } as UpdateSpaceDto; const spaceMock = { uuid: spaceUuid } as Space; - it('update space', async () => { - (spacesService.updateSpace as jest.Mock).mockResolvedValue(spaceMock); + beforeEach(() => { + spacesService.updateSpace = jest.fn(async () => spaceMock); + }); + it('update space', async () => { const response = controller.updateSpace(iconMock, spaceUuid, bodyMock); await expect(response).resolves.toEqual({ @@ -127,12 +120,14 @@ describe('SpacesController', () => { }); describe('joinSpace', () => { - it('join space', async () => { - const spaceMock = { uuid: 'space uuid' }; - const profileUuidMock = 'profile uuid'; + const spaceMock = { uuid: 'space uuid' } as Space; + const profileUuidMock = 'profile uuid'; - (spacesService.joinSpace as jest.Mock).mockResolvedValue(spaceMock); + beforeEach(() => { + spacesService.joinSpace = jest.fn(async () => spaceMock); + }); + it('join space', async () => { const response = controller.joinSpace(spaceMock.uuid, profileUuidMock); await expect(response).resolves.toEqual({ @@ -144,12 +139,14 @@ describe('SpacesController', () => { }); describe('leaveSpace', () => { - it('leave space', async () => { - const spaceMock = { uuid: 'space uuid' }; - const profileMock = { uuid: 'profile uuid' }; + const spaceMock = { uuid: 'space uuid' }; + const profileMock = { uuid: 'profile uuid' }; - (spacesService.leaveSpace as jest.Mock).mockResolvedValue(undefined); + beforeEach(() => { + spacesService.leaveSpace = jest.fn(async () => undefined); + }); + it('leave space', async () => { const response = controller.leaveSpace(spaceMock.uuid, profileMock.uuid); await expect(response).resolves.toEqual({ @@ -160,14 +157,14 @@ describe('SpacesController', () => { }); describe('findProfilesInSpace', () => { - it('get profiles', async () => { - const spaceMock = { uuid: 'space uuid' }; - const profilesMock = []; + const spaceMock = { uuid: 'space uuid' }; + const profilesMock = []; - (spacesService.findProfilesInSpace as jest.Mock).mockResolvedValue( - profilesMock, - ); + beforeEach(() => { + spacesService.findProfilesInSpace = jest.fn(async () => profilesMock); + }); + it('get profiles', async () => { const response = controller.findProfilesInSpace(spaceMock.uuid); await expect(response).resolves.toEqual({ From 0ec02ec4438f9978b95bdae4a4dbba6d64edfcd3 Mon Sep 17 00:00:00 2001 From: Conut-1 <1mim1@naver.com> Date: Mon, 23 Dec 2024 19:41:58 +0900 Subject: [PATCH 18/18] =?UTF-8?q?fix:=20=EB=AA=A8=EB=93=88=20imports=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nestjs-BE/server/src/spaces/spaces.module.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nestjs-BE/server/src/spaces/spaces.module.ts b/nestjs-BE/server/src/spaces/spaces.module.ts index 3bc7d956..c5b5a04f 100644 --- a/nestjs-BE/server/src/spaces/spaces.module.ts +++ b/nestjs-BE/server/src/spaces/spaces.module.ts @@ -3,10 +3,10 @@ import { SpacesService } from './spaces.service'; import { SpacesController } from './spaces.controller'; import { UploadModule } from '../upload/upload.module'; import { ProfileSpaceModule } from '../profile-space/profile-space.module'; -import { ProfilesModule } from '../profiles/profiles.module'; +import { AuthModule } from '../auth/auth.module'; @Module({ - imports: [ProfileSpaceModule, UploadModule, ProfilesModule], + imports: [ProfileSpaceModule, UploadModule, AuthModule], controllers: [SpacesController], providers: [SpacesService], exports: [SpacesService],