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.transaction.support.TransactionTemplate import roomescape.theme.util.TestThemeDataHelper import roomescape.util.CleanerMode import roomescape.util.DatabaseCleanerExtension import java.time.LocalDate import kotlin.random.Random @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) class MostReservedThemeApiTest( @LocalServerPort val port: Int, val transactionTemplate: TransactionTemplate, val entityManager: EntityManager, ) : FunSpec({ extension(DatabaseCleanerExtension(mode = CleanerMode.AFTER_SPEC)) }) { val helper = TestThemeDataHelper(entityManager, transactionTemplate) init { beforeSpec { transactionTemplate.executeWithoutResult { // 7일 전 ~ 1일 전 예약된 테마 10개 생성 for (i in 1..10) { helper.createThemeWithReservations( name = "테마$i", reservedCount = 1, date = LocalDate.now().minusDays(Random.nextLong(1, 7)) ) } // 8일 전 예약된 테마 1개 생성 helper.createThemeWithReservations( name = "테마11", reservedCount = 1, date = LocalDate.now().minusDays(8) ) // 당일 예약된 테마 1개 생성 helper.createThemeWithReservations( name = "테마12", reservedCount = 1, date = LocalDate.now() ) } } context("GET /themes/most-reserved-last-week") { val endpoint = "/themes/most-reserved-last-week" test("count 파라미터가 없으면 10개를 반환한다") { Given { port(port) } When { get(endpoint) } Then { statusCode(200) body("data.themes.size()", equalTo(10)) } } test("조회된 테마가 count보다 적으면 조회된 만큼 반환한다") { val count = 15 Given { port(port) param("count", count) } When { get(endpoint) } Then { statusCode(200) body("data.themes.size()", equalTo(10)) } } test("조회된 테마가 count보다 많으면 count만큼 반환한다") { val count = 5 Given { port(port) param("count", count) } When { get(endpoint) } Then { statusCode(200) body("data.themes.size()", equalTo(count)) } } test("지난 7일 동안의 예약만 집계한다") { // beforeSpec 에서 정의한 테스트 데이터 중, 8일 전 / 당일 예약 테마는 제외되어야 한다. val count = 12 Given { port(port) param("count", count) } When { get(endpoint) } Then { statusCode(200) body("data.themes.size()", equalTo(10)) } } } } }