diff --git a/backend/src/docs/group.adoc b/backend/src/docs/group.adoc index 56fc5e95..6e2a7422 100644 --- a/backend/src/docs/group.adoc +++ b/backend/src/docs/group.adoc @@ -17,6 +17,9 @@ operation::post join group[snippets='http-request,http-response'] === 그룹 초대 operation::post invite group[snippets='http-request,http-response'] +=== 그룹 초대 삭제 +operation::delete group invite[snippets='http-request,http-response'] + === 위치 공유 ON operation::post share location[snippets='http-request,http-response'] diff --git a/backend/src/docs/plan.adoc b/backend/src/docs/plan.adoc index 2b7dd926..1a3d5474 100644 --- a/backend/src/docs/plan.adoc +++ b/backend/src/docs/plan.adoc @@ -17,9 +17,15 @@ operation::get plan[snippets='http-request,http-response'] === 계획 삭제 operation::delete plan[snippets='http-request,http-response'] +=== 계획 초대 +operation::post invite plan[snippets='http-request,http-response'] + === 계획 참여 operation::post join plan[snippets='http-request,http-response'] +=== 계획 초대 삭제 +operation::delete plan invite[snippets='http-request,http-response'] + === 계획 탈퇴 operation::post out plan[snippets='http-request,http-response'] diff --git a/backend/src/main/java/com/twtw/backend/domain/group/controller/GroupController.java b/backend/src/main/java/com/twtw/backend/domain/group/controller/GroupController.java index 59deab5f..7ca3f5cf 100644 --- a/backend/src/main/java/com/twtw/backend/domain/group/controller/GroupController.java +++ b/backend/src/main/java/com/twtw/backend/domain/group/controller/GroupController.java @@ -1,22 +1,13 @@ package com.twtw.backend.domain.group.controller; -import com.twtw.backend.domain.group.dto.request.InviteGroupRequest; -import com.twtw.backend.domain.group.dto.request.JoinGroupRequest; -import com.twtw.backend.domain.group.dto.request.MakeGroupRequest; -import com.twtw.backend.domain.group.dto.request.OutGroupRequest; -import com.twtw.backend.domain.group.dto.request.UpdateLocationRequest; +import com.twtw.backend.domain.group.dto.request.DeleteGroupInviteRequest; +import com.twtw.backend.domain.group.dto.request.*; import com.twtw.backend.domain.group.dto.response.GroupInfoResponse; import com.twtw.backend.domain.group.dto.response.ShareInfoResponse; import com.twtw.backend.domain.group.dto.response.SimpleGroupInfoResponse; import com.twtw.backend.domain.group.service.GroupService; - import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.UUID; @@ -53,6 +44,12 @@ public ResponseEntity inviteGroup( return ResponseEntity.ok(groupService.inviteGroup(inviteGroupRequest)); } + @DeleteMapping("/invite") + public ResponseEntity deleteInvite(@RequestBody DeleteGroupInviteRequest deleteGroupInviteRequest) { + groupService.deleteInvite(deleteGroupInviteRequest); + return ResponseEntity.noContent().build(); + } + @PostMapping("/share/{id}") public ResponseEntity shareLocation(@PathVariable UUID id) { groupService.shareLocation(id); diff --git a/backend/src/main/java/com/twtw/backend/domain/group/dto/request/DeleteGroupInviteRequest.java b/backend/src/main/java/com/twtw/backend/domain/group/dto/request/DeleteGroupInviteRequest.java new file mode 100644 index 00000000..a35e3614 --- /dev/null +++ b/backend/src/main/java/com/twtw/backend/domain/group/dto/request/DeleteGroupInviteRequest.java @@ -0,0 +1,14 @@ +package com.twtw.backend.domain.group.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.UUID; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class DeleteGroupInviteRequest { + private UUID groupId; +} diff --git a/backend/src/main/java/com/twtw/backend/domain/group/entity/Group.java b/backend/src/main/java/com/twtw/backend/domain/group/entity/Group.java index f6db95ff..07f01d59 100644 --- a/backend/src/main/java/com/twtw/backend/domain/group/entity/Group.java +++ b/backend/src/main/java/com/twtw/backend/domain/group/entity/Group.java @@ -73,8 +73,19 @@ public void inviteAll(final List friends) { friends.forEach(friend -> addGroupMember(new GroupMember(this, friend))); } - private boolean addGroupMember(final GroupMember groupMember) { - return this.groupMembers.add(groupMember); + public List getGroupMembers() { + return this.groupMembers.stream().filter(GroupMember::isAccepted).toList(); + } + + private void addGroupMember(final GroupMember groupMember) { + if (hasSameMember(groupMember)) { + return; + } + this.groupMembers.add(groupMember); + } + + private boolean hasSameMember(final GroupMember groupMember) { + return this.groupMembers.stream().map(GroupMember::getMember).anyMatch(groupMember::isSameMember); } public void updateMemberLocation( @@ -100,4 +111,8 @@ public void outGroup(final Member member) { private boolean hasNoLeader() { return this.groupMembers.stream().noneMatch(GroupMember::isLeader); } + + public void deleteInvite(final Member member) { + this.groupMembers.removeIf(groupMember -> groupMember.isSameMember(member)); + } } diff --git a/backend/src/main/java/com/twtw/backend/domain/group/entity/GroupMember.java b/backend/src/main/java/com/twtw/backend/domain/group/entity/GroupMember.java index 7050dbff..8eef93fb 100644 --- a/backend/src/main/java/com/twtw/backend/domain/group/entity/GroupMember.java +++ b/backend/src/main/java/com/twtw/backend/domain/group/entity/GroupMember.java @@ -102,4 +102,8 @@ public boolean isSameMember(final Member member) { public boolean isLeader() { return this.group.getLeaderId().equals(this.member.getId()); } + + public boolean isAccepted() { + return this.groupInviteCode == GroupInviteCode.ACCEPTED; + } } diff --git a/backend/src/main/java/com/twtw/backend/domain/group/service/GroupService.java b/backend/src/main/java/com/twtw/backend/domain/group/service/GroupService.java index c96f7bcd..a4e86f4e 100644 --- a/backend/src/main/java/com/twtw/backend/domain/group/service/GroupService.java +++ b/backend/src/main/java/com/twtw/backend/domain/group/service/GroupService.java @@ -1,10 +1,6 @@ package com.twtw.backend.domain.group.service; -import com.twtw.backend.domain.group.dto.request.InviteGroupRequest; -import com.twtw.backend.domain.group.dto.request.JoinGroupRequest; -import com.twtw.backend.domain.group.dto.request.MakeGroupRequest; -import com.twtw.backend.domain.group.dto.request.OutGroupRequest; -import com.twtw.backend.domain.group.dto.request.UpdateLocationRequest; +import com.twtw.backend.domain.group.dto.request.*; import com.twtw.backend.domain.group.dto.response.GroupInfoResponse; import com.twtw.backend.domain.group.dto.response.ShareInfoResponse; import com.twtw.backend.domain.group.dto.response.SimpleGroupInfoResponse; @@ -148,4 +144,11 @@ public void outGroup(final OutGroupRequest outGroupRequest) { final Group group = getGroupEntity(outGroupRequest.getGroupId()); group.outGroup(member); } + + @Transactional + public void deleteInvite(final DeleteGroupInviteRequest deleteGroupInviteRequest) { + final Member member = authService.getMemberByJwt(); + final Group group = getGroupEntity(deleteGroupInviteRequest.getGroupId()); + group.deleteInvite(member); + } } diff --git a/backend/src/main/java/com/twtw/backend/domain/plan/controller/PlanController.java b/backend/src/main/java/com/twtw/backend/domain/plan/controller/PlanController.java index 9ef58f56..62eb5acb 100644 --- a/backend/src/main/java/com/twtw/backend/domain/plan/controller/PlanController.java +++ b/backend/src/main/java/com/twtw/backend/domain/plan/controller/PlanController.java @@ -53,9 +53,21 @@ public ResponseEntity deletePlanById(@PathVariable UUID id) { return ResponseEntity.noContent().build(); } + @PostMapping("/invite") + public ResponseEntity invitePlan(@RequestBody PlanMemberRequest request) { + return ResponseEntity.ok(planService.invitePlan(request)); + } + + @DeleteMapping("/invite") + public ResponseEntity deleteInvite(@RequestBody PlanMemberRequest request) { + planService.deleteInvite(request); + return ResponseEntity.noContent().build(); + } + @PostMapping("/join") - public ResponseEntity joinPlan(@RequestBody PlanMemberRequest request) { - return ResponseEntity.ok(planService.joinPlan(request)); + public ResponseEntity joinPlan(@RequestBody PlanMemberRequest request) { + planService.joinPlan(request); + return ResponseEntity.noContent().build(); } @PostMapping("/out") diff --git a/backend/src/main/java/com/twtw/backend/domain/plan/entity/Plan.java b/backend/src/main/java/com/twtw/backend/domain/plan/entity/Plan.java index 0dc6094a..644cc708 100644 --- a/backend/src/main/java/com/twtw/backend/domain/plan/entity/Plan.java +++ b/backend/src/main/java/com/twtw/backend/domain/plan/entity/Plan.java @@ -8,31 +8,18 @@ import com.twtw.backend.global.audit.AuditListener; import com.twtw.backend.global.audit.Auditable; import com.twtw.backend.global.audit.BaseTime; - -import jakarta.persistence.CascadeType; -import jakarta.persistence.Column; -import jakarta.persistence.Embedded; -import jakarta.persistence.Entity; -import jakarta.persistence.EntityListeners; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.OneToMany; -import jakarta.persistence.OneToOne; - +import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; - import org.hibernate.annotations.Where; import java.time.LocalDateTime; import java.util.HashSet; import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; @Getter @Entity @@ -74,11 +61,22 @@ public Plan(Member member, Place place, Group group, LocalDateTime planDay) { } public void addMember(final Member member) { + if (hasSameMember(member)) { + return; + } this.planMembers.add(new PlanMember(this, member, false)); } + private boolean hasSameMember(final Member member) { + return this.planMembers.stream().anyMatch(planMember -> planMember.isSameMember(member)); + } + + public Set getPlanMembers() { + return this.planMembers.stream().filter(PlanMember::isAccepted).collect(Collectors.toSet()); + } + public void deleteMember(final Member member) { - this.planMembers.removeIf(planMember -> planMember.hasSameMember(member)); + this.planMembers.removeIf(planMember -> planMember.isSameMember(member)); if (hasNoPlanMaker()) { this.planMembers.stream().findFirst().ifPresent(PlanMember::updateToPlanMaker); @@ -126,4 +124,15 @@ public UUID getPlanMakerId() { .getMember() .getId(); } + + public void acceptInvite(final Member member) { + this.planMembers.stream() + .filter(planMember -> planMember.isSameMember(member)) + .findFirst() + .ifPresent(PlanMember::acceptInvite); + } + + public void deleteInvite(final Member member) { + this.planMembers.removeIf(planMember -> planMember.isSameMember(member)); + } } diff --git a/backend/src/main/java/com/twtw/backend/domain/plan/entity/PlanInviteCode.java b/backend/src/main/java/com/twtw/backend/domain/plan/entity/PlanInviteCode.java new file mode 100644 index 00000000..d742ef0e --- /dev/null +++ b/backend/src/main/java/com/twtw/backend/domain/plan/entity/PlanInviteCode.java @@ -0,0 +1,12 @@ +package com.twtw.backend.domain.plan.entity; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum PlanInviteCode { + REQUESTED("요청"), + ACCEPTED("승인"), + DENIED("거절"); + + private final String toKorean; +} diff --git a/backend/src/main/java/com/twtw/backend/domain/plan/entity/PlanMember.java b/backend/src/main/java/com/twtw/backend/domain/plan/entity/PlanMember.java index 4f31feff..1937c651 100644 --- a/backend/src/main/java/com/twtw/backend/domain/plan/entity/PlanMember.java +++ b/backend/src/main/java/com/twtw/backend/domain/plan/entity/PlanMember.java @@ -5,15 +5,7 @@ import com.twtw.backend.global.audit.Auditable; import com.twtw.backend.global.audit.BaseTime; -import jakarta.persistence.Column; -import jakarta.persistence.Embedded; -import jakarta.persistence.Entity; -import jakarta.persistence.EntityListeners; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; +import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; @@ -44,6 +36,9 @@ public class PlanMember implements Auditable { @ManyToOne(fetch = FetchType.LAZY) private Member member; + @Enumerated(EnumType.STRING) + private PlanInviteCode planInviteCode; + private Boolean isPlanMaker; @Setter @@ -56,13 +51,22 @@ public PlanMember(final Plan plan, final Member member, final Boolean isPlanMake this.plan = plan; this.member = member; this.isPlanMaker = isPlanMaker; + this.planInviteCode = PlanInviteCode.REQUESTED; } - public boolean hasSameMember(final Member member) { + public boolean isSameMember(final Member member) { return this.member.equals(member); } public void updateToPlanMaker() { this.isPlanMaker = true; } + + public boolean isAccepted() { + return this.planInviteCode == PlanInviteCode.ACCEPTED; + } + + public void acceptInvite() { + this.planInviteCode = PlanInviteCode.ACCEPTED; + } } diff --git a/backend/src/main/java/com/twtw/backend/domain/plan/service/PlanService.java b/backend/src/main/java/com/twtw/backend/domain/plan/service/PlanService.java index 2fb04e1a..1177410c 100644 --- a/backend/src/main/java/com/twtw/backend/domain/plan/service/PlanService.java +++ b/backend/src/main/java/com/twtw/backend/domain/plan/service/PlanService.java @@ -84,7 +84,8 @@ public PlanResponse savePlan(final SavePlanRequest request) { return planMapper.toPlanResponse(planRepository.save(plan)); } - public PlanResponse joinPlan(PlanMemberRequest request) { + @Transactional + public PlanResponse invitePlan(PlanMemberRequest request) { Member member = authService.getMemberByJwt(); Plan plan = getPlanEntity(request.getPlanId()); plan.addMember(member); @@ -149,4 +150,18 @@ public void updatePlanDay(final UpdatePlanDayRequest request) { final Plan plan = getPlanEntity(request.getPlanId()); plan.updatePlanDay(request.getChangeDay()); } + + @Transactional + public void joinPlan(final PlanMemberRequest request) { + Member member = authService.getMemberByJwt(); + Plan plan = getPlanEntity(request.getPlanId()); + plan.acceptInvite(member); + } + + @Transactional + public void deleteInvite(final PlanMemberRequest request) { + Member member = authService.getMemberByJwt(); + Plan plan = getPlanEntity(request.getPlanId()); + plan.deleteInvite(member); + } } diff --git a/backend/src/test/java/com/twtw/backend/domain/group/controller/GroupControllerTest.java b/backend/src/test/java/com/twtw/backend/domain/group/controller/GroupControllerTest.java index 0b0a5ebc..113134d0 100644 --- a/backend/src/test/java/com/twtw/backend/domain/group/controller/GroupControllerTest.java +++ b/backend/src/test/java/com/twtw/backend/domain/group/controller/GroupControllerTest.java @@ -1,30 +1,12 @@ package com.twtw.backend.domain.group.controller; -import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentRequest; -import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentResponse; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.willDoNothing; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.twtw.backend.domain.group.dto.request.InviteGroupRequest; -import com.twtw.backend.domain.group.dto.request.JoinGroupRequest; -import com.twtw.backend.domain.group.dto.request.MakeGroupRequest; -import com.twtw.backend.domain.group.dto.request.OutGroupRequest; -import com.twtw.backend.domain.group.dto.request.UpdateLocationRequest; +import com.twtw.backend.domain.group.dto.request.*; import com.twtw.backend.domain.group.dto.response.GroupInfoResponse; import com.twtw.backend.domain.group.dto.response.ShareInfoResponse; import com.twtw.backend.domain.group.dto.response.SimpleGroupInfoResponse; import com.twtw.backend.domain.group.service.GroupService; import com.twtw.backend.domain.member.dto.response.MemberResponse; import com.twtw.backend.support.docs.RestDocsTest; - import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -36,6 +18,17 @@ import java.util.List; import java.util.UUID; +import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentRequest; +import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentResponse; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.willDoNothing; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + @DisplayName("GroupController의") @WebMvcTest(GroupController.class) class GroupControllerTest extends RestDocsTest { @@ -168,6 +161,30 @@ void inviteGroup() throws Exception { .andDo(document("post invite group", getDocumentRequest(), getDocumentResponse())); } + @Test + @DisplayName("그룹 초대 삭제 API가 수행되는가") + void deleteInvite() throws Exception { + // given + willDoNothing().given(groupService).deleteInvite(any()); + + // when + final ResultActions perform = + mockMvc.perform( + delete("/group/invite") + .contentType(MediaType.APPLICATION_JSON) + .content(toRequestBody(new DeleteGroupInviteRequest(UUID.randomUUID()))) + .header( + "Authorization", + "Bearer wefa3fsdczf32.gaoiuergf92.gb5hsa2jgh")); + + // then + perform.andExpect(status().isNoContent()); + + // docs + perform.andDo(print()) + .andDo(document("delete group invite", getDocumentRequest(), getDocumentResponse())); + } + @Test @DisplayName("위치 공유 수정 API가 수행되는가") void shareLocation() throws Exception { diff --git a/backend/src/test/java/com/twtw/backend/domain/group/repository/GroupRepositoryTest.java b/backend/src/test/java/com/twtw/backend/domain/group/repository/GroupRepositoryTest.java index f0d0a7b9..1a59a6a5 100644 --- a/backend/src/test/java/com/twtw/backend/domain/group/repository/GroupRepositoryTest.java +++ b/backend/src/test/java/com/twtw/backend/domain/group/repository/GroupRepositoryTest.java @@ -1,7 +1,5 @@ package com.twtw.backend.domain.group.repository; -import static org.assertj.core.api.Assertions.assertThat; - import com.twtw.backend.domain.group.entity.Group; import com.twtw.backend.domain.group.entity.GroupMember; import com.twtw.backend.domain.member.entity.Member; @@ -12,7 +10,6 @@ import com.twtw.backend.fixture.member.MemberEntityFixture; import com.twtw.backend.fixture.place.PlaceEntityFixture; import com.twtw.backend.support.repository.RepositoryTest; - import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -20,6 +17,8 @@ import java.time.LocalDateTime; import java.util.List; +import static org.assertj.core.api.Assertions.assertThat; + @DisplayName("GroupRepository의") class GroupRepositoryTest extends RepositoryTest { @@ -49,7 +48,7 @@ void makeGroup() { final Group saveGroup = groupRepository.save(group); // then - assertThat(saveGroup.getGroupMembers()).hasSize(2); + assertThat(saveGroup.getGroupMembers()).hasSize(1); } @Test diff --git a/backend/src/test/java/com/twtw/backend/domain/group/service/GroupServiceTest.java b/backend/src/test/java/com/twtw/backend/domain/group/service/GroupServiceTest.java index 68e8df64..ab352cc6 100644 --- a/backend/src/test/java/com/twtw/backend/domain/group/service/GroupServiceTest.java +++ b/backend/src/test/java/com/twtw/backend/domain/group/service/GroupServiceTest.java @@ -1,7 +1,5 @@ package com.twtw.backend.domain.group.service; -import static org.assertj.core.api.Assertions.assertThat; - import com.twtw.backend.domain.group.dto.request.InviteGroupRequest; import com.twtw.backend.domain.group.dto.request.JoinGroupRequest; import com.twtw.backend.domain.group.dto.request.MakeGroupRequest; @@ -15,13 +13,14 @@ import com.twtw.backend.domain.member.entity.Member; import com.twtw.backend.fixture.member.MemberEntityFixture; import com.twtw.backend.support.service.LoginTest; - import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import java.util.List; +import static org.assertj.core.api.Assertions.assertThat; + @DisplayName("GroupService의") class GroupServiceTest extends LoginTest { @Autowired private GroupService groupService; @@ -158,9 +157,7 @@ void getGroupById() { Group group1 = new Group("BABY_MONSTER", "YG_OFFICIAL_IMAGE", leader); - GroupMember groupMember1 = new GroupMember(group1, loginUser); - - group1.getGroupMembers().add(groupMember1); + group1.inviteAll(List.of(loginUser)); Group saveGroup1 = groupRepository.save(group1); // when @@ -168,6 +165,6 @@ void getGroupById() { GroupInfoResponse response = groupService.getGroupById(saveGroup1.getId()); // then - assertThat(response.getGroupMembers()).hasSize(2); + assertThat(response.getGroupMembers()).hasSize(1); } } diff --git a/backend/src/test/java/com/twtw/backend/domain/plan/controller/PlanControllerTest.java b/backend/src/test/java/com/twtw/backend/domain/plan/controller/PlanControllerTest.java index 343aca67..2eae1dad 100644 --- a/backend/src/test/java/com/twtw/backend/domain/plan/controller/PlanControllerTest.java +++ b/backend/src/test/java/com/twtw/backend/domain/plan/controller/PlanControllerTest.java @@ -1,17 +1,5 @@ package com.twtw.backend.domain.plan.controller; -import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentRequest; -import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentResponse; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.willDoNothing; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - import com.twtw.backend.domain.group.dto.response.GroupInfoResponse; import com.twtw.backend.domain.member.dto.response.MemberResponse; import com.twtw.backend.domain.place.entity.CategoryGroupCode; @@ -25,7 +13,6 @@ import com.twtw.backend.domain.plan.dto.response.PlanResponse; import com.twtw.backend.domain.plan.service.PlanService; import com.twtw.backend.support.docs.RestDocsTest; - import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -37,6 +24,17 @@ import java.util.List; import java.util.UUID; +import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentRequest; +import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentResponse; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.willDoNothing; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + @DisplayName("PlanController의") @WebMvcTest(PlanController.class) class PlanControllerTest extends RestDocsTest { @@ -196,11 +194,10 @@ void deletePlanById() throws Exception { } @Test - @DisplayName("계획 참여 API가 수행되는가") + @DisplayName("계획 초대 API가 수행되는가") void joinPlan() throws Exception { // given - final PlanResponse expected = new PlanResponse(UUID.randomUUID(), UUID.randomUUID()); - given(planService.joinPlan(any())).willReturn(expected); + willDoNothing().given(planService).joinPlan(any()); // when final ResultActions perform = @@ -209,28 +206,69 @@ void joinPlan() throws Exception { .contentType(MediaType.APPLICATION_JSON) .content( toRequestBody( - new SavePlanRequest( - UUID.randomUUID(), - LocalDateTime.of(2023, 12, 25, 13, 30), - new PlaceDetails( - "이디야커피 안성죽산점", - "http://place.map.kakao.com/1562566188", - "경기 안성시 죽산면 죽주로 287-1", - 127.426865189637, - 37.0764635355795)))) + new PlanMemberRequest(UUID.randomUUID()))) .header( "Authorization", "Bearer wefa3fsdczf32.gaoiuergf92.gb5hsa2jgh")); // then - perform.andExpect(status().isOk()) - .andExpect(jsonPath("$.planId").isString()) - .andExpect(jsonPath("$.groupId").isString()); + perform.andExpect(status().isNoContent()); // docs perform.andDo(print()) .andDo(document("post join plan", getDocumentRequest(), getDocumentResponse())); } + @Test + @DisplayName("계획 참여 API가 수행되는가") + void invitePlan() throws Exception { + // given + final PlanResponse expected = new PlanResponse(UUID.randomUUID(), UUID.randomUUID()); + given(planService.invitePlan(any())).willReturn(expected); + + // when + final ResultActions perform = + mockMvc.perform( + post("/plans/invite") + .contentType(MediaType.APPLICATION_JSON) + .content( + toRequestBody( + new PlanMemberRequest(UUID.randomUUID()))) + .header( + "Authorization", + "Bearer wefa3fsdczf32.gaoiuergf92.gb5hsa2jgh")); + // then + perform.andExpect(status().isOk()); + + // docs + perform.andDo(print()) + .andDo(document("post invite plan", getDocumentRequest(), getDocumentResponse())); + } + + @Test + @DisplayName("계획 초대 삭제 API가 수행되는가") + void deleteInvite() throws Exception { + // given + willDoNothing().given(planService).deletePlan(any()); + + // when + final ResultActions perform = + mockMvc.perform( + delete("/plans/invite") + .contentType(MediaType.APPLICATION_JSON) + .content( + toRequestBody( + new PlanMemberRequest(UUID.randomUUID()))) + .header( + "Authorization", + "Bearer wefa3fsdczf32.gaoiuergf92.gb5hsa2jgh")); + // then + perform.andExpect(status().isNoContent()); + + // docs + perform.andDo(print()) + .andDo(document("delete plan invite", getDocumentRequest(), getDocumentResponse())); + } + @Test @DisplayName("계획 탈퇴 API가 수행되는가") void outPlan() throws Exception { diff --git a/backend/src/test/java/com/twtw/backend/domain/plan/service/PlanServiceTest.java b/backend/src/test/java/com/twtw/backend/domain/plan/service/PlanServiceTest.java index 5b731f78..209c1bba 100644 --- a/backend/src/test/java/com/twtw/backend/domain/plan/service/PlanServiceTest.java +++ b/backend/src/test/java/com/twtw/backend/domain/plan/service/PlanServiceTest.java @@ -1,7 +1,5 @@ package com.twtw.backend.domain.plan.service; -import static org.assertj.core.api.Assertions.assertThat; - import com.twtw.backend.domain.group.repository.GroupRepository; import com.twtw.backend.domain.member.entity.Member; import com.twtw.backend.domain.place.entity.CategoryGroupCode; @@ -18,7 +16,6 @@ import com.twtw.backend.fixture.place.PlaceEntityFixture; import com.twtw.backend.fixture.plan.PlanEntityFixture; import com.twtw.backend.support.service.LoginTest; - import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -27,6 +24,8 @@ import java.util.Optional; import java.util.UUID; +import static org.assertj.core.api.Assertions.assertThat; + @DisplayName("PlanService의") class PlanServiceTest extends LoginTest { @@ -83,7 +82,9 @@ void joinPlan() { final UUID planId = plan.getId(); // when - planService.joinPlan(new PlanMemberRequest(planId)); + planService.invitePlan(new PlanMemberRequest(planId)); + plan.acceptInvite(loginUser); + plan.acceptInvite(member); // then final Plan result = planRepository.findById(planId).orElseThrow();