generated from pricelees/issue-pr-template
[#37] 테마 스키마 재정의 #38
681
src/test/kotlin/roomescape/theme/ThemeApiTest.kt
Normal file
681
src/test/kotlin/roomescape/theme/ThemeApiTest.kt
Normal file
@ -0,0 +1,681 @@
|
|||||||
|
package roomescape.theme
|
||||||
|
|
||||||
|
import io.kotest.matchers.date.shouldBeAfter
|
||||||
|
import io.kotest.matchers.nulls.shouldNotBeNull
|
||||||
|
import io.kotest.matchers.shouldBe
|
||||||
|
import io.kotest.matchers.shouldNotBe
|
||||||
|
import io.restassured.module.kotlin.extensions.Extract
|
||||||
|
import io.restassured.module.kotlin.extensions.Given
|
||||||
|
import io.restassured.module.kotlin.extensions.When
|
||||||
|
import io.restassured.response.ValidatableResponse
|
||||||
|
import org.hamcrest.CoreMatchers.equalTo
|
||||||
|
import org.hamcrest.CoreMatchers.notNullValue
|
||||||
|
import org.springframework.data.repository.findByIdOrNull
|
||||||
|
import org.springframework.http.HttpStatus
|
||||||
|
import org.springframework.http.MediaType
|
||||||
|
import roomescape.auth.exception.AuthErrorCode
|
||||||
|
import roomescape.member.infrastructure.persistence.Role
|
||||||
|
import roomescape.theme.business.MIN_DURATION
|
||||||
|
import roomescape.theme.business.MIN_PARTICIPANTS
|
||||||
|
import roomescape.theme.business.MIN_PRICE
|
||||||
|
import roomescape.theme.exception.ThemeErrorCode
|
||||||
|
import roomescape.theme.infrastructure.persistence.v2.Difficulty
|
||||||
|
import roomescape.theme.infrastructure.persistence.v2.ThemeEntityV2
|
||||||
|
import roomescape.theme.infrastructure.persistence.v2.ThemeRepositoryV2
|
||||||
|
import roomescape.theme.web.ThemeCreateRequestV2
|
||||||
|
import roomescape.theme.web.ThemeUpdateRequest
|
||||||
|
import roomescape.util.FunSpecSpringbootTest
|
||||||
|
import roomescape.util.assertProperties
|
||||||
|
import roomescape.util.runTest
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
class ThemeApiTest(
|
||||||
|
private val themeRepository: ThemeRepositoryV2
|
||||||
|
) : FunSpecSpringbootTest() {
|
||||||
|
|
||||||
|
private val request: ThemeCreateRequestV2 = ThemeCreateRequestV2(
|
||||||
|
name = "Matilda Green",
|
||||||
|
description = "constituto",
|
||||||
|
thumbnailUrl = "https://duckduckgo.com/?q=mediocrem",
|
||||||
|
difficulty = Difficulty.VERY_EASY,
|
||||||
|
price = 10000,
|
||||||
|
minParticipants = 3,
|
||||||
|
maxParticipants = 5,
|
||||||
|
availableMinutes = 80,
|
||||||
|
expectedMinutesFrom = 60,
|
||||||
|
expectedMinutesTo = 70,
|
||||||
|
isOpen = true
|
||||||
|
)
|
||||||
|
|
||||||
|
init {
|
||||||
|
context("관리자가 아니면 접근할 수 없다.") {
|
||||||
|
lateinit var token: String
|
||||||
|
|
||||||
|
beforeTest {
|
||||||
|
token = loginUtil.loginAsUser()
|
||||||
|
}
|
||||||
|
|
||||||
|
val commonAssertion: ValidatableResponse.() -> Unit = {
|
||||||
|
statusCode(HttpStatus.FORBIDDEN.value())
|
||||||
|
body("code", equalTo(AuthErrorCode.ACCESS_DENIED.errorCode))
|
||||||
|
}
|
||||||
|
|
||||||
|
test("테마 생성: POST /admin/themes") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(request)
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
post("/admin/themes")
|
||||||
|
},
|
||||||
|
expect = commonAssertion
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("테마 조회: GET /admin/themes") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
on = {
|
||||||
|
get("/admin/themes")
|
||||||
|
},
|
||||||
|
expect = commonAssertion
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("테마 상세 조회: GET /admin/themes/{id}") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
on = {
|
||||||
|
get("/admin/themes/1")
|
||||||
|
},
|
||||||
|
expect = commonAssertion
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("테마 수정: PATCH /admin/themes/{id}") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(request)
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
patch("/admin/themes/1")
|
||||||
|
},
|
||||||
|
expect = commonAssertion
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("테마 삭제: DELETE /admin/themes/{id}") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
on = {
|
||||||
|
delete("/admin/themes/1")
|
||||||
|
},
|
||||||
|
expect = commonAssertion
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context("일반 회원도 접근할 수 있다.") {
|
||||||
|
test("테마 조회: GET /v2/themes") {
|
||||||
|
createDummyTheme(request.copy(name = "test123", isOpen = true))
|
||||||
|
|
||||||
|
runTest(
|
||||||
|
token = loginUtil.loginAsUser(),
|
||||||
|
on = {
|
||||||
|
get("/v2/themes")
|
||||||
|
},
|
||||||
|
expect = {
|
||||||
|
statusCode(HttpStatus.OK.value())
|
||||||
|
body("data.themes.size()", equalTo(1))
|
||||||
|
body("data.themes[0].name", equalTo("test123"))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context("테마를 생성한다.") {
|
||||||
|
val apiPath = "/admin/themes"
|
||||||
|
|
||||||
|
lateinit var token: String
|
||||||
|
|
||||||
|
beforeTest {
|
||||||
|
token = loginUtil.loginAsAdmin()
|
||||||
|
}
|
||||||
|
|
||||||
|
test("정상 생성 및 감사 정보 확인") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(request)
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
post(apiPath)
|
||||||
|
},
|
||||||
|
expect = {
|
||||||
|
statusCode(HttpStatus.CREATED.value())
|
||||||
|
body("data.id", notNullValue())
|
||||||
|
}
|
||||||
|
).also {
|
||||||
|
val createdThemeId: String = it.extract().path("data.id")
|
||||||
|
val createdTheme: ThemeEntityV2 = themeRepository.findByIdOrNull(createdThemeId.toLong())
|
||||||
|
?: throw AssertionError("Unexpected Exception Occurred.")
|
||||||
|
|
||||||
|
createdTheme.name shouldBe request.name
|
||||||
|
createdTheme.createdAt shouldNotBeNull {}
|
||||||
|
createdTheme.createdBy shouldNotBeNull {}
|
||||||
|
createdTheme.updatedAt shouldNotBeNull {}
|
||||||
|
createdTheme.updatedBy shouldNotBeNull {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test("이미 동일한 이름의 테마가 있으면 실패한다.") {
|
||||||
|
val commonName = "test123"
|
||||||
|
createDummyTheme(request.copy(name = commonName))
|
||||||
|
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(request.copy(name = commonName))
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
post(apiPath)
|
||||||
|
},
|
||||||
|
expect = {
|
||||||
|
statusCode(HttpStatus.BAD_REQUEST.value())
|
||||||
|
body("code", equalTo(ThemeErrorCode.THEME_NAME_DUPLICATED.errorCode))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("금액이 ${MIN_PRICE}원 미만이면 실패한다.") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(request.copy(price = (MIN_PRICE - 1)))
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
post(apiPath)
|
||||||
|
},
|
||||||
|
expect = {
|
||||||
|
statusCode(HttpStatus.BAD_REQUEST.value())
|
||||||
|
body("code", equalTo(ThemeErrorCode.PRICE_BELOW_MINIMUM.errorCode))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
context("입력된 시간이 ${MIN_DURATION}분 미만이면 실패한다.") {
|
||||||
|
val commonAssertion: ValidatableResponse.() -> Unit = {
|
||||||
|
statusCode(HttpStatus.BAD_REQUEST.value())
|
||||||
|
body("code", equalTo(ThemeErrorCode.DURATION_BELOW_MINIMUM.errorCode))
|
||||||
|
}
|
||||||
|
|
||||||
|
test("field: availableMinutes") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(request.copy(availableMinutes = (MIN_DURATION - 1).toShort()))
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
post(apiPath)
|
||||||
|
},
|
||||||
|
expect = commonAssertion
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("field: expectedMinutesFrom") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(request.copy(expectedMinutesFrom = (MIN_DURATION - 1).toShort()))
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
post(apiPath)
|
||||||
|
},
|
||||||
|
expect = commonAssertion
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("field: expectedMinutesTo") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(request.copy(expectedMinutesTo = (MIN_DURATION - 1).toShort()))
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
post(apiPath)
|
||||||
|
},
|
||||||
|
expect = commonAssertion
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context("시간 범위가 잘못 지정되면 실패한다.") {
|
||||||
|
test("최소 예상 시간 > 최대 예상 시간") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(request.copy(expectedMinutesFrom = 100, expectedMinutesTo = 99))
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
post(apiPath)
|
||||||
|
},
|
||||||
|
expect = {
|
||||||
|
statusCode(HttpStatus.BAD_REQUEST.value())
|
||||||
|
body("code", equalTo(ThemeErrorCode.MIN_EXPECTED_TIME_EXCEEDS_MAX_EXPECTED_TIME.errorCode))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("최대 예상 시간 > 이용 가능 시간") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(
|
||||||
|
request.copy(
|
||||||
|
availableMinutes = 100,
|
||||||
|
expectedMinutesFrom = 101,
|
||||||
|
expectedMinutesTo = 101
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
post(apiPath)
|
||||||
|
},
|
||||||
|
expect = {
|
||||||
|
statusCode(HttpStatus.BAD_REQUEST.value())
|
||||||
|
body("code", equalTo(ThemeErrorCode.EXPECTED_TIME_EXCEEDS_AVAILABLE_TIME.errorCode))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context("입력된 인원이 ${MIN_PARTICIPANTS}명 미만이면 실패한다.") {
|
||||||
|
val commonAssertion: ValidatableResponse.() -> Unit = {
|
||||||
|
statusCode(HttpStatus.BAD_REQUEST.value())
|
||||||
|
body("code", equalTo(ThemeErrorCode.PARTICIPANT_BELOW_MINIMUM.errorCode))
|
||||||
|
}
|
||||||
|
|
||||||
|
test("field: minParticipants") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(request.copy(minParticipants = (MIN_PARTICIPANTS - 1).toShort()))
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
post(apiPath)
|
||||||
|
},
|
||||||
|
expect = commonAssertion
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("field: maxParticipants") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(request.copy(maxParticipants = (MIN_PARTICIPANTS - 1).toShort()))
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
post(apiPath)
|
||||||
|
},
|
||||||
|
expect = commonAssertion
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context("인원 범위가 잘못 지정되면 실패한다.") {
|
||||||
|
test("최소 인원 > 최대 인원") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(request.copy(minParticipants = 10, maxParticipants = 9))
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
post(apiPath)
|
||||||
|
},
|
||||||
|
expect = {
|
||||||
|
statusCode(HttpStatus.BAD_REQUEST.value())
|
||||||
|
body("code", equalTo(ThemeErrorCode.MIN_PARTICIPANT_EXCEEDS_MAX_PARTICIPANT.errorCode))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context("모든 테마를 조회한다.") {
|
||||||
|
beforeTest {
|
||||||
|
createDummyTheme(request.copy(name = "open", isOpen = true))
|
||||||
|
createDummyTheme(request.copy(name = "close", isOpen = false))
|
||||||
|
}
|
||||||
|
|
||||||
|
test("관리자 페이지에서는 비공개 테마까지 포함하여 간단한 정보만 조회된다.") {
|
||||||
|
runTest(
|
||||||
|
token = loginUtil.loginAsAdmin(),
|
||||||
|
on = {
|
||||||
|
get("/admin/themes")
|
||||||
|
},
|
||||||
|
expect = {
|
||||||
|
body("data.themes.size()", equalTo(2))
|
||||||
|
assertProperties(
|
||||||
|
props = setOf("id", "name", "difficulty", "price", "isOpen"),
|
||||||
|
propsNameIfList = "themes",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("예약 페이지에서는 공개된 테마의 전체 정보가 조회된다.") {
|
||||||
|
runTest(
|
||||||
|
token = loginUtil.loginAsUser(),
|
||||||
|
on = {
|
||||||
|
get("/v2/themes")
|
||||||
|
},
|
||||||
|
expect = {
|
||||||
|
body("data.themes.size()", equalTo(1))
|
||||||
|
body("data.themes[0].name", equalTo("open"))
|
||||||
|
assertProperties(
|
||||||
|
props = setOf(
|
||||||
|
"id", "name", "thumbnailUrl", "description", "difficulty", "price",
|
||||||
|
"minParticipants", "maxParticipants",
|
||||||
|
"availableMinutes", "expectedMinutesFrom", "expectedMinutesTo"
|
||||||
|
),
|
||||||
|
propsNameIfList = "themes",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context("관리자 페이지에서 특정 테마의 상세 정보를 조회한다.") {
|
||||||
|
test("정상 응답") {
|
||||||
|
val createdTheme: ThemeEntityV2 = createDummyTheme(request)
|
||||||
|
|
||||||
|
runTest(
|
||||||
|
token = loginUtil.loginAsAdmin(),
|
||||||
|
on = {
|
||||||
|
get("/admin/themes/${createdTheme.id}")
|
||||||
|
},
|
||||||
|
expect = {
|
||||||
|
statusCode(HttpStatus.OK.value())
|
||||||
|
body("data.id", equalTo(createdTheme.id.toString()))
|
||||||
|
assertProperties(
|
||||||
|
props = setOf(
|
||||||
|
"id", "name", "description", "thumbnailUrl", "difficulty", "price", "isOpen",
|
||||||
|
"minParticipants", "maxParticipants",
|
||||||
|
"availableMinutes", "expectedMinutesFrom", "expectedMinutesTo",
|
||||||
|
"createdAt", "createdBy", "updatedAt", "updatedBy"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("테마가 없으면 실패한다.") {
|
||||||
|
runTest(
|
||||||
|
token = loginUtil.loginAsAdmin(),
|
||||||
|
on = {
|
||||||
|
get("/admin/themes/1")
|
||||||
|
},
|
||||||
|
expect = {
|
||||||
|
statusCode(HttpStatus.NOT_FOUND.value())
|
||||||
|
body("code", equalTo(ThemeErrorCode.THEME_NOT_FOUND.errorCode))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context("테마를 삭제한다.") {
|
||||||
|
test("정상 삭제") {
|
||||||
|
val createdTheme = createDummyTheme(request)
|
||||||
|
|
||||||
|
runTest(
|
||||||
|
token = loginUtil.loginAsAdmin(),
|
||||||
|
on = {
|
||||||
|
delete("/admin/themes/${createdTheme.id}")
|
||||||
|
},
|
||||||
|
expect = {
|
||||||
|
statusCode(HttpStatus.NO_CONTENT.value())
|
||||||
|
}
|
||||||
|
).also {
|
||||||
|
themeRepository.findByIdOrNull(createdTheme.id) shouldBe null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test("테마가 없으면 실패한다.") {
|
||||||
|
runTest(
|
||||||
|
token = loginUtil.loginAsAdmin(),
|
||||||
|
on = {
|
||||||
|
delete("/admin/themes/1")
|
||||||
|
},
|
||||||
|
expect = {
|
||||||
|
statusCode(HttpStatus.NOT_FOUND.value())
|
||||||
|
body("code", equalTo(ThemeErrorCode.THEME_NOT_FOUND.errorCode))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context("테마를 수정한다.") {
|
||||||
|
lateinit var token: String
|
||||||
|
lateinit var createdTheme: ThemeEntityV2
|
||||||
|
lateinit var apiPath: String
|
||||||
|
|
||||||
|
val updateRequest = ThemeUpdateRequest(name = "modified")
|
||||||
|
|
||||||
|
beforeTest {
|
||||||
|
token = loginUtil.loginAsAdmin()
|
||||||
|
createdTheme = createDummyTheme(request.copy(name = "theme-${Random.nextInt()}"))
|
||||||
|
apiPath = "/admin/themes/${createdTheme.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
test("정상 수정 및 감사 정보 변경 확인") {
|
||||||
|
val otherAdminToken = loginUtil.login("admin1@admin.com", "admin1", Role.ADMIN)
|
||||||
|
|
||||||
|
runTest(
|
||||||
|
token = otherAdminToken,
|
||||||
|
using = {
|
||||||
|
body(updateRequest)
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
patch(apiPath)
|
||||||
|
},
|
||||||
|
expect = {
|
||||||
|
statusCode(HttpStatus.OK.value())
|
||||||
|
}
|
||||||
|
).also {
|
||||||
|
val updatedTheme = themeRepository.findByIdOrNull(createdTheme.id)!!
|
||||||
|
|
||||||
|
updatedTheme.id shouldBe createdTheme.id
|
||||||
|
updatedTheme.name shouldBe updateRequest.name
|
||||||
|
updatedTheme.updatedBy shouldNotBe createdTheme.updatedBy
|
||||||
|
updatedTheme.updatedAt shouldBeAfter createdTheme.updatedAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test("테마가 없으면 실패한다.") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(updateRequest)
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
patch("/admin/themes/1")
|
||||||
|
},
|
||||||
|
expect = {
|
||||||
|
statusCode(HttpStatus.NOT_FOUND.value())
|
||||||
|
body("code", equalTo(ThemeErrorCode.THEME_NOT_FOUND.errorCode))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("금액이 ${MIN_PRICE}원 미만이면 실패한다.") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(updateRequest.copy(price = (MIN_PRICE - 1)))
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
patch("/admin/themes/${createdTheme.id}")
|
||||||
|
},
|
||||||
|
expect = {
|
||||||
|
statusCode(HttpStatus.BAD_REQUEST.value())
|
||||||
|
body("code", equalTo(ThemeErrorCode.PRICE_BELOW_MINIMUM.errorCode))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
context("입력된 시간이 ${MIN_DURATION}분 미만이면 실패한다.") {
|
||||||
|
val commonAssertion: ValidatableResponse.() -> Unit = {
|
||||||
|
statusCode(HttpStatus.BAD_REQUEST.value())
|
||||||
|
body("code", equalTo(ThemeErrorCode.DURATION_BELOW_MINIMUM.errorCode))
|
||||||
|
}
|
||||||
|
|
||||||
|
test("field: availableMinutes") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(updateRequest.copy(availableMinutes = (MIN_DURATION - 1).toShort()))
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
patch(apiPath)
|
||||||
|
},
|
||||||
|
expect = commonAssertion
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("field: expectedMinutesFrom") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(updateRequest.copy(expectedMinutesFrom = (MIN_DURATION - 1).toShort()))
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
patch(apiPath)
|
||||||
|
},
|
||||||
|
expect = commonAssertion
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("field: expectedMinutesTo") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(updateRequest.copy(expectedMinutesTo = (MIN_DURATION - 1).toShort()))
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
patch(apiPath)
|
||||||
|
},
|
||||||
|
expect = commonAssertion
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context("시간 범위가 잘못 지정되면 실패한다.") {
|
||||||
|
test("최소 예상 시간 > 최대 예상 시간") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(updateRequest.copy(expectedMinutesFrom = 100, expectedMinutesTo = 99))
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
patch(apiPath)
|
||||||
|
},
|
||||||
|
expect = {
|
||||||
|
statusCode(HttpStatus.BAD_REQUEST.value())
|
||||||
|
body("code", equalTo(ThemeErrorCode.MIN_EXPECTED_TIME_EXCEEDS_MAX_EXPECTED_TIME.errorCode))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("최대 예상 시간 > 이용 가능 시간") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(
|
||||||
|
updateRequest.copy(
|
||||||
|
availableMinutes = 100,
|
||||||
|
expectedMinutesFrom = 101,
|
||||||
|
expectedMinutesTo = 101
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
patch(apiPath)
|
||||||
|
},
|
||||||
|
expect = {
|
||||||
|
statusCode(HttpStatus.BAD_REQUEST.value())
|
||||||
|
body("code", equalTo(ThemeErrorCode.EXPECTED_TIME_EXCEEDS_AVAILABLE_TIME.errorCode))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context("입력된 인원이 ${MIN_PARTICIPANTS}명 미만이면 실패한다.") {
|
||||||
|
val commonAssertion: ValidatableResponse.() -> Unit = {
|
||||||
|
statusCode(HttpStatus.BAD_REQUEST.value())
|
||||||
|
body("code", equalTo(ThemeErrorCode.PARTICIPANT_BELOW_MINIMUM.errorCode))
|
||||||
|
}
|
||||||
|
|
||||||
|
test("field: minParticipants") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(updateRequest.copy(minParticipants = (MIN_PARTICIPANTS - 1).toShort()))
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
patch(apiPath)
|
||||||
|
},
|
||||||
|
expect = commonAssertion
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("field: maxParticipants") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(updateRequest.copy(maxParticipants = (MIN_PARTICIPANTS - 1).toShort()))
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
patch(apiPath)
|
||||||
|
},
|
||||||
|
expect = commonAssertion
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context("인원 범위가 잘못 지정되면 실패한다.") {
|
||||||
|
test("최소 인원 > 최대 인원") {
|
||||||
|
runTest(
|
||||||
|
token = token,
|
||||||
|
using = {
|
||||||
|
body(updateRequest.copy(minParticipants = 10, maxParticipants = 9))
|
||||||
|
},
|
||||||
|
on = {
|
||||||
|
patch(apiPath)
|
||||||
|
},
|
||||||
|
expect = {
|
||||||
|
statusCode(HttpStatus.BAD_REQUEST.value())
|
||||||
|
body("code", equalTo(ThemeErrorCode.MIN_PARTICIPANT_EXCEEDS_MAX_PARTICIPANT.errorCode))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createDummyTheme(request: ThemeCreateRequestV2): ThemeEntityV2 {
|
||||||
|
val createdThemeId: String = Given {
|
||||||
|
contentType(MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
header("Authorization", "Bearer ${loginUtil.loginAsAdmin()}")
|
||||||
|
body(request)
|
||||||
|
} When {
|
||||||
|
post("/admin/themes")
|
||||||
|
} Extract {
|
||||||
|
path("data.id")
|
||||||
|
}
|
||||||
|
|
||||||
|
return themeRepository.findByIdOrNull(createdThemeId.toLong())
|
||||||
|
?: throw RuntimeException("unreachable line")
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user