From 182dd1b07a1d719ef7c4aff6efd44490df8cb0f8 Mon Sep 17 00:00:00 2001 From: kanguk Date: Wed, 13 Nov 2024 22:38:34 +0900 Subject: [PATCH 01/27] =?UTF-8?q?refactor:=20FCM=20=EB=A1=9C=EC=A7=81=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 --- .../splanet/core/exception/ErrorCode.java | 4 ++ .../notification/controller/FcmTokenApi.java | 5 +-- .../controller/FcmTokenController.java | 11 +++--- .../repository/FcmTokenRepository.java | 1 + .../notification/service/FcmTokenService.java | 12 +++--- .../service/FcmTokenServiceTest.java | 38 +++++++------------ 6 files changed, 33 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/splanet/splanet/core/exception/ErrorCode.java b/src/main/java/com/splanet/splanet/core/exception/ErrorCode.java index 145a5913..b96e6769 100644 --- a/src/main/java/com/splanet/splanet/core/exception/ErrorCode.java +++ b/src/main/java/com/splanet/splanet/core/exception/ErrorCode.java @@ -54,6 +54,10 @@ public enum ErrorCode { // redis REDIS_SCAN_FAILED("Redis 키 스캔 중 오류가 발생했습니다.", HttpStatus.SERVICE_UNAVAILABLE), + // fcm + TOKEN_NOT_FOUND("해당 FCM 토큰을 찾을 수 없습니다.", HttpStatus.NOT_FOUND), + + // ect INVALID_PLAN_FORMAT("", HttpStatus.BAD_REQUEST); diff --git a/src/main/java/com/splanet/splanet/notification/controller/FcmTokenApi.java b/src/main/java/com/splanet/splanet/notification/controller/FcmTokenApi.java index 5eb4ead0..ded58677 100644 --- a/src/main/java/com/splanet/splanet/notification/controller/FcmTokenApi.java +++ b/src/main/java/com/splanet/splanet/notification/controller/FcmTokenApi.java @@ -30,13 +30,13 @@ ResponseEntity registerFcmToken( @Operation(summary = "FCM 토큰 설정 수정", description = "알림 설정 및 알림 오프셋을 수정합니다.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "FCM 토큰 설정이 성공적으로 수정되었습니다."), - @ApiResponse(responseCode = "404", description = "유저를 찾을 수 없습니다.", content = @Content) + @ApiResponse(responseCode = "404", description = "토큰을 찾을 수 없습니다.", content = @Content) }) ResponseEntity updateFcmTokenSettings( - @AuthenticationPrincipal Long userId, @RequestBody FcmTokenUpdateRequest fcmTokenUpdateRequest ); + @DeleteMapping("/delete") @Operation(summary = "FCM 토큰 삭제", description = "유저의 FCM 토큰을 삭제합니다.") @ApiResponses(value = { @@ -44,7 +44,6 @@ ResponseEntity updateFcmTokenSettings( @ApiResponse(responseCode = "404", description = "해당 토큰을 찾을 수 없습니다.", content = @Content) }) ResponseEntity deleteFcmToken( - @AuthenticationPrincipal Long userId, @RequestParam String token ); } diff --git a/src/main/java/com/splanet/splanet/notification/controller/FcmTokenController.java b/src/main/java/com/splanet/splanet/notification/controller/FcmTokenController.java index 38523c35..93507b7b 100644 --- a/src/main/java/com/splanet/splanet/notification/controller/FcmTokenController.java +++ b/src/main/java/com/splanet/splanet/notification/controller/FcmTokenController.java @@ -21,14 +21,15 @@ public ResponseEntity registerFcmToken(Long userId, FcmTokenRequest fcmT } @Override - public ResponseEntity updateFcmTokenSettings(Long userId, FcmTokenUpdateRequest fcmTokenUpdateRequest) { - fcmTokenService.updateFcmTokenSettings(userId, fcmTokenUpdateRequest); - return ResponseEntity.ok("FCM token 수정 완료"); + public ResponseEntity updateFcmTokenSettings(FcmTokenUpdateRequest fcmTokenUpdateRequest) { + fcmTokenService.updateFcmTokenSettings(fcmTokenUpdateRequest); + return ResponseEntity.ok("FCM 토큰 수정 완료"); } + @Override - public ResponseEntity deleteFcmToken(Long userId, String token) { - fcmTokenService.deleteFcmToken(userId, token); + public ResponseEntity deleteFcmToken(String token) { + fcmTokenService.deleteFcmToken(token); return ResponseEntity.ok("FCM token 삭제 완료"); } } diff --git a/src/main/java/com/splanet/splanet/notification/repository/FcmTokenRepository.java b/src/main/java/com/splanet/splanet/notification/repository/FcmTokenRepository.java index 1f26d161..6fea10f3 100644 --- a/src/main/java/com/splanet/splanet/notification/repository/FcmTokenRepository.java +++ b/src/main/java/com/splanet/splanet/notification/repository/FcmTokenRepository.java @@ -12,4 +12,5 @@ public interface FcmTokenRepository extends JpaRepository { Optional findByUserIdAndToken(Long userId, String token); List findByUserId(Long userId); List findByUserIdIn(Collection userIds); + Optional findByToken(String token); } diff --git a/src/main/java/com/splanet/splanet/notification/service/FcmTokenService.java b/src/main/java/com/splanet/splanet/notification/service/FcmTokenService.java index 29190f26..6b3676d1 100644 --- a/src/main/java/com/splanet/splanet/notification/service/FcmTokenService.java +++ b/src/main/java/com/splanet/splanet/notification/service/FcmTokenService.java @@ -34,9 +34,9 @@ public void registerFcmToken(Long userId, String token) { } @Transactional - public void updateFcmTokenSettings(Long userId, FcmTokenUpdateRequest request) { - FcmToken fcmToken = fcmTokenRepository.findByUserIdAndToken(userId, request.token()) - .orElseThrow(() -> new BusinessException(ErrorCode.USER_NOT_FOUND)); + public void updateFcmTokenSettings(FcmTokenUpdateRequest request) { + FcmToken fcmToken = fcmTokenRepository.findByToken(request.token()) + .orElseThrow(() -> new BusinessException(ErrorCode.TOKEN_NOT_FOUND)); fcmToken = fcmToken.toBuilder() .isNotificationEnabled(request.isNotificationEnabled() != null @@ -51,9 +51,9 @@ public void updateFcmTokenSettings(Long userId, FcmTokenUpdateRequest request) { } @Transactional - public void deleteFcmToken(Long userId, String token) { - FcmToken fcmToken = fcmTokenRepository.findByUserIdAndToken(userId, token) - .orElseThrow(() -> new BusinessException(ErrorCode.USER_NOT_FOUND)); + public void deleteFcmToken(String token) { + FcmToken fcmToken = fcmTokenRepository.findByToken(token) + .orElseThrow(() -> new BusinessException(ErrorCode.TOKEN_NOT_FOUND)); fcmTokenRepository.delete(fcmToken); } } diff --git a/src/test/java/com/splanet/splanet/notification/service/FcmTokenServiceTest.java b/src/test/java/com/splanet/splanet/notification/service/FcmTokenServiceTest.java index 1390e6ff..2a8ece7d 100644 --- a/src/test/java/com/splanet/splanet/notification/service/FcmTokenServiceTest.java +++ b/src/test/java/com/splanet/splanet/notification/service/FcmTokenServiceTest.java @@ -1,6 +1,7 @@ package com.splanet.splanet.notification.service; import com.splanet.splanet.core.exception.BusinessException; +import com.splanet.splanet.core.exception.ErrorCode; import com.splanet.splanet.notification.dto.FcmTokenUpdateRequest; import com.splanet.splanet.notification.entity.FcmToken; import com.splanet.splanet.notification.repository.FcmTokenRepository; @@ -8,9 +9,10 @@ import com.splanet.splanet.user.repository.UserRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; import java.util.Optional; @@ -19,6 +21,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; +@ExtendWith(MockitoExtension.class) class FcmTokenServiceTest { @Mock @@ -30,11 +33,6 @@ class FcmTokenServiceTest { @InjectMocks private FcmTokenService fcmTokenService; - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - } - @Test void FCM토큰_등록_성공() { Long userId = 1L; @@ -65,61 +63,53 @@ void setUp() { @Test void FCM토큰_설정_수정_성공() { - Long userId = 1L; String token = "testToken"; FcmTokenUpdateRequest request = new FcmTokenUpdateRequest(token, true, 30); FcmToken fcmToken = FcmToken.builder() - .user(User.builder().id(userId).build()) .token(token) .isNotificationEnabled(false) .notificationOffset(15) .build(); - when(fcmTokenRepository.findByUserIdAndToken(userId, token)).thenReturn(Optional.of(fcmToken)); + when(fcmTokenRepository.findByToken(token)).thenReturn(Optional.of(fcmToken)); - assertDoesNotThrow(() -> fcmTokenService.updateFcmTokenSettings(userId, request)); + assertDoesNotThrow(() -> fcmTokenService.updateFcmTokenSettings(request)); verify(fcmTokenRepository, times(1)).save(any(FcmToken.class)); } @Test void FCM토큰_설정_수정_토큰없음_예외발생() { - Long userId = 1L; String token = "testToken"; FcmTokenUpdateRequest request = new FcmTokenUpdateRequest(token, true, 30); - when(fcmTokenRepository.findByUserIdAndToken(userId, token)).thenReturn(Optional.empty()); + when(fcmTokenRepository.findByToken(token)).thenReturn(Optional.empty()); BusinessException exception = assertThrows(BusinessException.class, () -> - fcmTokenService.updateFcmTokenSettings(userId, request)); + fcmTokenService.updateFcmTokenSettings(request)); verify(fcmTokenRepository, never()).save(any(FcmToken.class)); } @Test void FCM토큰_삭제_성공() { - Long userId = 1L; String token = "testToken"; - FcmToken fcmToken = FcmToken.builder() - .user(User.builder().id(userId).build()) - .token(token) - .build(); + FcmToken fcmToken = FcmToken.builder().token(token).build(); - when(fcmTokenRepository.findByUserIdAndToken(userId, token)).thenReturn(Optional.of(fcmToken)); + when(fcmTokenRepository.findByToken(token)).thenReturn(Optional.of(fcmToken)); - assertDoesNotThrow(() -> fcmTokenService.deleteFcmToken(userId, token)); + assertDoesNotThrow(() -> fcmTokenService.deleteFcmToken(token)); verify(fcmTokenRepository, times(1)).delete(fcmToken); } @Test void FCM토큰_삭제_토큰없음_예외발생() { - Long userId = 1L; String token = "testToken"; - when(fcmTokenRepository.findByUserIdAndToken(userId, token)).thenReturn(Optional.empty()); + when(fcmTokenRepository.findByToken(token)).thenReturn(Optional.empty()); BusinessException exception = assertThrows(BusinessException.class, () -> - fcmTokenService.deleteFcmToken(userId, token)); + fcmTokenService.deleteFcmToken(token)); verify(fcmTokenRepository, never()).delete(any(FcmToken.class)); } -} \ No newline at end of file +} From 7274b64c4049e358ad941ee6b12109c4ac76cb0a Mon Sep 17 00:00:00 2001 From: kanguk Date: Thu, 14 Nov 2024 09:23:23 +0900 Subject: [PATCH 02/27] =?UTF-8?q?refactor:=20GPT=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EB=8D=94=20=EB=B3=B4=EC=99=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 더 정확하게 한다. --- .../splanet/gpt/service/GptService.java | 14 ++++++++----- .../splanet/splanet/plan/dto/PlanTimeDto.java | 21 +++++++++++++++++++ .../plan/repository/PlanRepository.java | 3 +++ .../splanet/plan/service/PlanService.java | 12 ++++++----- 4 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/splanet/splanet/plan/dto/PlanTimeDto.java diff --git a/src/main/java/com/splanet/splanet/gpt/service/GptService.java b/src/main/java/com/splanet/splanet/gpt/service/GptService.java index a4fc07f2..0df8170d 100644 --- a/src/main/java/com/splanet/splanet/gpt/service/GptService.java +++ b/src/main/java/com/splanet/splanet/gpt/service/GptService.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.splanet.splanet.core.properties.GptProperties; import com.splanet.splanet.plan.dto.PlanResponseDto; +import com.splanet.splanet.plan.dto.PlanTimeDto; import com.splanet.splanet.plan.service.PlanService; import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.http.ResponseEntity; @@ -25,9 +26,9 @@ public class GptService { private static final double RESPONSE_TEMPERATURE = 0.8; private static final Map PROMPT_TEMPLATES = Map.of( - 3, "사용자 입력: \"%s\" (deviceId: %s) (groupId: %s) 기존 일정이 있다면 해당 시간과는 겹치지 않게 해 줘 기존일정:%s 현재 시간 이후로 가능한 자주 반복하여 짧고 집중적으로 일정을 완수할 수 있도록 계획을 세워줘. 시험이 포함된 경우, 시험 당일이 아닌 전날까지 준비가 완료되도록 해줘 (%s 기준). 모든 일정은 한국 시간(UTC+9)을 기준으로 설정해줘.", - 2, "사용자 입력: \"%s\" (deviceId: %s) (groupId: %s) 기존 일정이 있다면 해당 시간과는 겹치지 않게 해 줘 기존일정:%s 현재 시간 이후로 적당한 간격을 두고 모든 일정을 완수할 수 있도록 계획해줘. 시험이 포함된 경우, 시험 당일이 아닌 전날까지 준비가 완료되도록 해줘 (%s 기준). 모든 일정은 한국 시간(UTC+9)을 기준으로 설정해줘.", - 1, "사용자 입력: \"%s\" (deviceId: %s) (groupId: %s) 기존 일정이 있다면 해당 시간과는 겹치지 않게 해 줘 기존일정:%s 현재 시간 이후로 여유 있게 모든 일정을 완수할 수 있도록 계획해줘. 시험이 포함된 경우, 시험 당일이 아닌 전날까지 준비가 완료되도록 해줘 (%s 기준). 모든 일정은 한국 시간(UTC+9)을 기준으로 설정해줘." + 3, "사용자 입력: \"%s\" (deviceId: %s) (groupId: %s) 기존 startDate와 endDate사이에 일정을 생성하지 말아줘. 기존 startDate, endDate:%s 현재 시간 이후로 가능한 자주 반복하여 짧고 집중적으로 일정을 완수할 수 있도록 계획을 세워줘. 시험이 포함된 경우, 시험 당일이 아닌 전날까지 준비가 완료되도록 해줘 (%s 기준). 모든 일정은 한국 시간(UTC+9)을 기준으로 설정해줘.", + 2, "사용자 입력: \"%s\" (deviceId: %s) (groupId: %s) 기존 startDate와 endDate사이에 일정을 생성하지 말아줘. 기존 startDate, endDate:%s 현재 시간 이후로 적당한 간격을 두고 모든 일정을 완수할 수 있도록 계획해줘. 시험이 포함된 경우, 시험 당일이 아닌 전날까지 준비가 완료되도록 해줘 (%s 기준). 모든 일정은 한국 시간(UTC+9)을 기준으로 설정해줘.", + 1, "사용자 입력: \"%s\" (deviceId: %s) (groupId: %s) 기존 startDate와 endDate사이에 일정을 생성하지 말아줘. 기존 startDate, endDate:%s 현재 시간 이후로 여유 있게 모든 일정을 완수할 수 있도록 계획해줘. 시험이 포함된 경우, 시험 당일이 아닌 전날까지 준비가 완료되도록 해줘 (%s 기준). 모든 일정은 한국 시간(UTC+9)을 기준으로 설정해줘." ); public GptService(OpenAiApi openAiApi, GptProperties gptProperties, PlanService planService, ObjectMapper objectMapper) { @@ -39,7 +40,7 @@ public GptService(OpenAiApi openAiApi, GptProperties gptProperties, PlanService public String generateResponse(String userInput, Long userId, String deviceId, int groupId) { String currentTime = getCurrentTime(); - List futurePlans = (userId != null) ? planService.getAllFuturePlansByUserId(userId) : List.of(); + List futurePlans = (userId != null) ? planService.getAllFuturePlanTimesByUserId(userId) : List.of(); String planJson = convertPlansToJson(futurePlans); String promptTemplate = PROMPT_TEMPLATES.get(groupId); String fullPrompt = String.format(promptTemplate, userInput, deviceId, groupId, planJson, currentTime); @@ -47,14 +48,17 @@ public String generateResponse(String userInput, Long userId, String deviceId, i OpenAiApi.ChatCompletionMessage userMessage = createUserMessage(fullPrompt); OpenAiApi.ChatCompletionRequest chatRequest = createChatRequest(userMessage); + System.out.println(fullPrompt); + return getGptResponse(chatRequest); + } private String getCurrentTime() { return LocalDateTime.now(ZoneId.of("Asia/Seoul")).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); } - private String convertPlansToJson(List futurePlans) { + private String convertPlansToJson(List futurePlans) { try { return objectMapper.writeValueAsString(futurePlans); } catch (JsonProcessingException e) { diff --git a/src/main/java/com/splanet/splanet/plan/dto/PlanTimeDto.java b/src/main/java/com/splanet/splanet/plan/dto/PlanTimeDto.java new file mode 100644 index 00000000..09a951a6 --- /dev/null +++ b/src/main/java/com/splanet/splanet/plan/dto/PlanTimeDto.java @@ -0,0 +1,21 @@ +package com.splanet.splanet.plan.dto; + +import java.time.LocalDateTime; + +public class PlanTimeDto { + private LocalDateTime startDate; + private LocalDateTime endDate; + + public PlanTimeDto(LocalDateTime startDate, LocalDateTime endDate) { + this.startDate = startDate; + this.endDate = endDate; + } + + public LocalDateTime getStartDate() { + return startDate; + } + + public LocalDateTime getEndDate() { + return endDate; + } +} diff --git a/src/main/java/com/splanet/splanet/plan/repository/PlanRepository.java b/src/main/java/com/splanet/splanet/plan/repository/PlanRepository.java index 731c1f0c..5a57110d 100644 --- a/src/main/java/com/splanet/splanet/plan/repository/PlanRepository.java +++ b/src/main/java/com/splanet/splanet/plan/repository/PlanRepository.java @@ -18,4 +18,7 @@ public interface PlanRepository extends JpaRepository { @Query("SELECT p FROM Plan p JOIN FETCH p.user WHERE p.startDate > :now AND p.isCompleted = false") List findUpcomingPlans(@Param("now") LocalDateTime now); + @Query("SELECT p FROM Plan p WHERE p.user.id = :userId AND p.startDate > :currentTime") + List findAllFuturePlansByUserId(@Param("userId") Long userId, @Param("currentTime") LocalDateTime currentTime); + } \ No newline at end of file diff --git a/src/main/java/com/splanet/splanet/plan/service/PlanService.java b/src/main/java/com/splanet/splanet/plan/service/PlanService.java index d40d1796..f7dfa42c 100644 --- a/src/main/java/com/splanet/splanet/plan/service/PlanService.java +++ b/src/main/java/com/splanet/splanet/plan/service/PlanService.java @@ -2,6 +2,7 @@ import com.splanet.splanet.plan.dto.PlanRequestDto; import com.splanet.splanet.plan.dto.PlanResponseDto; +import com.splanet.splanet.plan.dto.PlanTimeDto; import com.splanet.splanet.plan.entity.Plan; import com.splanet.splanet.plan.mapper.PlanMapper; import com.splanet.splanet.plan.repository.PlanRepository; @@ -16,6 +17,7 @@ import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; +import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.List; import java.util.Set; @@ -118,11 +120,11 @@ private Plan convertToPlan(PlanCardResponseDto previewCard, User user, DateTimeF } @Transactional(readOnly = true) - public List getAllFuturePlansByUserId(Long userId) { - LocalDateTime now = LocalDateTime.now(); - List futurePlans = planRepository.findAllByUserIdAndStartDateAfter(userId, now); - return futurePlans.stream() - .map(planMapper::toResponseDto) + public List getAllFuturePlanTimesByUserId(Long userId) { + LocalDateTime currentTime = LocalDateTime.now(ZoneId.of("Asia/Seoul")); + return planRepository.findAllFuturePlansByUserId(userId, currentTime) + .stream() + .map(plan -> new PlanTimeDto(plan.getStartDate(), plan.getEndDate())) .collect(Collectors.toList()); } From ac877624ac49c6b372e8b9813f018f8d83c9efd4 Mon Sep 17 00:00:00 2001 From: kanguk Date: Thu, 14 Nov 2024 09:26:13 +0900 Subject: [PATCH 03/27] =?UTF-8?q?deploy:=20=EC=9D=BC=EB=8B=A8=20=EB=B0=B0?= =?UTF-8?q?=ED=8F=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/cd.yml | 2 +- .gitignore | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 872194b9..3defda5a 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -5,7 +5,7 @@ on: branches: - develop - 'weekly/**' - - 142-refactor-cd-update + - refactor/166-refactor-fcm jobs: deploy: diff --git a/.gitignore b/.gitignore index b502fe8e..f8c40ac3 100644 --- a/.gitignore +++ b/.gitignore @@ -56,4 +56,5 @@ splanet-db ### env ### .env /src/main/resources/env.properties +/src/main/resources/env.properties.base64 splanet-firebase.json \ No newline at end of file From fb27d23ccb26b27787096e6af039f09fed486e77 Mon Sep 17 00:00:00 2001 From: kanguk Date: Thu, 14 Nov 2024 13:21:38 +0900 Subject: [PATCH 04/27] =?UTF-8?q?refactor:=20plan=20=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=9D=98=EB=8F=84=EC=B9=98=20=EC=95=8A=EA=B2=8C=20=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EB=B6=80=EB=B6=84=EC=9D=B4=20=EB=A6=AC?= =?UTF-8?q?=ED=84=B4=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=B6=80?= =?UTF-8?q?=EB=B6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/splanet/splanet/plan/dto/PlanResponseDto.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/splanet/splanet/plan/dto/PlanResponseDto.java b/src/main/java/com/splanet/splanet/plan/dto/PlanResponseDto.java index 49279433..33ab0619 100644 --- a/src/main/java/com/splanet/splanet/plan/dto/PlanResponseDto.java +++ b/src/main/java/com/splanet/splanet/plan/dto/PlanResponseDto.java @@ -14,11 +14,9 @@ public class PlanResponseDto { private String description; private LocalDateTime startDate; private LocalDateTime endDate; - - @JsonIgnore private Boolean accessibility; - @JsonIgnore private Boolean isCompleted; + @JsonIgnore private LocalDateTime createdAt; @JsonIgnore From a6ec3433b7b32cb17621a0ea348301533059ce3e Mon Sep 17 00:00:00 2001 From: kanguk Date: Thu, 14 Nov 2024 20:46:09 +0900 Subject: [PATCH 05/27] =?UTF-8?q?refactor:=20GPT=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EB=B3=B4=EC=99=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/splanet/splanet/gpt/service/GptService.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/splanet/splanet/gpt/service/GptService.java b/src/main/java/com/splanet/splanet/gpt/service/GptService.java index 0df8170d..576dfbc7 100644 --- a/src/main/java/com/splanet/splanet/gpt/service/GptService.java +++ b/src/main/java/com/splanet/splanet/gpt/service/GptService.java @@ -26,9 +26,9 @@ public class GptService { private static final double RESPONSE_TEMPERATURE = 0.8; private static final Map PROMPT_TEMPLATES = Map.of( - 3, "사용자 입력: \"%s\" (deviceId: %s) (groupId: %s) 기존 startDate와 endDate사이에 일정을 생성하지 말아줘. 기존 startDate, endDate:%s 현재 시간 이후로 가능한 자주 반복하여 짧고 집중적으로 일정을 완수할 수 있도록 계획을 세워줘. 시험이 포함된 경우, 시험 당일이 아닌 전날까지 준비가 완료되도록 해줘 (%s 기준). 모든 일정은 한국 시간(UTC+9)을 기준으로 설정해줘.", - 2, "사용자 입력: \"%s\" (deviceId: %s) (groupId: %s) 기존 startDate와 endDate사이에 일정을 생성하지 말아줘. 기존 startDate, endDate:%s 현재 시간 이후로 적당한 간격을 두고 모든 일정을 완수할 수 있도록 계획해줘. 시험이 포함된 경우, 시험 당일이 아닌 전날까지 준비가 완료되도록 해줘 (%s 기준). 모든 일정은 한국 시간(UTC+9)을 기준으로 설정해줘.", - 1, "사용자 입력: \"%s\" (deviceId: %s) (groupId: %s) 기존 startDate와 endDate사이에 일정을 생성하지 말아줘. 기존 startDate, endDate:%s 현재 시간 이후로 여유 있게 모든 일정을 완수할 수 있도록 계획해줘. 시험이 포함된 경우, 시험 당일이 아닌 전날까지 준비가 완료되도록 해줘 (%s 기준). 모든 일정은 한국 시간(UTC+9)을 기준으로 설정해줘." + 3, "사용자 입력: \"%s\" (deviceId: %s) (groupId: %s) 제공된 가이드라인을 따르지 않으면 페널티가 부과될 것입니다. 모든 지침을 주의깊게 읽고 그에 따라 행동하세요. 기존 startDate와 endDate사이에 일정을 생성하지 말아줘. 기존 startDate, endDate:%s 현재 시간 이후로 가능한 자주 반복하여 짧고 집중적으로 일정을 완수할 수 있도록 계획을 세워줘. 현재 시간 : (%s 기준). 모든 일정은 한국 시간(UTC+9)을 기준으로 설정해줘. 또한, 기존 일정을 생각하고 새로운 일정을 적당한 간격을 두고 배치해줘.", + 2, "사용자 입력: \"%s\" (deviceId: %s) (groupId: %s) 제공된 가이드라인을 따르지 않으면 페널티가 부과될 것입니다. 모든 지침을 주의깊게 읽고 그에 따라 행동하세요. 기존 startDate와 endDate사이에 일정을 생성하지 말아줘. 기존 startDate, endDate:%s 현재 시간 이후로 적당한 간격을 두고 모든 일정을 완수할 수 있도록 계획해줘. 현재 시간 : (%s 기준). 모든 일정은 한국 시간(UTC+9)을 기준으로 설정해줘. 또한, 기존 일정을 생각하고 새로운 일정을 적당한 간격을 두고 배치해줘.", + 1, "사용자 입력: \"%s\" (deviceId: %s) (groupId: %s) 제공된 가이드라인을 따르지 않으면 페널티가 부과될 것입니다. 모든 지침을 주의깊게 읽고 그에 따라 행동하세요. 기존 startDate와 endDate사이에 일정을 생성하지 말아줘. 기존 startDate, endDate:%s 현재 시간 이후로 여유 있게 모든 일정을 완수할 수 있도록 계획해줘. 현재 시간 : (%s 기준). 모든 일정은 한국 시간(UTC+9)을 기준으로 설정해줘. 또한, 기존 일정을 생각하고 새로운 일정을 적당한 간격을 두고 배치해줘." ); public GptService(OpenAiApi openAiApi, GptProperties gptProperties, PlanService planService, ObjectMapper objectMapper) { @@ -89,3 +89,4 @@ private String getGptResponse(OpenAiApi.ChatCompletionRequest chatRequest) { } } } + From 4e97993f23faf1d3961aa64be36ac5678f2fbaa1 Mon Sep 17 00:00:00 2001 From: kanguk Date: Fri, 15 Nov 2024 01:49:04 +0900 Subject: [PATCH 06/27] =?UTF-8?q?refactor:=20FCM=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20API=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/controller/FcmTokenApi.java | 27 ++++-------- .../controller/FcmTokenController.java | 12 ++++-- .../notification/service/FcmTokenService.java | 24 +++++++---- .../service/FcmTokenServiceTest.java | 43 +++++++++++++++---- 4 files changed, 66 insertions(+), 40 deletions(-) diff --git a/src/main/java/com/splanet/splanet/notification/controller/FcmTokenApi.java b/src/main/java/com/splanet/splanet/notification/controller/FcmTokenApi.java index ded58677..9b14df7c 100644 --- a/src/main/java/com/splanet/splanet/notification/controller/FcmTokenApi.java +++ b/src/main/java/com/splanet/splanet/notification/controller/FcmTokenApi.java @@ -16,33 +16,24 @@ public interface FcmTokenApi { @PostMapping("/register") - @Operation(summary = "FCM 토큰 등록", description = "유저가 FCM 토큰을 등록합니다.") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "FCM 토큰이 성공적으로 등록되었습니다."), - @ApiResponse(responseCode = "404", description = "유저를 찾을 수 없습니다.", content = @Content) - }) ResponseEntity registerFcmToken( @AuthenticationPrincipal Long userId, @RequestBody FcmTokenRequest fcmTokenRequest ); - @PutMapping("/update") - @Operation(summary = "FCM 토큰 설정 수정", description = "알림 설정 및 알림 오프셋을 수정합니다.") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "FCM 토큰 설정이 성공적으로 수정되었습니다."), - @ApiResponse(responseCode = "404", description = "토큰을 찾을 수 없습니다.", content = @Content) - }) - ResponseEntity updateFcmTokenSettings( - @RequestBody FcmTokenUpdateRequest fcmTokenUpdateRequest + @PutMapping("/update/notification-enabled") + ResponseEntity updateNotificationEnabled( + @RequestParam String token, + @RequestParam Boolean isNotificationEnabled ); + @PutMapping("/update/notification-offset") + ResponseEntity updateNotificationOffset( + @RequestParam String token, + @RequestParam Integer notificationOffset + ); @DeleteMapping("/delete") - @Operation(summary = "FCM 토큰 삭제", description = "유저의 FCM 토큰을 삭제합니다.") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "FCM 토큰이 성공적으로 삭제되었습니다."), - @ApiResponse(responseCode = "404", description = "해당 토큰을 찾을 수 없습니다.", content = @Content) - }) ResponseEntity deleteFcmToken( @RequestParam String token ); diff --git a/src/main/java/com/splanet/splanet/notification/controller/FcmTokenController.java b/src/main/java/com/splanet/splanet/notification/controller/FcmTokenController.java index 93507b7b..d4b66f01 100644 --- a/src/main/java/com/splanet/splanet/notification/controller/FcmTokenController.java +++ b/src/main/java/com/splanet/splanet/notification/controller/FcmTokenController.java @@ -1,7 +1,6 @@ package com.splanet.splanet.notification.controller; import com.splanet.splanet.notification.dto.FcmTokenRequest; -import com.splanet.splanet.notification.dto.FcmTokenUpdateRequest; import com.splanet.splanet.notification.service.FcmTokenService; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -21,11 +20,16 @@ public ResponseEntity registerFcmToken(Long userId, FcmTokenRequest fcmT } @Override - public ResponseEntity updateFcmTokenSettings(FcmTokenUpdateRequest fcmTokenUpdateRequest) { - fcmTokenService.updateFcmTokenSettings(fcmTokenUpdateRequest); - return ResponseEntity.ok("FCM 토큰 수정 완료"); + public ResponseEntity updateNotificationEnabled(String token, Boolean isNotificationEnabled) { + fcmTokenService.updateNotificationEnabled(token, isNotificationEnabled); + return ResponseEntity.ok("FCM 알림 여부 수정 완료"); } + @Override + public ResponseEntity updateNotificationOffset(String token, Integer notificationOffset) { + fcmTokenService.updateNotificationOffset(token, notificationOffset); + return ResponseEntity.ok("FCM 알림 오프셋 수정 완료"); + } @Override public ResponseEntity deleteFcmToken(String token) { diff --git a/src/main/java/com/splanet/splanet/notification/service/FcmTokenService.java b/src/main/java/com/splanet/splanet/notification/service/FcmTokenService.java index 6b3676d1..fea0ddc0 100644 --- a/src/main/java/com/splanet/splanet/notification/service/FcmTokenService.java +++ b/src/main/java/com/splanet/splanet/notification/service/FcmTokenService.java @@ -1,4 +1,3 @@ -// src/main/java/com/splanet/splanet/notification/service/FcmTokenService.java package com.splanet.splanet.notification.service; import com.splanet.splanet.core.exception.BusinessException; @@ -34,17 +33,24 @@ public void registerFcmToken(Long userId, String token) { } @Transactional - public void updateFcmTokenSettings(FcmTokenUpdateRequest request) { - FcmToken fcmToken = fcmTokenRepository.findByToken(request.token()) + public void updateNotificationEnabled(String token, Boolean isNotificationEnabled) { + FcmToken fcmToken = fcmTokenRepository.findByToken(token) + .orElseThrow(() -> new BusinessException(ErrorCode.TOKEN_NOT_FOUND)); + + fcmToken = fcmToken.toBuilder() + .isNotificationEnabled(isNotificationEnabled != null ? isNotificationEnabled : fcmToken.getIsNotificationEnabled()) + .build(); + + fcmTokenRepository.save(fcmToken); + } + + @Transactional + public void updateNotificationOffset(String token, Integer notificationOffset) { + FcmToken fcmToken = fcmTokenRepository.findByToken(token) .orElseThrow(() -> new BusinessException(ErrorCode.TOKEN_NOT_FOUND)); fcmToken = fcmToken.toBuilder() - .isNotificationEnabled(request.isNotificationEnabled() != null - ? request.isNotificationEnabled() - : fcmToken.getIsNotificationEnabled()) - .notificationOffset(request.notificationOffset() != null - ? request.notificationOffset() - : fcmToken.getNotificationOffset()) + .notificationOffset(notificationOffset != null ? notificationOffset : fcmToken.getNotificationOffset()) .build(); fcmTokenRepository.save(fcmToken); diff --git a/src/test/java/com/splanet/splanet/notification/service/FcmTokenServiceTest.java b/src/test/java/com/splanet/splanet/notification/service/FcmTokenServiceTest.java index 2a8ece7d..766a0791 100644 --- a/src/test/java/com/splanet/splanet/notification/service/FcmTokenServiceTest.java +++ b/src/test/java/com/splanet/splanet/notification/service/FcmTokenServiceTest.java @@ -56,37 +56,62 @@ class FcmTokenServiceTest { when(userRepository.findById(userId)).thenReturn(Optional.empty()); - BusinessException exception = assertThrows(BusinessException.class, () -> + assertThrows(BusinessException.class, () -> fcmTokenService.registerFcmToken(userId, token)); verify(fcmTokenRepository, never()).save(any(FcmToken.class)); } @Test - void FCM토큰_설정_수정_성공() { + void FCM알림여부_수정_성공() { String token = "testToken"; - FcmTokenUpdateRequest request = new FcmTokenUpdateRequest(token, true, 30); + Boolean isNotificationEnabled = true; FcmToken fcmToken = FcmToken.builder() .token(token) .isNotificationEnabled(false) + .build(); + + when(fcmTokenRepository.findByToken(token)).thenReturn(Optional.of(fcmToken)); + + assertDoesNotThrow(() -> fcmTokenService.updateNotificationEnabled(token, isNotificationEnabled)); + verify(fcmTokenRepository, times(1)).save(any(FcmToken.class)); + } + + @Test + void FCM알림여부_수정_토큰없음_예외발생() { + String token = "testToken"; + + when(fcmTokenRepository.findByToken(token)).thenReturn(Optional.empty()); + + assertThrows(BusinessException.class, () -> + fcmTokenService.updateNotificationEnabled(token, true)); + verify(fcmTokenRepository, never()).save(any(FcmToken.class)); + } + + @Test + void FCM알림오프셋_수정_성공() { + String token = "testToken"; + Integer notificationOffset = 30; + + FcmToken fcmToken = FcmToken.builder() + .token(token) .notificationOffset(15) .build(); when(fcmTokenRepository.findByToken(token)).thenReturn(Optional.of(fcmToken)); - assertDoesNotThrow(() -> fcmTokenService.updateFcmTokenSettings(request)); + assertDoesNotThrow(() -> fcmTokenService.updateNotificationOffset(token, notificationOffset)); verify(fcmTokenRepository, times(1)).save(any(FcmToken.class)); } @Test - void FCM토큰_설정_수정_토큰없음_예외발생() { + void FCM알림오프셋_수정_토큰없음_예외발생() { String token = "testToken"; - FcmTokenUpdateRequest request = new FcmTokenUpdateRequest(token, true, 30); when(fcmTokenRepository.findByToken(token)).thenReturn(Optional.empty()); - BusinessException exception = assertThrows(BusinessException.class, () -> - fcmTokenService.updateFcmTokenSettings(request)); + assertThrows(BusinessException.class, () -> + fcmTokenService.updateNotificationOffset(token, 30)); verify(fcmTokenRepository, never()).save(any(FcmToken.class)); } @@ -108,7 +133,7 @@ class FcmTokenServiceTest { when(fcmTokenRepository.findByToken(token)).thenReturn(Optional.empty()); - BusinessException exception = assertThrows(BusinessException.class, () -> + assertThrows(BusinessException.class, () -> fcmTokenService.deleteFcmToken(token)); verify(fcmTokenRepository, never()).delete(any(FcmToken.class)); } From b3fb589042fabbee5babfeee95d5cdcb7367d8e0 Mon Sep 17 00:00:00 2001 From: kanguk Date: Fri, 15 Nov 2024 02:25:47 +0900 Subject: [PATCH 07/27] =?UTF-8?q?refactor:=20FCM=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=ED=81=B4=EB=A6=AD=20=EC=8B=9C=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=EB=A5=BC=20=EC=9C=84=ED=95=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/service/NotificationService.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/splanet/splanet/notification/service/NotificationService.java b/src/main/java/com/splanet/splanet/notification/service/NotificationService.java index 500289ac..828d0237 100644 --- a/src/main/java/com/splanet/splanet/notification/service/NotificationService.java +++ b/src/main/java/com/splanet/splanet/notification/service/NotificationService.java @@ -42,7 +42,16 @@ public void sendNotification(FcmToken fcmToken, Plan plan) { Notification notification = new Notification(title, body); - Message message = Message.builder().setToken(fcmToken.getToken()).setNotification(notification).putData("title", plan.getTitle()).putData("title", plan.getDescription()).putData("startDate", plan.getStartDate().toString()).build(); + String clickActionUrl = "https://www.splanet.co.kr"; + + Message message = Message.builder().setToken(fcmToken.getToken()) + .setNotification(notification) + .putData("click_action", clickActionUrl) + .putData("title", plan.getTitle()) + .putData("description", plan.getDescription()) + .putData("startDate", plan.getStartDate().toString()) + .build(); + try { String response = firebaseMessaging.send(message); log.info("알림을 정상적으로 전송하였습니다. : {}", response); From 0e89e97adf1055eab372c08abc929acda9f60a44 Mon Sep 17 00:00:00 2001 From: KimSongMok Date: Fri, 15 Nov 2024 03:02:08 +0900 Subject: [PATCH 08/27] =?UTF-8?q?bug:=20=ED=8C=80=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20api=20=EC=88=98=EC=A0=95(delete=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/TeamInvitationRepository.java | 1 + .../TeamUserRelationRepository.java | 1 + .../splanet/team/service/TeamService.java | 8 ++- .../splanet/team/service/TeamServiceTest.java | 66 ++++++++++++------- 4 files changed, 53 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/splanet/splanet/team/repository/TeamInvitationRepository.java b/src/main/java/com/splanet/splanet/team/repository/TeamInvitationRepository.java index ebf47868..8f1a7e28 100644 --- a/src/main/java/com/splanet/splanet/team/repository/TeamInvitationRepository.java +++ b/src/main/java/com/splanet/splanet/team/repository/TeamInvitationRepository.java @@ -13,4 +13,5 @@ public interface TeamInvitationRepository extends JpaRepository findAllByUserAndStatus(User user, InvitationStatus status); List findAllByTeamAndStatus(Team team, InvitationStatus status); Optional findByTeamAndUserAndStatus(Team team, User user, InvitationStatus status); + void deleteAllByTeam(Team team); } \ No newline at end of file diff --git a/src/main/java/com/splanet/splanet/team/repository/TeamUserRelationRepository.java b/src/main/java/com/splanet/splanet/team/repository/TeamUserRelationRepository.java index 45b3beb1..6da4fb1a 100644 --- a/src/main/java/com/splanet/splanet/team/repository/TeamUserRelationRepository.java +++ b/src/main/java/com/splanet/splanet/team/repository/TeamUserRelationRepository.java @@ -25,5 +25,6 @@ public interface TeamUserRelationRepository extends JpaRepository findByTeamIdAndUserId(@Param("teamId") Long teamId, @Param("userId") Long userId); int countByTeam(Team team); + void deleteAllByTeam(Team team); } \ No newline at end of file diff --git a/src/main/java/com/splanet/splanet/team/service/TeamService.java b/src/main/java/com/splanet/splanet/team/service/TeamService.java index 3c432c52..e09c21d7 100644 --- a/src/main/java/com/splanet/splanet/team/service/TeamService.java +++ b/src/main/java/com/splanet/splanet/team/service/TeamService.java @@ -293,7 +293,13 @@ public void deleteTeam(Long teamId, Long adminId) { throw new BusinessException(ErrorCode.ACCESS_DENIED); } - // 팀 삭제 - 연관된 엔티티도 함께 삭제되도록 설정 + // 관련된 초대 데이터 삭제 + teamInvitationRepository.deleteAllByTeam(team); + + // 관련된 사용자 관계 삭제 + teamUserRelationRepository.deleteAllByTeam(team); + + // 팀 삭제 teamRepository.delete(team); } diff --git a/src/test/java/com/splanet/splanet/team/service/TeamServiceTest.java b/src/test/java/com/splanet/splanet/team/service/TeamServiceTest.java index 1edf52fe..92333fd7 100644 --- a/src/test/java/com/splanet/splanet/team/service/TeamServiceTest.java +++ b/src/test/java/com/splanet/splanet/team/service/TeamServiceTest.java @@ -83,28 +83,6 @@ public void testCreateTeam_InvalidInput() { assertEquals(ErrorCode.TEAM_NAME_NOT_FOUND, exception.getErrorCode()); } - @Test - public void testDeleteTeam_Success() { - when(teamUserRelationRepository.findByTeamAndUser(any(Team.class), any(User.class))) - .thenReturn(Optional.of(testRelation)); - - teamService.deleteTeam(1L, 1L); - - verify(teamRepository, times(1)).delete(testTeam); - } - - @Test - public void testDeleteTeam_AccessDenied() { - TeamUserRelation memberRelation = new TeamUserRelation(testTeam, testUser, UserTeamRole.MEMBER); - when(teamUserRelationRepository.findByTeamAndUser(any(Team.class), any(User.class))) - .thenReturn(Optional.of(memberRelation)); - - BusinessException exception = assertThrows(BusinessException.class, () -> - teamService.deleteTeam(1L, 1L) - ); - - assertEquals(ErrorCode.ACCESS_DENIED, exception.getErrorCode()); - } @Test public void testLeaveTeam_Success() { @@ -238,5 +216,49 @@ public void testInviteUserToTeam_InvitationAlreadySent() { assertEquals(ErrorCode.INVITATION_ALREADY_SENT, exception.getErrorCode()); } + @Test + public void testDeleteTeam_Success() { + when(teamUserRelationRepository.findByTeamAndUser(testTeam, testUser)) + .thenReturn(Optional.of(testRelation)); + + // 팀 삭제 시 관련 데이터 삭제 확인 + doNothing().when(teamInvitationRepository).deleteAllByTeam(testTeam); + doNothing().when(teamUserRelationRepository).deleteAllByTeam(testTeam); + doNothing().when(teamRepository).delete(testTeam); + + teamService.deleteTeam(1L, 1L); + + verify(teamInvitationRepository, times(1)).deleteAllByTeam(testTeam); + verify(teamUserRelationRepository, times(1)).deleteAllByTeam(testTeam); + verify(teamRepository, times(1)).delete(testTeam); + } + + @Test + public void testDeleteTeam_AccessDenied() { + TeamUserRelation memberRelation = new TeamUserRelation(testTeam, testUser, UserTeamRole.MEMBER); + when(teamUserRelationRepository.findByTeamAndUser(testTeam, testUser)) + .thenReturn(Optional.of(memberRelation)); + + BusinessException exception = assertThrows(BusinessException.class, () -> + teamService.deleteTeam(1L, 1L) + ); + + assertEquals(ErrorCode.ACCESS_DENIED, exception.getErrorCode()); + verify(teamRepository, never()).delete(testTeam); + } + + @Test + public void testDeleteTeam_TeamNotFound() { + when(teamRepository.findById(1L)).thenReturn(Optional.empty()); + + BusinessException exception = assertThrows(BusinessException.class, () -> + teamService.deleteTeam(1L, 1L) + ); + + assertEquals(ErrorCode.TEAM_NOT_FOUND, exception.getErrorCode()); + verify(teamInvitationRepository, never()).deleteAllByTeam(any()); + verify(teamUserRelationRepository, never()).deleteAllByTeam(any()); + verify(teamRepository, never()).delete(any()); + } } \ No newline at end of file From c3af011a113b7140200130c4f91df3044546235b Mon Sep 17 00:00:00 2001 From: kanguk Date: Fri, 15 Nov 2024 02:29:15 +0900 Subject: [PATCH 09/27] =?UTF-8?q?refactor:=20=EB=94=94=EB=B2=84=EA=B9=85?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=B4=20=EC=B6=94=EA=B0=80=ED=96=88?= =?UTF-8?q?=EB=8D=98=20=EB=B6=80=EB=B6=84=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/cd.yml | 1 - src/main/java/com/splanet/splanet/gpt/service/GptService.java | 3 --- 2 files changed, 4 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 3defda5a..1bc58047 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -5,7 +5,6 @@ on: branches: - develop - 'weekly/**' - - refactor/166-refactor-fcm jobs: deploy: diff --git a/src/main/java/com/splanet/splanet/gpt/service/GptService.java b/src/main/java/com/splanet/splanet/gpt/service/GptService.java index 576dfbc7..89275423 100644 --- a/src/main/java/com/splanet/splanet/gpt/service/GptService.java +++ b/src/main/java/com/splanet/splanet/gpt/service/GptService.java @@ -48,10 +48,7 @@ public String generateResponse(String userInput, Long userId, String deviceId, i OpenAiApi.ChatCompletionMessage userMessage = createUserMessage(fullPrompt); OpenAiApi.ChatCompletionRequest chatRequest = createChatRequest(userMessage); - System.out.println(fullPrompt); - return getGptResponse(chatRequest); - } private String getCurrentTime() { From 088f0cf2783c844ce2638060672afd48406e9c9f Mon Sep 17 00:00:00 2001 From: kanguk Date: Fri, 15 Nov 2024 04:02:32 +0900 Subject: [PATCH 10/27] =?UTF-8?q?feat:=20=EC=BD=94=EB=93=9C=20=EC=BB=A4?= =?UTF-8?q?=EB=B2=84=EB=A6=AC=EC=A7=80=20=EC=B8=A1=EC=A0=95=20CI=EC=97=90?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 55 ++++++++++++++++++++++++++++++---------- build.gradle | 21 ++++++++++++++- 2 files changed, 62 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 16415da7..4f26b5c1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,6 +7,11 @@ on: - develop - 'weekly/**' +permissions: + contents: write + issues: write + pull-requests: write + jobs: build-and-test: runs-on: ubuntu-22.04 @@ -36,17 +41,6 @@ jobs: - name: Checkout Repository uses: actions/checkout@v2 -# - name: Cache Gradle dependencies -# uses: actions/cache@v3 -# with: -# path: | -# ~/.gradle/caches/modules-2/files-2.1 -# ~/.gradle/wrapper -# key: gradle-${{ runner.os }}-${{ hashFiles('build.gradle', 'settings.gradle') }} -# restore-keys: | -# gradle-${{ runner.os }}- - - - name: Decode env.properties from GitHub Secrets run: | echo "${{ secrets.ENV_FILE }}" | base64 --decode > ./src/main/resources/env.properties @@ -86,5 +80,40 @@ jobs: - name: Build with Gradle run: ./gradlew clean build -Dspring.profiles.active=test - - name: Run Tests - run: ./gradlew test -Dspring.profiles.active=test \ No newline at end of file + - name: Run Tests and Generate Code Coverage Report + run: ./gradlew test jacocoTestReport -Dspring.profiles.active=test + + - name: Upload Jacoco Report + uses: actions/upload-artifact@v3 + with: + name: jacoco-report + path: build/reports/jacoco/test/jacocoTestReport.xml + + - name: Post Coverage Comment to PR + uses: actions/github-script@v6 + with: + script: | + const fs = require('fs'); + const coverageReport = fs.readFileSync('build/reports/jacoco/test/jacocoTestReport.xml', 'utf8'); + + const match = coverageReport.match(//); + if (match) { + const missed = parseInt(match[1]); + const covered = parseInt(match[2]); + const coverage = ((covered / (missed + covered)) * 100).toFixed(2); + + const comment = `### Code Coverage Report\n\n- **Coverage**: ${coverage}%\n\n`; + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: comment + }); + } else { + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: "### Code Coverage Report\n\nUnable to parse coverage report." + }); + } diff --git a/build.gradle b/build.gradle index 388226ec..947b8776 100644 --- a/build.gradle +++ b/build.gradle @@ -3,9 +3,10 @@ plugins { id 'org.springframework.boot' version '3.3.3' id 'io.spring.dependency-management' version '1.1.6' id 'com.google.protobuf' version '0.9.4' - + id 'jacoco' } + group = 'com.splanet' version = '0.0.1-SNAPSHOT' @@ -119,4 +120,22 @@ sourceSets { srcDirs 'build/generated/source/proto/main/java', 'build/generated/source/proto/main/grpc' } } +} + +jacoco { + toolVersion = "0.8.10" +} + +tasks.jacocoTestReport { + dependsOn test + + reports { + xml.required = true + html.required = true + csv.required = false + } +} + +tasks.build { + dependsOn jacocoTestReport } \ No newline at end of file From ef7e41d84b63ae75e1c8bb3393d5cfbf9fe27b18 Mon Sep 17 00:00:00 2001 From: kanguk Date: Fri, 15 Nov 2024 04:53:18 +0900 Subject: [PATCH 11/27] =?UTF-8?q?feat:=20JaCoCo=20=EC=84=A4=EC=A0=95=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 --- .github/workflows/ci.yml | 46 +++++++++++----------------------------- build.gradle | 19 ++++++----------- 2 files changed, 18 insertions(+), 47 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f26b5c1..05fb819b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -80,40 +80,18 @@ jobs: - name: Build with Gradle run: ./gradlew clean build -Dspring.profiles.active=test - - name: Run Tests and Generate Code Coverage Report - run: ./gradlew test jacocoTestReport -Dspring.profiles.active=test + - name: Run Tests + run: ./gradlew test -Dspring.profiles.active=test - - name: Upload Jacoco Report - uses: actions/upload-artifact@v3 - with: - name: jacoco-report - path: build/reports/jacoco/test/jacocoTestReport.xml + - name: Generate JaCoCo Coverage Report + run: ./gradlew jacocoTestReport - - name: Post Coverage Comment to PR - uses: actions/github-script@v6 + - name: Generate Coverage Badge and Comment + uses: cicirello/jacoco-badge-generator@v2 with: - script: | - const fs = require('fs'); - const coverageReport = fs.readFileSync('build/reports/jacoco/test/jacocoTestReport.xml', 'utf8'); - - const match = coverageReport.match(//); - if (match) { - const missed = parseInt(match[1]); - const covered = parseInt(match[2]); - const coverage = ((covered / (missed + covered)) * 100).toFixed(2); - - const comment = `### Code Coverage Report\n\n- **Coverage**: ${coverage}%\n\n`; - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: comment - }); - } else { - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: "### Code Coverage Report\n\nUnable to parse coverage report." - }); - } + jacoco-csv-file: 'build/reports/jacoco/test/jacocoTestReport.csv' + badges-directory: 'badges' + generate-branches-badge: true + generate-summary: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/build.gradle b/build.gradle index 947b8776..1a0cbe8f 100644 --- a/build.gradle +++ b/build.gradle @@ -19,6 +19,7 @@ java { test { useJUnitPlatform() systemProperty 'spring.profiles.active', 'test' + finalizedBy jacocoTestReport } configurations { @@ -94,6 +95,7 @@ dependencies { tasks.named('test') { useJUnitPlatform() + finalizedBy jacocoTestReport } protobuf { @@ -122,20 +124,11 @@ sourceSets { } } -jacoco { - toolVersion = "0.8.10" -} - -tasks.jacocoTestReport { +jacocoTestReport { dependsOn test - reports { - xml.required = true - html.required = true - csv.required = false + xml.required.set(true) + html.required.set(true) + csv.required.set(true) } -} - -tasks.build { - dependsOn jacocoTestReport } \ No newline at end of file From 96ce1dfd1e47917a92424ff8b3db4ee35d94af38 Mon Sep 17 00:00:00 2001 From: kanguk Date: Fri, 15 Nov 2024 05:05:09 +0900 Subject: [PATCH 12/27] =?UTF-8?q?feat:=20=EB=8B=A4=EB=A5=B8=20=ED=98=95?= =?UTF-8?q?=EC=8B=9D=EC=9C=BC=EB=A1=9C=20=EB=82=98=EC=98=A4=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=8B=9C=EB=8F=84=ED=95=B4=EB=B4=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 44 ++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 05fb819b..ada444d0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -81,17 +81,39 @@ jobs: run: ./gradlew clean build -Dspring.profiles.active=test - name: Run Tests - run: ./gradlew test -Dspring.profiles.active=test + run: ./gradlew test jacocoTestReport -Dspring.profiles.active=test - - name: Generate JaCoCo Coverage Report - run: ./gradlew jacocoTestReport + - name: Upload Jacoco Report + uses: actions/upload-artifact@v3 + with: + name: jacoco-report + path: build/reports/jacoco/test/jacocoTestReport.xml - - name: Generate Coverage Badge and Comment - uses: cicirello/jacoco-badge-generator@v2 + - name: Post Coverage Comment to PR + uses: actions/github-script@v6 with: - jacoco-csv-file: 'build/reports/jacoco/test/jacocoTestReport.csv' - badges-directory: 'badges' - generate-branches-badge: true - generate-summary: true - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + script: | + const fs = require('fs'); + const coverageReport = fs.readFileSync('build/reports/jacoco/test/jacocoTestReport.xml', 'utf8'); + + const match = coverageReport.match(//); + if (match) { + const missed = parseInt(match[1]); + const covered = parseInt(match[2]); + const coverage = ((covered / (missed + covered)) * 100).toFixed(2); + + const comment = `### Code Coverage Report\n\n- **Coverage**: ${coverage}%\n\n`; + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: comment + }); + } else { + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: "### Code Coverage Report\n\nUnable to parse coverage report." + }); + } \ No newline at end of file From 70ce8182bda4e33dda4183521a56dc89829a9e28 Mon Sep 17 00:00:00 2001 From: kanguk Date: Fri, 15 Nov 2024 05:09:35 +0900 Subject: [PATCH 13/27] =?UTF-8?q?feat:=20=EC=BB=A4=EB=B2=84=EB=A6=AC?= =?UTF-8?q?=EC=A7=80=20=EC=B8=A1=EC=A0=95=20=ED=95=84=ED=84=B0=EB=A7=81?= =?UTF-8?q?=ED=95=98=EA=B3=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR에 남기는거 시도중 --- .github/workflows/ci.yml | 44 ++++++++++------------------------------ build.gradle | 14 +++++++++++++ 2 files changed, 25 insertions(+), 33 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ada444d0..4aee0ee8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -81,39 +81,17 @@ jobs: run: ./gradlew clean build -Dspring.profiles.active=test - name: Run Tests - run: ./gradlew test jacocoTestReport -Dspring.profiles.active=test + run: ./gradlew test -Dspring.profiles.active=test - - name: Upload Jacoco Report - uses: actions/upload-artifact@v3 - with: - name: jacoco-report - path: build/reports/jacoco/test/jacocoTestReport.xml + - name: Generate JaCoCo Coverage Report + run: ./gradlew jacocoTestReport - - name: Post Coverage Comment to PR - uses: actions/github-script@v6 + - name: Generate Coverage Badge and Summary + uses: cicirello/jacoco-badge-generator@v2 with: - script: | - const fs = require('fs'); - const coverageReport = fs.readFileSync('build/reports/jacoco/test/jacocoTestReport.xml', 'utf8'); - - const match = coverageReport.match(//); - if (match) { - const missed = parseInt(match[1]); - const covered = parseInt(match[2]); - const coverage = ((covered / (missed + covered)) * 100).toFixed(2); - - const comment = `### Code Coverage Report\n\n- **Coverage**: ${coverage}%\n\n`; - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: comment - }); - } else { - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: "### Code Coverage Report\n\nUnable to parse coverage report." - }); - } \ No newline at end of file + jacoco-csv-file: 'build/reports/jacoco/test/jacocoTestReport.csv' + badges-directory: 'badges' + generate-branches-badge: true + generate-summary: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/build.gradle b/build.gradle index 1a0cbe8f..5d238c37 100644 --- a/build.gradle +++ b/build.gradle @@ -124,6 +124,10 @@ sourceSets { } } +jacoco { + toolVersion = "0.8.10" +} + jacocoTestReport { dependsOn test reports { @@ -131,4 +135,14 @@ jacocoTestReport { html.required.set(true) csv.required.set(true) } + classDirectories.setFrom( + files(classDirectories.files.collect { + fileTree(dir: it, exclude: [ + '**/dto/**', // dto 패키지 제외 + '**/config/**', // config 패키지 제외 + '**/exception/**', // exception 패키지 제외 + '**/core/**', // core 패키지 제외 + ]) + }) + ) } \ No newline at end of file From 3390d855b059bf40f58fbdb37b7cf4618e7f4fcb Mon Sep 17 00:00:00 2001 From: kanguk Date: Fri, 15 Nov 2024 05:24:14 +0900 Subject: [PATCH 14/27] =?UTF-8?q?feat:=20=EC=BB=A4=EB=B2=84=EB=A6=AC?= =?UTF-8?q?=EC=A7=80=20=EA=B2=B0=EA=B3=BC=EA=B0=80=20PR=EC=97=90=20?= =?UTF-8?q?=EB=82=A8=EB=8F=84=EB=A1=9D=20=ED=95=9C=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 16 ++++++++++++++++ build.gradle | 3 +++ 2 files changed, 19 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4aee0ee8..3039bcc0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -95,3 +95,19 @@ jobs: generate-summary: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Display Coverage Summary JSON + run: | + cat badges/coverage-summary.json + + - name: Extract Coverage Information + if: ${{ github.event_name == 'pull_request' }} + run: | + COVERAGE=$(jq '.coverage' badges/coverage-summary.json) + BRANCH_COVERAGE=$(jq '.branches' badges/coverage-summary.json) + FORMATTED_COVERAGE=$(printf "%.2f" $COVERAGE) + FORMATTED_BRANCH_COVERAGE=$(printf "%.2f" $BRANCH_COVERAGE) + curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + -X POST \ + -d "{\"body\": \"### 코드 커버리지\n- Coverage: ${FORMATTED_COVERAGE}%\n- Branches: ${FORMATTED_BRANCH_COVERAGE}%\n\"}" \ + "https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments" diff --git a/build.gradle b/build.gradle index 5d238c37..d5def0b7 100644 --- a/build.gradle +++ b/build.gradle @@ -142,6 +142,9 @@ jacocoTestReport { '**/config/**', // config 패키지 제외 '**/exception/**', // exception 패키지 제외 '**/core/**', // core 패키지 제외 + '**/mapper/**', // mapper 패키지 제외 + '**/grpc/**', // grpc 패키지 제외 + '**/log/**', // log 패키지 제외 ]) }) ) From 5d84ddfab7caab8387bf37f8927913cf6cdc6f8c Mon Sep 17 00:00:00 2001 From: KimSongMok Date: Sun, 10 Nov 2024 19:43:07 +0900 Subject: [PATCH 15/27] =?UTF-8?q?refactor:=20cd=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/cd.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 1bc58047..872194b9 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -5,6 +5,7 @@ on: branches: - develop - 'weekly/**' + - 142-refactor-cd-update jobs: deploy: From 44cb71086bc4664cba71b150dfd7e3482b4150e7 Mon Sep 17 00:00:00 2001 From: ez23re Date: Fri, 15 Nov 2024 00:00:43 +0900 Subject: [PATCH 16/27] =?UTF-8?q?test:=20=EC=B9=9C=EA=B5=AC=ED=94=8C?= =?UTF-8?q?=EB=9E=9C=EC=A1=B0=ED=9A=8C=5F=ED=9B=84=5F=EB=8C=93=EA=B8=80?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FriendControllerAcceptanceTest.java | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 src/test/java/com/splanet/splanet/friend/controller/FriendControllerAcceptanceTest.java diff --git a/src/test/java/com/splanet/splanet/friend/controller/FriendControllerAcceptanceTest.java b/src/test/java/com/splanet/splanet/friend/controller/FriendControllerAcceptanceTest.java new file mode 100644 index 00000000..298a4afd --- /dev/null +++ b/src/test/java/com/splanet/splanet/friend/controller/FriendControllerAcceptanceTest.java @@ -0,0 +1,129 @@ +package com.splanet.splanet.friend.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.splanet.splanet.comment.dto.CommentRequest; +import com.splanet.splanet.comment.entity.Comment; +import com.splanet.splanet.comment.repository.CommentRepository; +import com.splanet.splanet.friendRequest.entity.FriendRequest; +import com.splanet.splanet.friendRequest.repository.FriendRequestRepository; +import com.splanet.splanet.jwt.JwtTokenProvider; +import com.splanet.splanet.plan.dto.PlanRequestDto; +import com.splanet.splanet.plan.dto.PlanResponseDto; +import com.splanet.splanet.user.entity.User; +import com.splanet.splanet.user.repository.UserRepository; +import jakarta.transaction.Transactional; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.web.servlet.MockMvc; + +import java.time.LocalDateTime; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +class FriendControllerAcceptanceTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private UserRepository userRepository; + + @Autowired + private FriendRequestRepository friendRequestRepository; + + @Autowired + private CommentRepository commentRepository; + + @Autowired + private JwtTokenProvider jwtTokenProvider; + + private String userAToken; + private String userBToken; + private Long userAId; + private Long userBId; + private User userA; + private User userB; + + @BeforeEach + void setUp() { + userA = User.builder() + .nickname("testUser") + .kakaoId(123456789L) + .profileImage("http://example.com/profile.jpg") + .isPremium(false) + .build(); + userB = User.builder() + .nickname("testWriter") + .kakaoId(987654321L) + .profileImage("http://example.com/profile.jpg") + .isPremium(false) + .build(); + + userRepository.saveAll(List.of(userA, userB)); + + userAId = userA.getId(); + userBId = userB.getId(); + + userAToken = jwtTokenProvider.createAccessToken(userAId); + userBToken = jwtTokenProvider.createAccessToken(userBId); + + FriendRequest friendRequest = new FriendRequest(userA, userB, FriendRequest.Status.ACCEPTED); + friendRequestRepository.save(friendRequest); + } + + @Test + @WithMockUser + void 친구_플랜조회_후_댓글작성() throws Exception { + PlanRequestDto requestDto = PlanRequestDto.builder() + .title("테스트 플랜") + .description("테스트 설명") + .startDate(LocalDateTime.now().plusDays(1)) + .endDate(LocalDateTime.now().plusDays(2)) + .build(); + + String planResponse = mockMvc.perform(post("/api/plans") + .header("Authorization", "Bearer " + userAToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(requestDto))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.title").value("테스트 플랜")) + .andExpect(jsonPath("$.description").value("테스트 설명")) + .andReturn().getResponse().getContentAsString(); + + Long planId = objectMapper.readValue(planResponse, PlanResponseDto.class).getId(); + + mockMvc.perform(get("/api/plans/" + planId) + .header("Authorization", "Bearer " + userAToken)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.title").value("테스트 플랜")) + .andExpect(jsonPath("$.description").value("테스트 설명")); + + CommentRequest commentRequest = new CommentRequest(userAId, "테스트 댓글"); + + mockMvc.perform(post("/api/comments") + .header("Authorization", "Bearer " + userAToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(commentRequest))) + .andExpect(status().isOk()) + .andExpect(content().string("댓글이 성공적으로 작성되었습니다.")); + + List comments = commentRepository.findByUserId(userAId); + assertThat(comments).hasSize(1); + assertThat(comments.get(0).getContent()).isEqualTo("테스트 댓글"); + } +} \ No newline at end of file From a894b654e93260b873cdf53d683939614688095b Mon Sep 17 00:00:00 2001 From: ez23re Date: Fri, 15 Nov 2024 00:09:38 +0900 Subject: [PATCH 17/27] =?UTF-8?q?test:=20=ED=8C=80=ED=94=8C=EB=9E=9C=5F?= =?UTF-8?q?=EC=83=9D=EC=84=B1=ED=9B=84=5F=EC=88=98=EC=A0=95=ED=9B=84=5F?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/TeamPlanAcceptanceTest.java | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 src/test/java/com/splanet/splanet/teamplan/controller/TeamPlanAcceptanceTest.java diff --git a/src/test/java/com/splanet/splanet/teamplan/controller/TeamPlanAcceptanceTest.java b/src/test/java/com/splanet/splanet/teamplan/controller/TeamPlanAcceptanceTest.java new file mode 100644 index 00000000..bb7d7658 --- /dev/null +++ b/src/test/java/com/splanet/splanet/teamplan/controller/TeamPlanAcceptanceTest.java @@ -0,0 +1,146 @@ +package com.splanet.splanet.teamplan.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.jayway.jsonpath.JsonPath; +import com.splanet.splanet.team.entity.Team; +import com.splanet.splanet.team.entity.TeamUserRelation; +import com.splanet.splanet.team.entity.UserTeamRole; +import com.splanet.splanet.team.repository.TeamRepository; +import com.splanet.splanet.team.repository.TeamUserRelationRepository; +import com.splanet.splanet.teamplan.dto.TeamPlanRequestDto; +import com.splanet.splanet.teamplan.repository.TeamPlanRepository; +import com.splanet.splanet.jwt.JwtTokenProvider; +import com.splanet.splanet.user.entity.User; +import com.splanet.splanet.user.repository.UserRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +class TeamPlanAcceptanceTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private JwtTokenProvider jwtTokenProvider; + + @Autowired + private TeamRepository teamRepository; + + @Autowired + private UserRepository userRepository; + + @Autowired + private TeamUserRelationRepository teamUserRelationRepository; + + @Autowired + private TeamPlanRepository teamPlanRepository; + + private String userAccessToken; + private Long userId; + private Long friendId; + private Long teamId; + private Long planId; + + @BeforeEach + void setUp() { + User user = User.builder() + .nickname("testuser") + .profileImage("testimage.png") + .build(); + userRepository.save(user); + userId = user.getId(); + + User friend = User.builder() + .nickname("frienduser") + .profileImage("friendimage.png") + .build(); + userRepository.save(friend); + friendId = friend.getId(); + + Team team = new Team("친구팀", user); + teamRepository.save(team); + teamId = team.getId(); + + TeamUserRelation userRelation = new TeamUserRelation(team, user, UserTeamRole.ADMIN); + TeamUserRelation friendRelation = new TeamUserRelation(team, friend, UserTeamRole.MEMBER); + teamUserRelationRepository.save(userRelation); + teamUserRelationRepository.save(friendRelation); + + userAccessToken = "Bearer " + jwtTokenProvider.createAccessToken(userId); + } + + @Test + void 팀플랜_생성후_수정후_삭제() throws Exception { + TeamPlanRequestDto requestDto = new TeamPlanRequestDto( + "친구 팀 플랜", + "친구 팀에서 만든 플랜", + LocalDateTime.parse("2024-11-12T10:00:00"), + LocalDateTime.parse("2024-11-12T11:00:00"), + true, + true + ); + + String response = mockMvc.perform(post("/api/teams/{teamId}/plans", teamId) + .header("Authorization", userAccessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(requestDto))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.title").value("친구 팀 플랜")) + .andExpect(jsonPath("$.description").value("친구 팀에서 만든 플랜")) + .andExpect(jsonPath("$.startDate").value("2024-11-12T10:00:00")) + .andExpect(jsonPath("$.endDate").value("2024-11-12T11:00:00")) + .andExpect(jsonPath("$.accessibility").value(true)) + .andExpect(jsonPath("$.isCompleted").value(true)) + .andReturn().getResponse().getContentAsString(); + + planId = JsonPath.parse(response).read("$.id", Long.class); + + TeamPlanRequestDto updateRequestDto = new TeamPlanRequestDto( + "수정된 친구 팀 플랜", + "수정된 플랜 설명", + LocalDateTime.parse("2024-11-12T11:00:00"), + LocalDateTime.parse("2024-11-12T12:00:00"), + false, + false + ); + + mockMvc.perform(put("/api/teams/{teamId}/plans/{planId}", teamId, planId) + .header("Authorization", userAccessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(updateRequestDto))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.title").value("수정된 친구 팀 플랜")) + .andExpect(jsonPath("$.description").value("수정된 플랜 설명")) + .andExpect(jsonPath("$.startDate").value("2024-11-12T11:00:00")) + .andExpect(jsonPath("$.endDate").value("2024-11-12T12:00:00")) + .andExpect(jsonPath("$.accessibility").value(false)) + .andExpect(jsonPath("$.isCompleted").value(false)); + + mockMvc.perform(delete("/api/teams/{teamId}/plans/{planId}", teamId, planId) + .header("Authorization", userAccessToken)) + .andExpect(status().isNoContent()); + + mockMvc.perform(get("/api/teams/{teamId}/plans/{planId}", teamId, planId) + .header("Authorization", userAccessToken)) + .andExpect(status().isNotFound()) + .andExpect(jsonPath("$.message").value("플랜이 존재하지 않습니다.")); + } +} From 7cf04f314db48c2f1cafbbcec329b86084b0b718 Mon Sep 17 00:00:00 2001 From: ez23re Date: Fri, 15 Nov 2024 01:01:47 +0900 Subject: [PATCH 18/27] =?UTF-8?q?test:=20=ED=8C=80=ED=94=8C=EB=9E=9C=5F?= =?UTF-8?q?=EC=83=9D=EC=84=B1=ED=9B=84=5F=EC=88=98=EC=A0=95=ED=9B=84=5F?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/controller/TeamAcceptanceTest.java | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 src/test/java/com/splanet/splanet/team/controller/TeamAcceptanceTest.java diff --git a/src/test/java/com/splanet/splanet/team/controller/TeamAcceptanceTest.java b/src/test/java/com/splanet/splanet/team/controller/TeamAcceptanceTest.java new file mode 100644 index 00000000..9fb80a5b --- /dev/null +++ b/src/test/java/com/splanet/splanet/team/controller/TeamAcceptanceTest.java @@ -0,0 +1,123 @@ +package com.splanet.splanet.team.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.splanet.splanet.team.entity.*; +import com.splanet.splanet.team.repository.TeamInvitationRepository; +import com.splanet.splanet.team.repository.TeamRepository; +import com.splanet.splanet.team.repository.TeamUserRelationRepository; +import com.splanet.splanet.jwt.JwtTokenProvider; +import com.splanet.splanet.user.entity.User; +import com.splanet.splanet.user.repository.UserRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +class TeamAcceptanceTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private TeamRepository teamRepository; + + @Autowired + private TeamInvitationRepository teamInvitationRepository; + + @Autowired + private TeamUserRelationRepository teamUserRelationRepository; + + @Autowired + private UserRepository userRepository; + + @Autowired + private JwtTokenProvider jwtTokenProvider; + + private String adminAccessToken; + private String invitedUserAccessToken; + private Long teamId; + private Long adminUserId; + private Long invitedUserId; + + @BeforeEach + void setUp() { + User adminUser = User.builder() + .nickname("adminUser") + .profileImage("admin.png") + .build(); + userRepository.save(adminUser); + adminUserId = adminUser.getId(); + + User invitedUser = User.builder() + .nickname("invitedUser") + .profileImage("invited.png") + .build(); + userRepository.save(invitedUser); + invitedUserId = invitedUser.getId(); + + Team team = new Team("Test Team", adminUser); + teamRepository.save(team); + teamId = team.getId(); + + TeamUserRelation adminRelation = new TeamUserRelation(team, adminUser, UserTeamRole.ADMIN); + teamUserRelationRepository.save(adminRelation); + + adminAccessToken = "Bearer " + jwtTokenProvider.createAccessToken(adminUserId); + invitedUserAccessToken = "Bearer " + jwtTokenProvider.createAccessToken(invitedUserId); + } + + @Test + void 팀생성후_유저초대_유저가_수락후_내보내기() throws Exception { + mockMvc.perform(post("/api/teams") + .header("Authorization", adminAccessToken) + .param("teamName", "New Test Team")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.teamName").value("New Test Team")) + .andExpect(jsonPath("$.user.nickname").value("adminUser")); + + mockMvc.perform(post("/api/teams/{teamId}/invite", teamId) + .header("Authorization", adminAccessToken) + .param("nickname", "invitedUser")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.nickname").value("invitedUser")) + .andExpect(jsonPath("$.teamId").value(teamId)) + .andExpect(jsonPath("$.status").value("PENDING")); + + TeamInvitation invitation = teamInvitationRepository.findAllByUserAndStatus(userRepository.findById(invitedUserId).get(), InvitationStatus.PENDING).get(0); + assertThat(invitation.getUser().getId()).isEqualTo(invitedUserId); + assertThat(invitation.getTeam().getId()).isEqualTo(teamId); + assertThat(invitation.getStatus()).isEqualTo(InvitationStatus.PENDING); + + mockMvc.perform(put("/api/teams/invitation/{invitationId}/response", invitation.getId()) + .header("Authorization", invitedUserAccessToken) + .param("isAccepted", "true")) + .andExpect(status().isNoContent()); + + TeamInvitation updatedInvitation = teamInvitationRepository.findById(invitation.getId()).orElseThrow(); + assertThat(updatedInvitation.getStatus()).isEqualTo(InvitationStatus.ACCEPTED); + + TeamUserRelation userRelation = teamUserRelationRepository.findByTeamAndUser(teamRepository.findById(teamId).get(), userRepository.findById(invitedUserId).get()).orElseThrow(); + assertThat(userRelation.getUser().getId()).isEqualTo(invitedUserId); + + mockMvc.perform(delete("/api/teams/{teamId}/users/{userId}", teamId, invitedUserId) + .header("Authorization", adminAccessToken)) + .andExpect(status().isNoContent()); + + TeamUserRelation removedUserRelation = teamUserRelationRepository.findByTeamAndUser(teamRepository.findById(teamId).get(), userRepository.findById(invitedUserId).get()).orElse(null); + assertThat(removedUserRelation).isNull(); + } +} \ No newline at end of file From 932be0b4c01b37ec207d183f837f4f586adb2ee6 Mon Sep 17 00:00:00 2001 From: ez23re Date: Fri, 15 Nov 2024 01:04:12 +0900 Subject: [PATCH 19/27] =?UTF-8?q?test:=20=ED=8C=80=EC=83=9D=EC=84=B1?= =?UTF-8?q?=ED=9B=84=5F=EC=9C=A0=EC=A0=80=EC=B4=88=EB=8C=80=5F=EC=9C=A0?= =?UTF-8?q?=EC=A0=80=EA=B0=80=5F=EC=88=98=EB=9D=BD=ED=9B=84=5F=EB=82=B4?= =?UTF-8?q?=EB=B3=B4=EB=82=B4=EA=B8=B0=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../splanet/splanet/team/controller/TeamAcceptanceTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/splanet/splanet/team/controller/TeamAcceptanceTest.java b/src/test/java/com/splanet/splanet/team/controller/TeamAcceptanceTest.java index 9fb80a5b..d5edc802 100644 --- a/src/test/java/com/splanet/splanet/team/controller/TeamAcceptanceTest.java +++ b/src/test/java/com/splanet/splanet/team/controller/TeamAcceptanceTest.java @@ -84,9 +84,9 @@ void setUp() { void 팀생성후_유저초대_유저가_수락후_내보내기() throws Exception { mockMvc.perform(post("/api/teams") .header("Authorization", adminAccessToken) - .param("teamName", "New Test Team")) + .param("teamName", "새로운 팀")) .andExpect(status().isOk()) - .andExpect(jsonPath("$.teamName").value("New Test Team")) + .andExpect(jsonPath("$.teamName").value("새로운 팀")) .andExpect(jsonPath("$.user.nickname").value("adminUser")); mockMvc.perform(post("/api/teams/{teamId}/invite", teamId) From 294f9857fa4f3e61d88a717413844ac0561eedab Mon Sep 17 00:00:00 2001 From: ez23re Date: Fri, 15 Nov 2024 01:27:05 +0900 Subject: [PATCH 20/27] =?UTF-8?q?refactor:=20=ED=81=B4=EB=9E=98=EC=8A=A4?= =?UTF-8?q?=20=EB=A6=AC=EB=84=A4=EC=9D=B4=EB=B0=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...eamAcceptanceTest.java => TeamControllerAcceptanceTest.java} | 2 +- ...cceptanceTest.java => TeamPlanControllerAcceptanceTest.java} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/test/java/com/splanet/splanet/team/controller/{TeamAcceptanceTest.java => TeamControllerAcceptanceTest.java} (99%) rename src/test/java/com/splanet/splanet/teamplan/controller/{TeamPlanAcceptanceTest.java => TeamPlanControllerAcceptanceTest.java} (99%) diff --git a/src/test/java/com/splanet/splanet/team/controller/TeamAcceptanceTest.java b/src/test/java/com/splanet/splanet/team/controller/TeamControllerAcceptanceTest.java similarity index 99% rename from src/test/java/com/splanet/splanet/team/controller/TeamAcceptanceTest.java rename to src/test/java/com/splanet/splanet/team/controller/TeamControllerAcceptanceTest.java index d5edc802..5c8d4f3f 100644 --- a/src/test/java/com/splanet/splanet/team/controller/TeamAcceptanceTest.java +++ b/src/test/java/com/splanet/splanet/team/controller/TeamControllerAcceptanceTest.java @@ -24,7 +24,7 @@ @SpringBootTest @AutoConfigureMockMvc @Transactional -class TeamAcceptanceTest { +class TeamControllerAcceptanceTest { @Autowired private MockMvc mockMvc; diff --git a/src/test/java/com/splanet/splanet/teamplan/controller/TeamPlanAcceptanceTest.java b/src/test/java/com/splanet/splanet/teamplan/controller/TeamPlanControllerAcceptanceTest.java similarity index 99% rename from src/test/java/com/splanet/splanet/teamplan/controller/TeamPlanAcceptanceTest.java rename to src/test/java/com/splanet/splanet/teamplan/controller/TeamPlanControllerAcceptanceTest.java index bb7d7658..1370bb7a 100644 --- a/src/test/java/com/splanet/splanet/teamplan/controller/TeamPlanAcceptanceTest.java +++ b/src/test/java/com/splanet/splanet/teamplan/controller/TeamPlanControllerAcceptanceTest.java @@ -30,7 +30,7 @@ @SpringBootTest @AutoConfigureMockMvc @Transactional -class TeamPlanAcceptanceTest { +class TeamPlanControllerAcceptanceTest { @Autowired private MockMvc mockMvc; From 2905a4ee884a5c16ed81643eb2ff0ee3fdf6a679 Mon Sep 17 00:00:00 2001 From: ez23re Date: Fri, 15 Nov 2024 02:19:06 +0900 Subject: [PATCH 21/27] =?UTF-8?q?test:=20=EB=82=B4=EA=B0=80=5F=EC=B9=9C?= =?UTF-8?q?=EA=B5=AC=5F=EC=9A=94=EC=B2=AD=5F=EB=B3=B4=EB=82=B4=EB=A9=B4=5F?= =?UTF-8?q?=EC=B9=9C=EA=B5=AC=EA=B0=80=5F=EC=88=98=EB=9D=BD=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...FriendRequestControllerAcceptanceTest.java | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 src/test/java/com/splanet/splanet/friendRequest/controller/FriendRequestControllerAcceptanceTest.java diff --git a/src/test/java/com/splanet/splanet/friendRequest/controller/FriendRequestControllerAcceptanceTest.java b/src/test/java/com/splanet/splanet/friendRequest/controller/FriendRequestControllerAcceptanceTest.java new file mode 100644 index 00000000..ccb17188 --- /dev/null +++ b/src/test/java/com/splanet/splanet/friendRequest/controller/FriendRequestControllerAcceptanceTest.java @@ -0,0 +1,97 @@ +package com.splanet.splanet.friendRequest.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.splanet.splanet.core.exception.BusinessException; +import com.splanet.splanet.friend.repository.FriendRepository; +import com.splanet.splanet.friendRequest.dto.FriendRequestCreateRequest; +import com.splanet.splanet.friendRequest.entity.FriendRequest; +import com.splanet.splanet.friendRequest.repository.FriendRequestRepository; +import com.splanet.splanet.jwt.JwtTokenProvider; +import com.splanet.splanet.user.entity.User; +import com.splanet.splanet.user.repository.UserRepository; +import jakarta.transaction.Transactional; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +class FriendRequestControllerAcceptanceTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private JwtTokenProvider jwtTokenProvider; + + @Autowired + private UserRepository userRepository; + + @Autowired + private FriendRepository friendRepository; + + @Autowired + private FriendRequestRepository friendRequestRepository; + + private String accessToken; + private Long requesterId; + private Long receiverId; + + @BeforeEach + void setUp() { + User requester = User.builder() + .nickname("requester") + .profileImage("requesterImage.png") + .build(); + userRepository.save(requester); + requesterId = requester.getId(); + + User receiver = User.builder() + .nickname("receiver") + .profileImage("receiverImage.png") + .build(); + userRepository.save(receiver); + receiverId = receiver.getId(); + + accessToken = "Bearer " + jwtTokenProvider.createAccessToken(requesterId); + } + + @Test + void 내가_친구_요청_보내면_친구가_수락하기() throws Exception { + FriendRequestCreateRequest request = new FriendRequestCreateRequest(receiverId); + mockMvc.perform(post("/api/friends/requests") + .header("Authorization", accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.message").value("친구 요청이 성공적으로 전송되었습니다.")); + + List pendingRequests = friendRequestRepository.findPendingRequestsByReceiverId(receiverId, requesterId, FriendRequest.Status.PENDING); + FriendRequest friendRequest = pendingRequests.get(0); + + String receiverAccessToken = "Bearer " + jwtTokenProvider.createAccessToken(receiverId); + + mockMvc.perform(post("/api/friends/requests/{requestId}/accept", friendRequest.getId()) + .header("Authorization", receiverAccessToken) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.status").value("ACCEPTED")); + } +} \ No newline at end of file From 445f134aa4b1416e7f1faabe93b11fcf4cadff12 Mon Sep 17 00:00:00 2001 From: ez23re Date: Fri, 15 Nov 2024 02:46:48 +0900 Subject: [PATCH 22/27] =?UTF-8?q?chore:=20splanet-test.log=20=EC=99=9C=20?= =?UTF-8?q?=EC=9E=90=EA=BE=B8=20=EB=9C=A8=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- splanet-test.log | 485 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 485 insertions(+) create mode 100644 splanet-test.log diff --git a/splanet-test.log b/splanet-test.log new file mode 100644 index 00000000..4ca64d9e --- /dev/null +++ b/splanet-test.log @@ -0,0 +1,485 @@ +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T01:30:47.1860528, requestPath: /api/teams/292/invite, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T01:30:47.8163936, requestPath: /api/teams/invitation/56/cancel, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T01:30:47.942391, requestPath: /api/teams/294/invite, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T01:30:48.0655639, requestPath: /api/teams/295/users/2361/role, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T01:30:48.3306743, requestPath: /api/teams/invitations, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T01:30:48.6284571, requestPath: /api/teams/297/members, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T01:30:48.8827197, requestPath: /api/teams/invitation/58/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T01:30:49.072135, requestPath: /api/teams, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T01:34:15.9980698, requestPath: /api/teams/invitation/59/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:12:52.5109433, requestPath: /api/teams/invitation/60/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:15:28.7888321, requestPath: /api/teams/invitation/61/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:15:28.9399327, requestPath: /api/teams/303/users/2375/role, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:18:22.4189859, requestPath: /api/teams/304/invite, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:18:23.3406885, requestPath: /api/teams/invitation/63/cancel, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:18:23.4573551, requestPath: /api/teams/306/invite, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:18:23.6584028, requestPath: /api/teams/invitation/64/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:18:23.7225922, requestPath: /api/teams/307/users/2384/role, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:18:23.9879624, requestPath: /api/teams/invitations, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:18:24.2387469, requestPath: /api/teams/309/members, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:18:24.6542278, requestPath: /api/teams/invitation/66/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:18:24.909439, requestPath: /api/teams, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:22:58.4115848, requestPath: /api/teams/invitation/67/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:24:55.3411523, requestPath: /api/teams/invitations, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:26:39.7535168, requestPath: /api/teams/315/invite, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:26:40.6483468, requestPath: /api/teams/invitation/70/cancel, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:26:40.7956308, requestPath: /api/teams/317/invite, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:26:41.0087913, requestPath: /api/teams/invitation/71/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:26:41.1112843, requestPath: /api/teams/318/users/2405/role, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:26:41.4204024, requestPath: /api/teams/invitations, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:26:41.6102337, requestPath: /api/teams/320/members, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:26:41.8940681, requestPath: /api/teams/invitation/73/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:26:42.063906, requestPath: /api/teams, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:28:02.5629894, requestPath: /api/teams/324/invite, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:28:03.7140563, requestPath: /api/teams/invitation/75/cancel, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:28:03.8805958, requestPath: /api/teams/326/invite, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:28:04.0587861, requestPath: /api/teams/invitation/76/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:28:04.1264443, requestPath: /api/teams/327/users/2422/role, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:28:04.4360911, requestPath: /api/teams/invitations, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:28:04.7011395, requestPath: /api/teams/329/members, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:28:05.0007518, requestPath: /api/teams/invitation/78/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:28:05.1655281, requestPath: /api/teams, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:30:27.9648354, requestPath: /api/teams/333/users/2432, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:34:28.3032912, requestPath: /api/teams/334/users/2435, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:50.5522316, requestPath: /api/comments/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:50.7912981, requestPath: /api/comments/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:51.1415171, requestPath: /api/comments, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:51.2849148, requestPath: /api/comments/2442, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:51.3890202, requestPath: /api/comments/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:51.4803386, requestPath: /api/comments/449, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:51.5921475, requestPath: /api/comments/2448, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:51.8367186, requestPath: /api/comments/452, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:51.9090987, requestPath: /api/comments, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:51.9884984, requestPath: /api/comments/454, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:54.3298593, requestPath: /api/friends/999/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:54.5153576, requestPath: /api/friends/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:54.6435791, requestPath: /api/friends/1/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:54.8633012, requestPath: /api/friends/2460, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:55.140562, requestPath: /api/friends, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:55.2711714, requestPath: /api/friends/1, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:55.428424, requestPath: /api/friends, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:56.7492194, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:56.837646, requestPath: /api/friends/requests/999/cancel, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:56.9837246, requestPath: /api/friends/requests/173/accept, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:57.0676166, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:57.1943555, requestPath: /api/friends/requests/174/cancel, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:57.2395291, requestPath: /api/friends/requests/sent, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:57.4009325, requestPath: /api/friends/requests/175/cancel, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:57.5241516, requestPath: /api/friends/requests/176/reject, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:57.6440745, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:57.7926852, requestPath: /api/friends/requests/received, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:36:58.0291299, requestPath: /api/friends/requests/sent, headers: +eventType: API_REQUEST, userId: 2, deviceId: apiTestDeviceId, timestamp: 2024-11-13T02:37:13.8183349, requestPath: /test/api, headers: User-Agent: ApiTestAgent, Accept: application/json +eventType: LOGIN_SUCCESS, userId: 1, deviceId: testDeviceId, timestamp: 2024-11-13T02:37:13.8369525, requestPath: /test/login, headers: User-Agent: TestAgent, Accept: */* +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:14.5721839, requestPath: /api/payment/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:14.6576132, requestPath: /api/payment/69, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:14.7227753, requestPath: /api/payment/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:14.7976534, requestPath: /api/payment/71, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:15.2281971, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:15.3237317, requestPath: /api/plans/33, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:15.3477231, requestPath: /api/plans/33, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:15.4191482, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:15.446887, requestPath: /api/plans/34, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:15.5068766, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:15.5390804, requestPath: /api/plans/35, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:15.5970357, requestPath: /api/plans/9999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:15.6759658, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:15.7452256, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:15.8438973, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:15.9202902, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:16.003572, requestPath: /api/plans/38, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:16.0815436, requestPath: /api/plans/9999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:16.183495, requestPath: /api/plans/39, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:16.2673954, requestPath: /api/plans/40, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:16.3543681, requestPath: /api/plans/9999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:16.414049, requestPath: /api/plans/9999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:16.4925541, requestPath: /api/plans/41, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:16.5542434, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:16.6219232, requestPath: /api/plans/42, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:16.6792633, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:17.6532471, requestPath: /api/subscription/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:17.7544701, requestPath: /api/subscription/me/subscribe, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:17.8432613, requestPath: /api/subscription/me/subscribe, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:17.9700391, requestPath: /api/subscriptions/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:18.3358253, requestPath: /api/teams/335/users/2508, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:18.4795394, requestPath: /api/teams/336/invite, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:18.7015124, requestPath: /api/teams/invitation/82/cancel, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:18.7911217, requestPath: /api/teams/338/invite, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:18.9105623, requestPath: /api/teams/invitation/83/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:18.9434427, requestPath: /api/teams/339/users/2517/role, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:19.0684144, requestPath: /api/teams/340/members, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:19.2275766, requestPath: /api/teams/invitation/84/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:19.316441, requestPath: /api/teams/342/users/2523, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:19.3852945, requestPath: /api/teams, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:19.939926, requestPath: /api/teams/345/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:20.0092834, requestPath: /api/teams/345/plans/74, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:20.0801684, requestPath: /api/teams/346/plans/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:20.15345, requestPath: /api/teams/347/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:20.2434092, requestPath: /api/teams/348/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:20.3664733, requestPath: /api/teams/349/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:20.4449252, requestPath: /api/teams/350/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:20.476685, requestPath: /api/teams/350/plans/76, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:20.5037028, requestPath: /api/teams/350/plans/76, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:20.5699068, requestPath: /api/teams/351/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:20.6012895, requestPath: /api/teams/351/plans/77, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:20.6669845, requestPath: /api/teams/352/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:20.6979221, requestPath: /api/teams/352/plans/78, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:20.7756559, requestPath: /api/teams/353/plans/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:20.843362, requestPath: /api/teams/354/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:20.871979, requestPath: /api/teams/354/plans/79, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:21.6428745, requestPath: /api/users/create, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:21.6821109, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:21.7020622, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:21.7494743, requestPath: /api/users/create, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:21.7823246, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:21.7966717, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:21.8213417, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:21.8599923, requestPath: /api/users/create, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:21.8904398, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:21.954743, requestPath: /api/users/create, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:22.1368969, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:22.1845135, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:22.2501266, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:22.3077124, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:22.3624514, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:22.4165367, requestPath: /api/users/create, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:37:22.4884116, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:40:48.1118797, requestPath: /api/teams/355/users/2558, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:40:49.666562, requestPath: /api/teams/356/users/2560, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:40:50.3471282, requestPath: /api/teams/999/users/2562, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:40:50.5004763, requestPath: /api/teams/358/invite, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:40:51.1205584, requestPath: /api/teams/invitation/87/cancel, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:40:51.2688202, requestPath: /api/teams/360/invite, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:40:51.4627571, requestPath: /api/teams/invitation/88/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:40:51.5286431, requestPath: /api/teams/361/users/2571/role, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:40:51.7166468, requestPath: /api/teams/362/members, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:40:52.0240492, requestPath: /api/teams/invitation/89/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:40:52.2275458, requestPath: /api/teams/364/users/2577, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:40:52.3973095, requestPath: /api/teams, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:43:10.141278, requestPath: /api/teams/367/users/2583, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:43:10.5845694, requestPath: /api/teams/invitation/90/cancel, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:43:10.7718762, requestPath: /api/teams/369/users/2588, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:43:11.1713409, requestPath: /api/teams/999/users/2590, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:43:11.2874055, requestPath: /api/teams/371/invite, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:43:11.6443585, requestPath: /api/teams, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:43:11.8102735, requestPath: /api/teams/invitation/93/cancel, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:43:11.9397144, requestPath: /api/teams/374/invite, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:43:12.1831742, requestPath: /api/teams/invitation/94/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:43:12.2290732, requestPath: /api/teams/375/users/2601/role, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:43:12.3742489, requestPath: /api/teams/376/users/2603/role, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:43:12.5241722, requestPath: /api/teams/invitation/95/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:43:12.6334208, requestPath: /api/teams/378/members, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:43:12.9206027, requestPath: /api/teams/379/members, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:43:13.2195216, requestPath: /api/teams/invitation/96/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:43:13.3670059, requestPath: /api/teams, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:43:13.5130763, requestPath: /api/teams/382/users/2617, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:43:13.9793759, requestPath: /api/teams, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:48:10.1257236, requestPath: /api/teams/386/members, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:50:57.1546558, requestPath: /api/teams/388/members, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:25.5370199, requestPath: /api/comments/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:25.7850735, requestPath: /api/comments/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:26.0530337, requestPath: /api/comments, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:26.1651293, requestPath: /api/comments/2631, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:26.2416298, requestPath: /api/comments/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:26.3179979, requestPath: /api/comments/462, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:26.4235611, requestPath: /api/comments/2637, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:26.6689509, requestPath: /api/comments/465, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:26.7399988, requestPath: /api/comments, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:26.8317109, requestPath: /api/comments/467, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:28.4352026, requestPath: /api/friends/999/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:28.5943521, requestPath: /api/friends/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:28.7506151, requestPath: /api/friends/1/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:28.9479387, requestPath: /api/friends/2649, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:29.215656, requestPath: /api/friends, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:29.3351501, requestPath: /api/friends/1, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:29.4761274, requestPath: /api/friends, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:30.5109494, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:30.6056946, requestPath: /api/friends/requests/999/cancel, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:30.749297, requestPath: /api/friends/requests/178/accept, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:30.8284083, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:30.9686757, requestPath: /api/friends/requests/179/cancel, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:31.0109352, requestPath: /api/friends/requests/sent, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:31.1440963, requestPath: /api/friends/requests/180/cancel, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:31.2375536, requestPath: /api/friends/requests/181/reject, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:31.3177624, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:31.4011777, requestPath: /api/friends/requests/received, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:31.497779, requestPath: /api/friends/requests/sent, headers: +eventType: API_REQUEST, userId: 2, deviceId: apiTestDeviceId, timestamp: 2024-11-13T02:53:46.5413504, requestPath: /test/api, headers: User-Agent: ApiTestAgent, Accept: application/json +eventType: LOGIN_SUCCESS, userId: 1, deviceId: testDeviceId, timestamp: 2024-11-13T02:53:46.5688795, requestPath: /test/login, headers: User-Agent: TestAgent, Accept: */* +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:47.5292803, requestPath: /api/payment/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:47.6540046, requestPath: /api/payment/73, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:47.7441847, requestPath: /api/payment/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:47.8529949, requestPath: /api/payment/75, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:48.5008018, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:48.5979283, requestPath: /api/plans/43, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:48.641395, requestPath: /api/plans/43, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:48.7292402, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:48.7620267, requestPath: /api/plans/44, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:48.8589573, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:48.9026338, requestPath: /api/plans/45, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:48.978235, requestPath: /api/plans/9999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:49.1260509, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:49.2023644, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:49.3139543, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:49.4024525, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:49.4824209, requestPath: /api/plans/48, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:49.5447553, requestPath: /api/plans/9999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:49.6196053, requestPath: /api/plans/49, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:49.6853723, requestPath: /api/plans/50, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:49.7410549, requestPath: /api/plans/9999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:49.7960073, requestPath: /api/plans/9999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:49.8660332, requestPath: /api/plans/51, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:49.9463483, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:50.0057485, requestPath: /api/plans/52, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:50.0714845, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:50.9529861, requestPath: /api/subscription/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:51.039119, requestPath: /api/subscription/me/subscribe, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:51.1105475, requestPath: /api/subscription/me/subscribe, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:51.222783, requestPath: /api/subscriptions/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:51.4566731, requestPath: /api/teams/389/users/2698, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:51.6296005, requestPath: /api/teams/invitation/97/cancel, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:51.7881189, requestPath: /api/teams/391/users/2703, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:51.9306289, requestPath: /api/teams/999/users/2705, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:52.0144251, requestPath: /api/teams/393/invite, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:52.2015531, requestPath: /api/teams, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:52.3759522, requestPath: /api/teams/invitation/100/cancel, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:52.4778886, requestPath: /api/teams/396/invite, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:52.6109664, requestPath: /api/teams/invitation/101/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:52.6432484, requestPath: /api/teams/397/users/2716/role, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:52.776377, requestPath: /api/teams/398/users/2718/role, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:52.9149526, requestPath: /api/teams/invitation/102/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:52.97981, requestPath: /api/teams/400/members, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:53.1359649, requestPath: /api/teams/invitation/103/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:53.2320442, requestPath: /api/teams/402/users/2727, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:53.3065474, requestPath: /api/teams, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:53.9409898, requestPath: /api/teams/405/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:54.0107706, requestPath: /api/teams/405/plans/80, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:54.0891041, requestPath: /api/teams/406/plans/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:54.1886601, requestPath: /api/teams/407/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:54.2782075, requestPath: /api/teams/408/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:54.4353482, requestPath: /api/teams/409/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:54.5566504, requestPath: /api/teams/410/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:54.5964185, requestPath: /api/teams/410/plans/82, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:54.6237363, requestPath: /api/teams/410/plans/82, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:54.7297431, requestPath: /api/teams/411/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:54.7699229, requestPath: /api/teams/411/plans/83, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:54.8652319, requestPath: /api/teams/412/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:54.9067464, requestPath: /api/teams/412/plans/84, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:55.0012801, requestPath: /api/teams/413/plans/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:55.0901562, requestPath: /api/teams/414/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:55.1259617, requestPath: /api/teams/414/plans/85, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:55.9602196, requestPath: /api/users/create, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:56.007865, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:56.0389543, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:56.0952887, requestPath: /api/users/create, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:56.130556, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:56.153634, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:56.1809809, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:56.2803682, requestPath: /api/users/create, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:56.3320244, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:56.4042785, requestPath: /api/users/create, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:56.6270754, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:56.691206, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:56.7573221, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:56.8168091, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:56.8780105, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:56.9342054, requestPath: /api/users/create, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T02:53:57.0028144, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:22:42.2161333, requestPath: /api/preview-plan/card, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:22:42.958393, requestPath: /api/preview-plan/card/testDevice/testGroup/testCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:22:43.1620282, requestPath: /api/preview-plan/card/testDevice/testGroup/testCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:22:43.2908867, requestPath: /api/preview-plan/card/testDevice/testGroup/testCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:24:42.502575, requestPath: /api/preview-plan/card, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:24:43.4650389, requestPath: /api/preview-plan/card/testDevice/testGroup/testCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:24:43.7014496, requestPath: /api/preview-plan/card/testDevice/testGroup/testCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:24:43.8507348, requestPath: /api/preview-plan/delete-all, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:24:44.0984697, requestPath: /api/preview-plan/card/testDevice/testGroup/testCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:36:53.0030602, requestPath: /api/preview-plan/card/testDevice/testGroup/nonExistentCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:36:54.0315003, requestPath: /api/preview-plan/card, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:36:54.3487901, requestPath: /api/preview-plan/card/testDevice/testGroup/testCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:36:54.6069956, requestPath: /api/preview-plan/card/testDevice/testGroup/testCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:36:54.7283961, requestPath: /api/preview-plan/card/testDevice/testGroup/nonExistentCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:36:54.8689791, requestPath: /api/preview-plan/card, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:36:55.0174004, requestPath: /api/preview-plan/card/testDevice/testGroup/nonExistentCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:36:55.1318441, requestPath: /api/preview-plan/card/testDevice/testGroup/testCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:38:53.1884276, requestPath: /api/preview-plan/card/testDevice/testGroup/nonExistentCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:38:53.6818705, requestPath: /api/preview-plan/card, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:38:53.9347176, requestPath: /api/preview-plan/card/testDevice/testGroup/testCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:38:54.1172187, requestPath: /api/preview-plan/card/testDevice/testGroup/testCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:38:54.2194285, requestPath: /api/preview-plan/card/testDevice/testGroup/nonExistentCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:38:54.3150695, requestPath: /api/preview-plan/card, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:38:54.4497181, requestPath: /api/preview-plan/card/testDevice/testGroup/nonExistentCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:38:54.5501698, requestPath: /api/preview-plan/card/testDevice/testGroup/testCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:36.6721799, requestPath: /api/comments/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:36.8617225, requestPath: /api/comments/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:37.1072613, requestPath: /api/comments, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:37.2259553, requestPath: /api/comments/2766, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:37.3091239, requestPath: /api/comments/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:37.3913257, requestPath: /api/comments/475, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:37.4745601, requestPath: /api/comments/2772, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:37.649729, requestPath: /api/comments/478, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:37.7168988, requestPath: /api/comments, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:37.7750013, requestPath: /api/comments/480, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:39.7134411, requestPath: /api/friends/999/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:39.8724832, requestPath: /api/friends/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:39.9933656, requestPath: /api/friends/1/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:40.1535194, requestPath: /api/friends/2784, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:40.3819408, requestPath: /api/friends, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:40.4765353, requestPath: /api/friends/1, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:40.5727592, requestPath: /api/friends, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:41.6025093, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:41.6856534, requestPath: /api/friends/requests/999/cancel, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:41.8487633, requestPath: /api/friends/requests/183/accept, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:41.9584669, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:42.1048632, requestPath: /api/friends/requests/184/cancel, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:42.1537167, requestPath: /api/friends/requests/sent, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:42.3025632, requestPath: /api/friends/requests/185/cancel, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:42.4167708, requestPath: /api/friends/requests/186/reject, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:42.5190009, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:42.6171823, requestPath: /api/friends/requests/received, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:42.7401364, requestPath: /api/friends/requests/sent, headers: +eventType: API_REQUEST, userId: 2, deviceId: apiTestDeviceId, timestamp: 2024-11-13T16:45:58.0386012, requestPath: /test/api, headers: User-Agent: ApiTestAgent, Accept: application/json +eventType: LOGIN_SUCCESS, userId: 1, deviceId: testDeviceId, timestamp: 2024-11-13T16:45:58.0578632, requestPath: /test/login, headers: User-Agent: TestAgent, Accept: */* +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:58.9247368, requestPath: /api/payment/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:59.0068309, requestPath: /api/payment/77, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:59.0696013, requestPath: /api/payment/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:59.15817, requestPath: /api/payment/79, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:59.7691924, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:59.8401586, requestPath: /api/plans/53, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:59.8663223, requestPath: /api/plans/53, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:59.9258984, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:45:59.9575042, requestPath: /api/plans/54, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:00.0156165, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:00.0426377, requestPath: /api/plans/55, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:00.0938499, requestPath: /api/plans/9999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:00.1726955, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:00.3185267, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:00.4389994, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:00.5263014, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:00.6067312, requestPath: /api/plans/58, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:00.6927198, requestPath: /api/plans/9999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:00.7752503, requestPath: /api/plans/59, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:00.855168, requestPath: /api/plans/60, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:00.9153744, requestPath: /api/plans/9999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:00.9817942, requestPath: /api/plans/9999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:01.1996999, requestPath: /api/plans/61, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:01.2742533, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:01.3596318, requestPath: /api/plans/62, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:01.4290989, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:04.0060578, requestPath: /api/preview-plan/card/testDevice/testGroup/nonExistentCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:04.1910285, requestPath: /api/preview-plan/card, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:04.3827562, requestPath: /api/preview-plan/card/testDevice/testGroup/testCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:04.553435, requestPath: /api/preview-plan/card/testDevice/testGroup/testCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:04.6244138, requestPath: /api/preview-plan/card/testDevice/testGroup/nonExistentCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:04.6776178, requestPath: /api/preview-plan/card/testDevice/testGroup/nonExistentCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:04.7583688, requestPath: /api/preview-plan/card/testDevice/testGroup/testCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:05.2488392, requestPath: /api/subscription/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:05.3377159, requestPath: /api/subscription/me/subscribe, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:05.4277046, requestPath: /api/subscription/me/subscribe, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:05.5648555, requestPath: /api/subscriptions/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:06.0787939, requestPath: /api/teams/415/users/2833, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:06.3426506, requestPath: /api/teams/invitation/104/cancel, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:06.7117655, requestPath: /api/teams/417/users/2838, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:07.0857495, requestPath: /api/teams/999/users/2840, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:07.2659447, requestPath: /api/teams/419/invite, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:07.5055229, requestPath: /api/teams, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:07.7313356, requestPath: /api/teams/invitation/107/cancel, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:07.9114666, requestPath: /api/teams/422/invite, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:08.3960094, requestPath: /api/teams/invitation/108/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:08.4596387, requestPath: /api/teams/423/users/2851/role, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:08.5958579, requestPath: /api/teams/424/users/2853/role, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:08.7722243, requestPath: /api/teams/invitation/109/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:08.8795601, requestPath: /api/teams/426/members, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:09.1158543, requestPath: /api/teams/invitation/110/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:09.2372138, requestPath: /api/teams/428/users/2862, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:09.3680782, requestPath: /api/teams, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:10.4578669, requestPath: /api/teams/431/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:10.5431723, requestPath: /api/teams/431/plans/86, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:10.6119373, requestPath: /api/teams/432/plans/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:10.690798, requestPath: /api/teams/433/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:10.7573024, requestPath: /api/teams/434/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:10.8943745, requestPath: /api/teams/435/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:11.001092, requestPath: /api/teams/436/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:11.0556572, requestPath: /api/teams/436/plans/88, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:11.0879185, requestPath: /api/teams/436/plans/88, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:11.1886776, requestPath: /api/teams/437/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:11.233035, requestPath: /api/teams/437/plans/89, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:11.3689649, requestPath: /api/teams/438/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:11.4419392, requestPath: /api/teams/438/plans/90, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:11.5460027, requestPath: /api/teams/439/plans/999, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:11.6581052, requestPath: /api/teams/440/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:11.6911924, requestPath: /api/teams/440/plans/91, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:12.6422076, requestPath: /api/users/create, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:12.6797423, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:12.6982733, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:12.7368973, requestPath: /api/users/create, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:12.7627302, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:12.7780556, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:12.7963611, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:12.8359576, requestPath: /api/users/create, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:12.8646735, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:12.9163884, requestPath: /api/users/create, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:13.0513373, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:13.1005287, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:13.1546985, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:13.20467, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:13.2553336, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:13.3017336, requestPath: /api/users/create, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-13T16:46:13.3631375, requestPath: /api/users/me, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T13:24:48.1165219, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T13:27:04.2760546, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T13:35:34.8788792, requestPath: /api/friends/999/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T13:41:42.1459963, requestPath: /api/friends/2902/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T22:26:31.2012127, requestPath: /api/friends/2904/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T22:41:54.3386745, requestPath: /api/friends/2906/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T22:51:34.0332552, requestPath: /api/friends/2908/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T22:58:03.5637471, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T22:58:03.9411426, requestPath: /api/friends/2910/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T23:11:42.6327312, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T23:11:43.2196307, requestPath: /api/friends/2912/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T23:41:03.1896894, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T23:41:03.5499993, requestPath: /api/plans/65, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T23:41:03.5930102, requestPath: /api/plans/65/comments, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T23:51:25.9435048, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T23:51:26.2220829, requestPath: /api/plans/66, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T23:51:26.2510476, requestPath: /api/comments, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T23:52:35.2958618, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T23:52:35.6262677, requestPath: /api/plans/67, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T23:52:35.6602526, requestPath: /api/comments, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T23:57:44.8987963, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T23:57:45.2414632, requestPath: /api/plans/68, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-14T23:57:45.2734635, requestPath: /api/comments, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T00:07:18.0954846, requestPath: /api/teams/441/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T00:07:18.4066708, requestPath: /api/teams/441/plans/92, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T00:07:18.4476294, requestPath: /api/teams/441/plans/92, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T00:07:18.4834075, requestPath: /api/teams/441/plans/92, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T00:39:20.0699321, requestPath: /api/teams, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T00:39:20.6226807, requestPath: /api/teams/442/invite, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T00:39:21.2271203, requestPath: /api/teams/invitation/111/response, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T00:39:21.3397947, requestPath: /api/teams/442/users/2924, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:27:49.6244116, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:27:49.9321973, requestPath: /api/friends/requests/200/reject, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:27:50.042428, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:27:50.120066, requestPath: /api/friends/requests/201/accept, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:37:48.0193452, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:37:48.2984272, requestPath: /api/friends/requests/202/reject, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:43:07.5555823, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:43:08.2500464, requestPath: /api/friends/requests/203/reject, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:43:08.5059392, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:43:08.666134, requestPath: /api/friends/requests/204/accept, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:45:33.0785423, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:45:33.3879218, requestPath: /api/friends/requests/205/reject, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:45:33.4996167, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:45:33.5762156, requestPath: /api/friends/requests/206/accept, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:49:09.5148297, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:49:09.9149935, requestPath: /api/friends/requests/received, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:49:10.0541672, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:49:10.1099951, requestPath: /api/friends/requests/208/accept, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:51:25.2533392, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:51:25.7725847, requestPath: /api/friends/requests/209/reject, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:51:25.9678684, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:51:26.0741538, requestPath: /api/friends/requests/210/accept, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:53:29.5559943, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:53:30.551043, requestPath: /api/friends/requests/211/reject, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:53:30.7611028, requestPath: /api/friends/requests, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:53:30.85865, requestPath: /api/friends/requests/212/accept, headers: From 2a006609147e4c7d73c5d20438eb139a9a9aef4e Mon Sep 17 00:00:00 2001 From: ez23re Date: Fri, 15 Nov 2024 03:06:58 +0900 Subject: [PATCH 23/27] =?UTF-8?q?chore:=20splanet-test.log=20=EA=B3=84?= =?UTF-8?q?=EC=86=8D=20=EB=9C=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- splanet-test.log | 12 ++++++++++++ .../splanet/friend/repository/FriendRepository.java | 2 +- .../splanet/friend/service/FriendService.java | 2 -- .../controller/FriendControllerAcceptanceTest.java | 3 +-- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/splanet-test.log b/splanet-test.log index 4ca64d9e..c17d998f 100644 --- a/splanet-test.log +++ b/splanet-test.log @@ -483,3 +483,15 @@ eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:5 eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:53:30.551043, requestPath: /api/friends/requests/211/reject, headers: eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:53:30.7611028, requestPath: /api/friends/requests, headers: eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T01:53:30.85865, requestPath: /api/friends/requests/212/accept, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:01:33.0965042, requestPath: /api/friends, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:01:33.4535829, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:01:33.6291489, requestPath: /api/plans/69, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:01:33.6750939, requestPath: /api/comments, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:03:52.9544924, requestPath: /api/friends, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:03:53.4180404, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:03:53.6649917, requestPath: /api/plans/70, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:03:53.7259943, requestPath: /api/comments, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:05:08.4801025, requestPath: /api/friends, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:05:08.7888016, requestPath: /api/plans, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:05:08.9704432, requestPath: /api/plans/71, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:05:09.0113407, requestPath: /api/comments, headers: diff --git a/src/main/java/com/splanet/splanet/friend/repository/FriendRepository.java b/src/main/java/com/splanet/splanet/friend/repository/FriendRepository.java index 03b87d14..7106f7bd 100644 --- a/src/main/java/com/splanet/splanet/friend/repository/FriendRepository.java +++ b/src/main/java/com/splanet/splanet/friend/repository/FriendRepository.java @@ -9,10 +9,10 @@ import java.util.List; - @Repository public interface FriendRepository extends JpaRepository { List findByUserId(Long userId); + boolean existsByUserIdAndFriendId(Long userId, Long friendId); @Modifying diff --git a/src/main/java/com/splanet/splanet/friend/service/FriendService.java b/src/main/java/com/splanet/splanet/friend/service/FriendService.java index cfcbe7c3..d01ac0f4 100644 --- a/src/main/java/com/splanet/splanet/friend/service/FriendService.java +++ b/src/main/java/com/splanet/splanet/friend/service/FriendService.java @@ -84,8 +84,6 @@ public ResponseEntity> getFriendPlan(Long friendId, Long u return ResponseEntity.ok(planResponseDtos); } - // 친구 삭제(취소)하기 - // 친구 삭제(취소)하기 @Transactional public ResponseEntity> unfriend(Long friendId, Long userId) { diff --git a/src/test/java/com/splanet/splanet/friend/controller/FriendControllerAcceptanceTest.java b/src/test/java/com/splanet/splanet/friend/controller/FriendControllerAcceptanceTest.java index 298a4afd..e3faadf8 100644 --- a/src/test/java/com/splanet/splanet/friend/controller/FriendControllerAcceptanceTest.java +++ b/src/test/java/com/splanet/splanet/friend/controller/FriendControllerAcceptanceTest.java @@ -25,8 +25,7 @@ import java.util.List; import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @SpringBootTest From 14f6a28407e699cedf6273e3ffd56b94bc27a59b Mon Sep 17 00:00:00 2001 From: ez23re Date: Fri, 15 Nov 2024 03:22:14 +0900 Subject: [PATCH 24/27] =?UTF-8?q?chore:=20=EB=B8=8C=EB=9E=9C=EC=B9=98=20?= =?UTF-8?q?=EC=98=AE=EA=B2=A8=EC=84=9C=20rm=20--cached=EB=A5=BC=20?= =?UTF-8?q?=ED=96=88=EB=8A=94=EB=8D=B0=EB=90=B4..!!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- splanet-test.log | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/splanet-test.log b/splanet-test.log index c17d998f..8e38ea22 100644 --- a/splanet-test.log +++ b/splanet-test.log @@ -495,3 +495,7 @@ eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:0 eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:05:08.7888016, requestPath: /api/plans, headers: eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:05:08.9704432, requestPath: /api/plans/71, headers: eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:05:09.0113407, requestPath: /api/comments, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:21:41.9436992, requestPath: /api/preview-plan/card, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:21:42.5546871, requestPath: /api/preview-plan/card/testDevice/testGroup/testCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:21:42.6185005, requestPath: /api/preview-plan/card/testDevice/testGroup/testCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:21:42.6644158, requestPath: /api/preview-plan/card/testDevice/testGroup/testCard, headers: From 52df8fe0660761ae2f491792834f36e53fc7f221 Mon Sep 17 00:00:00 2001 From: ez23re Date: Fri, 15 Nov 2024 03:22:35 +0900 Subject: [PATCH 25/27] =?UTF-8?q?test:=20=ED=94=8C=EB=9E=9C=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=5F=EC=83=9D=EC=84=B1=ED=9B=84=5F=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=EC=88=98=5F=EC=88=98=EC=A0=95=ED=9B=84=5F=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PreviewPlanControllerAccecptanceTest.java | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 src/test/java/com/splanet/splanet/previewplan/controller/PreviewPlanControllerAccecptanceTest.java diff --git a/src/test/java/com/splanet/splanet/previewplan/controller/PreviewPlanControllerAccecptanceTest.java b/src/test/java/com/splanet/splanet/previewplan/controller/PreviewPlanControllerAccecptanceTest.java new file mode 100644 index 00000000..b662a4a7 --- /dev/null +++ b/src/test/java/com/splanet/splanet/previewplan/controller/PreviewPlanControllerAccecptanceTest.java @@ -0,0 +1,97 @@ +package com.splanet.splanet.previewplan.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.splanet.splanet.previewplan.dto.PlanCardRequestDto; +import com.splanet.splanet.previewplan.entity.PlanCard; +import com.splanet.splanet.previewplan.repository.PlanCardRepository; +import com.splanet.splanet.previewplan.repository.PlanGroupRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +class PreviewPlanControllerAccecptanceTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private RedisTemplate redisTemplate; + + @Autowired + private PlanCardRepository planCardRepository; + + @Autowired + private PlanGroupRepository planGroupRepository; + + private static final String BASE_URL = "/api/preview-plan"; + + @BeforeEach + void setup() { + redisTemplate.getConnectionFactory().getConnection().flushAll(); + } + + private void saveSamplePlanCard(String deviceId, String groupId, String cardId) { + PlanCard planCard = PlanCard.builder() + .customKey(deviceId + ":" + groupId + ":" + cardId) + .deviceId(deviceId) + .groupId(groupId) + .cardId(cardId) + .title("Sample Title") + .description("Sample Description") + .startDate("2024-01-01") + .endDate("2024-12-31") + .expiration(3600L) + .build(); + planCardRepository.save(planCard); + } + + @Test + void 플랜카드_생성후_조회수_수정후_삭제() throws Exception { + String deviceId = "testDevice"; + String groupId = "testGroup"; + String cardId = "testCard"; + + PlanCardRequestDto requestDto = new PlanCardRequestDto("Title", "Description", "2024-01-01", "2024-12-31"); + mockMvc.perform(post(BASE_URL + "/card") + .param("deviceId", deviceId) + .param("groupId", groupId) + .contentType(MediaType.APPLICATION_JSON) + .content(new ObjectMapper().writeValueAsString(requestDto))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.title").value("Title")) + .andExpect(jsonPath("$.description").value("Description")); + + saveSamplePlanCard(deviceId, groupId, cardId); + + mockMvc.perform(get(BASE_URL + "/card/{deviceId}/{groupId}/{cardId}", deviceId, groupId, cardId)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.title").value("Sample Title")); + + PlanCardRequestDto updateRequest = new PlanCardRequestDto("Updated Title", "Updated Description", "2024-01-01", "2024-12-31"); + mockMvc.perform(put(BASE_URL + "/card/{deviceId}/{groupId}/{cardId}", deviceId, groupId, cardId) + .contentType(MediaType.APPLICATION_JSON) + .content(new ObjectMapper().writeValueAsString(updateRequest))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.title").value("Updated Title")) + .andExpect(jsonPath("$.description").value("Updated Description")); + + mockMvc.perform(delete(BASE_URL + "/card/{deviceId}/{groupId}/{cardId}", deviceId, groupId, cardId)) + .andExpect(status().isOk()); + + assertFalse(planCardRepository.findById(deviceId + ":" + groupId + ":" + cardId).isPresent()); + } +} \ No newline at end of file From b5912ed509b4fc3f6c435efd6f37683371501e0e Mon Sep 17 00:00:00 2001 From: ez23re Date: Fri, 15 Nov 2024 03:23:26 +0900 Subject: [PATCH 26/27] =?UTF-8?q?refactor:=20=EB=A9=94=EC=86=8C=EB=93=9C?= =?UTF-8?q?=EB=AA=85=20typo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/PreviewPlanControllerAccecptanceTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/splanet/splanet/previewplan/controller/PreviewPlanControllerAccecptanceTest.java b/src/test/java/com/splanet/splanet/previewplan/controller/PreviewPlanControllerAccecptanceTest.java index b662a4a7..801bce51 100644 --- a/src/test/java/com/splanet/splanet/previewplan/controller/PreviewPlanControllerAccecptanceTest.java +++ b/src/test/java/com/splanet/splanet/previewplan/controller/PreviewPlanControllerAccecptanceTest.java @@ -60,7 +60,7 @@ private void saveSamplePlanCard(String deviceId, String groupId, String cardId) } @Test - void 플랜카드_생성후_조회수_수정후_삭제() throws Exception { + void 플랜카드_생성후_조회후_수정후_삭제() throws Exception { String deviceId = "testDevice"; String groupId = "testGroup"; String cardId = "testCard"; From 9d5c9ab9d0435161985237517968a98e4b399a5a Mon Sep 17 00:00:00 2001 From: ez23re Date: Fri, 15 Nov 2024 04:47:46 +0900 Subject: [PATCH 27/27] =?UTF-8?q?test:=20=EA=B5=AC=EB=8F=85=5F=EC=83=9D?= =?UTF-8?q?=EC=84=B1=ED=9B=84=5F=EC=A1=B0=ED=9A=8C=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- splanet-test.log | 2 + ...SubscriptionControllerAccecptanceTest.java | 99 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 src/test/java/com/splanet/splanet/subscription/controller/SubscriptionControllerAccecptanceTest.java diff --git a/splanet-test.log b/splanet-test.log index 8e38ea22..f9ca94fa 100644 --- a/splanet-test.log +++ b/splanet-test.log @@ -499,3 +499,5 @@ eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:2 eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:21:42.5546871, requestPath: /api/preview-plan/card/testDevice/testGroup/testCard, headers: eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:21:42.6185005, requestPath: /api/preview-plan/card/testDevice/testGroup/testCard, headers: eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T03:21:42.6644158, requestPath: /api/preview-plan/card/testDevice/testGroup/testCard, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T04:47:11.0257337, requestPath: /api/subscription/me/subscribe, headers: +eventType: API_REQUEST, userId: null, deviceId: null, timestamp: 2024-11-15T04:47:11.5584523, requestPath: /api/subscription/me, headers: diff --git a/src/test/java/com/splanet/splanet/subscription/controller/SubscriptionControllerAccecptanceTest.java b/src/test/java/com/splanet/splanet/subscription/controller/SubscriptionControllerAccecptanceTest.java new file mode 100644 index 00000000..944f0244 --- /dev/null +++ b/src/test/java/com/splanet/splanet/subscription/controller/SubscriptionControllerAccecptanceTest.java @@ -0,0 +1,99 @@ +package com.splanet.splanet.subscription.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.splanet.splanet.core.exception.ErrorCode; +import com.splanet.splanet.subscription.dto.SubscriptionRequest; +import com.splanet.splanet.subscription.entity.Subscription; +import com.splanet.splanet.subscription.repository.SubscriptionRepository; +import com.splanet.splanet.user.entity.User; +import com.splanet.splanet.user.repository.UserRepository; +import com.splanet.splanet.jwt.JwtTokenProvider; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; + +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +class SubscriptionControllerAccecptanceTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private UserRepository userRepository; + + @Autowired + private SubscriptionRepository subscriptionRepository; + + @Autowired + private JwtTokenProvider jwtTokenProvider; + + private String token; + private User testUser; + + @BeforeEach + void setUp() { + testUser = User.builder() + .nickname("구독 테스트 사용자") + .profileImage("http://example.com/profile.jpg") + .kakaoId(123456789L) + .isPremium(false) + .build(); + userRepository.save(testUser); + + token = "Bearer " + jwtTokenProvider.createAccessToken(testUser.getId()); + } + + @Test + void 구독_생성후_조회() throws Exception { + SubscriptionRequest request = new SubscriptionRequest(); + request.setType(Subscription.Type.MONTHLY); + + mockMvc.perform(post("/api/subscription/me/subscribe") + .header("Authorization", token) + .contentType(MediaType.APPLICATION_JSON) + .content(new ObjectMapper().writeValueAsString(request))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.message").value("구독이 성공적으로 완료되었습니다.")) + .andExpect(jsonPath("$.subscription.id").exists()) + .andExpect(jsonPath("$.subscription.startDate").exists()) + .andExpect(jsonPath("$.subscription.endDate").doesNotExist()); + + Subscription newSubscription = subscriptionRepository.findTopByUserIdAndStatusOrderByStartDateDesc(testUser.getId(), Subscription.Status.ACTIVE) + .orElseThrow(() -> new AssertionError("구독 정보가 저장되지 않았습니다.")); + + assertThat(newSubscription.getType()).isEqualTo(request.getType()); + assertThat(newSubscription.getStatus()).isEqualTo(Subscription.Status.ACTIVE); + + Subscription subscription = Subscription.builder() + .user(testUser) + .type(Subscription.Type.MONTHLY) + .startDate(LocalDateTime.now()) + .endDate(LocalDateTime.now().plusMonths(1)) + .build(); + subscriptionRepository.save(subscription); + + mockMvc.perform(get("/api/subscription/me") + .header("Authorization", token) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.message").value("구독 정보가 성공적으로 조회되었습니다.")) + .andExpect(jsonPath("$.subscription.id").exists()) + .andExpect(jsonPath("$.subscription.startDate").exists()) + .andExpect(jsonPath("$.subscription.endDate").exists()); + } +}