From 3733ee3589650968e0c8247af120f65f848f5124 Mon Sep 17 00:00:00 2001 From: seungsje Date: Mon, 2 Sep 2024 13:04:43 +0900 Subject: [PATCH] =?UTF-8?q?[Test]=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AgendaTeamController.java | 8 + .../agendateam/AgendaTeamControllerTest.java | 200 ++++++++++++++++-- .../java/gg/utils/exception/ErrorCode.java | 2 +- 3 files changed, 188 insertions(+), 22 deletions(-) diff --git a/gg-agenda-api/src/main/java/gg/agenda/api/user/agendateam/controller/AgendaTeamController.java b/gg-agenda-api/src/main/java/gg/agenda/api/user/agendateam/controller/AgendaTeamController.java index 4798b347a..3674e8b57 100644 --- a/gg-agenda-api/src/main/java/gg/agenda/api/user/agendateam/controller/AgendaTeamController.java +++ b/gg-agenda-api/src/main/java/gg/agenda/api/user/agendateam/controller/AgendaTeamController.java @@ -1,6 +1,7 @@ package gg.agenda.api.user.agendateam.controller; import static gg.data.agenda.type.AgendaTeamStatus.*; +import static gg.utils.exception.ErrorCode.*; import java.util.List; import java.util.Optional; @@ -42,6 +43,7 @@ import gg.data.agenda.type.Coalition; import gg.utils.dto.PageRequestDto; import gg.utils.dto.PageResponseDto; +import gg.utils.exception.custom.ForbiddenException; import io.swagger.v3.oas.annotations.Parameter; import lombok.RequiredArgsConstructor; @@ -115,6 +117,9 @@ public ResponseEntity leaveAgendaTeam(@Parameter(hidden = true) @Login Use AgendaTeam agendaTeam = agendaTeamService.getAgendaTeam(teamKeyReqDto.getTeamKey()); agendaTeam.getAgenda().agendaStatusMustBeOpen(); agendaTeam.agendaTeamStatusMustBeOpenAndConfirm(); + if (!agendaTeam.getLeaderIntraId().equals(user.getIntraId())) { + throw new ForbiddenException(TEAM_LEADER_FORBIDDEN); + } agendaTeamService.leaveTeamAll(agendaTeam); agendaSlackService.slackCancelAgendaTeam(agendaTeam.getAgenda(), agendaTeam); return ResponseEntity.noContent().build(); @@ -130,6 +135,9 @@ public ResponseEntity dropAgendaTeamMate(@Parameter(hidden = true) @Login AgendaTeam agendaTeam = agendaTeamService.getAgendaTeam(teamKeyReqDto.getTeamKey()); agendaTeam.getAgenda().agendaStatusMustBeOpen(); agendaTeam.agendaTeamStatusMustBeOpen(); + if (agendaTeam.getLeaderIntraId().equals(user.getIntraId())) { + throw new ForbiddenException(NOT_TEAM_MATE); + } agendaTeamService.leaveTeamMate(agendaTeam, user); agendaSlackService.slackLeaveTeamMate(agendaTeam.getAgenda(), agendaTeam, user.getIntraId()); return ResponseEntity.noContent().build(); diff --git a/gg-agenda-api/src/test/java/gg/agenda/api/user/agendateam/AgendaTeamControllerTest.java b/gg-agenda-api/src/test/java/gg/agenda/api/user/agendateam/AgendaTeamControllerTest.java index eaeec8f1e..ccc21e603 100644 --- a/gg-agenda-api/src/test/java/gg/agenda/api/user/agendateam/AgendaTeamControllerTest.java +++ b/gg-agenda-api/src/test/java/gg/agenda/api/user/agendateam/AgendaTeamControllerTest.java @@ -827,7 +827,7 @@ public void notValidAgendaTeam() throws Exception { } @Nested - @DisplayName("팀 Leave 테스트") + @DisplayName("팀장 Leave 테스트") class LeaveTeamTest { @BeforeEach void beforeEach() { @@ -843,13 +843,13 @@ void beforeEach() { } @Test - @DisplayName("200 팀원 팀 나가기 성공") + @DisplayName("403 팀원 팀 나가기 실패") public void leaveTeamMateSuccess() throws Exception { //given Agenda agenda = agendaMockData.createAgenda(SEOUL); AgendaTeam team = agendaMockData.createAgendaTeam(agenda, seoulUser, 2); agendaMockData.createAgendaTeamProfile(team, seoulUserAgendaProfile); - AgendaTeamProfile atp = agendaMockData.createAgendaTeamProfile(team, anotherSeoulUserAgendaProfile); + agendaMockData.createAgendaTeamProfile(team, anotherSeoulUserAgendaProfile); // when mockMvc.perform( patch("/agenda/team/cancel") @@ -857,20 +857,8 @@ public void leaveTeamMateSuccess() throws Exception { .param("agenda_key", agenda.getAgendaKey().toString()) .param("teamKey", team.getTeamKey().toString()) .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isNoContent()); + .andExpect(status().isForbidden()); // then - AgendaTeam updatedTeam = agendaTeamRepository.findByTeamKey(team.getTeamKey()).orElse(null); - assert updatedTeam != null; - assertThat(updatedTeam.getMateCount()).isEqualTo(1); - assertThat(agenda.getCurrentTeam()).isEqualTo(1); - AgendaTeamProfile updatedAtp = agendaTeamProfileRepository.findById(atp.getId()).orElse(null); - assert updatedAtp != null; - assertThat(updatedAtp.getIsExist()).isFalse(); - ticketRepository.findFirstByAgendaProfileAndIsApprovedTrueAndIsUsedFalseOrderByCreatedAtAsc( - updatedAtp.getProfile()) - .ifPresent(ticket -> { - assertThat(ticket.getUsedTo()).isNull(); - }); } @Test @@ -999,6 +987,176 @@ public void notValidAgendaTeamStatusWhenTeamLeader() throws Exception { .andExpect(status().isBadRequest()); } + @Test + @DisplayName("400 탈퇴 불가능한 Agenda 시간으로 인한 실패") + public void notValidAgendaDeadline() throws Exception { + //given + Agenda agenda = agendaMockData.createAgenda(LocalDateTime.now().minusHours(1)); + AgendaTeam team = agendaMockData.createAgendaTeam(agenda, seoulUser, SEOUL); + agendaMockData.createAgendaTeamProfile(team, seoulUserAgendaProfile); + TeamKeyReqDto req = new TeamKeyReqDto(team.getTeamKey()); + String content = objectMapper.writeValueAsString(req); + // when && then + mockMvc.perform( + patch("/agenda/team/cancel") + .header("Authorization", "Bearer " + seoulUserAccessToken) + .param("agenda_key", agenda.getAgendaKey().toString()) + .content(content) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isBadRequest()); + } + + @Test + @DisplayName("403 탈퇴 불가능한 Agenda Status 으로 인한 실패") + public void notValidAgendaStatus() throws Exception { + //given + Agenda agenda = agendaMockData.createAgenda(FINISH); + AgendaTeam team = agendaMockData.createAgendaTeam(agenda, seoulUser, SEOUL); + agendaMockData.createAgendaTeamProfile(team, seoulUserAgendaProfile); + TeamKeyReqDto req = new TeamKeyReqDto(team.getTeamKey()); + String content = objectMapper.writeValueAsString(req); + // when && then + mockMvc.perform( + patch("/agenda/team/cancel") + .header("Authorization", "Bearer " + seoulUserAccessToken) + .param("agenda_key", agenda.getAgendaKey().toString()) + .content(content) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isBadRequest()); + } + + @Test + @DisplayName("403 팀장이 아님으로 인한 실패") + public void notTeamMateFail() throws Exception { + //given + Agenda agenda = agendaMockData.createAgenda(SEOUL); + AgendaTeam team = agendaMockData.createAgendaTeam(agenda, seoulUser, 2); + agendaMockData.createAgendaTeamProfile(team, seoulUserAgendaProfile); + // when && then + mockMvc.perform( + patch("/agenda/team/cancel") + .header("Authorization", "Bearer " + gyeongsanUserAccessToken) + .param("agenda_key", agenda.getAgendaKey().toString()) + .param("teamKey", team.getTeamKey().toString()) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isForbidden()); + } + } + + @Nested + @DisplayName("팀원 Drop 테스트") + class DropTeamTest { + @BeforeEach + void beforeEach() { + seoulUser = testDataUtils.createNewUser(); + seoulUserAccessToken = testDataUtils.getLoginAccessTokenFromUser(seoulUser); + seoulUserAgendaProfile = agendaMockData.createAgendaProfile(seoulUser, SEOUL); + anotherSeoulUser = testDataUtils.createNewUser(); + anotherSeoulUserAccessToken = testDataUtils.getLoginAccessTokenFromUser(anotherSeoulUser); + anotherSeoulUserAgendaProfile = agendaMockData.createAgendaProfile(anotherSeoulUser, SEOUL); + gyeongsanUser = testDataUtils.createNewUser(); + gyeongsanUserAccessToken = testDataUtils.getLoginAccessTokenFromUser(gyeongsanUser); + gyeongsanUserAgendaProfile = agendaMockData.createAgendaProfile(gyeongsanUser, GYEONGSAN); + } + + @Test + @DisplayName("200 팀원 팀 나가기 성공") + public void leaveTeamMateSuccess() throws Exception { + //given + Agenda agenda = agendaMockData.createAgenda(SEOUL); + AgendaTeam team = agendaMockData.createAgendaTeam(agenda, seoulUser, 2); + agendaMockData.createAgendaTeamProfile(team, seoulUserAgendaProfile); + AgendaTeamProfile atp = agendaMockData.createAgendaTeamProfile(team, anotherSeoulUserAgendaProfile); + // when + mockMvc.perform( + patch("/agenda/team/drop") + .header("Authorization", "Bearer " + anotherSeoulUserAccessToken) + .param("agenda_key", agenda.getAgendaKey().toString()) + .param("teamKey", team.getTeamKey().toString()) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isNoContent()); + // then + AgendaTeam updatedTeam = agendaTeamRepository.findByTeamKey(team.getTeamKey()).orElse(null); + assert updatedTeam != null; + assertThat(updatedTeam.getMateCount()).isEqualTo(1); + assertThat(agenda.getCurrentTeam()).isEqualTo(1); + AgendaTeamProfile updatedAtp = agendaTeamProfileRepository.findById(atp.getId()).orElse(null); + assert updatedAtp != null; + assertThat(updatedAtp.getIsExist()).isFalse(); + ticketRepository.findFirstByAgendaProfileAndIsApprovedTrueAndIsUsedFalseOrderByCreatedAtAsc( + updatedAtp.getProfile()) + .ifPresent(ticket -> { + assertThat(ticket.getUsedTo()).isNull(); + }); + } + + @Test + @DisplayName("403 팀리더 팀 나가기 실패") + public void leaveTeamLeaderSuccess() throws Exception { + //given + Agenda agenda = agendaMockData.createAgenda(SEOUL); + AgendaTeam team = agendaMockData.createAgendaTeam(agenda, seoulUser, 2); + AgendaTeamProfile atpLeader = agendaMockData.createAgendaTeamProfile(team, seoulUserAgendaProfile); + AgendaTeamProfile atp = agendaMockData.createAgendaTeamProfile(team, anotherSeoulUserAgendaProfile); + // when + mockMvc.perform( + patch("/agenda/team/drop") + .header("Authorization", "Bearer " + seoulUserAccessToken) + .param("agenda_key", agenda.getAgendaKey().toString()) + .param("teamKey", team.getTeamKey().toString()) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isForbidden()); + } + + @Test + @DisplayName("403 Confirm 팀 리더 팀 나가기 실패") + public void leaveTeamLeaderTeamStatusConfirmSuccess() throws Exception { + //given + Agenda agenda = agendaMockData.createAgenda(SEOUL); + AgendaTeam team = agendaMockData.createAgendaTeam(agenda, seoulUser, SEOUL, AgendaTeamStatus.CONFIRM); + agendaMockData.createAgendaTeamProfile(team, seoulUserAgendaProfile); + agendaMockData.createAgendaTeamProfile(team, anotherSeoulUserAgendaProfile); + // when + mockMvc.perform( + patch("/agenda/team/drop") + .header("Authorization", "Bearer " + seoulUserAccessToken) + .param("agenda_key", agenda.getAgendaKey().toString()) + .param("teamKey", team.getTeamKey().toString()) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isBadRequest()); + } + + @Test + @DisplayName("404 agenda 없음으로 인한 실패") + public void noAgendaFail() throws Exception { + //given + UUID noAgendaKey = UUID.randomUUID(); + UUID noTeamKey = UUID.randomUUID(); + // when && then + mockMvc.perform( + patch("/agenda/team/drop") + .header("Authorization", "Bearer " + seoulUserAccessToken) + .param("agenda_key", noAgendaKey.toString()) + .param("teamKey", noTeamKey.toString()) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isNotFound()); + } + + @Test + @DisplayName("404 team 없음으로 인한 실패") + public void noTeamFail() throws Exception { + //given + Agenda agenda = agendaMockData.createAgenda(SEOUL); + // when && then + mockMvc.perform( + patch("/agenda/team/drop") + .header("Authorization", "Bearer " + seoulUserAccessToken) + .param("agenda_key", agenda.getAgendaKey().toString()) + .param("teamKey", UUID.randomUUID().toString()) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isNotFound()); + } + @Test @DisplayName("400 탈퇴 불가능한 AgendaTeam Status로 인한 팀원의 나가기 실패") public void notValidAgendaTeamStatusConfirmWhenTeamMate() throws Exception { @@ -1011,7 +1169,7 @@ public void notValidAgendaTeamStatusConfirmWhenTeamMate() throws Exception { String content = objectMapper.writeValueAsString(req); // when && then mockMvc.perform( - patch("/agenda/team/cancel") + patch("/agenda/team/drop") .header("Authorization", "Bearer " + anotherSeoulUserAccessToken) .param("agenda_key", agenda.getAgendaKey().toString()) .content(content) @@ -1031,7 +1189,7 @@ public void notValidAgendaTeamStatusCoiWhenTeamMate() throws Exception { String content = objectMapper.writeValueAsString(req); // when && then mockMvc.perform( - patch("/agenda/team/cancel") + patch("/agenda/team/drop") .header("Authorization", "Bearer " + anotherSeoulUserAccessToken) .param("agenda_key", agenda.getAgendaKey().toString()) .content(content) @@ -1050,7 +1208,7 @@ public void notValidAgendaDeadline() throws Exception { String content = objectMapper.writeValueAsString(req); // when && then mockMvc.perform( - patch("/agenda/team/cancel") + patch("/agenda/team/drop") .header("Authorization", "Bearer " + seoulUserAccessToken) .param("agenda_key", agenda.getAgendaKey().toString()) .content(content) @@ -1069,7 +1227,7 @@ public void notValidAgendaStatus() throws Exception { String content = objectMapper.writeValueAsString(req); // when && then mockMvc.perform( - patch("/agenda/team/cancel") + patch("/agenda/team/drop") .header("Authorization", "Bearer " + seoulUserAccessToken) .param("agenda_key", agenda.getAgendaKey().toString()) .content(content) @@ -1086,7 +1244,7 @@ public void notTeamMateFail() throws Exception { agendaMockData.createAgendaTeamProfile(team, seoulUserAgendaProfile); // when && then mockMvc.perform( - patch("/agenda/team/cancel") + patch("/agenda/team/drop") .header("Authorization", "Bearer " + gyeongsanUserAccessToken) .param("agenda_key", agenda.getAgendaKey().toString()) .param("teamKey", team.getTeamKey().toString()) diff --git a/gg-utils/src/main/java/gg/utils/exception/ErrorCode.java b/gg-utils/src/main/java/gg/utils/exception/ErrorCode.java index b3c68558c..cdc8162f1 100644 --- a/gg-utils/src/main/java/gg/utils/exception/ErrorCode.java +++ b/gg-utils/src/main/java/gg/utils/exception/ErrorCode.java @@ -213,7 +213,7 @@ public enum ErrorCode { NOT_TEAM_MATE(403, "AG204", "팀원이 아닙니다."), CONFIRM_FORBIDDEN(403, "AG205", "개최자만 일정을 종료할 수 있습니다."), TICKET_FORBIDDEN(403, "AG206", "티켓 신청은 1분의 대기시간이 있습니다."), - TEAM_LEADER_FORBIDDEN(403, "AG207", "팀장만 팀을 확정할 수 있습니다."), + TEAM_LEADER_FORBIDDEN(403, "AG207", "팀장이 아닙니다."), AGENDA_TEAM_FORBIDDEN(403, "AG208", "일정에 참여한 팀이 있습니다."), AGENDA_MODIFICATION_FORBIDDEN(403, "AG209", "개최자만 일정을 수정할 수 있습니다."), AUTH_NOT_FOUND(404, "AG301", "42 정보가 만료되었습니다."),