Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Friend CRUD #36

Merged
merged 3 commits into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import com.server.domain.friend.enums.FriendState;
import com.server.domain.friend.service.FriendService;
import com.server.global.dto.ApiResponseDto;
import com.server.global.jwt.JwtService;

import io.swagger.v3.oas.annotations.Operation;
import jakarta.servlet.http.HttpServletRequest;
Expand All @@ -29,16 +28,14 @@
@RequestMapping("/api/friends")
public class FriendController {

private final JwtService jwtService;
private final FriendService friendService;

@ResponseStatus(HttpStatus.CREATED)
@PostMapping("/request")
@Operation(summary = "친구 신청 생성", description = "친구 신청할 사용자의 이름을 입력하여 친구 신청 생성")
public ApiResponseDto<String> createFriendRequest(HttpServletRequest request,
@RequestParam String receiptUsername) {
String requestUsername = jwtService.extractUsernameFromToken(request).get();
friendService.createFriendRequest(requestUsername, receiptUsername);
String requestUsername = friendService.createFriendRequest(request, receiptUsername);

Check warning on line 38 in src/main/java/com/server/domain/friend/controller/FriendController.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/server/domain/friend/controller/FriendController.java#L38

Added line #L38 was not covered by tests
return ApiResponseDto.success(HttpStatus.CREATED.value(),
String.format("A friend request from User '%s' to User '%s' has been created.",
requestUsername, receiptUsername));
Expand All @@ -50,8 +47,7 @@
public ApiResponseDto<List<GetFriendOutDto>> getFriendRequest(
@RequestParam(required = false) FriendState state,
HttpServletRequest request) {
String username = jwtService.extractUsernameFromToken(request).get();
List<GetFriendOutDto> getUserOutDtos = friendService.getRequestUser(username, state);
List<GetFriendOutDto> getUserOutDtos = friendService.getRequestUser(request, state);

Check warning on line 50 in src/main/java/com/server/domain/friend/controller/FriendController.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/server/domain/friend/controller/FriendController.java#L50

Added line #L50 was not covered by tests
return ApiResponseDto.success(HttpStatus.OK.value(), getUserOutDtos);
}

Expand All @@ -60,8 +56,7 @@
@Operation(summary = "친구 신청 취소", description = "친구 신청할 사용자의 이름을 입력하여 친구 신청 삭제")
public ApiResponseDto<String> deleteFriendRequest(HttpServletRequest request,
@RequestParam String receiptUsername) {
String requestUsername = jwtService.extractUsernameFromToken(request).get();
friendService.deleteFriendRequest(requestUsername, receiptUsername);
String requestUsername = friendService.deleteFriendRequest(request, receiptUsername);

Check warning on line 59 in src/main/java/com/server/domain/friend/controller/FriendController.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/server/domain/friend/controller/FriendController.java#L59

Added line #L59 was not covered by tests
return ApiResponseDto.success(HttpStatus.OK.value(), String
.format("The friend request from '%s' to '%s' has been deleted.", requestUsername, receiptUsername));
}
Expand All @@ -71,8 +66,7 @@
@Operation(summary = "친구 내역 조회", description = "사용자 기준 신청 받은 내역")
public ApiResponseDto<List<GetFriendOutDto>> getFriendReceipt(HttpServletRequest request,
@RequestParam(required = false) FriendState state) {
String username = jwtService.extractUsernameFromToken(request).get();
List<GetFriendOutDto> getUserOutDtos = friendService.getReceiptUser(username, state);
List<GetFriendOutDto> getUserOutDtos = friendService.getReceiptUser(request, state);

Check warning on line 69 in src/main/java/com/server/domain/friend/controller/FriendController.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/server/domain/friend/controller/FriendController.java#L69

Added line #L69 was not covered by tests
return ApiResponseDto.success(HttpStatus.OK.value(), getUserOutDtos);
}

Expand All @@ -81,8 +75,7 @@
@Operation(summary = "친구 신청 승인", description = "친구 신청을 승인할 사용자의 이름을 입력하여 친구 신청 승인")
public ApiResponseDto<String> approveFriendRequest(HttpServletRequest request,
@RequestParam String requestUsername) {
String receiptUsername = jwtService.extractUsernameFromToken(request).get();
friendService.acceptFriendRequest(requestUsername, receiptUsername);
String receiptUsername = friendService.acceptFriendRequest(requestUsername, request);

Check warning on line 78 in src/main/java/com/server/domain/friend/controller/FriendController.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/server/domain/friend/controller/FriendController.java#L78

Added line #L78 was not covered by tests
return ApiResponseDto.success(HttpStatus.CREATED.value(), String.format(
"The friend request from User '%s' to User '%s' has been accepted.", requestUsername, receiptUsername));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
import com.server.global.error.code.FriendErrorCode;
import com.server.global.error.code.UserErrorCode;
import com.server.global.error.exception.BusinessException;
import com.server.global.jwt.JwtService;

import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;

@Service
Expand All @@ -29,9 +31,11 @@
private final UserRepository userRepository;
private final FriendRepository friendRepository;
private final FriendMapper friendMapper;
private final JwtService jwtService;

public List<GetFriendOutDto> getRequestUser(String username, FriendState state) {
public List<GetFriendOutDto> getRequestUser(HttpServletRequest request, FriendState state) {
List<Friend> friends;
String username = jwtService.extractUsernameFromToken(request).get();

Check warning on line 38 in src/main/java/com/server/domain/friend/service/FriendService.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/server/domain/friend/service/FriendService.java#L38

Added line #L38 was not covered by tests
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new BusinessException(UserErrorCode.NOT_FOUND));
if (state == null) {
Expand All @@ -47,7 +51,8 @@
return getFriendOutDtos;
}

public List<GetFriendOutDto> getReceiptUser(String username, FriendState state) {
public List<GetFriendOutDto> getReceiptUser(HttpServletRequest request, FriendState state) {
String username = jwtService.extractUsernameFromToken(request).get();
List<Friend> friends;
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new BusinessException(UserErrorCode.NOT_FOUND));
Expand Down Expand Up @@ -87,7 +92,8 @@
}

@Transactional
public Friend createFriendRequest(String requestUsername, String receiptUsername) {
public String createFriendRequest(HttpServletRequest request, String receiptUsername) {
String requestUsername = jwtService.extractUsernameFromToken(request).get();
User requestUser = userRepository.findByUsername(requestUsername)
.orElseThrow(() -> new BusinessException(UserErrorCode.NOT_FOUND));
User receiptUser = userRepository.findByUsername(receiptUsername)
Expand All @@ -98,11 +104,13 @@
.receiptUser(receiptUser)
.state(FriendState.SENDING)
.build();
return friendRepository.save(friend);
friendRepository.save(friend);
return requestUsername;
}

@Transactional
public void deleteFriendRequest(String requestUsername, String receiptUsername) {
public String deleteFriendRequest(HttpServletRequest request, String receiptUsername) {
String requestUsername = jwtService.extractUsernameFromToken(request).get();
User requestUser = userRepository.findByUsername(requestUsername)
.orElseThrow(() -> new BusinessException(UserErrorCode.NOT_FOUND));
User receiptUser = userRepository.findByUsername(receiptUsername)
Expand All @@ -116,10 +124,12 @@
throw new BusinessException(FriendErrorCode.REQUEST_ALREADY_REMOVED);
}
friend.setState(FriendState.REMOVED);
return requestUsername;
}

@Transactional
public void acceptFriendRequest(String requestUsername, String receiptUsername) {
public String acceptFriendRequest(String requestUsername, HttpServletRequest request) {
String receiptUsername = jwtService.extractUsernameFromToken(request).get();
User requestUser = userRepository.findByUsername(requestUsername)
.orElseThrow(() -> new BusinessException(UserErrorCode.NOT_FOUND));
User receiptUser = userRepository.findByUsername(receiptUsername)
Expand All @@ -144,5 +154,6 @@
.build();
friendRepository.save(friendApproved);
}
return receiptUsername;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
package com.server.domain.friend.service;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.times;

import java.util.List;
import java.util.Optional;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.mock.web.MockHttpServletRequest;

import com.server.domain.friend.dto.GetFriendOutDto;
import com.server.domain.friend.entity.Friend;
import com.server.domain.friend.enums.FriendState;
import com.server.domain.friend.mapper.FriendMapper;
import com.server.domain.friend.repository.FriendRepository;
import com.server.domain.user.entity.User;
import com.server.domain.user.repository.UserRepository;
import com.server.global.jwt.JwtService;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@ExtendWith(MockitoExtension.class)
class FriendServiceTest {

@InjectMocks
private FriendService friendService;

@Mock
private JwtService jwtService;

@Mock
private UserRepository userRepository;

@Mock
private FriendRepository friendRepository;

@Mock
private FriendMapper friendMapper;

@Test
@DisplayName("본인이 다른 사용자에게 친구 신청")
void createFriendRequest_requestUser_returnsFriendRequest() {
/* given */
String requestUsername = "request user";
String receiptUsername = "receipt user";
User requestUser = User.builder()
.username(requestUsername)
.email("[email protected]")
.thumbnail("https://avatars.githubusercontent.com/u/0?v=4")
.oauth("github")
.githubToken("gho1234")
.build();
User receiptUser = User.builder()
.username(receiptUsername)
.email("[email protected]")
.thumbnail("https://avatars.githubusercontent.com/u/0?v=4")
.oauth("github")
.githubToken("gho4321")
.build();
MockHttpServletRequest request = new MockHttpServletRequest();
given(jwtService.extractUsernameFromToken(request)).willReturn(Optional.of(requestUsername));
given(userRepository.findByUsername(requestUsername)).willReturn(Optional.of(requestUser));
given(userRepository.findByUsername(receiptUsername)).willReturn(Optional.of(receiptUser));

/* when */
ArgumentCaptor<Friend> friendCaptor = ArgumentCaptor.forClass(Friend.class);
friendService.createFriendRequest(request, receiptUsername);

/* then */
then(friendRepository).should(times(1)).save(friendCaptor.capture());
Friend savedFriend = friendCaptor.getValue();
assertThat(savedFriend.getRequestUser()).isEqualTo(requestUser);
assertThat(savedFriend.getReceiptUser()).isEqualTo(receiptUser);
assertThat(savedFriend.getState()).isEqualTo(FriendState.SENDING);
}

@Test
@DisplayName("다른 사용자가 보낸 친구 신청 수락")
void acceptFriendRequest_receiptUser_returnsFriendRequest() {
/* given */
String requestUsername = "request user";
String receiptUsername = "receipt user";
User requestUser = User.builder()
.username(requestUsername)
.email("[email protected]")
.thumbnail("https://avatars.githubusercontent.com/u/0?v=4")
.oauth("github")
.githubToken("gho1234")
.build();
User receiptUser = User.builder()
.username(receiptUsername)
.email("[email protected]")
.thumbnail("https://avatars.githubusercontent.com/u/0?v=4")
.oauth("github")
.githubToken("gho4321")
.build();
Friend friendRequested = Friend.builder().requestUser(requestUser).receiptUser(receiptUser)
.state(FriendState.SENDING).build();
MockHttpServletRequest request = new MockHttpServletRequest();
given(jwtService.extractUsernameFromToken(request)).willReturn(Optional.of(receiptUsername));
given(userRepository.findByUsername(requestUsername)).willReturn(Optional.of(requestUser));
given(userRepository.findByUsername(receiptUsername)).willReturn(Optional.of(receiptUser));
given(friendRepository.findByRequestUserAndReceiptUser(requestUser, receiptUser))
.willReturn(Optional.of(friendRequested));
given(friendRepository.findByRequestUserAndReceiptUser(receiptUser, requestUser))
.willReturn(Optional.empty());

/* when */
ArgumentCaptor<Friend> friendCaptor = ArgumentCaptor.forClass(Friend.class);
friendService.acceptFriendRequest(requestUsername, request);

/* then */
assertThat(friendRequested.getState()).isEqualTo(FriendState.ACCEPTED);
then(friendRepository).should(times(1)).save(friendCaptor.capture());
List<Friend> capturedFriends = friendCaptor.getAllValues();
assertThat(capturedFriends.get(0).getState()).isEqualTo(FriendState.ACCEPTED);
}

@Test
@DisplayName("본인이 보낸 친구 신청 삭제")
void deleteFriendRequest_requestUser_returnsFriendRequest() {
/* given */
String requestUsername = "request user";
String receiptUsername = "receipt user";
User requestUser = User.builder()
.username(requestUsername)
.email("[email protected]")
.thumbnail("https://avatars.githubusercontent.com/u/0?v=4")
.oauth("github")
.githubToken("gho1234")
.build();
User receiptUser = User.builder()
.username(receiptUsername)
.email("[email protected]")
.thumbnail("https://avatars.githubusercontent.com/u/0?v=4")
.oauth("github")
.githubToken("gho4321")
.build();
Friend friendRequested = Friend.builder().requestUser(requestUser).receiptUser(receiptUser)
.state(FriendState.SENDING).build();
MockHttpServletRequest request = new MockHttpServletRequest();
given(jwtService.extractUsernameFromToken(request)).willReturn(Optional.of(requestUsername));
given(userRepository.findByUsername(requestUsername)).willReturn(Optional.of(requestUser));
given(userRepository.findByUsername(receiptUsername)).willReturn(Optional.of(receiptUser));
given(friendRepository.findByRequestUserAndReceiptUser(requestUser, receiptUser))
.willReturn(Optional.of(friendRequested));

/* when */
friendService.deleteFriendRequest(request, receiptUsername);

/* then */
assertThat(friendRequested.getState()).isEqualTo(FriendState.REMOVED);
}

@Test
@DisplayName("타인이 친구 신청했을 때 본인이 친구 신청 목록 조회")
void getFriendRequest_receiptUser_returnsFriendRequest() {
/* given */
String requestUsername = "request user";
String receiptUsername = "receipt user";
User requestUser = User.builder()
.username(requestUsername)
.email("[email protected]")
.thumbnail("https://avatars.githubusercontent.com/u/0?v=4")
.oauth("github")
.githubToken("gho1234")
.build();
User receiptUser = User.builder()
.username(receiptUsername)
.email("[email protected]")
.thumbnail("https://avatars.githubusercontent.com/u/0?v=4")
.oauth("github")
.githubToken("gho4321")
.build();
Friend friendRequested = Friend.builder().requestUser(requestUser).receiptUser(receiptUser)
.state(FriendState.SENDING).build();
List<Friend> friends = List.of(friendRequested);
MockHttpServletRequest request = new MockHttpServletRequest();
GetFriendOutDto dto = new GetFriendOutDto();
dto.setUsername(requestUser.getUsername());
dto.setEmail(requestUser.getEmail());
dto.setState(FriendState.SENDING);
given(jwtService.extractUsernameFromToken(request)).willReturn(Optional.of(receiptUsername));
given(userRepository.findByUsername(receiptUsername)).willReturn(Optional.of(receiptUser));
given(friendRepository.findByReceiptUser(receiptUser)).willReturn(Optional.of(friends));
given(friendMapper.toGetFriendOutDto(requestUser, FriendState.SENDING)).willReturn(dto);

/* when */
List<GetFriendOutDto> dtos = friendService.getReceiptUser(request, null);

/* then */
assertThat(dtos).hasSize(1);
GetFriendOutDto dto0 = dtos.get(0);
assertThat(dto0.getUsername()).isEqualTo(requestUser.getUsername());
assertThat(dto0.getState()).isEqualTo(FriendState.SENDING);
}
}
Loading