generated from pricelees/issue-pr-template
194 lines
6.2 KiB
Kotlin
194 lines
6.2 KiB
Kotlin
package roomescape.supports
|
|
|
|
import io.restassured.module.kotlin.extensions.Extract
|
|
import io.restassured.module.kotlin.extensions.Given
|
|
import io.restassured.module.kotlin.extensions.Then
|
|
import io.restassured.module.kotlin.extensions.When
|
|
import io.restassured.response.Response
|
|
import io.restassured.response.ValidatableResponse
|
|
import io.restassured.specification.RequestSpecification
|
|
import org.hamcrest.CoreMatchers.equalTo
|
|
import org.springframework.data.repository.findByIdOrNull
|
|
import org.springframework.http.HttpMethod
|
|
import org.springframework.http.HttpStatus
|
|
import org.springframework.http.MediaType
|
|
import roomescape.admin.infrastructure.persistence.AdminEntity
|
|
import roomescape.admin.infrastructure.persistence.AdminRepository
|
|
import roomescape.auth.web.LoginRequest
|
|
import roomescape.common.dto.PrincipalType
|
|
import roomescape.common.exception.ErrorCode
|
|
import roomescape.store.infrastructure.persistence.StoreRepository
|
|
import roomescape.user.infrastructure.persistence.UserEntity
|
|
import roomescape.user.infrastructure.persistence.UserRepository
|
|
import roomescape.user.web.UserCreateRequest
|
|
import kotlin.random.Random
|
|
|
|
class AuthUtil(
|
|
private val userRepository: UserRepository,
|
|
private val adminRepository: AdminRepository,
|
|
private val storeRepository: StoreRepository,
|
|
) {
|
|
fun createAdmin(admin: AdminEntity): AdminEntity {
|
|
val storeId = admin.storeId
|
|
if (storeId != null && storeRepository.findByIdOrNull(storeId) == null) {
|
|
storeRepository.save(
|
|
StoreFixture.create(
|
|
id = storeId,
|
|
businessRegNum = generateBusinessRegNum(),
|
|
)
|
|
)
|
|
}
|
|
|
|
return adminRepository.save(admin)
|
|
}
|
|
|
|
fun signup(request: UserCreateRequest): UserEntity {
|
|
val userId: Long = Given {
|
|
contentType(MediaType.APPLICATION_JSON_VALUE)
|
|
body(request)
|
|
} When {
|
|
post("/users")
|
|
} Then {
|
|
statusCode(HttpStatus.OK.value())
|
|
} Extract {
|
|
path("data.id")
|
|
}
|
|
|
|
return userRepository.findByIdOrNull(userId)
|
|
?: throw AssertionError("Unexpected Exception Occurred.")
|
|
}
|
|
|
|
fun adminLogin(admin: AdminEntity): String {
|
|
val saved = createAdmin(admin)
|
|
val requestBody = LoginRequest(saved.account, saved.password, PrincipalType.ADMIN)
|
|
|
|
return Given {
|
|
contentType(MediaType.APPLICATION_JSON_VALUE)
|
|
body(requestBody)
|
|
} When {
|
|
post("/auth/login")
|
|
} Then {
|
|
statusCode(200)
|
|
} Extract {
|
|
path("data.accessToken")
|
|
}
|
|
}
|
|
|
|
fun defaultStoreAdminLogin(): String = adminLogin(AdminFixture.storeDefault)
|
|
fun defaultHqAdminLogin(): String = adminLogin(AdminFixture.hqDefault)
|
|
|
|
fun userLogin(user: UserEntity): String {
|
|
if (userRepository.findByEmail(user.email) == null) {
|
|
userRepository.save(user)
|
|
}
|
|
|
|
return Given {
|
|
contentType(MediaType.APPLICATION_JSON_VALUE)
|
|
body(LoginRequest(account = user.email, password = user.password, principalType = PrincipalType.USER))
|
|
} When {
|
|
post("/auth/login")
|
|
} Then {
|
|
statusCode(200)
|
|
} Extract {
|
|
path("data.accessToken")
|
|
}
|
|
}
|
|
|
|
fun defaultUserLogin(): String = userLogin(UserFixture.default)
|
|
|
|
fun defaultUser(): UserEntity = userRepository.findByEmail(UserFixture.default.email)
|
|
?: userRepository.save(UserFixture.default)
|
|
}
|
|
|
|
fun runTest(
|
|
token: String? = null,
|
|
using: RequestSpecification.() -> RequestSpecification = { this },
|
|
on: RequestSpecification.() -> Response,
|
|
expect: ValidatableResponse.() -> Unit
|
|
): ValidatableResponse {
|
|
return Given {
|
|
contentType(MediaType.APPLICATION_JSON_VALUE)
|
|
token?.also { header("Authorization", "Bearer $token") }
|
|
using()
|
|
} When {
|
|
on()
|
|
} Then {
|
|
expect()
|
|
}
|
|
}
|
|
|
|
fun runExceptionTest(
|
|
token: String? = null,
|
|
method: HttpMethod,
|
|
requestBody: Any? = null,
|
|
endpoint: String,
|
|
expectedErrorCode: ErrorCode
|
|
): ValidatableResponse {
|
|
return runTest(
|
|
token = token,
|
|
using = {
|
|
requestBody?.let { body(requestBody) } ?: this
|
|
},
|
|
on = {
|
|
when (method) {
|
|
HttpMethod.GET -> get(endpoint)
|
|
HttpMethod.POST -> post(endpoint)
|
|
HttpMethod.PATCH -> patch(endpoint)
|
|
HttpMethod.DELETE -> delete(endpoint)
|
|
|
|
else -> {
|
|
throw AssertionError("Unsupported HTTP method: $method")
|
|
}
|
|
}
|
|
},
|
|
expect = {
|
|
statusCode(expectedErrorCode.httpStatus.value())
|
|
body("code", equalTo(expectedErrorCode.errorCode))
|
|
}
|
|
)
|
|
}
|
|
|
|
/**
|
|
* @param props: RestAssured 응답 Body 에서 존재 & Null 여부를 확인할 프로퍼티 이름
|
|
*/
|
|
fun ValidatableResponse.assertProperties(props: Set<String>, propsNameIfList: String? = null) {
|
|
val jsonDefaultPath = propsNameIfList?.let { "data.$propsNameIfList" } ?: "data"
|
|
val json = extract().jsonPath().get<Any>(jsonDefaultPath)
|
|
|
|
fun checkMap(map: Map<*, *>) {
|
|
val responseKeys = map.keys.map { it.toString() }.toSet()
|
|
val expectedKeys = props
|
|
|
|
val missing = expectedKeys - responseKeys
|
|
val extra = responseKeys - expectedKeys
|
|
|
|
require(missing.isEmpty() && extra.isEmpty()) {
|
|
buildString {
|
|
if (missing.isNotEmpty()) append("Missing keys: $missing. ")
|
|
if (extra.isNotEmpty()) append("Unexpected keys: $extra.")
|
|
}
|
|
}
|
|
|
|
expectedKeys.forEach { key ->
|
|
require(map[key] != null) { "Property '$key' is null" }
|
|
}
|
|
}
|
|
|
|
when (json) {
|
|
is List<*> -> json.forEach { item ->
|
|
val map = item as? Map<*, *> ?: error("Expected Map but got ${item?.javaClass}")
|
|
checkMap(map)
|
|
}
|
|
|
|
is Map<*, *> -> checkMap(json)
|
|
else -> error("Unexpected data type: ${json::class}")
|
|
}
|
|
}
|
|
|
|
private fun generateBusinessRegNum(): String {
|
|
val part1 = Random.nextInt(100, 1000)
|
|
val part2 = Random.nextInt(10, 100)
|
|
val part3 = Random.nextInt(10000, 100000)
|
|
return "$part1-$part2-$part3"
|
|
}
|