generated from pricelees/issue-pr-template
<!-- 제목 양식 --> <!-- [이슈번호] 작업 요약 (예시: [#10] Gitea 템플릿 생성) --> ## 📝 관련 이슈 및 PR **PR과 관련된 이슈 번호** - #13 ## ✨ 작업 내용 <!-- 어떤 작업을 했는지 알려주세요! --> theme 패키지 내 코드 및 테스트 코틀린 전환 ## 🧪 테스트 <!-- 어떤 테스트를 생각했고 진행했는지 알려주세요! --> 다른 테스트는 코틀린으로 전환 시 크게 문제가 없었으나, GET /themes/most-reserved-last-week API의 경우 쿼리에 크게 의존하여 mocking을 사용하는 기존 테스트로 처리하기 애매한 부분이 있었음. 따라서, API 테스트는 mocking이 아닌 RestAssured를 이용한 실제 테스트로 진행하였고 \@RequestParam, 날짜 등 실제 비즈니스와 관련된 부분을 위주로 처리하고 쿼리 자체는 Repository 테스트에서 상세하게 검증하였음. ## 📚 참고 자료 및 기타 <!-- 참고한 자료, 또는 논의할 사항이 있다면 알려주세요! --> 패키지를 reservation 안에 넣는 것은 고민이 조금 더 필요할 것 같음. 현재는 단일 매장에 대한 서비스지만 매장별로 분리하는 것을 고민중인 만큼 코틀린 마이그레이션이 끝난 이후 생각해볼 예정 Reviewed-on: #15 Co-authored-by: pricelees <priceelees@gmail.com> Co-committed-by: pricelees <priceelees@gmail.com>
This commit is contained in:
parent
ed383c3092
commit
8a4f71be39
@ -69,9 +69,9 @@ class AdminInterceptor(
|
|||||||
val token: String? = request.accessTokenCookie().value
|
val token: String? = request.accessTokenCookie().value
|
||||||
val memberId: Long = jwtHandler.getMemberIdFromToken(token)
|
val memberId: Long = jwtHandler.getMemberIdFromToken(token)
|
||||||
member = memberService.findById(memberId)
|
member = memberService.findById(memberId)
|
||||||
} catch (e: RoomescapeException) {
|
} catch (_: RoomescapeException) {
|
||||||
response.sendRedirect("/login")
|
response.sendRedirect("/login")
|
||||||
throw e
|
throw RoomescapeException(ErrorType.LOGIN_REQUIRED, HttpStatus.FORBIDDEN)
|
||||||
}
|
}
|
||||||
|
|
||||||
with(member) {
|
with(member) {
|
||||||
|
|||||||
@ -8,11 +8,4 @@ import roomescape.common.exception.ErrorType
|
|||||||
data class RoomescapeErrorResponse(
|
data class RoomescapeErrorResponse(
|
||||||
val errorType: ErrorType,
|
val errorType: ErrorType,
|
||||||
val message: String
|
val message: String
|
||||||
) {
|
)
|
||||||
|
|
||||||
companion object {
|
|
||||||
@JvmStatic
|
|
||||||
fun of(errorType: ErrorType, message: String? = null): RoomescapeErrorResponse =
|
|
||||||
RoomescapeErrorResponse(errorType, message ?: errorType.description)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -18,7 +18,7 @@ import jakarta.persistence.ManyToOne;
|
|||||||
import roomescape.common.exception.ErrorType;
|
import roomescape.common.exception.ErrorType;
|
||||||
import roomescape.common.exception.RoomescapeException;
|
import roomescape.common.exception.RoomescapeException;
|
||||||
import roomescape.member.infrastructure.persistence.Member;
|
import roomescape.member.infrastructure.persistence.Member;
|
||||||
import roomescape.theme.domain.Theme;
|
import roomescape.theme.infrastructure.persistence.ThemeEntity;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
public class Reservation {
|
public class Reservation {
|
||||||
@ -35,7 +35,7 @@ public class Reservation {
|
|||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
@JoinColumn(name = "theme_id", nullable = false)
|
@JoinColumn(name = "theme_id", nullable = false)
|
||||||
private Theme theme;
|
private ThemeEntity theme;
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
@JoinColumn(name = "member_id", nullable = false)
|
@JoinColumn(name = "member_id", nullable = false)
|
||||||
@ -50,7 +50,7 @@ public class Reservation {
|
|||||||
public Reservation(
|
public Reservation(
|
||||||
LocalDate date,
|
LocalDate date,
|
||||||
ReservationTime reservationTime,
|
ReservationTime reservationTime,
|
||||||
Theme theme,
|
ThemeEntity theme,
|
||||||
Member member,
|
Member member,
|
||||||
ReservationStatus status
|
ReservationStatus status
|
||||||
) {
|
) {
|
||||||
@ -61,7 +61,7 @@ public class Reservation {
|
|||||||
Long id,
|
Long id,
|
||||||
LocalDate date,
|
LocalDate date,
|
||||||
ReservationTime reservationTime,
|
ReservationTime reservationTime,
|
||||||
Theme theme,
|
ThemeEntity theme,
|
||||||
Member member,
|
Member member,
|
||||||
ReservationStatus status
|
ReservationStatus status
|
||||||
) {
|
) {
|
||||||
@ -74,7 +74,7 @@ public class Reservation {
|
|||||||
this.reservationStatus = status;
|
this.reservationStatus = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateIsNull(LocalDate date, ReservationTime reservationTime, Theme theme, Member member,
|
private void validateIsNull(LocalDate date, ReservationTime reservationTime, ThemeEntity theme, Member member,
|
||||||
ReservationStatus reservationStatus) {
|
ReservationStatus reservationStatus) {
|
||||||
if (date == null || reservationTime == null || theme == null || member == null || reservationStatus == null) {
|
if (date == null || reservationTime == null || theme == null || member == null || reservationStatus == null) {
|
||||||
throw new RoomescapeException(ErrorType.REQUEST_DATA_BLANK, String.format("[values: %s]", this),
|
throw new RoomescapeException(ErrorType.REQUEST_DATA_BLANK, String.format("[values: %s]", this),
|
||||||
@ -98,7 +98,7 @@ public class Reservation {
|
|||||||
return reservationTime;
|
return reservationTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Theme getTheme() {
|
public ThemeEntity getTheme() {
|
||||||
return theme;
|
return theme;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||||||
import roomescape.member.web.MemberResponse;
|
import roomescape.member.web.MemberResponse;
|
||||||
import roomescape.reservation.domain.Reservation;
|
import roomescape.reservation.domain.Reservation;
|
||||||
import roomescape.reservation.domain.ReservationStatus;
|
import roomescape.reservation.domain.ReservationStatus;
|
||||||
import roomescape.theme.dto.ThemeResponse;
|
import roomescape.theme.web.ThemeResponse;
|
||||||
|
|
||||||
@Schema(name = "예약 정보", description = "예약 저장 및 조회 응답에 사용됩니다.")
|
@Schema(name = "예약 정보", description = "예약 저장 및 조회 응답에 사용됩니다.")
|
||||||
public record ReservationResponse(
|
public record ReservationResponse(
|
||||||
|
|||||||
@ -24,8 +24,8 @@ import roomescape.reservation.dto.request.WaitingRequest;
|
|||||||
import roomescape.reservation.dto.response.MyReservationsResponse;
|
import roomescape.reservation.dto.response.MyReservationsResponse;
|
||||||
import roomescape.reservation.dto.response.ReservationResponse;
|
import roomescape.reservation.dto.response.ReservationResponse;
|
||||||
import roomescape.reservation.dto.response.ReservationsResponse;
|
import roomescape.reservation.dto.response.ReservationsResponse;
|
||||||
import roomescape.theme.domain.Theme;
|
import roomescape.theme.infrastructure.persistence.ThemeEntity;
|
||||||
import roomescape.theme.service.ThemeService;
|
import roomescape.theme.business.ThemeService;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Transactional
|
@Transactional
|
||||||
@ -146,7 +146,7 @@ public class ReservationService {
|
|||||||
private Reservation getReservationForSave(Long timeId, Long themeId, LocalDate date, Long memberId,
|
private Reservation getReservationForSave(Long timeId, Long themeId, LocalDate date, Long memberId,
|
||||||
ReservationStatus status) {
|
ReservationStatus status) {
|
||||||
ReservationTime time = reservationTimeService.findTimeById(timeId);
|
ReservationTime time = reservationTimeService.findTimeById(timeId);
|
||||||
Theme theme = themeService.findThemeById(themeId);
|
ThemeEntity theme = themeService.findThemeById(themeId);
|
||||||
Member member = memberService.findById(memberId);
|
Member member = memberService.findById(memberId);
|
||||||
|
|
||||||
validateDateAndTime(date, time);
|
validateDateAndTime(date, time);
|
||||||
|
|||||||
74
src/main/java/roomescape/theme/business/ThemeService.kt
Normal file
74
src/main/java/roomescape/theme/business/ThemeService.kt
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
package roomescape.theme.business
|
||||||
|
|
||||||
|
import org.springframework.data.repository.findByIdOrNull
|
||||||
|
import org.springframework.http.HttpStatus
|
||||||
|
import org.springframework.stereotype.Service
|
||||||
|
import org.springframework.transaction.annotation.Transactional
|
||||||
|
import roomescape.common.exception.ErrorType
|
||||||
|
import roomescape.common.exception.RoomescapeException
|
||||||
|
import roomescape.theme.infrastructure.persistence.ThemeEntity
|
||||||
|
import roomescape.theme.infrastructure.persistence.ThemeRepository
|
||||||
|
import roomescape.theme.web.ThemeRequest
|
||||||
|
import roomescape.theme.web.ThemeResponse
|
||||||
|
import roomescape.theme.web.ThemesResponse
|
||||||
|
import roomescape.theme.web.toResponse
|
||||||
|
import java.time.LocalDate
|
||||||
|
|
||||||
|
@Service
|
||||||
|
class ThemeService(
|
||||||
|
private val themeRepository: ThemeRepository
|
||||||
|
) {
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
fun findThemeById(id: Long): ThemeEntity = themeRepository.findByIdOrNull(id)
|
||||||
|
?: throw RoomescapeException(
|
||||||
|
ErrorType.THEME_NOT_FOUND,
|
||||||
|
"[themeId: $id]",
|
||||||
|
HttpStatus.BAD_REQUEST
|
||||||
|
)
|
||||||
|
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
fun findAllThemes(): ThemesResponse = themeRepository.findAll()
|
||||||
|
.toResponse()
|
||||||
|
|
||||||
|
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
fun getMostReservedThemesByCount(count: Int): ThemesResponse {
|
||||||
|
val today = LocalDate.now()
|
||||||
|
val startDate = today.minusDays(7)
|
||||||
|
val endDate = today.minusDays(1)
|
||||||
|
|
||||||
|
return themeRepository.findTopNThemeBetweenStartDateAndEndDate(startDate, endDate, count)
|
||||||
|
.toResponse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
fun save(request: ThemeRequest): ThemeResponse {
|
||||||
|
if (themeRepository.existsByName(request.name)) {
|
||||||
|
throw RoomescapeException(
|
||||||
|
ErrorType.THEME_DUPLICATED,
|
||||||
|
"[name: ${request.name}]",
|
||||||
|
HttpStatus.CONFLICT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ThemeEntity(
|
||||||
|
name = request.name,
|
||||||
|
description = request.description,
|
||||||
|
thumbnail = request.thumbnail
|
||||||
|
).also {
|
||||||
|
themeRepository.save(it)
|
||||||
|
}.toResponse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
fun deleteById(id: Long) {
|
||||||
|
if (themeRepository.isReservedTheme(id)) {
|
||||||
|
throw RoomescapeException(
|
||||||
|
ErrorType.THEME_IS_USED_CONFLICT,
|
||||||
|
"[themeId: %d]",
|
||||||
|
HttpStatus.CONFLICT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
themeRepository.deleteById(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,101 +0,0 @@
|
|||||||
package roomescape.theme.controller;
|
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Content;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import jakarta.validation.Valid;
|
|
||||||
import jakarta.validation.constraints.NotNull;
|
|
||||||
import roomescape.auth.web.support.Admin;
|
|
||||||
import roomescape.auth.web.support.LoginRequired;
|
|
||||||
import roomescape.common.dto.response.RoomescapeApiResponse;
|
|
||||||
import roomescape.common.dto.response.RoomescapeErrorResponse;
|
|
||||||
import roomescape.theme.dto.ThemeRequest;
|
|
||||||
import roomescape.theme.dto.ThemeResponse;
|
|
||||||
import roomescape.theme.dto.ThemesResponse;
|
|
||||||
import roomescape.theme.service.ThemeService;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@Tag(name = "5. 테마 API", description = "테마를 조회 / 추가 / 삭제할 때 사용합니다.")
|
|
||||||
public class ThemeController {
|
|
||||||
|
|
||||||
private final ThemeService themeService;
|
|
||||||
|
|
||||||
public ThemeController(ThemeService themeService) {
|
|
||||||
this.themeService = themeService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@LoginRequired
|
|
||||||
@GetMapping("/themes")
|
|
||||||
@ResponseStatus(HttpStatus.OK)
|
|
||||||
@Operation(summary = "모든 테마 조회", description = "모든 테마를 조회합니다.", tags = "로그인이 필요한 API")
|
|
||||||
@ApiResponses({
|
|
||||||
@ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)
|
|
||||||
})
|
|
||||||
public RoomescapeApiResponse<ThemesResponse> getAllThemes() {
|
|
||||||
return RoomescapeApiResponse.success(themeService.findAllThemes());
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/themes/most-reserved-last-week")
|
|
||||||
@ResponseStatus(HttpStatus.OK)
|
|
||||||
@Operation(summary = "가장 많이 예약된 테마 조회")
|
|
||||||
@ApiResponses({
|
|
||||||
@ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)
|
|
||||||
})
|
|
||||||
public RoomescapeApiResponse<ThemesResponse> getMostReservedThemes(
|
|
||||||
@RequestParam(defaultValue = "10") @Parameter(description = "최대로 조회할 테마 갯수") int count
|
|
||||||
) {
|
|
||||||
return RoomescapeApiResponse.success(themeService.getMostReservedThemesByCount(count));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Admin
|
|
||||||
@PostMapping("/themes")
|
|
||||||
@ResponseStatus(HttpStatus.CREATED)
|
|
||||||
@Operation(summary = "테마 추가", tags = "관리자 로그인이 필요한 API")
|
|
||||||
@ApiResponses({
|
|
||||||
@ApiResponse(responseCode = "201", description = "성공", useReturnTypeSchema = true),
|
|
||||||
@ApiResponse(responseCode = "409", description = "같은 이름의 테마를 추가할 수 없습니다.",
|
|
||||||
content = @Content(schema = @Schema(implementation = RoomescapeErrorResponse.class)))
|
|
||||||
})
|
|
||||||
public RoomescapeApiResponse<ThemeResponse> saveTheme(
|
|
||||||
@Valid @RequestBody ThemeRequest request,
|
|
||||||
HttpServletResponse response
|
|
||||||
) {
|
|
||||||
ThemeResponse themeResponse = themeService.addTheme(request);
|
|
||||||
response.setHeader(HttpHeaders.LOCATION, "/themes/" + themeResponse.id());
|
|
||||||
|
|
||||||
return RoomescapeApiResponse.success(themeResponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Admin
|
|
||||||
@DeleteMapping("/themes/{id}")
|
|
||||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
|
||||||
@Operation(summary = "테마 삭제", tags = "관리자 로그인이 필요한 API")
|
|
||||||
@ApiResponses({
|
|
||||||
@ApiResponse(responseCode = "204", description = "성공", useReturnTypeSchema = true),
|
|
||||||
@ApiResponse(responseCode = "409", description = "예약된 테마는 삭제할 수 없습니다.",
|
|
||||||
content = @Content(schema = @Schema(implementation = RoomescapeErrorResponse.class)))
|
|
||||||
})
|
|
||||||
public RoomescapeApiResponse<Void> removeTheme(
|
|
||||||
@NotNull(message = "themeId는 null일 수 없습니다.") @PathVariable Long id
|
|
||||||
) {
|
|
||||||
themeService.removeThemeById(id);
|
|
||||||
|
|
||||||
return RoomescapeApiResponse.success();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
51
src/main/java/roomescape/theme/docs/ThemeAPI.kt
Normal file
51
src/main/java/roomescape/theme/docs/ThemeAPI.kt
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package roomescape.theme.docs
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponse
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponses
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag
|
||||||
|
import jakarta.validation.Valid
|
||||||
|
import org.springframework.http.ResponseEntity
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam
|
||||||
|
import roomescape.auth.web.support.Admin
|
||||||
|
import roomescape.auth.web.support.LoginRequired
|
||||||
|
import roomescape.common.dto.response.CommonApiResponse
|
||||||
|
import roomescape.theme.web.ThemeRequest
|
||||||
|
import roomescape.theme.web.ThemeResponse
|
||||||
|
import roomescape.theme.web.ThemesResponse
|
||||||
|
|
||||||
|
@Tag(name = "5. 테마 API", description = "테마를 조회 / 추가 / 삭제할 때 사용합니다.")
|
||||||
|
interface ThemeAPI {
|
||||||
|
|
||||||
|
@LoginRequired
|
||||||
|
@Operation(summary = "모든 테마 조회", description = "모든 테마를 조회합니다.", tags = ["로그인이 필요한 API"])
|
||||||
|
@ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true))
|
||||||
|
fun getAllThemes(): ResponseEntity<CommonApiResponse<ThemesResponse>>
|
||||||
|
|
||||||
|
@Operation(summary = "가장 많이 예약된 테마 조회")
|
||||||
|
@ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true))
|
||||||
|
fun getMostReservedThemes(
|
||||||
|
@RequestParam(defaultValue = "10") @Parameter(description = "최대로 조회할 테마 갯수") count: Int
|
||||||
|
): ResponseEntity<CommonApiResponse<ThemesResponse>>
|
||||||
|
|
||||||
|
@Admin
|
||||||
|
@Operation(summary = "테마 추가", tags = ["관리자 로그인이 필요한 API"])
|
||||||
|
@ApiResponses(
|
||||||
|
ApiResponse(responseCode = "201", description = "성공", useReturnTypeSchema = true),
|
||||||
|
)
|
||||||
|
fun saveTheme(
|
||||||
|
@Valid @RequestBody request: ThemeRequest,
|
||||||
|
): ResponseEntity<CommonApiResponse<ThemeResponse>>
|
||||||
|
|
||||||
|
@Admin
|
||||||
|
@Operation(summary = "테마 삭제", tags = ["관리자 로그인이 필요한 API"])
|
||||||
|
@ApiResponses(
|
||||||
|
ApiResponse(responseCode = "204", description = "성공", useReturnTypeSchema = true),
|
||||||
|
)
|
||||||
|
fun removeTheme(
|
||||||
|
@PathVariable id: Long
|
||||||
|
): ResponseEntity<CommonApiResponse<Unit>>
|
||||||
|
}
|
||||||
@ -1,65 +0,0 @@
|
|||||||
package roomescape.theme.domain;
|
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.GenerationType;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
public class Theme {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
private String description;
|
|
||||||
|
|
||||||
private String thumbnail;
|
|
||||||
|
|
||||||
protected Theme() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public Theme(String name, String description, String thumbnail) {
|
|
||||||
this(null, name, description, thumbnail);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Theme(
|
|
||||||
Long id,
|
|
||||||
String name,
|
|
||||||
String description,
|
|
||||||
String thumbnail
|
|
||||||
) {
|
|
||||||
this.id = id;
|
|
||||||
this.name = name;
|
|
||||||
this.description = description;
|
|
||||||
this.thumbnail = thumbnail;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDescription() {
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getThumbnail() {
|
|
||||||
return thumbnail;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Theme{" +
|
|
||||||
"id=" + id +
|
|
||||||
", name=" + name +
|
|
||||||
", description=" + description +
|
|
||||||
", thumbnail=" + thumbnail +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
package roomescape.theme.domain.repository;
|
|
||||||
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.data.jpa.repository.Query;
|
|
||||||
|
|
||||||
import roomescape.theme.domain.Theme;
|
|
||||||
|
|
||||||
public interface ThemeRepository extends JpaRepository<Theme, Long> {
|
|
||||||
|
|
||||||
@Query(value = """
|
|
||||||
SELECT t
|
|
||||||
FROM Theme t
|
|
||||||
RIGHT JOIN Reservation r ON t.id = r.theme.id
|
|
||||||
WHERE r.date BETWEEN :startDate AND :endDate
|
|
||||||
GROUP BY r.theme.id
|
|
||||||
ORDER BY COUNT(r.theme.id) DESC, t.id ASC
|
|
||||||
LIMIT :limit
|
|
||||||
""")
|
|
||||||
List<Theme> findTopNThemeBetweenStartDateAndEndDate(LocalDate startDate, LocalDate endDate, int limit);
|
|
||||||
|
|
||||||
boolean existsByName(String name);
|
|
||||||
|
|
||||||
@Query(value = """
|
|
||||||
SELECT EXISTS(
|
|
||||||
SELECT 1
|
|
||||||
FROM Reservation r
|
|
||||||
WHERE r.theme.id = :id
|
|
||||||
)
|
|
||||||
""")
|
|
||||||
boolean isReservedTheme(Long id);
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
package roomescape.theme.dto;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
|
||||||
import jakarta.validation.constraints.Size;
|
|
||||||
|
|
||||||
@Schema(name = "테마 저장 요청", description = "테마 정보를 저장할 때 사용합니다.")
|
|
||||||
public record ThemeRequest(
|
|
||||||
@NotBlank(message = "테마의 이름은 null 또는 공백일 수 없습니다.")
|
|
||||||
@Size(min = 1, max = 20, message = "테마의 이름은 1~20글자 사이여야 합니다.")
|
|
||||||
@Schema(description = "필수 값이며, 최대 20글자까지 입력 가능합니다.")
|
|
||||||
String name,
|
|
||||||
@NotBlank(message = "테마의 설명은 null 또는 공백일 수 없습니다.")
|
|
||||||
@Size(min = 1, max = 100, message = "테마의 설명은 1~100글자 사이여야 합니다.")
|
|
||||||
@Schema(description = "필수 값이며, 최대 100글자까지 입력 가능합니다.")
|
|
||||||
String description,
|
|
||||||
@NotBlank(message = "테마의 쌈네일은 null 또는 공백일 수 없습니다.")
|
|
||||||
@Schema(description = "필수 값이며, 썸네일 이미지 URL 을 입력해주세요.")
|
|
||||||
String thumbnail
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
package roomescape.theme.dto;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import roomescape.theme.domain.Theme;
|
|
||||||
|
|
||||||
@Schema(name = "테마 정보", description = "테마 추가 및 조회 응답에 사용됩니다.")
|
|
||||||
public record ThemeResponse(
|
|
||||||
@Schema(description = "테마 번호. 테마를 식별할 때 사용합니다.")
|
|
||||||
Long id,
|
|
||||||
@Schema(description = "테마 이름. 중복을 허용하지 않습니다.")
|
|
||||||
String name,
|
|
||||||
@Schema(description = "테마 설명")
|
|
||||||
String description,
|
|
||||||
@Schema(description = "테마 썸네일 이미지 URL")
|
|
||||||
String thumbnail
|
|
||||||
) {
|
|
||||||
|
|
||||||
public static ThemeResponse from(Theme theme) {
|
|
||||||
return new ThemeResponse(theme.getId(), theme.getName(), theme.getDescription(), theme.getThumbnail());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
package roomescape.theme.dto;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
|
|
||||||
@Schema(name = "테마 목록 조회 응답", description = "모든 테마 목록 조회 응답시 사용됩니다.")
|
|
||||||
public record ThemesResponse(
|
|
||||||
@Schema(description = "모든 테마 목록") List<ThemeResponse> themes
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
package roomescape.theme.infrastructure.persistence
|
||||||
|
|
||||||
|
import jakarta.persistence.*
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "theme")
|
||||||
|
class ThemeEntity(
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
var id: Long? = null,
|
||||||
|
|
||||||
|
var name: String,
|
||||||
|
var description: String,
|
||||||
|
var thumbnail: String
|
||||||
|
)
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
package roomescape.theme.infrastructure.persistence
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository
|
||||||
|
import org.springframework.data.jpa.repository.Query
|
||||||
|
import java.time.LocalDate
|
||||||
|
|
||||||
|
interface ThemeRepository : JpaRepository<ThemeEntity, Long> {
|
||||||
|
|
||||||
|
@Query(value = """
|
||||||
|
SELECT t
|
||||||
|
FROM ThemeEntity t
|
||||||
|
RIGHT JOIN Reservation r ON t.id = r.theme.id
|
||||||
|
WHERE r.date BETWEEN :startDate AND :endDate
|
||||||
|
GROUP BY r.theme.id
|
||||||
|
ORDER BY COUNT(r.theme.id) DESC, t.id ASC
|
||||||
|
LIMIT :limit
|
||||||
|
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
fun findTopNThemeBetweenStartDateAndEndDate(startDate: LocalDate, endDate: LocalDate, limit: Int): List<ThemeEntity>
|
||||||
|
|
||||||
|
fun existsByName(name: String): Boolean
|
||||||
|
|
||||||
|
@Query(value = """
|
||||||
|
SELECT EXISTS(
|
||||||
|
SELECT 1
|
||||||
|
FROM Reservation r
|
||||||
|
WHERE r.theme.id = :id
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
fun isReservedTheme(id: Long): Boolean
|
||||||
|
}
|
||||||
@ -1,82 +0,0 @@
|
|||||||
package roomescape.theme.service;
|
|
||||||
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import roomescape.common.exception.ErrorType;
|
|
||||||
import roomescape.common.exception.RoomescapeException;
|
|
||||||
import roomescape.reservation.domain.repository.ReservationRepository;
|
|
||||||
import roomescape.theme.domain.Theme;
|
|
||||||
import roomescape.theme.domain.repository.ThemeRepository;
|
|
||||||
import roomescape.theme.dto.ThemeRequest;
|
|
||||||
import roomescape.theme.dto.ThemeResponse;
|
|
||||||
import roomescape.theme.dto.ThemesResponse;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@Transactional
|
|
||||||
public class ThemeService {
|
|
||||||
|
|
||||||
private final ThemeRepository themeRepository;
|
|
||||||
|
|
||||||
public ThemeService(ThemeRepository themeRepository) {
|
|
||||||
this.themeRepository = themeRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
|
||||||
public Theme findThemeById(Long id) {
|
|
||||||
return themeRepository.findById(id)
|
|
||||||
.orElseThrow(() -> new RoomescapeException(ErrorType.THEME_NOT_FOUND,
|
|
||||||
String.format("[themeId: %d]", id), HttpStatus.BAD_REQUEST));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
|
||||||
public ThemesResponse findAllThemes() {
|
|
||||||
List<ThemeResponse> response = themeRepository.findAll()
|
|
||||||
.stream()
|
|
||||||
.map(ThemeResponse::from)
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
return new ThemesResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
|
||||||
public ThemesResponse getMostReservedThemesByCount(int count) {
|
|
||||||
LocalDate today = LocalDate.now();
|
|
||||||
LocalDate startDate = today.minusDays(7);
|
|
||||||
LocalDate endDate = today.minusDays(1);
|
|
||||||
|
|
||||||
List<ThemeResponse> response = themeRepository.findTopNThemeBetweenStartDateAndEndDate(startDate, endDate,
|
|
||||||
count)
|
|
||||||
.stream()
|
|
||||||
.map(ThemeResponse::from)
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
return new ThemesResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ThemeResponse addTheme(ThemeRequest request) {
|
|
||||||
validateIsSameThemeNameExist(request.name());
|
|
||||||
Theme theme = themeRepository.save(new Theme(request.name(), request.description(), request.thumbnail()));
|
|
||||||
|
|
||||||
return ThemeResponse.from(theme);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void validateIsSameThemeNameExist(String name) {
|
|
||||||
if (themeRepository.existsByName(name)) {
|
|
||||||
throw new RoomescapeException(ErrorType.THEME_DUPLICATED,
|
|
||||||
String.format("[name: %s]", name), HttpStatus.CONFLICT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeThemeById(Long id) {
|
|
||||||
if (themeRepository.isReservedTheme(id)) {
|
|
||||||
throw new RoomescapeException(ErrorType.THEME_IS_USED_CONFLICT,
|
|
||||||
String.format("[themeId: %d]", id), HttpStatus.CONFLICT);
|
|
||||||
}
|
|
||||||
themeRepository.deleteById(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
51
src/main/java/roomescape/theme/web/ThemeController.kt
Normal file
51
src/main/java/roomescape/theme/web/ThemeController.kt
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package roomescape.theme.web
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter
|
||||||
|
import jakarta.validation.Valid
|
||||||
|
import org.springframework.http.ResponseEntity
|
||||||
|
import org.springframework.web.bind.annotation.*
|
||||||
|
import roomescape.common.dto.response.CommonApiResponse
|
||||||
|
import roomescape.theme.business.ThemeService
|
||||||
|
import roomescape.theme.docs.ThemeAPI
|
||||||
|
import java.net.URI
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
class ThemeController(
|
||||||
|
private val themeService: ThemeService
|
||||||
|
) : ThemeAPI {
|
||||||
|
|
||||||
|
@GetMapping("/themes")
|
||||||
|
override fun getAllThemes(): ResponseEntity<CommonApiResponse<ThemesResponse>> {
|
||||||
|
val response: ThemesResponse = themeService.findAllThemes()
|
||||||
|
|
||||||
|
return ResponseEntity.ok(CommonApiResponse(response))
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/themes/most-reserved-last-week")
|
||||||
|
override fun getMostReservedThemes(
|
||||||
|
@RequestParam(defaultValue = "10") @Parameter(description = "최대로 조회할 테마 갯수") count: Int
|
||||||
|
): ResponseEntity<CommonApiResponse<ThemesResponse>> {
|
||||||
|
val response: ThemesResponse = themeService.getMostReservedThemesByCount(count)
|
||||||
|
|
||||||
|
return ResponseEntity.ok(CommonApiResponse(response))
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/themes")
|
||||||
|
override fun saveTheme(
|
||||||
|
@RequestBody @Valid request: ThemeRequest
|
||||||
|
): ResponseEntity<CommonApiResponse<ThemeResponse>> {
|
||||||
|
val themeResponse: ThemeResponse = themeService.save(request)
|
||||||
|
|
||||||
|
return ResponseEntity.created(URI.create("/themes/${themeResponse.id}"))
|
||||||
|
.body(CommonApiResponse(themeResponse))
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/themes/{id}")
|
||||||
|
override fun removeTheme(
|
||||||
|
@PathVariable id: Long
|
||||||
|
): ResponseEntity<CommonApiResponse<Unit>> {
|
||||||
|
themeService.deleteById(id)
|
||||||
|
|
||||||
|
return ResponseEntity.noContent().build()
|
||||||
|
}
|
||||||
|
}
|
||||||
68
src/main/java/roomescape/theme/web/ThemeDTO.kt
Normal file
68
src/main/java/roomescape/theme/web/ThemeDTO.kt
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package roomescape.theme.web
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema
|
||||||
|
import jakarta.validation.constraints.NotBlank
|
||||||
|
import jakarta.validation.constraints.Size
|
||||||
|
import org.hibernate.validator.constraints.URL
|
||||||
|
import roomescape.theme.infrastructure.persistence.ThemeEntity
|
||||||
|
|
||||||
|
@Schema(name = "테마 저장 요청", description = "테마 정보를 저장할 때 사용합니다.")
|
||||||
|
@JvmRecord
|
||||||
|
data class ThemeRequest(
|
||||||
|
@field:Schema(description = "필수 값이며, 최대 20글자까지 입력 가능합니다.")
|
||||||
|
@NotBlank
|
||||||
|
@Size(max = 20, message = "테마의 이름은 1~20글자 사이여야 합니다.")
|
||||||
|
val name: String,
|
||||||
|
|
||||||
|
@field:Schema(description = "필수 값이며, 최대 100글자까지 입력 가능합니다.")
|
||||||
|
@NotBlank
|
||||||
|
@Size(max = 100, message = "테마의 설명은 1~100글자 사이여야 합니다.")
|
||||||
|
val description: String,
|
||||||
|
|
||||||
|
@field:Schema(description = "필수 값이며, 썸네일 이미지 URL 을 입력해주세요.")
|
||||||
|
@NotBlank
|
||||||
|
@URL
|
||||||
|
val thumbnail: String
|
||||||
|
)
|
||||||
|
|
||||||
|
@Schema(name = "테마 정보", description = "테마 추가 및 조회 응답에 사용됩니다.")
|
||||||
|
@JvmRecord
|
||||||
|
data class ThemeResponse(
|
||||||
|
@field:Schema(description = "테마 번호. 테마를 식별할 때 사용합니다.")
|
||||||
|
val id: Long,
|
||||||
|
|
||||||
|
@field:Schema(description = "테마 이름. 중복을 허용하지 않습니다.")
|
||||||
|
val name: String,
|
||||||
|
|
||||||
|
@field:Schema(description = "테마 설명")
|
||||||
|
val description: String,
|
||||||
|
|
||||||
|
@field:Schema(description = "테마 썸네일 이미지 URL")
|
||||||
|
val thumbnail: String
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun from(themeEntity: ThemeEntity): ThemeResponse {
|
||||||
|
return ThemeResponse(themeEntity.id!!, themeEntity.name, themeEntity.description, themeEntity.thumbnail)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ThemeEntity.toResponse(): ThemeResponse = ThemeResponse(
|
||||||
|
id = this.id!!,
|
||||||
|
name = this.name,
|
||||||
|
description = this.description,
|
||||||
|
thumbnail = this.thumbnail
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@Schema(name = "테마 목록 조회 응답", description = "모든 테마 목록 조회 응답시 사용됩니다.")
|
||||||
|
@JvmRecord
|
||||||
|
data class ThemesResponse(
|
||||||
|
@field:Schema(description = "모든 테마 목록")
|
||||||
|
val themes: List<ThemeResponse>
|
||||||
|
)
|
||||||
|
|
||||||
|
fun List<ThemeEntity>.toResponse(): ThemesResponse = ThemesResponse(
|
||||||
|
themes = this.map { it.toResponse()}
|
||||||
|
)
|
||||||
@ -27,8 +27,8 @@ import roomescape.reservation.domain.ReservationStatus;
|
|||||||
import roomescape.reservation.domain.ReservationTime;
|
import roomescape.reservation.domain.ReservationTime;
|
||||||
import roomescape.reservation.domain.repository.ReservationRepository;
|
import roomescape.reservation.domain.repository.ReservationRepository;
|
||||||
import roomescape.reservation.domain.repository.ReservationTimeRepository;
|
import roomescape.reservation.domain.repository.ReservationTimeRepository;
|
||||||
import roomescape.theme.domain.Theme;
|
import roomescape.theme.infrastructure.persistence.ThemeEntity;
|
||||||
import roomescape.theme.domain.repository.ThemeRepository;
|
import roomescape.theme.infrastructure.persistence.ThemeRepository;
|
||||||
|
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
@Sql(scripts = "/truncate.sql", executionPhase = ExecutionPhase.BEFORE_TEST_METHOD)
|
@Sql(scripts = "/truncate.sql", executionPhase = ExecutionPhase.BEFORE_TEST_METHOD)
|
||||||
@ -57,7 +57,7 @@ class PaymentServiceTest {
|
|||||||
LocalDate date = localDateTime.toLocalDate();
|
LocalDate date = localDateTime.toLocalDate();
|
||||||
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
||||||
Member member = memberRepository.save(new Member(null, "member", "email@email.com", "password", Role.MEMBER));
|
Member member = memberRepository.save(new Member(null, "member", "email@email.com", "password", Role.MEMBER));
|
||||||
Theme theme = themeRepository.save(new Theme("name", "desc", "thumbnail"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "name", "desc", "thumbnail"));
|
||||||
Reservation reservation = reservationRepository.save(new Reservation(date, time, theme, member,
|
Reservation reservation = reservationRepository.save(new Reservation(date, time, theme, member,
|
||||||
ReservationStatus.CONFIRMED));
|
ReservationStatus.CONFIRMED));
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ class PaymentServiceTest {
|
|||||||
LocalDate date = localDateTime.toLocalDate();
|
LocalDate date = localDateTime.toLocalDate();
|
||||||
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
||||||
Member member = memberRepository.save(new Member(null, "member", "email@email.com", "password", Role.MEMBER));
|
Member member = memberRepository.save(new Member(null, "member", "email@email.com", "password", Role.MEMBER));
|
||||||
Theme theme = themeRepository.save(new Theme("name", "desc", "thumbnail"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "name", "desc", "thumbnail"));
|
||||||
Reservation reservation = reservationRepository.save(new Reservation(date, time, theme, member,
|
Reservation reservation = reservationRepository.save(new Reservation(date, time, theme, member,
|
||||||
ReservationStatus.CONFIRMED));
|
ReservationStatus.CONFIRMED));
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ class PaymentServiceTest {
|
|||||||
LocalDate date = localDateTime.toLocalDate();
|
LocalDate date = localDateTime.toLocalDate();
|
||||||
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
||||||
Member member = memberRepository.save(new Member(null, "member", "email@email.com", "password", Role.MEMBER));
|
Member member = memberRepository.save(new Member(null, "member", "email@email.com", "password", Role.MEMBER));
|
||||||
Theme theme = themeRepository.save(new Theme("name", "desc", "thumbnail"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "name", "desc", "thumbnail"));
|
||||||
Reservation reservation = reservationRepository.save(new Reservation(date, time, theme, member,
|
Reservation reservation = reservationRepository.save(new Reservation(date, time, theme, member,
|
||||||
ReservationStatus.CONFIRMED));
|
ReservationStatus.CONFIRMED));
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,6 @@ package roomescape.reservation.controller;
|
|||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
import static org.assertj.core.api.Assertions.*;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.mockito.ArgumentMatchers.*;
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
@ -12,7 +11,6 @@ import java.time.LocalTime;
|
|||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
@ -51,8 +49,8 @@ import roomescape.reservation.domain.repository.ReservationTimeRepository;
|
|||||||
import roomescape.reservation.dto.request.AdminReservationRequest;
|
import roomescape.reservation.dto.request.AdminReservationRequest;
|
||||||
import roomescape.reservation.dto.request.ReservationRequest;
|
import roomescape.reservation.dto.request.ReservationRequest;
|
||||||
import roomescape.reservation.dto.request.WaitingRequest;
|
import roomescape.reservation.dto.request.WaitingRequest;
|
||||||
import roomescape.theme.domain.Theme;
|
import roomescape.theme.infrastructure.persistence.ThemeEntity;
|
||||||
import roomescape.theme.domain.repository.ThemeRepository;
|
import roomescape.theme.infrastructure.persistence.ThemeRepository;
|
||||||
|
|
||||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||||
@Sql(scripts = "/truncate.sql", executionPhase = ExecutionPhase.BEFORE_TEST_METHOD)
|
@Sql(scripts = "/truncate.sql", executionPhase = ExecutionPhase.BEFORE_TEST_METHOD)
|
||||||
@ -91,7 +89,7 @@ public class ReservationControllerTest {
|
|||||||
LocalDate date = LocalDate.now().plusDays(1L);
|
LocalDate date = LocalDate.now().plusDays(1L);
|
||||||
|
|
||||||
reservationTimeRepository.save(new ReservationTime(time));
|
reservationTimeRepository.save(new ReservationTime(time));
|
||||||
themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
|
|
||||||
Map<String, String> reservationParams = Map.of(
|
Map<String, String> reservationParams = Map.of(
|
||||||
"date", date.toString(),
|
"date", date.toString(),
|
||||||
@ -126,7 +124,7 @@ public class ReservationControllerTest {
|
|||||||
String accessTokenCookie = getAccessTokenCookieByLogin("email@email.com", "password");
|
String accessTokenCookie = getAccessTokenCookieByLogin("email@email.com", "password");
|
||||||
|
|
||||||
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 30)));
|
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 30)));
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
Member member1 = memberRepository.save(new Member(null, "name1", "email1r@email.com", "password", Role.MEMBER));
|
Member member1 = memberRepository.save(new Member(null, "name1", "email1r@email.com", "password", Role.MEMBER));
|
||||||
|
|
||||||
// when
|
// when
|
||||||
@ -154,7 +152,7 @@ public class ReservationControllerTest {
|
|||||||
String accessTokenCookie = getAccessTokenCookieByLogin("email@email.com", "password");
|
String accessTokenCookie = getAccessTokenCookieByLogin("email@email.com", "password");
|
||||||
|
|
||||||
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 30)));
|
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 30)));
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
Member waitingMember = memberRepository.save(
|
Member waitingMember = memberRepository.save(
|
||||||
new Member(null, "name1", "email1r@email.com", "password", Role.MEMBER));
|
new Member(null, "name1", "email1r@email.com", "password", Role.MEMBER));
|
||||||
|
|
||||||
@ -181,7 +179,7 @@ public class ReservationControllerTest {
|
|||||||
String accessTokenCookie = getAdminAccessTokenCookieByLogin("admin@admin.com", "12341234");
|
String accessTokenCookie = getAdminAccessTokenCookieByLogin("admin@admin.com", "12341234");
|
||||||
|
|
||||||
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 30)));
|
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 30)));
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||||
|
|
||||||
// when
|
// when
|
||||||
@ -210,7 +208,7 @@ public class ReservationControllerTest {
|
|||||||
String accessTokenCookie = getAccessTokenCookieByLogin(member.getEmail(), member.getPassword());
|
String accessTokenCookie = getAccessTokenCookieByLogin(member.getEmail(), member.getPassword());
|
||||||
|
|
||||||
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 30)));
|
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 30)));
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
Reservation reservation = reservationRepository.save(
|
Reservation reservation = reservationRepository.save(
|
||||||
new Reservation(LocalDate.now(), reservationTime, theme, member, ReservationStatus.CONFIRMED));
|
new Reservation(LocalDate.now(), reservationTime, theme, member, ReservationStatus.CONFIRMED));
|
||||||
|
|
||||||
@ -230,7 +228,7 @@ public class ReservationControllerTest {
|
|||||||
String adminTokenCookie = getAdminAccessTokenCookieByLogin("admin@email.com", "password");
|
String adminTokenCookie = getAdminAccessTokenCookieByLogin("admin@email.com", "password");
|
||||||
|
|
||||||
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 30)));
|
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 30)));
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
Member confirmedMember = memberRepository.save(
|
Member confirmedMember = memberRepository.save(
|
||||||
new Member(null, "name1", "email@email.com", "password", Role.MEMBER));
|
new Member(null, "name1", "email@email.com", "password", Role.MEMBER));
|
||||||
Member waitingMember = memberRepository.save(
|
Member waitingMember = memberRepository.save(
|
||||||
@ -258,7 +256,7 @@ public class ReservationControllerTest {
|
|||||||
String accessTokenCookie = getAccessTokenCookieByLogin(member.getEmail(), member.getPassword());
|
String accessTokenCookie = getAccessTokenCookieByLogin(member.getEmail(), member.getPassword());
|
||||||
|
|
||||||
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 30)));
|
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 30)));
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
Member anotherMember = memberRepository.save(
|
Member anotherMember = memberRepository.save(
|
||||||
new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||||
|
|
||||||
@ -339,7 +337,7 @@ public class ReservationControllerTest {
|
|||||||
void getAllReservations(String requestURI, String responseFieldName, int expectedSize) {
|
void getAllReservations(String requestURI, String responseFieldName, int expectedSize) {
|
||||||
// given
|
// given
|
||||||
LocalDate date = LocalDate.now().plusDays(1);
|
LocalDate date = LocalDate.now().plusDays(1);
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
ReservationTime time = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 30)));
|
ReservationTime time = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 30)));
|
||||||
ReservationTime time1 = reservationTimeRepository.save(new ReservationTime(LocalTime.of(18, 30)));
|
ReservationTime time1 = reservationTimeRepository.save(new ReservationTime(LocalTime.of(18, 30)));
|
||||||
ReservationTime time2 = reservationTimeRepository.save(new ReservationTime(LocalTime.of(19, 30)));
|
ReservationTime time2 = reservationTimeRepository.save(new ReservationTime(LocalTime.of(19, 30)));
|
||||||
@ -368,7 +366,7 @@ public class ReservationControllerTest {
|
|||||||
void removeNotPaidReservation() {
|
void removeNotPaidReservation() {
|
||||||
// given
|
// given
|
||||||
LocalDate date = LocalDate.now().plusDays(1);
|
LocalDate date = LocalDate.now().plusDays(1);
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
ReservationTime time = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 30)));
|
ReservationTime time = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 30)));
|
||||||
String accessToken = getAdminAccessTokenCookieByLogin("admin@email.com", "password");
|
String accessToken = getAdminAccessTokenCookieByLogin("admin@email.com", "password");
|
||||||
|
|
||||||
@ -392,7 +390,7 @@ public class ReservationControllerTest {
|
|||||||
// given
|
// given
|
||||||
String accessToken = getAdminAccessTokenCookieByLogin("admin@email.com", "password");
|
String accessToken = getAdminAccessTokenCookieByLogin("admin@email.com", "password");
|
||||||
LocalDate date = LocalDate.now().plusDays(1);
|
LocalDate date = LocalDate.now().plusDays(1);
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
ReservationTime time = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 30)));
|
ReservationTime time = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 30)));
|
||||||
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||||
|
|
||||||
@ -423,7 +421,7 @@ public class ReservationControllerTest {
|
|||||||
LocalDateTime localDateTime = LocalDateTime.now().minusHours(1L).withNano(0);
|
LocalDateTime localDateTime = LocalDateTime.now().minusHours(1L).withNano(0);
|
||||||
LocalDate date = localDateTime.toLocalDate();
|
LocalDate date = localDateTime.toLocalDate();
|
||||||
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||||
String accessToken = getAccessTokenCookieByLogin(member.getEmail(), member.getPassword());
|
String accessToken = getAccessTokenCookieByLogin(member.getEmail(), member.getPassword());
|
||||||
|
|
||||||
@ -516,7 +514,7 @@ public class ReservationControllerTest {
|
|||||||
LocalDateTime localDateTime = LocalDateTime.now().plusDays(1L).withNano(0);
|
LocalDateTime localDateTime = LocalDateTime.now().plusDays(1L).withNano(0);
|
||||||
LocalDate date = localDateTime.toLocalDate();
|
LocalDate date = localDateTime.toLocalDate();
|
||||||
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||||
Member member1 = memberRepository.save(new Member(null, "name1", "email1@email.com", "password", Role.MEMBER));
|
Member member1 = memberRepository.save(new Member(null, "name1", "email1@email.com", "password", Role.MEMBER));
|
||||||
|
|
||||||
@ -542,7 +540,7 @@ public class ReservationControllerTest {
|
|||||||
LocalDateTime localDateTime = LocalDateTime.now().plusHours(1L);
|
LocalDateTime localDateTime = LocalDateTime.now().plusHours(1L);
|
||||||
LocalDate date = localDateTime.toLocalDate();
|
LocalDate date = localDateTime.toLocalDate();
|
||||||
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||||
|
|
||||||
String accessToken = getAdminAccessTokenCookieByLogin("admin@email.com", "password");
|
String accessToken = getAdminAccessTokenCookieByLogin("admin@email.com", "password");
|
||||||
@ -587,7 +585,7 @@ public class ReservationControllerTest {
|
|||||||
LocalDateTime localDateTime = LocalDateTime.now().plusDays(1L).withNano(0);
|
LocalDateTime localDateTime = LocalDateTime.now().plusDays(1L).withNano(0);
|
||||||
LocalDate date = localDateTime.toLocalDate();
|
LocalDate date = localDateTime.toLocalDate();
|
||||||
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||||
|
|
||||||
String adminAccessToken = getAdminAccessTokenCookieByLogin("admin@email.com", "password");
|
String adminAccessToken = getAdminAccessTokenCookieByLogin("admin@email.com", "password");
|
||||||
|
|||||||
@ -29,8 +29,8 @@ import roomescape.reservation.domain.ReservationStatus;
|
|||||||
import roomescape.reservation.domain.ReservationTime;
|
import roomescape.reservation.domain.ReservationTime;
|
||||||
import roomescape.reservation.domain.repository.ReservationRepository;
|
import roomescape.reservation.domain.repository.ReservationRepository;
|
||||||
import roomescape.reservation.domain.repository.ReservationTimeRepository;
|
import roomescape.reservation.domain.repository.ReservationTimeRepository;
|
||||||
import roomescape.theme.domain.Theme;
|
import roomescape.theme.infrastructure.persistence.ThemeEntity;
|
||||||
import roomescape.theme.domain.repository.ThemeRepository;
|
import roomescape.theme.infrastructure.persistence.ThemeRepository;
|
||||||
|
|
||||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||||
@Sql(scripts = "/truncate.sql", executionPhase = ExecutionPhase.BEFORE_TEST_METHOD)
|
@Sql(scripts = "/truncate.sql", executionPhase = ExecutionPhase.BEFORE_TEST_METHOD)
|
||||||
@ -224,7 +224,7 @@ public class ReservationTimeControllerTest {
|
|||||||
ReservationTime reservationTime1 = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 0)));
|
ReservationTime reservationTime1 = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 0)));
|
||||||
ReservationTime reservationTime2 = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 30)));
|
ReservationTime reservationTime2 = reservationTimeRepository.save(new ReservationTime(LocalTime.of(17, 30)));
|
||||||
ReservationTime reservationTime3 = reservationTimeRepository.save(new ReservationTime(LocalTime.of(18, 30)));
|
ReservationTime reservationTime3 = reservationTimeRepository.save(new ReservationTime(LocalTime.of(18, 30)));
|
||||||
Theme theme = themeRepository.save(new Theme("테마명1", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명1", "설명", "썸네일URL"));
|
||||||
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||||
|
|
||||||
reservationRepository.save(
|
reservationRepository.save(
|
||||||
|
|||||||
@ -13,14 +13,14 @@ import org.junit.jupiter.params.provider.MethodSource;
|
|||||||
import roomescape.member.infrastructure.persistence.Member;
|
import roomescape.member.infrastructure.persistence.Member;
|
||||||
import roomescape.member.infrastructure.persistence.Role;
|
import roomescape.member.infrastructure.persistence.Role;
|
||||||
import roomescape.common.exception.RoomescapeException;
|
import roomescape.common.exception.RoomescapeException;
|
||||||
import roomescape.theme.domain.Theme;
|
import roomescape.theme.infrastructure.persistence.ThemeEntity;
|
||||||
|
|
||||||
public class ReservationTest {
|
public class ReservationTest {
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("validateConstructorParameterBlankSource")
|
@MethodSource("validateConstructorParameterBlankSource")
|
||||||
@DisplayName("객체 생성 시, null 또는 공백이 존재하면 예외를 발생한다.")
|
@DisplayName("객체 생성 시, null 또는 공백이 존재하면 예외를 발생한다.")
|
||||||
void validateConstructorParameterBlank(LocalDate date, ReservationTime reservationTime, Theme theme,
|
void validateConstructorParameterBlank(LocalDate date, ReservationTime reservationTime, ThemeEntity theme,
|
||||||
Member member) {
|
Member member) {
|
||||||
|
|
||||||
// when & then
|
// when & then
|
||||||
@ -33,12 +33,12 @@ public class ReservationTest {
|
|||||||
return Stream.of(
|
return Stream.of(
|
||||||
Arguments.of(null,
|
Arguments.of(null,
|
||||||
new ReservationTime(LocalTime.now().plusHours(1)),
|
new ReservationTime(LocalTime.now().plusHours(1)),
|
||||||
new Theme("테마명", "설명", "썸네일URI"),
|
new ThemeEntity(null, "테마명", "설명", "썸네일URI"),
|
||||||
new Member(null, "name", "email@email.com", "password", Role.MEMBER)),
|
new Member(null, "name", "email@email.com", "password", Role.MEMBER)),
|
||||||
Arguments.of(
|
Arguments.of(
|
||||||
LocalDate.now(),
|
LocalDate.now(),
|
||||||
null,
|
null,
|
||||||
new Theme("테마명", "설명", "썸네일URI"),
|
new ThemeEntity(null, "테마명", "설명", "썸네일URI"),
|
||||||
new Member(null, "name", "email@email.com", "password", Role.MEMBER)),
|
new Member(null, "name", "email@email.com", "password", Role.MEMBER)),
|
||||||
Arguments.of(
|
Arguments.of(
|
||||||
LocalDate.now(),
|
LocalDate.now(),
|
||||||
@ -48,7 +48,7 @@ public class ReservationTest {
|
|||||||
Arguments.of(
|
Arguments.of(
|
||||||
LocalDate.now(),
|
LocalDate.now(),
|
||||||
new ReservationTime(LocalTime.now().plusHours(1)),
|
new ReservationTime(LocalTime.now().plusHours(1)),
|
||||||
new Theme("테마명", "설명", "썸네일URI"),
|
new ThemeEntity(null, "테마명", "설명", "썸네일URI"),
|
||||||
null)
|
null)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,8 +19,8 @@ import roomescape.member.infrastructure.persistence.Role;
|
|||||||
import roomescape.reservation.domain.Reservation;
|
import roomescape.reservation.domain.Reservation;
|
||||||
import roomescape.reservation.domain.ReservationStatus;
|
import roomescape.reservation.domain.ReservationStatus;
|
||||||
import roomescape.reservation.domain.ReservationTime;
|
import roomescape.reservation.domain.ReservationTime;
|
||||||
import roomescape.theme.domain.Theme;
|
import roomescape.theme.infrastructure.persistence.ThemeEntity;
|
||||||
import roomescape.theme.domain.repository.ThemeRepository;
|
import roomescape.theme.infrastructure.persistence.ThemeRepository;
|
||||||
|
|
||||||
@DataJpaTest
|
@DataJpaTest
|
||||||
class ReservationSearchSpecificationTest {
|
class ReservationSearchSpecificationTest {
|
||||||
@ -52,7 +52,7 @@ class ReservationSearchSpecificationTest {
|
|||||||
LocalDateTime dateTime = LocalDateTime.now();
|
LocalDateTime dateTime = LocalDateTime.now();
|
||||||
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||||
ReservationTime time = timeRepository.save(new ReservationTime(dateTime.toLocalTime()));
|
ReservationTime time = timeRepository.save(new ReservationTime(dateTime.toLocalTime()));
|
||||||
Theme theme = themeRepository.save(new Theme("name", "description", "thumbnail"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "name", "description", "thumbnail"));
|
||||||
|
|
||||||
reservation1 = reservationRepository.save(
|
reservation1 = reservationRepository.save(
|
||||||
new Reservation(dateTime.toLocalDate(), time, theme, member, ReservationStatus.CONFIRMED));
|
new Reservation(dateTime.toLocalDate(), time, theme, member, ReservationStatus.CONFIRMED));
|
||||||
|
|||||||
@ -27,9 +27,9 @@ import roomescape.reservation.dto.request.ReservationRequest;
|
|||||||
import roomescape.reservation.dto.request.WaitingRequest;
|
import roomescape.reservation.dto.request.WaitingRequest;
|
||||||
import roomescape.reservation.dto.response.ReservationResponse;
|
import roomescape.reservation.dto.response.ReservationResponse;
|
||||||
import roomescape.common.exception.RoomescapeException;
|
import roomescape.common.exception.RoomescapeException;
|
||||||
import roomescape.theme.domain.Theme;
|
import roomescape.theme.infrastructure.persistence.ThemeEntity;
|
||||||
import roomescape.theme.domain.repository.ThemeRepository;
|
import roomescape.theme.infrastructure.persistence.ThemeRepository;
|
||||||
import roomescape.theme.service.ThemeService;
|
import roomescape.theme.business.ThemeService;
|
||||||
|
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
@Sql(scripts = "/truncate.sql", executionPhase = ExecutionPhase.BEFORE_TEST_METHOD)
|
@Sql(scripts = "/truncate.sql", executionPhase = ExecutionPhase.BEFORE_TEST_METHOD)
|
||||||
@ -52,7 +52,7 @@ class ReservationServiceTest {
|
|||||||
void reservationAlreadyExistFail() {
|
void reservationAlreadyExistFail() {
|
||||||
// given
|
// given
|
||||||
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(12, 30)));
|
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(12, 30)));
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
Member member1 = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
Member member1 = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||||
Member member2 = memberRepository.save(new Member(null, "name2", "email2@email.com", "password", Role.MEMBER));
|
Member member2 = memberRepository.save(new Member(null, "name2", "email2@email.com", "password", Role.MEMBER));
|
||||||
LocalDate date = LocalDate.now().plusDays(1L);
|
LocalDate date = LocalDate.now().plusDays(1L);
|
||||||
@ -74,7 +74,7 @@ class ReservationServiceTest {
|
|||||||
void requestWaitWhenAlreadyReserveFail() {
|
void requestWaitWhenAlreadyReserveFail() {
|
||||||
// given
|
// given
|
||||||
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(12, 30)));
|
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(12, 30)));
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||||
LocalDate date = LocalDate.now().plusDays(1L);
|
LocalDate date = LocalDate.now().plusDays(1L);
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ class ReservationServiceTest {
|
|||||||
void requestWaitTwiceFail() {
|
void requestWaitTwiceFail() {
|
||||||
// given
|
// given
|
||||||
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(12, 30)));
|
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(12, 30)));
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||||
Member member1 = memberRepository.save(new Member(null, "name1", "email1@email.com", "password", Role.MEMBER));
|
Member member1 = memberRepository.save(new Member(null, "name1", "email1@email.com", "password", Role.MEMBER));
|
||||||
LocalDate date = LocalDate.now().plusDays(1L);
|
LocalDate date = LocalDate.now().plusDays(1L);
|
||||||
@ -118,7 +118,7 @@ class ReservationServiceTest {
|
|||||||
void beforeDateReservationFail() {
|
void beforeDateReservationFail() {
|
||||||
// given
|
// given
|
||||||
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(12, 30)));
|
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(12, 30)));
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||||
LocalDate beforeDate = LocalDate.now().minusDays(1L);
|
LocalDate beforeDate = LocalDate.now().minusDays(1L);
|
||||||
|
|
||||||
@ -135,7 +135,7 @@ class ReservationServiceTest {
|
|||||||
// given
|
// given
|
||||||
LocalDateTime beforeTime = LocalDateTime.now().minusHours(1L).withNano(0);
|
LocalDateTime beforeTime = LocalDateTime.now().minusHours(1L).withNano(0);
|
||||||
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(beforeTime.toLocalTime()));
|
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(beforeTime.toLocalTime()));
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||||
|
|
||||||
// when & then
|
// when & then
|
||||||
@ -151,7 +151,7 @@ class ReservationServiceTest {
|
|||||||
// given
|
// given
|
||||||
LocalDateTime beforeTime = LocalDateTime.now().minusDays(1L).withNano(0);
|
LocalDateTime beforeTime = LocalDateTime.now().minusDays(1L).withNano(0);
|
||||||
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(beforeTime.toLocalTime()));
|
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(beforeTime.toLocalTime()));
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
Long NotExistMemberId = 1L;
|
Long NotExistMemberId = 1L;
|
||||||
|
|
||||||
// when & then
|
// when & then
|
||||||
@ -179,7 +179,7 @@ class ReservationServiceTest {
|
|||||||
void confirmWaitingWhenReservationExist() {
|
void confirmWaitingWhenReservationExist() {
|
||||||
// given
|
// given
|
||||||
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(12, 30)));
|
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(12, 30)));
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
Member admin = memberRepository.save(new Member(null, "admin", "admin@email.com", "password", Role.ADMIN));
|
Member admin = memberRepository.save(new Member(null, "admin", "admin@email.com", "password", Role.ADMIN));
|
||||||
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||||
Member member1 = memberRepository.save(new Member(null, "name1", "email1@email.com", "password", Role.MEMBER));
|
Member member1 = memberRepository.save(new Member(null, "name1", "email1@email.com", "password", Role.MEMBER));
|
||||||
@ -202,7 +202,7 @@ class ReservationServiceTest {
|
|||||||
void approveWaiting() {
|
void approveWaiting() {
|
||||||
// given
|
// given
|
||||||
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(12, 30)));
|
ReservationTime reservationTime = reservationTimeRepository.save(new ReservationTime(LocalTime.of(12, 30)));
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
Member admin = memberRepository.save(new Member(null, "admin", "admin@email.com", "password", Role.ADMIN));
|
Member admin = memberRepository.save(new Member(null, "admin", "admin@email.com", "password", Role.ADMIN));
|
||||||
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||||
|
|
||||||
|
|||||||
@ -23,8 +23,8 @@ import roomescape.reservation.domain.repository.ReservationRepository;
|
|||||||
import roomescape.reservation.domain.repository.ReservationTimeRepository;
|
import roomescape.reservation.domain.repository.ReservationTimeRepository;
|
||||||
import roomescape.reservation.dto.request.ReservationTimeRequest;
|
import roomescape.reservation.dto.request.ReservationTimeRequest;
|
||||||
import roomescape.common.exception.RoomescapeException;
|
import roomescape.common.exception.RoomescapeException;
|
||||||
import roomescape.theme.domain.Theme;
|
import roomescape.theme.infrastructure.persistence.ThemeEntity;
|
||||||
import roomescape.theme.domain.repository.ThemeRepository;
|
import roomescape.theme.infrastructure.persistence.ThemeRepository;
|
||||||
|
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
@Import(ReservationTimeService.class)
|
@Import(ReservationTimeService.class)
|
||||||
@ -74,7 +74,7 @@ class ReservationTimeServiceTest {
|
|||||||
LocalDateTime localDateTime = LocalDateTime.now().plusDays(1L).withNano(0);
|
LocalDateTime localDateTime = LocalDateTime.now().plusDays(1L).withNano(0);
|
||||||
ReservationTime reservationTime = reservationTimeRepository.save(
|
ReservationTime reservationTime = reservationTimeRepository.save(
|
||||||
new ReservationTime(localDateTime.toLocalTime()));
|
new ReservationTime(localDateTime.toLocalTime()));
|
||||||
Theme theme = themeRepository.save(new Theme("테마명", "설명", "썸네일URL"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||||
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
Member member = memberRepository.save(new Member(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||||
|
|
||||||
// when
|
// when
|
||||||
|
|||||||
@ -28,8 +28,8 @@ import roomescape.reservation.domain.repository.ReservationRepository;
|
|||||||
import roomescape.reservation.domain.repository.ReservationTimeRepository;
|
import roomescape.reservation.domain.repository.ReservationTimeRepository;
|
||||||
import roomescape.reservation.dto.request.ReservationRequest;
|
import roomescape.reservation.dto.request.ReservationRequest;
|
||||||
import roomescape.reservation.dto.response.ReservationResponse;
|
import roomescape.reservation.dto.response.ReservationResponse;
|
||||||
import roomescape.theme.domain.Theme;
|
import roomescape.theme.infrastructure.persistence.ThemeEntity;
|
||||||
import roomescape.theme.domain.repository.ThemeRepository;
|
import roomescape.theme.infrastructure.persistence.ThemeRepository;
|
||||||
|
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
@Sql(scripts = "/truncate.sql", executionPhase = ExecutionPhase.BEFORE_TEST_METHOD)
|
@Sql(scripts = "/truncate.sql", executionPhase = ExecutionPhase.BEFORE_TEST_METHOD)
|
||||||
@ -60,7 +60,7 @@ class ReservationWithPaymentServiceTest {
|
|||||||
LocalDate date = localDateTime.toLocalDate();
|
LocalDate date = localDateTime.toLocalDate();
|
||||||
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
||||||
Member member = memberRepository.save(new Member(null, "member", "email@email.com", "password", Role.MEMBER));
|
Member member = memberRepository.save(new Member(null, "member", "email@email.com", "password", Role.MEMBER));
|
||||||
Theme theme = themeRepository.save(new Theme("name", "desc", "thumbnail"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "name", "desc", "thumbnail"));
|
||||||
ReservationRequest reservationRequest = new ReservationRequest(date, time.getId(), theme.getId(), "payment-key",
|
ReservationRequest reservationRequest = new ReservationRequest(date, time.getId(), theme.getId(), "payment-key",
|
||||||
"order-id", 10000L, "NORMAL");
|
"order-id", 10000L, "NORMAL");
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ class ReservationWithPaymentServiceTest {
|
|||||||
LocalDate date = localDateTime.toLocalDate();
|
LocalDate date = localDateTime.toLocalDate();
|
||||||
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
||||||
Member member = memberRepository.save(new Member(null, "member", "admin@email.com", "password", Role.ADMIN));
|
Member member = memberRepository.save(new Member(null, "member", "admin@email.com", "password", Role.ADMIN));
|
||||||
Theme theme = themeRepository.save(new Theme("name", "desc", "thumbnail"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "name", "desc", "thumbnail"));
|
||||||
ReservationRequest reservationRequest = new ReservationRequest(date, time.getId(), theme.getId(), "payment-key",
|
ReservationRequest reservationRequest = new ReservationRequest(date, time.getId(), theme.getId(), "payment-key",
|
||||||
"order-id", 10000L, "NORMAL");
|
"order-id", 10000L, "NORMAL");
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ class ReservationWithPaymentServiceTest {
|
|||||||
LocalDate date = localDateTime.toLocalDate();
|
LocalDate date = localDateTime.toLocalDate();
|
||||||
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
||||||
Member member = memberRepository.save(new Member(null, "member", "admin@email.com", "password", Role.ADMIN));
|
Member member = memberRepository.save(new Member(null, "member", "admin@email.com", "password", Role.ADMIN));
|
||||||
Theme theme = themeRepository.save(new Theme("name", "desc", "thumbnail"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "name", "desc", "thumbnail"));
|
||||||
|
|
||||||
Reservation saved = reservationRepository.save(
|
Reservation saved = reservationRepository.save(
|
||||||
new Reservation(date, time, theme, member, ReservationStatus.CONFIRMED_PAYMENT_REQUIRED));
|
new Reservation(date, time, theme, member, ReservationStatus.CONFIRMED_PAYMENT_REQUIRED));
|
||||||
@ -146,7 +146,7 @@ class ReservationWithPaymentServiceTest {
|
|||||||
LocalDate date = localDateTime.toLocalDate();
|
LocalDate date = localDateTime.toLocalDate();
|
||||||
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
ReservationTime time = reservationTimeRepository.save(new ReservationTime(localDateTime.toLocalTime()));
|
||||||
Member member = memberRepository.save(new Member(null, "member", "admin@email.com", "password", Role.ADMIN));
|
Member member = memberRepository.save(new Member(null, "member", "admin@email.com", "password", Role.ADMIN));
|
||||||
Theme theme = themeRepository.save(new Theme("name", "desc", "thumbnail"));
|
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "name", "desc", "thumbnail"));
|
||||||
ReservationRequest reservationRequest = new ReservationRequest(date, time.getId(), theme.getId(), "payment-key",
|
ReservationRequest reservationRequest = new ReservationRequest(date, time.getId(), theme.getId(), "payment-key",
|
||||||
"order-id", 10000L, "NORMAL");
|
"order-id", 10000L, "NORMAL");
|
||||||
|
|
||||||
|
|||||||
103
src/test/java/roomescape/theme/business/ThemeServiceTest.kt
Normal file
103
src/test/java/roomescape/theme/business/ThemeServiceTest.kt
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
package roomescape.theme.business
|
||||||
|
|
||||||
|
import io.kotest.assertions.assertSoftly
|
||||||
|
import io.kotest.assertions.throwables.shouldThrow
|
||||||
|
import io.kotest.core.spec.style.FunSpec
|
||||||
|
import io.kotest.matchers.shouldBe
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import org.springframework.data.repository.findByIdOrNull
|
||||||
|
import org.springframework.http.HttpStatus
|
||||||
|
import roomescape.common.exception.ErrorType
|
||||||
|
import roomescape.common.exception.RoomescapeException
|
||||||
|
import roomescape.theme.infrastructure.persistence.ThemeEntity
|
||||||
|
import roomescape.theme.infrastructure.persistence.ThemeRepository
|
||||||
|
import roomescape.theme.web.ThemeRequest
|
||||||
|
import roomescape.util.ThemeFixture
|
||||||
|
|
||||||
|
class ThemeServiceTest : FunSpec({
|
||||||
|
|
||||||
|
val themeRepository: ThemeRepository = mockk()
|
||||||
|
val themeService = ThemeService(themeRepository)
|
||||||
|
|
||||||
|
context("findThemeById") {
|
||||||
|
val themeId = 1L
|
||||||
|
test("조회 성공") {
|
||||||
|
val theme: ThemeEntity = ThemeFixture.create(id = themeId)
|
||||||
|
every {
|
||||||
|
themeRepository.findByIdOrNull(themeId)
|
||||||
|
} returns theme
|
||||||
|
|
||||||
|
theme.id shouldBe themeId
|
||||||
|
}
|
||||||
|
|
||||||
|
test("ID로 테마를 찾을 수 없으면 400 예외를 던진다.") {
|
||||||
|
every {
|
||||||
|
themeRepository.findByIdOrNull(themeId)
|
||||||
|
} returns null
|
||||||
|
|
||||||
|
val exception = shouldThrow<RoomescapeException> {
|
||||||
|
themeService.findThemeById(themeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
exception.errorType shouldBe ErrorType.THEME_NOT_FOUND
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context("findAllThemes") {
|
||||||
|
test("모든 테마를 조회한다.") {
|
||||||
|
val themes = listOf(ThemeFixture.create(id = 1, name = "t1"), ThemeFixture.create(id = 2, name = "t2"))
|
||||||
|
every {
|
||||||
|
themeRepository.findAll()
|
||||||
|
} returns themes
|
||||||
|
|
||||||
|
assertSoftly(themeService.findAllThemes()) {
|
||||||
|
this.themes.size shouldBe themes.size
|
||||||
|
this.themes[0].name shouldBe "t1"
|
||||||
|
this.themes[1].name shouldBe "t2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context("save") {
|
||||||
|
test("테마 이름이 중복되면 409 예외를 던진다.") {
|
||||||
|
val name = "Duplicate Theme"
|
||||||
|
|
||||||
|
every {
|
||||||
|
themeRepository.existsByName(name)
|
||||||
|
} returns true
|
||||||
|
|
||||||
|
val exception = shouldThrow<RoomescapeException> {
|
||||||
|
themeService.save(ThemeRequest(
|
||||||
|
name = name,
|
||||||
|
description = "Description",
|
||||||
|
thumbnail = "http://example.com/thumbnail.jpg"
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
assertSoftly(exception) {
|
||||||
|
this.errorType shouldBe ErrorType.THEME_DUPLICATED
|
||||||
|
this.httpStatus shouldBe HttpStatus.CONFLICT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context("deleteById") {
|
||||||
|
test("이미 예약 중인 테마라면 409 예외를 던진다.") {
|
||||||
|
val themeId = 1L
|
||||||
|
|
||||||
|
every {
|
||||||
|
themeRepository.isReservedTheme(themeId)
|
||||||
|
} returns true
|
||||||
|
|
||||||
|
val exception = shouldThrow<RoomescapeException> {
|
||||||
|
themeService.deleteById(themeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
assertSoftly(exception) {
|
||||||
|
this.errorType shouldBe ErrorType.THEME_IS_USED_CONFLICT
|
||||||
|
this.httpStatus shouldBe HttpStatus.CONFLICT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
@ -1,184 +0,0 @@
|
|||||||
package roomescape.theme.controller;
|
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.*;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.DisplayName;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import org.springframework.boot.test.web.server.LocalServerPort;
|
|
||||||
import org.springframework.test.context.jdbc.Sql;
|
|
||||||
import org.springframework.test.context.jdbc.Sql.ExecutionPhase;
|
|
||||||
|
|
||||||
import io.restassured.RestAssured;
|
|
||||||
import io.restassured.http.ContentType;
|
|
||||||
import io.restassured.http.Header;
|
|
||||||
import roomescape.member.infrastructure.persistence.Member;
|
|
||||||
import roomescape.member.infrastructure.persistence.MemberRepository;
|
|
||||||
import roomescape.member.infrastructure.persistence.Role;
|
|
||||||
|
|
||||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
|
||||||
@Sql(scripts = "/truncate.sql", executionPhase = ExecutionPhase.BEFORE_TEST_METHOD)
|
|
||||||
class ThemeControllerTest {
|
|
||||||
|
|
||||||
@LocalServerPort
|
|
||||||
private int port;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private MemberRepository memberRepository;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@DisplayName("모든 테마 정보를 조회한다.")
|
|
||||||
void readThemes() {
|
|
||||||
String email = "admin@test.com";
|
|
||||||
String password = "12341234";
|
|
||||||
String adminAccessTokenCookie = getAdminAccessTokenCookieByLogin(email, password);
|
|
||||||
|
|
||||||
RestAssured.given().log().all()
|
|
||||||
.contentType(ContentType.JSON)
|
|
||||||
.header(new Header("Cookie", adminAccessTokenCookie))
|
|
||||||
.port(port)
|
|
||||||
.when().get("/themes")
|
|
||||||
.then().log().all()
|
|
||||||
.statusCode(200)
|
|
||||||
.body("data.themes.size()", is(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@DisplayName("테마를 추가한다.")
|
|
||||||
void createThemes() {
|
|
||||||
String email = "admin@test.com";
|
|
||||||
String password = "12341234";
|
|
||||||
String adminAccessTokenCookie = getAdminAccessTokenCookieByLogin(email, password);
|
|
||||||
|
|
||||||
Map<String, String> params = Map.of(
|
|
||||||
"name", "테마명",
|
|
||||||
"description", "설명",
|
|
||||||
"thumbnail", "http://testsfasdgasd.com"
|
|
||||||
);
|
|
||||||
|
|
||||||
RestAssured.given().log().all()
|
|
||||||
.contentType(ContentType.JSON)
|
|
||||||
.header(new Header("Cookie", adminAccessTokenCookie))
|
|
||||||
.port(port)
|
|
||||||
.body(params)
|
|
||||||
.when().post("/themes")
|
|
||||||
.then().log().all()
|
|
||||||
.statusCode(201)
|
|
||||||
.body("data.id", is(1))
|
|
||||||
.header("Location", "/themes/1");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@DisplayName("테마를 삭제한다.")
|
|
||||||
void deleteThemes() {
|
|
||||||
String email = "admin@test.com";
|
|
||||||
String password = "12341234";
|
|
||||||
String adminAccessTokenCookie = getAdminAccessTokenCookieByLogin(email, password);
|
|
||||||
|
|
||||||
Map<String, String> params = Map.of(
|
|
||||||
"name", "테마명",
|
|
||||||
"description", "설명",
|
|
||||||
"thumbnail", "http://testsfasdgasd.com"
|
|
||||||
);
|
|
||||||
|
|
||||||
RestAssured.given().log().all()
|
|
||||||
.contentType(ContentType.JSON)
|
|
||||||
.header(new Header("Cookie", adminAccessTokenCookie))
|
|
||||||
.port(port)
|
|
||||||
.body(params)
|
|
||||||
.when().post("/themes")
|
|
||||||
.then().log().all()
|
|
||||||
.statusCode(201)
|
|
||||||
.body("data.id", is(1))
|
|
||||||
.header("Location", "/themes/1");
|
|
||||||
|
|
||||||
RestAssured.given().log().all()
|
|
||||||
.contentType(ContentType.JSON)
|
|
||||||
.header(new Header("Cookie", adminAccessTokenCookie))
|
|
||||||
.port(port)
|
|
||||||
.when().delete("/themes/1")
|
|
||||||
.then().log().all()
|
|
||||||
.statusCode(204);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* reservationData DataSet ThemeID 별 reservation 개수
|
|
||||||
* 5,4,2,5,2,3,1,1,1,1,1
|
|
||||||
* 예약 수 내림차순 + ThemeId 오름차순 정렬 순서
|
|
||||||
* 1, 4, 2, 6, 3, 5, 7, 8, 9, 10
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
@DisplayName("예약 수 상위 10개 테마를 조회했을 때 내림차순으로 정렬된다. 만약 예약 수가 같다면, id 순으로 오름차순 정렬된다.")
|
|
||||||
@Sql(scripts = {"/truncate.sql", "/reservationData.sql"}, executionPhase = ExecutionPhase.BEFORE_TEST_METHOD)
|
|
||||||
void readTop10ThemesDescOrder() {
|
|
||||||
RestAssured.given().log().all()
|
|
||||||
.contentType(ContentType.JSON)
|
|
||||||
.port(port)
|
|
||||||
.when().get("/themes/most-reserved-last-week?count=10")
|
|
||||||
.then().log().all()
|
|
||||||
.statusCode(200)
|
|
||||||
.body("data.themes.size()", is(10))
|
|
||||||
.body("data.themes.id", contains(1, 4, 2, 6, 3, 5, 7, 8, 9, 10));
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest
|
|
||||||
@MethodSource("requestValidateSource")
|
|
||||||
@DisplayName("테마 생성 시, 요청 값에 공백 또는 null이 포함되어 있으면 400 에러를 발생한다.")
|
|
||||||
void validateBlankRequest(Map<String, String> invalidRequestBody) {
|
|
||||||
String email = "admin@test.com";
|
|
||||||
String password = "12341234";
|
|
||||||
String adminAccessTokenCookie = getAdminAccessTokenCookieByLogin(email, password);
|
|
||||||
|
|
||||||
RestAssured.given().log().all()
|
|
||||||
.contentType(ContentType.JSON)
|
|
||||||
.header(new Header("Cookie", adminAccessTokenCookie))
|
|
||||||
.port(port)
|
|
||||||
.body(invalidRequestBody)
|
|
||||||
.when().post("/themes")
|
|
||||||
.then().log().all()
|
|
||||||
.statusCode(400);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Stream<Map<String, String>> requestValidateSource() {
|
|
||||||
return Stream.of(
|
|
||||||
Map.of(
|
|
||||||
"name", "테마명",
|
|
||||||
"thumbnail", "http://testsfasdgasd.com"
|
|
||||||
),
|
|
||||||
Map.of(
|
|
||||||
"name", "",
|
|
||||||
"description", "설명",
|
|
||||||
"thumbnail", "http://testsfasdgasd.com"
|
|
||||||
),
|
|
||||||
Map.of(
|
|
||||||
"name", " ",
|
|
||||||
"description", "설명",
|
|
||||||
"thumbnail", "http://testsfasdgasd.com"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getAdminAccessTokenCookieByLogin(final String email, final String password) {
|
|
||||||
memberRepository.save(new Member(null, "이름", email, password, Role.ADMIN));
|
|
||||||
|
|
||||||
Map<String, String> loginParams = Map.of(
|
|
||||||
"email", email,
|
|
||||||
"password", password
|
|
||||||
);
|
|
||||||
|
|
||||||
String accessToken = RestAssured.given().log().all()
|
|
||||||
.contentType(ContentType.JSON)
|
|
||||||
.port(port)
|
|
||||||
.body(loginParams)
|
|
||||||
.when().post("/login")
|
|
||||||
.then().log().all().extract().cookie("accessToken");
|
|
||||||
|
|
||||||
return "accessToken=" + accessToken;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,147 @@
|
|||||||
|
package roomescape.theme.infrastructure.persistence
|
||||||
|
|
||||||
|
import io.kotest.core.spec.style.FunSpec
|
||||||
|
import io.kotest.matchers.collections.shouldContainInOrder
|
||||||
|
import io.kotest.matchers.shouldBe
|
||||||
|
import jakarta.persistence.EntityManager
|
||||||
|
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
|
||||||
|
import roomescape.theme.util.TestThemeCreateUtil
|
||||||
|
import java.time.LocalDate
|
||||||
|
|
||||||
|
@DataJpaTest
|
||||||
|
class ThemeRepositoryTest(
|
||||||
|
val themeRepository: ThemeRepository,
|
||||||
|
val entityManager: EntityManager
|
||||||
|
) : FunSpec() {
|
||||||
|
|
||||||
|
init {
|
||||||
|
context("findTopNThemeBetweenStartDateAndEndDate") {
|
||||||
|
beforeTest {
|
||||||
|
for (i in 1..10) {
|
||||||
|
TestThemeCreateUtil.createThemeWithReservations(
|
||||||
|
entityManager = entityManager,
|
||||||
|
name = "테마$i",
|
||||||
|
reservedCount = i,
|
||||||
|
date = LocalDate.now().minusDays(i.toLong()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test("지난 10일간 예약 수가 가장 많은 테마 5개를 조회한다.") {
|
||||||
|
themeRepository.findTopNThemeBetweenStartDateAndEndDate(
|
||||||
|
LocalDate.now().minusDays(10),
|
||||||
|
LocalDate.now().minusDays(1),
|
||||||
|
5
|
||||||
|
).also { themes ->
|
||||||
|
themes.size shouldBe 5
|
||||||
|
themes.map { it.name } shouldContainInOrder listOf(
|
||||||
|
"테마10", "테마9", "테마8", "테마7", "테마6"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test("8일 전부터 5일 전까지 예약 수가 가장 많은 테마 3개를 조회한다.") {
|
||||||
|
themeRepository.findTopNThemeBetweenStartDateAndEndDate(
|
||||||
|
LocalDate.now().minusDays(8),
|
||||||
|
LocalDate.now().minusDays(5),
|
||||||
|
3
|
||||||
|
).also { themes ->
|
||||||
|
themes.size shouldBe 3
|
||||||
|
themes.map { it.name } shouldContainInOrder listOf(
|
||||||
|
"테마8", "테마7", "테마6"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test("예약 수가 동일하면 먼저 생성된 테마를 우선 조회한다.") {
|
||||||
|
TestThemeCreateUtil.createThemeWithReservations(
|
||||||
|
entityManager = entityManager,
|
||||||
|
name = "테마11",
|
||||||
|
reservedCount = 5,
|
||||||
|
date = LocalDate.now().minusDays(5),
|
||||||
|
)
|
||||||
|
|
||||||
|
themeRepository.findTopNThemeBetweenStartDateAndEndDate(
|
||||||
|
LocalDate.now().minusDays(6),
|
||||||
|
LocalDate.now().minusDays(4),
|
||||||
|
5
|
||||||
|
).also { themes ->
|
||||||
|
themes.size shouldBe 4
|
||||||
|
themes.map { it.name } shouldContainInOrder listOf(
|
||||||
|
"테마6", "테마5", "테마11", "테마4"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test("입력된 갯수보다 조회된 갯수가 작으면, 조회된 갯수만큼 반환한다.") {
|
||||||
|
themeRepository.findTopNThemeBetweenStartDateAndEndDate(
|
||||||
|
LocalDate.now().minusDays(10),
|
||||||
|
LocalDate.now().minusDays(6),
|
||||||
|
10
|
||||||
|
).also { themes ->
|
||||||
|
themes.size shouldBe 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test("입력된 갯수보다 조회된 갯수가 많으면, 입력된 갯수만큼 반환한다.") {
|
||||||
|
themeRepository.findTopNThemeBetweenStartDateAndEndDate(
|
||||||
|
LocalDate.now().minusDays(10),
|
||||||
|
LocalDate.now().minusDays(1),
|
||||||
|
15
|
||||||
|
).also { themes ->
|
||||||
|
themes.size shouldBe 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test("입력된 날짜 범위에 예약된 테마가 없을 경우 빈 리스트를 반환한다.") {
|
||||||
|
themeRepository.findTopNThemeBetweenStartDateAndEndDate(
|
||||||
|
LocalDate.now().plusDays(1),
|
||||||
|
LocalDate.now().plusDays(10),
|
||||||
|
5
|
||||||
|
).also { themes ->
|
||||||
|
themes.size shouldBe 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context("existsByName ") {
|
||||||
|
val themeName = "test-theme"
|
||||||
|
beforeTest {
|
||||||
|
TestThemeCreateUtil.createThemeWithReservations(
|
||||||
|
entityManager = entityManager,
|
||||||
|
name = themeName,
|
||||||
|
reservedCount = 0,
|
||||||
|
date = LocalDate.now()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
test("테마 이름이 존재하면 true를 반환한다.") {
|
||||||
|
themeRepository.existsByName(themeName) shouldBe true
|
||||||
|
}
|
||||||
|
|
||||||
|
test("테마 이름이 존재하지 않으면 false를 반환한다.") {
|
||||||
|
themeRepository.existsByName(themeName.repeat(2)) shouldBe false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context("isReservedTheme") {
|
||||||
|
test("테마가 예약 중이면 true를 반환한다.") {
|
||||||
|
val theme = TestThemeCreateUtil.createThemeWithReservations(
|
||||||
|
entityManager = entityManager,
|
||||||
|
name = "예약된 테마",
|
||||||
|
reservedCount = 1,
|
||||||
|
date = LocalDate.now()
|
||||||
|
)
|
||||||
|
themeRepository.isReservedTheme(theme.id!!) shouldBe true
|
||||||
|
}
|
||||||
|
|
||||||
|
test("테마가 예약 중이 아니면 false를 반환한다.") {
|
||||||
|
val theme = TestThemeCreateUtil.createThemeWithReservations(
|
||||||
|
entityManager = entityManager,
|
||||||
|
name = "예약되지 않은 테마",
|
||||||
|
reservedCount = 0,
|
||||||
|
date = LocalDate.now()
|
||||||
|
)
|
||||||
|
themeRepository.isReservedTheme(theme.id!!) shouldBe false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,164 +0,0 @@
|
|||||||
package roomescape.theme.service;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
|
||||||
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.DisplayName;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
|
||||||
import org.springframework.context.annotation.Import;
|
|
||||||
import org.springframework.test.context.jdbc.Sql;
|
|
||||||
|
|
||||||
import roomescape.member.business.MemberService;
|
|
||||||
import roomescape.member.infrastructure.persistence.Member;
|
|
||||||
import roomescape.member.infrastructure.persistence.MemberRepository;
|
|
||||||
import roomescape.member.infrastructure.persistence.Role;
|
|
||||||
import roomescape.reservation.dto.request.ReservationRequest;
|
|
||||||
import roomescape.reservation.dto.request.ReservationTimeRequest;
|
|
||||||
import roomescape.reservation.dto.response.ReservationTimeResponse;
|
|
||||||
import roomescape.reservation.service.ReservationService;
|
|
||||||
import roomescape.reservation.service.ReservationTimeService;
|
|
||||||
import roomescape.common.exception.RoomescapeException;
|
|
||||||
import roomescape.theme.domain.Theme;
|
|
||||||
import roomescape.theme.domain.repository.ThemeRepository;
|
|
||||||
import roomescape.theme.dto.ThemeRequest;
|
|
||||||
import roomescape.theme.dto.ThemeResponse;
|
|
||||||
import roomescape.theme.dto.ThemesResponse;
|
|
||||||
|
|
||||||
@DataJpaTest
|
|
||||||
@Import({ReservationTimeService.class, ReservationService.class, MemberService.class, ThemeService.class})
|
|
||||||
@Sql(scripts = "/truncate.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
|
|
||||||
class ThemeServiceTest {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ThemeRepository themeRepository;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ThemeService themeService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ReservationTimeService reservationTimeService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private MemberRepository memberRepository;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ReservationService reservationService;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@DisplayName("테마를 조회한다.")
|
|
||||||
void findThemeById() {
|
|
||||||
// given
|
|
||||||
Theme theme = themeRepository.save(new Theme("name", "description", "thumbnail"));
|
|
||||||
|
|
||||||
// when
|
|
||||||
Theme foundTheme = themeService.findThemeById(theme.getId());
|
|
||||||
|
|
||||||
// then
|
|
||||||
assertThat(foundTheme).isEqualTo(theme);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@DisplayName("존재하지 않는 ID로 테마를 조회하면 예외가 발생한다.")
|
|
||||||
void findThemeByNotExistId() {
|
|
||||||
// given
|
|
||||||
Theme theme = themeRepository.save(new Theme("name", "description", "thumbnail"));
|
|
||||||
|
|
||||||
// when
|
|
||||||
Long notExistId = theme.getId() + 1;
|
|
||||||
|
|
||||||
// then
|
|
||||||
assertThatThrownBy(() -> themeService.findThemeById(notExistId))
|
|
||||||
.isInstanceOf(RoomescapeException.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@DisplayName("모든 테마를 조회한다.")
|
|
||||||
void findAllThemes() {
|
|
||||||
// given
|
|
||||||
Theme theme = themeRepository.save(new Theme("name", "description", "thumbnail"));
|
|
||||||
Theme theme1 = themeRepository.save(new Theme("name1", "description1", "thumbnail1"));
|
|
||||||
|
|
||||||
// when
|
|
||||||
ThemesResponse found = themeService.findAllThemes();
|
|
||||||
|
|
||||||
// then
|
|
||||||
assertThat(found.themes()).extracting("id").containsExactly(theme.getId(), theme1.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@DisplayName("예약 수 상위 10개 테마를 조회했을 때 내림차순으로 정렬된다. 만약 예약 수가 같다면, id 순으로 오름차순 정렬된다.")
|
|
||||||
@Sql({"/truncate.sql", "/reservationData.sql"})
|
|
||||||
void getMostReservedThemesByCount() {
|
|
||||||
// given
|
|
||||||
LocalDate today = LocalDate.now();
|
|
||||||
|
|
||||||
// when
|
|
||||||
List<ThemeResponse> found = themeService.getMostReservedThemesByCount(10).themes();
|
|
||||||
|
|
||||||
// then : 11번 테마는 조회되지 않아야 한다.
|
|
||||||
assertThat(found).extracting("id").containsExactly(1L, 4L, 2L, 6L, 3L, 5L, 7L, 8L, 9L, 10L);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@DisplayName("테마를 추가한다.")
|
|
||||||
void addTheme() {
|
|
||||||
// given
|
|
||||||
ThemeResponse themeResponse = themeService.addTheme(new ThemeRequest("name", "description", "thumbnail"));
|
|
||||||
|
|
||||||
// when
|
|
||||||
Theme found = themeRepository.findById(themeResponse.id()).orElse(null);
|
|
||||||
|
|
||||||
// then
|
|
||||||
assertThat(found).isNotNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@DisplayName("테마를 추가할 때 같은 이름의 테마가 존재하면 예외가 발생한다. ")
|
|
||||||
void addDuplicateTheme() {
|
|
||||||
// given
|
|
||||||
ThemeResponse themeResponse = themeService.addTheme(new ThemeRequest("name", "description", "thumbnail"));
|
|
||||||
|
|
||||||
// when
|
|
||||||
ThemeRequest invalidRequest = new ThemeRequest(themeResponse.name(), "description", "thumbnail");
|
|
||||||
|
|
||||||
// then
|
|
||||||
assertThatThrownBy(() -> themeService.addTheme(invalidRequest))
|
|
||||||
.isInstanceOf(RoomescapeException.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@DisplayName("테마를 삭제한다.")
|
|
||||||
void removeThemeById() {
|
|
||||||
// given
|
|
||||||
Theme theme = themeRepository.save(new Theme("name", "description", "thumbnail"));
|
|
||||||
|
|
||||||
// when
|
|
||||||
themeService.removeThemeById(theme.getId());
|
|
||||||
|
|
||||||
// then
|
|
||||||
assertThat(themeRepository.findById(theme.getId())).isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@DisplayName("예약이 존재하는 테마를 삭제하면 예외가 발생한다.")
|
|
||||||
void removeReservedTheme() {
|
|
||||||
// given
|
|
||||||
LocalDateTime dateTime = LocalDateTime.now().plusDays(1);
|
|
||||||
ReservationTimeResponse time = reservationTimeService.addTime(
|
|
||||||
new ReservationTimeRequest(dateTime.toLocalTime()));
|
|
||||||
Theme theme = themeRepository.save(new Theme("name", "description", "thumbnail"));
|
|
||||||
Member member = memberRepository.save(new Member(null, "member", "password", "name", Role.MEMBER));
|
|
||||||
reservationService.addReservation(
|
|
||||||
new ReservationRequest(dateTime.toLocalDate(), time.id(), theme.getId(), "paymentKey", "orderId", 1000L,
|
|
||||||
"NORMAL"), member.getId());
|
|
||||||
|
|
||||||
// when & then
|
|
||||||
assertThatThrownBy(() -> themeService.removeThemeById(theme.getId()))
|
|
||||||
.isInstanceOf(RoomescapeException.class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
44
src/test/java/roomescape/theme/util/TestThemeCreateUtil.kt
Normal file
44
src/test/java/roomescape/theme/util/TestThemeCreateUtil.kt
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package roomescape.theme.util
|
||||||
|
|
||||||
|
import jakarta.persistence.EntityManager
|
||||||
|
import roomescape.member.infrastructure.persistence.Member
|
||||||
|
import roomescape.reservation.domain.ReservationStatus
|
||||||
|
import roomescape.reservation.domain.ReservationTime
|
||||||
|
import roomescape.theme.infrastructure.persistence.ThemeEntity
|
||||||
|
import roomescape.util.MemberFixture
|
||||||
|
import roomescape.util.ReservationFixture
|
||||||
|
import roomescape.util.ReservationTimeFixture
|
||||||
|
import roomescape.util.ThemeFixture
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.time.LocalTime
|
||||||
|
|
||||||
|
object TestThemeCreateUtil {
|
||||||
|
fun createThemeWithReservations(
|
||||||
|
entityManager: EntityManager,
|
||||||
|
name: String,
|
||||||
|
reservedCount: Int,
|
||||||
|
date: LocalDate,
|
||||||
|
): ThemeEntity {
|
||||||
|
val themeEntity: ThemeEntity = ThemeFixture.create(name = name).also { entityManager.persist(it) }
|
||||||
|
val member: Member = MemberFixture.create().also { entityManager.persist(it) }
|
||||||
|
|
||||||
|
for (i in 1..reservedCount) {
|
||||||
|
val time: ReservationTime = ReservationTimeFixture.create(
|
||||||
|
startAt = LocalTime.now().plusMinutes(i.toLong())
|
||||||
|
).also { entityManager.persist(it) }
|
||||||
|
|
||||||
|
ReservationFixture.create(
|
||||||
|
date = date,
|
||||||
|
themeEntity = themeEntity,
|
||||||
|
member = member,
|
||||||
|
reservationTime = time,
|
||||||
|
status = ReservationStatus.CONFIRMED
|
||||||
|
).also { entityManager.persist(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
entityManager.flush()
|
||||||
|
entityManager.clear()
|
||||||
|
|
||||||
|
return themeEntity
|
||||||
|
}
|
||||||
|
}
|
||||||
113
src/test/java/roomescape/theme/web/MostReservedThemeAPITest.kt
Normal file
113
src/test/java/roomescape/theme/web/MostReservedThemeAPITest.kt
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
package roomescape.theme.web
|
||||||
|
|
||||||
|
import io.kotest.core.spec.style.FunSpec
|
||||||
|
import io.restassured.module.kotlin.extensions.Given
|
||||||
|
import io.restassured.module.kotlin.extensions.Then
|
||||||
|
import io.restassured.module.kotlin.extensions.When
|
||||||
|
import jakarta.persistence.EntityManager
|
||||||
|
import org.hamcrest.Matchers.equalTo
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest
|
||||||
|
import org.springframework.boot.test.web.server.LocalServerPort
|
||||||
|
import org.springframework.test.context.jdbc.Sql
|
||||||
|
import org.springframework.transaction.support.TransactionTemplate
|
||||||
|
import roomescape.theme.business.ThemeService
|
||||||
|
import roomescape.theme.util.TestThemeCreateUtil
|
||||||
|
import java.time.LocalDate
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /themes/most-reserved-last-week API 테스트
|
||||||
|
* 상세 테스트는 Repository 테스트에서 진행
|
||||||
|
* 날짜 범위, 예약 수만 검증
|
||||||
|
*/
|
||||||
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||||
|
@Sql(value = ["/truncate.sql"], executionPhase = Sql.ExecutionPhase.AFTER_TEST_CLASS)
|
||||||
|
class MostReservedThemeAPITest(
|
||||||
|
@LocalServerPort val port: Int,
|
||||||
|
val themeService: ThemeService,
|
||||||
|
val transactionTemplate: TransactionTemplate,
|
||||||
|
val entityManager: EntityManager,
|
||||||
|
) : FunSpec() {
|
||||||
|
init {
|
||||||
|
beforeSpec {
|
||||||
|
transactionTemplate.executeWithoutResult {
|
||||||
|
// 지난 7일간 예약된 테마 10개 생성
|
||||||
|
for (i in 1..10) {
|
||||||
|
TestThemeCreateUtil.createThemeWithReservations(
|
||||||
|
entityManager = entityManager,
|
||||||
|
name = "테마$i",
|
||||||
|
reservedCount = 1,
|
||||||
|
date = LocalDate.now().minusDays(Random.nextLong(1, 7))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8일 전 예약된 테마 1개 생성
|
||||||
|
TestThemeCreateUtil.createThemeWithReservations(
|
||||||
|
entityManager = entityManager,
|
||||||
|
name = "테마11",
|
||||||
|
reservedCount = 1,
|
||||||
|
date = LocalDate.now().minusDays(8)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context("가장 많이 예약된 테마를 조회할 때, ") {
|
||||||
|
val endpoint = "/themes/most-reserved-last-week"
|
||||||
|
test("갯수를 입력하지 않으면 10개를 반환한다.") {
|
||||||
|
Given {
|
||||||
|
port(port)
|
||||||
|
} When {
|
||||||
|
get(endpoint)
|
||||||
|
} Then {
|
||||||
|
log().all()
|
||||||
|
statusCode(200)
|
||||||
|
body("data.themes.size()", equalTo(10))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test("입력된 갯수가 조회된 갯수보다 크면 조회된 갯수만큼 반환한다.") {
|
||||||
|
val count = 15
|
||||||
|
Given {
|
||||||
|
port(port)
|
||||||
|
} When {
|
||||||
|
param("count", count)
|
||||||
|
get("/themes/most-reserved-last-week")
|
||||||
|
} Then {
|
||||||
|
log().all()
|
||||||
|
statusCode(200)
|
||||||
|
body("data.themes.size()", equalTo(10))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test("입력된 갯수가 조회된 갯수보다 작으면 입력된 갯수만큼 반환한다.") {
|
||||||
|
val count = 5
|
||||||
|
Given {
|
||||||
|
port(port)
|
||||||
|
} When {
|
||||||
|
param("count", count)
|
||||||
|
get("/themes/most-reserved-last-week")
|
||||||
|
} Then {
|
||||||
|
log().all()
|
||||||
|
statusCode(200)
|
||||||
|
body("data.themes.size()", equalTo(count))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test("7일 전 부터 1일 전 까지 예약된 테마를 대상으로 한다.") {
|
||||||
|
// 현재 저장된 데이터는 지난 7일간 예약된 테마 10개와 8일 전 예약된 테마 1개
|
||||||
|
// 8일 전 예약된 테마는 제외되어야 하므로, 10개가 조회되어야 한다.
|
||||||
|
val count = 11
|
||||||
|
Given {
|
||||||
|
port(port)
|
||||||
|
} When {
|
||||||
|
param("count", count)
|
||||||
|
get("/themes/most-reserved-last-week")
|
||||||
|
} Then {
|
||||||
|
log().all()
|
||||||
|
statusCode(200)
|
||||||
|
body("data.themes.size()", equalTo(10))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
307
src/test/java/roomescape/theme/web/ThemeControllerTest.kt
Normal file
307
src/test/java/roomescape/theme/web/ThemeControllerTest.kt
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
package roomescape.theme.web
|
||||||
|
|
||||||
|
import com.ninjasquad.springmockk.MockkBean
|
||||||
|
import com.ninjasquad.springmockk.SpykBean
|
||||||
|
import io.kotest.assertions.assertSoftly
|
||||||
|
import io.kotest.matchers.collections.shouldContainAll
|
||||||
|
import io.kotest.matchers.shouldBe
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.just
|
||||||
|
import io.mockk.runs
|
||||||
|
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
|
||||||
|
import org.springframework.http.MediaType
|
||||||
|
import org.springframework.test.web.servlet.MockMvc
|
||||||
|
import roomescape.theme.business.ThemeService
|
||||||
|
import roomescape.theme.infrastructure.persistence.ThemeRepository
|
||||||
|
import roomescape.util.RoomescapeApiTest
|
||||||
|
import roomescape.util.ThemeFixture
|
||||||
|
|
||||||
|
@WebMvcTest(ThemeController::class)
|
||||||
|
class ThemeControllerTest(mockMvc: MockMvc) : RoomescapeApiTest() {
|
||||||
|
|
||||||
|
@SpykBean
|
||||||
|
private lateinit var themeService: ThemeService
|
||||||
|
|
||||||
|
@MockkBean
|
||||||
|
private lateinit var themeRepository: ThemeRepository
|
||||||
|
|
||||||
|
init {
|
||||||
|
Given("모든 테마를 조회할 때") {
|
||||||
|
val endpoint = "/themes"
|
||||||
|
|
||||||
|
When("로그인 상태가 아니라면") {
|
||||||
|
doNotLogin()
|
||||||
|
|
||||||
|
Then("로그인 페이지로 이동한다.") {
|
||||||
|
runGetTest(
|
||||||
|
mockMvc = mockMvc,
|
||||||
|
endpoint = endpoint,
|
||||||
|
log = true
|
||||||
|
) {
|
||||||
|
status { is3xxRedirection() }
|
||||||
|
header {
|
||||||
|
string("Location", "/login")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
When("로그인 상태라면") {
|
||||||
|
loginAsUser()
|
||||||
|
|
||||||
|
Then("조회에 성공한다.") {
|
||||||
|
every {
|
||||||
|
themeRepository.findAll()
|
||||||
|
} returns listOf(
|
||||||
|
ThemeFixture.create(id = 1, name = "theme1"),
|
||||||
|
ThemeFixture.create(id = 2, name = "theme2"),
|
||||||
|
ThemeFixture.create(id = 3, name = "theme3")
|
||||||
|
)
|
||||||
|
|
||||||
|
val response: ThemesResponse = runGetTest(
|
||||||
|
mockMvc = mockMvc,
|
||||||
|
endpoint = endpoint,
|
||||||
|
log = true
|
||||||
|
) {
|
||||||
|
status { isOk() }
|
||||||
|
content {
|
||||||
|
contentType(MediaType.APPLICATION_JSON)
|
||||||
|
}
|
||||||
|
}.andReturn().readValue(ThemesResponse::class.java)
|
||||||
|
|
||||||
|
assertSoftly(response.themes) {
|
||||||
|
it.size shouldBe 3
|
||||||
|
it.map { m -> m.name } shouldContainAll listOf("theme1", "theme2", "theme3")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Given("테마를 추가할 때") {
|
||||||
|
val endpoint = "/themes"
|
||||||
|
val request = ThemeRequest(
|
||||||
|
name = "theme1",
|
||||||
|
description = "description1",
|
||||||
|
thumbnail = "http://example.com/thumbnail1.jpg"
|
||||||
|
)
|
||||||
|
|
||||||
|
When("로그인 상태가 아니라면") {
|
||||||
|
doNotLogin()
|
||||||
|
Then("로그인 페이지로 이동한다.") {
|
||||||
|
runPostTest(
|
||||||
|
mockMvc = mockMvc,
|
||||||
|
endpoint = endpoint,
|
||||||
|
body = request,
|
||||||
|
log = true
|
||||||
|
) {
|
||||||
|
status { is3xxRedirection() }
|
||||||
|
header {
|
||||||
|
string("Location", "/login")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
When("관리자가 아닌 회원은") {
|
||||||
|
loginAsUser()
|
||||||
|
Then("로그인 페이지로 이동한다.") {
|
||||||
|
runPostTest(
|
||||||
|
mockMvc = mockMvc,
|
||||||
|
endpoint = endpoint,
|
||||||
|
body = request,
|
||||||
|
log = true
|
||||||
|
) {
|
||||||
|
status { is3xxRedirection() }
|
||||||
|
jsonPath("$.errorType") { value("PERMISSION_DOES_NOT_EXIST") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
When("동일한 이름의 테마가 있으면") {
|
||||||
|
loginAsAdmin()
|
||||||
|
|
||||||
|
Then("409 에러를 응답한다.") {
|
||||||
|
every {
|
||||||
|
themeRepository.existsByName(request.name)
|
||||||
|
} returns true
|
||||||
|
|
||||||
|
runPostTest(
|
||||||
|
mockMvc = mockMvc,
|
||||||
|
endpoint = endpoint,
|
||||||
|
body = request,
|
||||||
|
log = true
|
||||||
|
) {
|
||||||
|
status { isConflict() }
|
||||||
|
jsonPath("$.errorType") { value("THEME_DUPLICATED") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
When("값이 잘못 입력되면 400 에러를 응답한다") {
|
||||||
|
beforeTest {
|
||||||
|
loginAsAdmin()
|
||||||
|
}
|
||||||
|
|
||||||
|
val request = ThemeRequest(
|
||||||
|
name = "theme1",
|
||||||
|
description = "description1",
|
||||||
|
thumbnail = "http://example.com/thumbnail1.jpg"
|
||||||
|
)
|
||||||
|
|
||||||
|
fun runTest(request: ThemeRequest) {
|
||||||
|
runPostTest(
|
||||||
|
mockMvc = mockMvc,
|
||||||
|
endpoint = endpoint,
|
||||||
|
body = request,
|
||||||
|
log = true
|
||||||
|
) {
|
||||||
|
status { isBadRequest() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Then("이름이 공백인 경우") {
|
||||||
|
val invalidRequest = request.copy(name = " ")
|
||||||
|
runTest(invalidRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
Then("이름이 20글자를 초과하는 경우") {
|
||||||
|
val invalidRequest = request.copy(name = "a".repeat(21))
|
||||||
|
runTest(invalidRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
Then("설명이 공백인 경우") {
|
||||||
|
val invalidRequest = request.copy(description = " ")
|
||||||
|
runTest(invalidRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
Then("설명이 100글자를 초과하는 경우") {
|
||||||
|
val invalidRequest = request.copy(description = "a".repeat(101))
|
||||||
|
runTest(invalidRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
Then("썸네일이 공백인 경우") {
|
||||||
|
val invalidRequest = request.copy(thumbnail = " ")
|
||||||
|
runTest(invalidRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
Then("썸네일이 URL 형식이 아닌 경우") {
|
||||||
|
val invalidRequest = request.copy(thumbnail = "invalid-url")
|
||||||
|
runTest(invalidRequest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
When("저장에 성공하면") {
|
||||||
|
loginAsAdmin()
|
||||||
|
|
||||||
|
val theme = ThemeFixture.create(
|
||||||
|
id = 1,
|
||||||
|
name = request.name,
|
||||||
|
description = request.description,
|
||||||
|
thumbnail = request.thumbnail
|
||||||
|
)
|
||||||
|
|
||||||
|
every {
|
||||||
|
themeRepository.existsByName(request.name)
|
||||||
|
} returns false
|
||||||
|
|
||||||
|
every {
|
||||||
|
themeRepository.save(any())
|
||||||
|
} returns theme
|
||||||
|
|
||||||
|
Then("201 응답을 받는다.") {
|
||||||
|
runPostTest(
|
||||||
|
mockMvc = mockMvc,
|
||||||
|
endpoint = endpoint,
|
||||||
|
body = request,
|
||||||
|
log = true
|
||||||
|
) {
|
||||||
|
status { isCreated() }
|
||||||
|
header {
|
||||||
|
string("Location", "/themes/${theme.id}")
|
||||||
|
}
|
||||||
|
jsonPath("$.data.id") { value(theme.id) }
|
||||||
|
jsonPath("$.data.name") { value(theme.name) }
|
||||||
|
jsonPath("$.data.description") { value(theme.description) }
|
||||||
|
jsonPath("$.data.thumbnail") { value(theme.thumbnail) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Given("테마를 제거할 때") {
|
||||||
|
val themeId = 1L
|
||||||
|
val endpoint = "/themes/$themeId"
|
||||||
|
|
||||||
|
When("로그인 상태가 아니라면") {
|
||||||
|
doNotLogin()
|
||||||
|
Then("로그인 페이지로 이동한다.") {
|
||||||
|
runDeleteTest(
|
||||||
|
mockMvc = mockMvc,
|
||||||
|
endpoint = endpoint,
|
||||||
|
log = true
|
||||||
|
) {
|
||||||
|
status { is3xxRedirection() }
|
||||||
|
header {
|
||||||
|
string("Location", "/login")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
When("관리자가 아닌 회원은") {
|
||||||
|
loginAsUser()
|
||||||
|
Then("로그인 페이지로 이동한다.") {
|
||||||
|
runDeleteTest(
|
||||||
|
mockMvc = mockMvc,
|
||||||
|
endpoint = endpoint,
|
||||||
|
log = true
|
||||||
|
) {
|
||||||
|
status { is3xxRedirection() }
|
||||||
|
jsonPath("$.errorType") { value("PERMISSION_DOES_NOT_EXIST") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
When("입력된 ID에 해당하는 테마가 없으면") {
|
||||||
|
loginAsAdmin()
|
||||||
|
|
||||||
|
Then("409 에러를 응답한다.") {
|
||||||
|
every {
|
||||||
|
themeRepository.isReservedTheme(themeId)
|
||||||
|
} returns true
|
||||||
|
|
||||||
|
runDeleteTest(
|
||||||
|
mockMvc = mockMvc,
|
||||||
|
endpoint = endpoint,
|
||||||
|
log = true
|
||||||
|
) {
|
||||||
|
status { isConflict() }
|
||||||
|
jsonPath("$.errorType") { value("THEME_IS_USED_CONFLICT") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
When("정상적으로 제거되면") {
|
||||||
|
loginAsAdmin()
|
||||||
|
|
||||||
|
every {
|
||||||
|
themeRepository.isReservedTheme(themeId)
|
||||||
|
} returns false
|
||||||
|
|
||||||
|
every {
|
||||||
|
themeRepository.deleteById(themeId)
|
||||||
|
} just runs
|
||||||
|
|
||||||
|
Then("204 응답을 받는다.") {
|
||||||
|
runDeleteTest(
|
||||||
|
mockMvc = mockMvc,
|
||||||
|
endpoint = endpoint,
|
||||||
|
log = true
|
||||||
|
) {
|
||||||
|
status { isNoContent() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -11,7 +11,7 @@ import roomescape.payment.web.PaymentCancel
|
|||||||
import roomescape.reservation.domain.Reservation
|
import roomescape.reservation.domain.Reservation
|
||||||
import roomescape.reservation.domain.ReservationStatus
|
import roomescape.reservation.domain.ReservationStatus
|
||||||
import roomescape.reservation.domain.ReservationTime
|
import roomescape.reservation.domain.ReservationTime
|
||||||
import roomescape.theme.domain.Theme
|
import roomescape.theme.infrastructure.persistence.ThemeEntity
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalTime
|
import java.time.LocalTime
|
||||||
import java.time.OffsetDateTime
|
import java.time.OffsetDateTime
|
||||||
@ -62,18 +62,18 @@ object ThemeFixture {
|
|||||||
name: String = "Default Theme",
|
name: String = "Default Theme",
|
||||||
description: String = "Default Description",
|
description: String = "Default Description",
|
||||||
thumbnail: String = "https://example.com/default-thumbnail.jpg"
|
thumbnail: String = "https://example.com/default-thumbnail.jpg"
|
||||||
): Theme = Theme(id, name, description, thumbnail)
|
): ThemeEntity = ThemeEntity(id, name, description, thumbnail)
|
||||||
}
|
}
|
||||||
|
|
||||||
object ReservationFixture {
|
object ReservationFixture {
|
||||||
fun create(
|
fun create(
|
||||||
id: Long? = null,
|
id: Long? = null,
|
||||||
date: LocalDate = LocalDate.now().plusWeeks(1),
|
date: LocalDate = LocalDate.now().plusWeeks(1),
|
||||||
theme: Theme = ThemeFixture.create(),
|
themeEntity: ThemeEntity = ThemeFixture.create(),
|
||||||
reservationTime: ReservationTime = ReservationTimeFixture.create(),
|
reservationTime: ReservationTime = ReservationTimeFixture.create(),
|
||||||
member: Member = MemberFixture.create(),
|
member: Member = MemberFixture.create(),
|
||||||
status: ReservationStatus = ReservationStatus.CONFIRMED_PAYMENT_REQUIRED
|
status: ReservationStatus = ReservationStatus.CONFIRMED_PAYMENT_REQUIRED
|
||||||
): Reservation = Reservation(id, date, reservationTime, theme, member, status)
|
): Reservation = Reservation(id, date, reservationTime, themeEntity, member, status)
|
||||||
}
|
}
|
||||||
|
|
||||||
object JwtFixture {
|
object JwtFixture {
|
||||||
|
|||||||
@ -55,9 +55,7 @@ abstract class RoomescapeApiTest : BehaviorSpec() {
|
|||||||
header(HttpHeaders.COOKIE, "accessToken=token")
|
header(HttpHeaders.COOKIE, "accessToken=token")
|
||||||
}.apply {
|
}.apply {
|
||||||
log.takeIf { it }?.let { this.andDo { print() } }
|
log.takeIf { it }?.let { this.andDo { print() } }
|
||||||
}.andExpect {
|
}.andExpect(assert)
|
||||||
assert
|
|
||||||
}
|
|
||||||
|
|
||||||
fun runPostTest(
|
fun runPostTest(
|
||||||
mockMvc: MockMvc,
|
mockMvc: MockMvc,
|
||||||
@ -77,6 +75,19 @@ abstract class RoomescapeApiTest : BehaviorSpec() {
|
|||||||
assert
|
assert
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun runDeleteTest(
|
||||||
|
mockMvc: MockMvc,
|
||||||
|
endpoint: String,
|
||||||
|
log: Boolean = false,
|
||||||
|
assert: MockMvcResultMatchersDsl.() -> Unit
|
||||||
|
): ResultActionsDsl = mockMvc.delete(endpoint) {
|
||||||
|
header(HttpHeaders.COOKIE, "accessToken=token")
|
||||||
|
}.apply {
|
||||||
|
log.takeIf { it }?.let { this.andDo { print() } }
|
||||||
|
}.andExpect {
|
||||||
|
assert
|
||||||
|
}
|
||||||
|
|
||||||
fun loginAsAdmin() {
|
fun loginAsAdmin() {
|
||||||
every {
|
every {
|
||||||
jwtHandler.getMemberIdFromToken(any())
|
jwtHandler.getMemberIdFromToken(any())
|
||||||
@ -104,6 +115,13 @@ abstract class RoomescapeApiTest : BehaviorSpec() {
|
|||||||
every { memberRepository.findByIdOrNull(NOT_LOGGED_IN_USERID) } returns null
|
every { memberRepository.findByIdOrNull(NOT_LOGGED_IN_USERID) } returns null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T> MvcResult.readValue(valueType: Class<T>): T = this.response.contentAsString
|
||||||
|
.takeIf { it.isNotBlank() }
|
||||||
|
?.let { readValue(it, valueType) }
|
||||||
|
?: throw RuntimeException("""
|
||||||
|
[Test] Exception occurred while reading response json: ${this.response.contentAsString} with value type: $valueType
|
||||||
|
""".trimIndent())
|
||||||
|
|
||||||
fun <T> readValue(responseJson: String, valueType: Class<T>): T = objectMapper
|
fun <T> readValue(responseJson: String, valueType: Class<T>): T = objectMapper
|
||||||
.readTree(responseJson)["data"]
|
.readTree(responseJson)["data"]
|
||||||
?.let { objectMapper.convertValue(it, valueType) }
|
?.let { objectMapper.convertValue(it, valueType) }
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user