diff --git a/src/docs/asciidoc/grooming-test-api.adoc b/src/docs/asciidoc/grooming-test-api.adoc index fd7392f..15747b4 100644 --- a/src/docs/asciidoc/grooming-test-api.adoc +++ b/src/docs/asciidoc/grooming-test-api.adoc @@ -24,3 +24,29 @@ include::{snippetsDir}/submitGroomingTests/1/http-response.adoc[] include::{snippetsDir}/submitGroomingTests/1/response-fields.adoc[] --- + +=== **3. 그루밍 테스트 가능 여부 조회** + +그루밍 테스트가 가능한지 여부를 체크하는 api 입니다. (인증된 회원) + +==== Request +include::{snippetsDir}/checkGroomingTestAvailability/1/http-request.adoc[] + +==== 성공 Response +성공 1. 마지막 테스트일로부터 7일이 지나지 않아, 그루밍 테스트가 불가능한 경우 (테스트가 가능하기까지 남은 일수, 마지막으로 테스트한 날짜, 테스트가 가능한 날짜 정보 응답) + +include::{snippetsDir}/checkGroomingTestAvailability/1/http-response.adoc[] + +성공 2. 마지막 테스트일로부터 7일 이상 경과해 그루밍 테스트가 가능한 경우 (마지막으로 테스트한 날짜 정보 응답) + +include::{snippetsDir}/checkGroomingTestAvailability/2/http-response.adoc[] + +성공 3. 이전 테스트 기록이 없고 즉시 그루밍 테스트가 가능한 경우 + +include::{snippetsDir}/checkGroomingTestAvailability/3/http-response.adoc[] + +==== Response Body Fields +include::{snippetsDir}/checkGroomingTestAvailability/1/response-fields.adoc[] + +==== 실패 Response +include::{snippetsDir}/checkGroomingTestAvailability/4/http-response.adoc[] \ No newline at end of file diff --git a/src/main/java/com/ftm/server/adapter/in/web/grooming/controller/CheckGroomingTestAvailabilityController.java b/src/main/java/com/ftm/server/adapter/in/web/grooming/controller/CheckGroomingTestAvailabilityController.java new file mode 100644 index 0000000..930b9c0 --- /dev/null +++ b/src/main/java/com/ftm/server/adapter/in/web/grooming/controller/CheckGroomingTestAvailabilityController.java @@ -0,0 +1,35 @@ +package com.ftm.server.adapter.in.web.grooming.controller; + +import com.ftm.server.adapter.in.web.grooming.dto.response.CheckGroomingTestAvailabilityResponse; +import com.ftm.server.application.port.in.grooming.CheckGroomingTestAvailabilityUseCase; +import com.ftm.server.application.query.FindByUserIdQuery; +import com.ftm.server.application.vo.grooming.GroomingTestAvailabilityVo; +import com.ftm.server.common.response.ApiResponse; +import com.ftm.server.common.response.enums.SuccessResponseCode; +import com.ftm.server.infrastructure.security.UserPrincipal; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +public class CheckGroomingTestAvailabilityController { + + private final CheckGroomingTestAvailabilityUseCase checkGroomingTestAvailabilityUseCase; + + @GetMapping("/api/grooming/tests/availability") + public ResponseEntity> checkAvailability( + @AuthenticationPrincipal UserPrincipal userPrincipal) { + GroomingTestAvailabilityVo result = + checkGroomingTestAvailabilityUseCase.execute( + FindByUserIdQuery.of(userPrincipal.getId())); + return ResponseEntity.status(HttpStatus.OK) + .body( + ApiResponse.success( + SuccessResponseCode.OK, + CheckGroomingTestAvailabilityResponse.from(result))); + } +} diff --git a/src/main/java/com/ftm/server/adapter/in/web/grooming/dto/response/CheckGroomingTestAvailabilityResponse.java b/src/main/java/com/ftm/server/adapter/in/web/grooming/dto/response/CheckGroomingTestAvailabilityResponse.java new file mode 100644 index 0000000..2ea862f --- /dev/null +++ b/src/main/java/com/ftm/server/adapter/in/web/grooming/dto/response/CheckGroomingTestAvailabilityResponse.java @@ -0,0 +1,33 @@ +package com.ftm.server.adapter.in.web.grooming.dto.response; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ftm.server.application.vo.grooming.GroomingTestAvailabilityVo; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Getter; + +@Getter +public class CheckGroomingTestAvailabilityResponse { + + private final boolean available; + private final Long remainingDays; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm", shape = JsonFormat.Shape.STRING) + private final LocalDateTime lastTestedAt; + + @JsonFormat(pattern = "yyyy-MM-dd", shape = JsonFormat.Shape.STRING) + private final LocalDate nextAvailableAt; + + private CheckGroomingTestAvailabilityResponse( + GroomingTestAvailabilityVo groomingTestAvailabilityVo) { + this.available = groomingTestAvailabilityVo.isAvailable(); + this.remainingDays = groomingTestAvailabilityVo.getRemainingDays(); + this.lastTestedAt = groomingTestAvailabilityVo.getLastTestedAt(); + this.nextAvailableAt = groomingTestAvailabilityVo.getNextAvailableAt(); + } + + public static CheckGroomingTestAvailabilityResponse from( + GroomingTestAvailabilityVo groomingTestAvailabilityVo) { + return new CheckGroomingTestAvailabilityResponse(groomingTestAvailabilityVo); + } +} diff --git a/src/main/java/com/ftm/server/adapter/out/persistence/adapter/grooming/GroomingDomainPersistenceAdapter.java b/src/main/java/com/ftm/server/adapter/out/persistence/adapter/grooming/GroomingDomainPersistenceAdapter.java index 43784d9..d6a83d5 100644 --- a/src/main/java/com/ftm/server/adapter/out/persistence/adapter/grooming/GroomingDomainPersistenceAdapter.java +++ b/src/main/java/com/ftm/server/adapter/out/persistence/adapter/grooming/GroomingDomainPersistenceAdapter.java @@ -6,10 +6,12 @@ import com.ftm.server.application.port.out.persistence.grooming.*; import com.ftm.server.application.query.FIndGroomingLevelByScoreQuery; import com.ftm.server.application.query.FindByIdQuery; +import com.ftm.server.application.query.FindByUserIdQuery; import com.ftm.server.common.annotation.Adapter; import com.ftm.server.common.exception.CustomException; import com.ftm.server.common.response.enums.ErrorResponseCode; import com.ftm.server.domain.entity.*; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -25,7 +27,8 @@ public class GroomingDomainPersistenceAdapter LoadUserForGroomingPort, SaveGroomingTestResultPort, LoadGroomingLevelPort, - UpdateUserForGroomingPort { + UpdateUserForGroomingPort, + LoadGroomingTestResultPort { // Repository private final GroomingTestQuestionRepository groomingTestQuestionRepository; @@ -113,4 +116,9 @@ public void updateUserGroomingStatus(User user) { // 유저 그루밍 레벨 업데이트 userJpaEntity.updateGroomingLevel(groomingLevelJpaEntity); } + + @Override + public LocalDateTime loadLatestTestedAtByUserId(FindByUserIdQuery query) { + return groomingTestResultRepository.fetchLatestTestedAtByUserId(query); + } } diff --git a/src/main/java/com/ftm/server/adapter/out/persistence/repository/GroomingTestResultCustomRepository.java b/src/main/java/com/ftm/server/adapter/out/persistence/repository/GroomingTestResultCustomRepository.java new file mode 100644 index 0000000..514004a --- /dev/null +++ b/src/main/java/com/ftm/server/adapter/out/persistence/repository/GroomingTestResultCustomRepository.java @@ -0,0 +1,9 @@ +package com.ftm.server.adapter.out.persistence.repository; + +import com.ftm.server.application.query.FindByUserIdQuery; +import java.time.LocalDateTime; + +public interface GroomingTestResultCustomRepository { + + LocalDateTime fetchLatestTestedAtByUserId(FindByUserIdQuery query); +} diff --git a/src/main/java/com/ftm/server/adapter/out/persistence/repository/GroomingTestResultCustomRepositoryImpl.java b/src/main/java/com/ftm/server/adapter/out/persistence/repository/GroomingTestResultCustomRepositoryImpl.java new file mode 100644 index 0000000..c254c49 --- /dev/null +++ b/src/main/java/com/ftm/server/adapter/out/persistence/repository/GroomingTestResultCustomRepositoryImpl.java @@ -0,0 +1,25 @@ +package com.ftm.server.adapter.out.persistence.repository; + +import static com.ftm.server.adapter.out.persistence.model.QGroomingTestResultJpaEntity.groomingTestResultJpaEntity; + +import com.ftm.server.application.query.FindByUserIdQuery; +import com.querydsl.jpa.impl.JPAQueryFactory; +import java.time.LocalDateTime; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +@Repository +@RequiredArgsConstructor +public class GroomingTestResultCustomRepositoryImpl implements GroomingTestResultCustomRepository { + + private final JPAQueryFactory queryFactory; + + @Override + public LocalDateTime fetchLatestTestedAtByUserId(FindByUserIdQuery query) { + return queryFactory + .select(groomingTestResultJpaEntity.testedAt.max()) + .from(groomingTestResultJpaEntity) + .where(groomingTestResultJpaEntity.user.id.eq(query.getUserId())) + .fetchOne(); + } +} diff --git a/src/main/java/com/ftm/server/adapter/out/persistence/repository/GroomingTestResultRepository.java b/src/main/java/com/ftm/server/adapter/out/persistence/repository/GroomingTestResultRepository.java index 7457fcf..9ff8fa7 100644 --- a/src/main/java/com/ftm/server/adapter/out/persistence/repository/GroomingTestResultRepository.java +++ b/src/main/java/com/ftm/server/adapter/out/persistence/repository/GroomingTestResultRepository.java @@ -4,4 +4,5 @@ import org.springframework.data.jpa.repository.JpaRepository; public interface GroomingTestResultRepository - extends JpaRepository {} + extends JpaRepository, + GroomingTestResultCustomRepository {} diff --git a/src/main/java/com/ftm/server/application/port/in/grooming/CheckGroomingTestAvailabilityUseCase.java b/src/main/java/com/ftm/server/application/port/in/grooming/CheckGroomingTestAvailabilityUseCase.java new file mode 100644 index 0000000..66e8dc6 --- /dev/null +++ b/src/main/java/com/ftm/server/application/port/in/grooming/CheckGroomingTestAvailabilityUseCase.java @@ -0,0 +1,11 @@ +package com.ftm.server.application.port.in.grooming; + +import com.ftm.server.application.query.FindByUserIdQuery; +import com.ftm.server.application.vo.grooming.GroomingTestAvailabilityVo; +import com.ftm.server.common.annotation.UseCase; + +@UseCase +public interface CheckGroomingTestAvailabilityUseCase { + + GroomingTestAvailabilityVo execute(FindByUserIdQuery query); +} diff --git a/src/main/java/com/ftm/server/application/port/out/persistence/grooming/LoadGroomingTestResultPort.java b/src/main/java/com/ftm/server/application/port/out/persistence/grooming/LoadGroomingTestResultPort.java new file mode 100644 index 0000000..12fa119 --- /dev/null +++ b/src/main/java/com/ftm/server/application/port/out/persistence/grooming/LoadGroomingTestResultPort.java @@ -0,0 +1,11 @@ +package com.ftm.server.application.port.out.persistence.grooming; + +import com.ftm.server.application.query.FindByUserIdQuery; +import com.ftm.server.common.annotation.Port; +import java.time.LocalDateTime; + +@Port +public interface LoadGroomingTestResultPort { + + LocalDateTime loadLatestTestedAtByUserId(FindByUserIdQuery query); +} diff --git a/src/main/java/com/ftm/server/application/service/grooming/CheckGroomingTestAvailabilityService.java b/src/main/java/com/ftm/server/application/service/grooming/CheckGroomingTestAvailabilityService.java new file mode 100644 index 0000000..e1fc17e --- /dev/null +++ b/src/main/java/com/ftm/server/application/service/grooming/CheckGroomingTestAvailabilityService.java @@ -0,0 +1,46 @@ +package com.ftm.server.application.service.grooming; + +import static com.ftm.server.common.consts.StaticConsts.MINIMUM_DAYS_BETWEEN_TESTS; + +import com.ftm.server.application.port.in.grooming.CheckGroomingTestAvailabilityUseCase; +import com.ftm.server.application.port.out.persistence.grooming.LoadGroomingTestResultPort; +import com.ftm.server.application.query.FindByUserIdQuery; +import com.ftm.server.application.vo.grooming.GroomingTestAvailabilityVo; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.temporal.ChronoUnit; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class CheckGroomingTestAvailabilityService implements CheckGroomingTestAvailabilityUseCase { + + private final LoadGroomingTestResultPort loadGroomingTestResultPort; + + @Override + public GroomingTestAvailabilityVo execute(FindByUserIdQuery query) { + // 가장 최근 테스트 날짜 조회 + LocalDateTime lastTestDateTime = + loadGroomingTestResultPort.loadLatestTestedAtByUserId(query); + if (lastTestDateTime == null) { // 테스트 기록이 없는 경우 + return GroomingTestAvailabilityVo.available(null); + } + + LocalDate now = LocalDate.now(ZoneId.of("Asia/Seoul")); + LocalDate lastTestDate = lastTestDateTime.toLocalDate(); + + // 가장 마지막에 수행한 테스트 날짜와 현재 날짜를 비교해 테스트 가능 여부 판단 + long daysSinceLastTest = ChronoUnit.DAYS.between(lastTestDate, now); + if (daysSinceLastTest < MINIMUM_DAYS_BETWEEN_TESTS) { // 마지막 테스트일로부터 7일이 지나지 않은 경우 + long remainingDays = MINIMUM_DAYS_BETWEEN_TESTS - daysSinceLastTest; + return GroomingTestAvailabilityVo.unavailable( + remainingDays, + lastTestDateTime, + lastTestDate.plusDays(MINIMUM_DAYS_BETWEEN_TESTS)); + } + + return GroomingTestAvailabilityVo.available(lastTestDateTime); // 마지막 테스트일로부터 7일이 지난 경우 + } +} diff --git a/src/main/java/com/ftm/server/application/vo/grooming/GroomingTestAvailabilityVo.java b/src/main/java/com/ftm/server/application/vo/grooming/GroomingTestAvailabilityVo.java new file mode 100644 index 0000000..d2fe997 --- /dev/null +++ b/src/main/java/com/ftm/server/application/vo/grooming/GroomingTestAvailabilityVo.java @@ -0,0 +1,34 @@ +package com.ftm.server.application.vo.grooming; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Getter; + +@Getter +public class GroomingTestAvailabilityVo { + + private final boolean available; + private final Long remainingDays; + private final LocalDateTime lastTestedAt; + private final LocalDate nextAvailableAt; + + private GroomingTestAvailabilityVo( + boolean available, + Long remainingDays, + LocalDateTime lastTestedAt, + LocalDate nextAvailableAt) { + this.available = available; + this.remainingDays = remainingDays; + this.lastTestedAt = lastTestedAt; + this.nextAvailableAt = nextAvailableAt; + } + + public static GroomingTestAvailabilityVo available(LocalDateTime lastTestedAt) { + return new GroomingTestAvailabilityVo(true, null, lastTestedAt, null); + } + + public static GroomingTestAvailabilityVo unavailable( + Long remainingDays, LocalDateTime lastTestedAt, LocalDate nextAvailableAt) { + return new GroomingTestAvailabilityVo(false, remainingDays, lastTestedAt, nextAvailableAt); + } +} diff --git a/src/main/java/com/ftm/server/common/consts/StaticConsts.java b/src/main/java/com/ftm/server/common/consts/StaticConsts.java index 8eeb150..bf9a7e7 100644 --- a/src/main/java/com/ftm/server/common/consts/StaticConsts.java +++ b/src/main/java/com/ftm/server/common/consts/StaticConsts.java @@ -7,7 +7,7 @@ public class StaticConsts { public static final int HAIR_CATEGORY_MAX_SCORE = 11; public static final int WORKOUT_CATEGORY_MAX_SCORE = 40; public static final int FASHION_CATEGORY_MAX_SCORE = 14; - + public static final int MINIMUM_DAYS_BETWEEN_TESTS = 7; public static final String AUTHORIZATION_HEADER_PREFIX = "Bearer "; public static final String AUTHORIZATION_GRANT_TYPE = "authorization_code"; public static final String PENDING_SOCIAL_USER_SESSION_KEY = "PENDING_SOCIAL_USER_INFO"; diff --git a/src/test/java/com/ftm/server/grooming/CheckGroomingTestAvailabilityTest.java b/src/test/java/com/ftm/server/grooming/CheckGroomingTestAvailabilityTest.java new file mode 100644 index 0000000..22ef00d --- /dev/null +++ b/src/test/java/com/ftm/server/grooming/CheckGroomingTestAvailabilityTest.java @@ -0,0 +1,217 @@ +package com.ftm.server.grooming; + +import static com.epages.restdocs.apispec.ResourceDocumentation.resource; +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.*; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.payload.JsonFieldType.*; +import static org.springframework.restdocs.payload.JsonFieldType.NUMBER; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.epages.restdocs.apispec.ResourceSnippetParameters; +import com.ftm.server.BaseTest; +import com.ftm.server.adapter.in.web.auth.dto.request.GeneralLoginRequest; +import com.ftm.server.application.command.user.GeneralUserCreationCommand; +import com.ftm.server.application.port.out.persistence.auth.LoadUserForAuthPort; +import com.ftm.server.application.port.out.persistence.grooming.SaveGroomingTestResultPort; +import com.ftm.server.application.port.out.persistence.user.SaveUserImagePort; +import com.ftm.server.application.port.out.persistence.user.SaveUserPort; +import com.ftm.server.application.port.out.security.SecurityAuthenticationPort; +import com.ftm.server.application.query.FindByEmailQuery; +import com.ftm.server.common.response.enums.ErrorResponseCode; +import com.ftm.server.domain.entity.GroomingTestResult; +import com.ftm.server.domain.entity.User; +import com.ftm.server.domain.entity.UserImage; +import java.time.LocalDateTime; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; +import org.springframework.restdocs.payload.FieldDescriptor; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.transaction.annotation.Transactional; + +public class CheckGroomingTestAvailabilityTest extends BaseTest { + + @Autowired private SecurityAuthenticationPort securityAuthenticationPort; + @Autowired private SaveUserPort saveUserPort; + @Autowired private SaveUserImagePort saveUserImagePort; + @Autowired private LoadUserForAuthPort loadUserForAuthPort; + @Autowired private SaveGroomingTestResultPort saveGroomingTestResultPort; + + private final List responseFieldCheckGroomingTestAvailability = + List.of( + fieldWithPath("status").type(NUMBER).description("응답 상태"), + fieldWithPath("code").type(STRING).description("상태 코드"), + fieldWithPath("message").type(STRING).description("메시지"), + fieldWithPath("data").type(OBJECT).optional().description("data"), + fieldWithPath("data.available") + .type(BOOLEAN) + .description("그루밍 테스트 가능 여부 (true일 경우 테스트 가능)"), + fieldWithPath("data.remainingDays") + .type(NUMBER) + .optional() + .description("다음 테스트까지 남은 일수"), + fieldWithPath("data.lastTestedAt") + .type(STRING) + .optional() + .description("마지막으로 테스트한 날짜"), + fieldWithPath("data.nextAvailableAt") + .type(STRING) + .optional() + .description("테스트가 가능해지는 날짜")); + + private RestDocumentationResultHandler getDocument(Integer identifier) { + return document( + "checkGroomingTestAvailability/" + identifier, + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint(), getModifiedHeader()), + requestHeaders( + headerWithName("Cookie") + .description("로그인 시 발급받은 SESSION Cookie") + .optional()), + responseFields(responseFieldCheckGroomingTestAvailability), + resource( + ResourceSnippetParameters.builder() + .tag("그루밍 테스트") + .summary("그루밍 테스트 가능 여부 api") + .description("그루밍 테스트 가능 여부를 조회하는 api 입니다.") + .responseFields(responseFieldCheckGroomingTestAvailability) + .build())); + } + + private MockHttpSession getLoginResultActions() throws Exception { + GeneralLoginRequest request = new GeneralLoginRequest("test@gmail.com", "test1234!"); + + MvcResult loginResult = + mockMvc.perform( + RestDocumentationRequestBuilders.post("/api/auth/login") + .contentType(APPLICATION_JSON_VALUE) + .content(mapper.writeValueAsString(request))) + .andExpect(status().isOk()) + .andReturn(); + + return (MockHttpSession) loginResult.getRequest().getSession(false); + } + + private ResultActions getResultActions(MockHttpSession session) throws Exception { + return mockMvc.perform( + RestDocumentationRequestBuilders.get("/api/grooming/tests/availability") + .session(session)); + } + + @BeforeEach + void setUp() { + GeneralUserCreationCommand command = + new GeneralUserCreationCommand( + "test@gmail.com", + securityAuthenticationPort.passwordEncode("test1234!"), + "test", + null, + null); + User testUser = saveUserPort.saveUser(User.createGeneralUser(command)); + saveUserImagePort.saveUserDefaultImage(UserImage.createUserImage(testUser.getId())); + } + + @Test + @Transactional + void 그루밍_테스트_가능_여부_조회_성공1() throws Exception { + // given + User user = + loadUserForAuthPort.loadUserByEmail(FindByEmailQuery.of("test@gmail.com")).get(); + List results = + List.of( + GroomingTestResult.create(user.getId(), 1L, 1L, LocalDateTime.now()), + GroomingTestResult.create( + user.getId(), 1L, 1L, LocalDateTime.now().minusDays(7))); + saveGroomingTestResultPort.saveGroomingTestResults(results); + + // when + MockHttpSession session = getLoginResultActions(); + ResultActions resultActions = getResultActions(session); + resultActions + .andReturn() + .getRequest() + .addHeader("Cookie", "SESSION=mock-session-id; Path=/; HttpOnly"); + + // then + resultActions.andExpect(status().isOk()).andDo(print()); + + // documentation + resultActions.andDo(getDocument(1)); + } + + @Test + @Transactional + void 그루밍_테스트_가능_여부_조회_성공2() throws Exception { + // given + User user = + loadUserForAuthPort.loadUserByEmail(FindByEmailQuery.of("test@gmail.com")).get(); + List results = + List.of( + GroomingTestResult.create( + user.getId(), 1L, 1L, LocalDateTime.now().minusDays(7))); + saveGroomingTestResultPort.saveGroomingTestResults(results); + + // when + MockHttpSession session = getLoginResultActions(); + ResultActions resultActions = getResultActions(session); + resultActions + .andReturn() + .getRequest() + .addHeader("Cookie", "SESSION=mock-session-id; Path=/; HttpOnly"); + + // then + resultActions.andExpect(status().isOk()).andDo(print()); + + // documentation + resultActions.andDo(getDocument(2)); + } + + @Test + @Transactional + void 그루밍_테스트_가능_여부_조회_성공3() throws Exception { + // when + MockHttpSession session = getLoginResultActions(); + ResultActions resultActions = getResultActions(session); + resultActions + .andReturn() + .getRequest() + .addHeader("Cookie", "SESSION=mock-session-id; Path=/; HttpOnly"); + + // then + resultActions.andExpect(status().isOk()).andDo(print()); + + // documentation + resultActions.andDo(getDocument(3)); + } + + @Test + @Transactional + void 그루밍_테스트_가능_여부_조회_실패() throws Exception { + // when + ResultActions resultActions = + mockMvc.perform( + RestDocumentationRequestBuilders.get("/api/grooming/tests/availability")); + + // then + resultActions + .andExpect(status().is(ErrorResponseCode.NOT_AUTHENTICATED.getHttpStatus().value())) + .andExpect(jsonPath("code").value(ErrorResponseCode.NOT_AUTHENTICATED.getCode())) + .andDo(print()); + + // documentation + resultActions.andDo(getDocument(4)); + } +}