generated from pricelees/issue-pr-template
171 lines
6.5 KiB
Kotlin
171 lines
6.5 KiB
Kotlin
package roomescape.reservation.implement
|
|
|
|
import io.kotest.assertions.throwables.shouldNotThrow
|
|
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.jpa.domain.Specification
|
|
import roomescape.member.infrastructure.persistence.Role
|
|
import roomescape.reservation.exception.ReservationErrorCode
|
|
import roomescape.reservation.exception.ReservationException
|
|
import roomescape.reservation.infrastructure.persistence.ReservationEntity
|
|
import roomescape.reservation.infrastructure.persistence.ReservationRepository
|
|
import roomescape.reservation.infrastructure.persistence.ReservationStatus
|
|
import roomescape.util.MemberFixture
|
|
import roomescape.util.ReservationFixture
|
|
import roomescape.util.ThemeFixture
|
|
import roomescape.util.TimeFixture
|
|
import java.time.LocalDate
|
|
import java.time.LocalTime
|
|
|
|
class ReservationValidatorTest : FunSpec({
|
|
val reservationRepository: ReservationRepository = mockk()
|
|
|
|
val reservationValidator = ReservationValidator(reservationRepository)
|
|
|
|
context("validateIsNotPast") {
|
|
val today = LocalDate.now()
|
|
val now = LocalTime.now()
|
|
|
|
test("입력된 날짜가 오늘 이전이면 예외를 던진다.") {
|
|
val requestDate = today.minusDays(1)
|
|
|
|
shouldThrow<ReservationException> {
|
|
reservationValidator.validateIsPast(requestDate, now)
|
|
}.also {
|
|
it.errorCode shouldBe ReservationErrorCode.PAST_REQUEST_DATETIME
|
|
}
|
|
}
|
|
|
|
test("오늘 날짜라도 시간이 지났다면 예외를 던진다.") {
|
|
val requestTime = now.minusMinutes(1)
|
|
|
|
shouldThrow<ReservationException> {
|
|
reservationValidator.validateIsPast(today, requestTime)
|
|
}.also {
|
|
it.errorCode shouldBe ReservationErrorCode.PAST_REQUEST_DATETIME
|
|
}
|
|
}
|
|
}
|
|
|
|
context("validateSearchDateRange") {
|
|
test("시작 날짜만 입력되면 종료한다.") {
|
|
shouldNotThrow<ReservationException> {
|
|
reservationValidator.validateSearchDateRange(LocalDate.now(), null)
|
|
}
|
|
}
|
|
|
|
test("종료 날짜만 입력되면 종료한다.") {
|
|
shouldNotThrow<ReservationException> {
|
|
reservationValidator.validateSearchDateRange(null, LocalDate.now())
|
|
}
|
|
}
|
|
|
|
test("두 날짜가 같으면 종료한다.") {
|
|
shouldNotThrow<ReservationException> {
|
|
reservationValidator.validateSearchDateRange(LocalDate.now(), LocalDate.now())
|
|
}
|
|
}
|
|
|
|
test("종료 날짜가 시작 날짜 이전이면 예외를 던진다.") {
|
|
shouldThrow<ReservationException> {
|
|
reservationValidator.validateSearchDateRange(LocalDate.now(), LocalDate.now().minusDays(1))
|
|
}.also {
|
|
it.errorCode shouldBe ReservationErrorCode.INVALID_SEARCH_DATE_RANGE
|
|
}
|
|
}
|
|
}
|
|
|
|
context("validateIsAlreadyExists") {
|
|
test("동일한 날짜, 시간, 테마를 가지는 예약이 있으면 예외를 던진다.") {
|
|
every {
|
|
reservationRepository.exists(any<Specification<ReservationEntity>>())
|
|
} returns true
|
|
|
|
shouldThrow<ReservationException> {
|
|
reservationValidator.validateIsAlreadyExists(
|
|
LocalDate.now(),
|
|
TimeFixture.create(),
|
|
ThemeFixture.create()
|
|
)
|
|
}.also {
|
|
it.errorCode shouldBe ReservationErrorCode.RESERVATION_DUPLICATED
|
|
}
|
|
}
|
|
}
|
|
|
|
context("validateMemberAlreadyReserve") {
|
|
test("회원이 동일한 날짜, 시간, 테마인 예약(대기)를 이미 했다면 예외를 던진다.") {
|
|
every {
|
|
reservationRepository.exists(any<Specification<ReservationEntity>>())
|
|
} returns true
|
|
|
|
shouldThrow<ReservationException> {
|
|
reservationValidator.validateMemberAlreadyReserve(1L, 1L, LocalDate.now(), 1L)
|
|
}.also {
|
|
it.errorCode shouldBe ReservationErrorCode.ALREADY_RESERVE
|
|
}
|
|
}
|
|
}
|
|
|
|
context("validateIsWaiting") {
|
|
test("예약 상태가 WAITING이 아니면 예외를 던진다.") {
|
|
ReservationStatus.confirmedStatus().forEach { status ->
|
|
shouldThrow<ReservationException> {
|
|
val reservation = ReservationFixture.create(status = status)
|
|
reservationValidator.validateIsWaiting(reservation)
|
|
}.also {
|
|
it.errorCode shouldBe ReservationErrorCode.ALREADY_CONFIRMED
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
context("validateCreateAuthority") {
|
|
test("관리자가 아니면 예외를 던진다.") {
|
|
shouldThrow<ReservationException> {
|
|
reservationValidator.validateCreateAuthority(MemberFixture.user())
|
|
}.also {
|
|
it.errorCode shouldBe ReservationErrorCode.NO_PERMISSION
|
|
}
|
|
}
|
|
}
|
|
|
|
context("validateDeleteAuthority") {
|
|
test("입력된 회원이 관리자이면 종료한다.") {
|
|
shouldNotThrow<ReservationException> {
|
|
reservationValidator.validateDeleteAuthority(mockk(), MemberFixture.admin())
|
|
}
|
|
}
|
|
|
|
test("입력된 회원이 관리자가 아니고, 예약한 회원과 다른 회원이면 예외를 던진다.") {
|
|
shouldThrow<ReservationException> {
|
|
reservationValidator.validateDeleteAuthority(
|
|
ReservationFixture.create(member = MemberFixture.create(id = 1L)),
|
|
MemberFixture.create(id = 2L, role = Role.MEMBER)
|
|
)
|
|
}.also {
|
|
it.errorCode shouldBe ReservationErrorCode.NOT_RESERVATION_OWNER
|
|
}
|
|
}
|
|
}
|
|
|
|
context("validateAlreadyConfirmed") {
|
|
val reservationId = 1L
|
|
|
|
test("입력된 ID의 예약과 동일한 날짜, 시간, 테마를 가지는 다른 확정 예약이 있으면 예외를 던진다.") {
|
|
every {
|
|
reservationRepository.isExistConfirmedReservation(reservationId)
|
|
} returns true
|
|
|
|
shouldThrow<ReservationException> {
|
|
reservationValidator.validateAlreadyConfirmed(reservationId)
|
|
}.also {
|
|
it.errorCode shouldBe ReservationErrorCode.CONFIRMED_RESERVATION_ALREADY_EXISTS
|
|
}
|
|
}
|
|
}
|
|
})
|