From c3eceedea1da38d9cd93cff8e7e8a0d8cd65408f Mon Sep 17 00:00:00 2001 From: pricelees Date: Sun, 14 Sep 2025 23:35:22 +0900 Subject: [PATCH] =?UTF-8?q?test:=20=ED=85=8C=EB=A7=88=20API=20=EA=B6=8C?= =?UTF-8?q?=ED=95=9C=20=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/roomescape/supports/Fixtures.kt | 43 ++++- .../kotlin/roomescape/theme/ThemeApiTest.kt | 163 +++++++++++++----- 2 files changed, 159 insertions(+), 47 deletions(-) diff --git a/src/test/kotlin/roomescape/supports/Fixtures.kt b/src/test/kotlin/roomescape/supports/Fixtures.kt index 7c77fc2c..683900c0 100644 --- a/src/test/kotlin/roomescape/supports/Fixtures.kt +++ b/src/test/kotlin/roomescape/supports/Fixtures.kt @@ -64,12 +64,53 @@ object AdminFixture { storeId = null ) + fun createStoreAdmin( + id: Long = tsidFactory.next(), + account: String = "admin", + password: String = "adminPassword", + name: String = "admin12345", + phone: String = randomPhoneNumber(), + storeId: Long = tsidFactory.next(), + permissionLevel: AdminPermissionLevel = AdminPermissionLevel.FULL_ACCESS + ): AdminEntity { + return create( + id = id, + account = account, + password = password, + name = name, + phone = phone, + type = AdminType.STORE, + storeId = storeId, + permissionLevel = permissionLevel + ) + } + + fun createHqAdmin( + id: Long = tsidFactory.next(), + account: String = "admin", + password: String = "adminPassword", + name: String = "admin12345", + phone: String = randomPhoneNumber(), + permissionLevel: AdminPermissionLevel = AdminPermissionLevel.FULL_ACCESS + ): AdminEntity { + return create( + id = id, + account = account, + password = password, + name = name, + phone = phone, + type = AdminType.HQ, + storeId = null, + permissionLevel = permissionLevel + ) + } + fun create( id: Long = tsidFactory.next(), account: String = "admin", password: String = "adminPassword", name: String = "admin12345", - phone: String = "01012345678", + phone: String = randomPhoneNumber(), type: AdminType = AdminType.STORE, storeId: Long? = tsidFactory.next(), permissionLevel: AdminPermissionLevel = AdminPermissionLevel.FULL_ACCESS diff --git a/src/test/kotlin/roomescape/theme/ThemeApiTest.kt b/src/test/kotlin/roomescape/theme/ThemeApiTest.kt index 01aa4fa3..9e6e1645 100644 --- a/src/test/kotlin/roomescape/theme/ThemeApiTest.kt +++ b/src/test/kotlin/roomescape/theme/ThemeApiTest.kt @@ -11,6 +11,7 @@ import org.springframework.data.repository.findByIdOrNull import org.springframework.http.HttpMethod import org.springframework.http.HttpStatus import roomescape.admin.infrastructure.persistence.AdminPermissionLevel +import roomescape.admin.infrastructure.persistence.AdminType import roomescape.auth.exception.AuthErrorCode import roomescape.theme.business.MIN_DURATION import roomescape.theme.business.MIN_PARTICIPANTS @@ -52,9 +53,9 @@ class ThemeApiTest( ) } - listOf(AdminPermissionLevel.READ_SUMMARY, AdminPermissionLevel.READ_ALL).forEach { - test("권한이 ${it}인 관리자") { - val admin = AdminFixture.create(permissionLevel = it) + AdminPermissionLevel.entries.forEach { + test("관리자: Type=${AdminType.STORE} / Permission=${it}") { + val admin = AdminFixture.createStoreAdmin(permissionLevel = it) runExceptionTest( token = authUtil.adminLogin(admin), @@ -64,12 +65,26 @@ class ThemeApiTest( expectedErrorCode = AuthErrorCode.ACCESS_DENIED ) } + + if (it == AdminPermissionLevel.READ_ALL || it == AdminPermissionLevel.READ_SUMMARY) { + test("관리자: Type=${AdminType.HQ} / Permission=${it}") { + val admin = AdminFixture.createHqAdmin(permissionLevel = it) + + runExceptionTest( + token = authUtil.adminLogin(admin), + method = HttpMethod.POST, + requestBody = createRequest, + endpoint = endpoint, + expectedErrorCode = AuthErrorCode.ACCESS_DENIED + ) + } + } } } test("정상 생성 및 감사 정보 확인") { - val token = authUtil.defaultStoreAdminLogin() + val token = authUtil.defaultHqAdminLogin() runTest( token = token, @@ -97,7 +112,7 @@ class ThemeApiTest( } test("이미 동일한 이름의 테마가 있으면 실패한다.") { - val token = authUtil.defaultStoreAdminLogin() + val token = authUtil.defaultHqAdminLogin() val commonName = "test123" dummyInitializer.createTheme( adminToken = token, @@ -120,7 +135,7 @@ class ThemeApiTest( } test("금액이 ${MIN_PRICE}원 미만이면 실패한다.") { - val token = authUtil.defaultStoreAdminLogin() + val token = authUtil.defaultHqAdminLogin() runTest( token = token, using = { @@ -143,7 +158,7 @@ class ThemeApiTest( } test("field: availableMinutes") { - val token = authUtil.defaultStoreAdminLogin() + val token = authUtil.defaultHqAdminLogin() runTest( token = token, using = { @@ -157,7 +172,7 @@ class ThemeApiTest( } test("field: expectedMinutesFrom") { - val token = authUtil.defaultStoreAdminLogin() + val token = authUtil.defaultHqAdminLogin() runTest( token = token, using = { @@ -171,7 +186,7 @@ class ThemeApiTest( } test("field: expectedMinutesTo") { - val token = authUtil.defaultStoreAdminLogin() + val token = authUtil.defaultHqAdminLogin() runTest( token = token, using = { @@ -187,7 +202,7 @@ class ThemeApiTest( context("시간 범위가 잘못 지정되면 실패한다.") { test("최소 예상 시간 > 최대 예상 시간") { - val token = authUtil.defaultStoreAdminLogin() + val token = authUtil.defaultHqAdminLogin() runTest( token = token, using = { @@ -204,7 +219,7 @@ class ThemeApiTest( } test("최대 예상 시간 > 이용 가능 시간") { - val token = authUtil.defaultStoreAdminLogin() + val token = authUtil.defaultHqAdminLogin() runTest( token = token, using = { @@ -234,7 +249,7 @@ class ThemeApiTest( } test("field: minParticipants") { - val token = authUtil.defaultStoreAdminLogin() + val token = authUtil.defaultHqAdminLogin() runTest( token = token, using = { @@ -248,7 +263,7 @@ class ThemeApiTest( } test("field: maxParticipants") { - val token = authUtil.defaultStoreAdminLogin() + val token = authUtil.defaultHqAdminLogin() runTest( token = token, using = { @@ -264,7 +279,7 @@ class ThemeApiTest( context("인원 범위가 잘못 지정되면 실패한다.") { test("최소 인원 > 최대 인원") { - val token = authUtil.defaultStoreAdminLogin() + val token = authUtil.defaultHqAdminLogin() runTest( token = token, using = { @@ -284,7 +299,7 @@ class ThemeApiTest( context("입력된 모든 ID에 대한 테마를 조회한다.") { test("정상 응답") { - val adminToken = authUtil.defaultStoreAdminLogin() + val adminToken = authUtil.defaultHqAdminLogin() val themeSize = 3 val themeIds = mutableListOf() @@ -309,7 +324,7 @@ class ThemeApiTest( } test("없는 테마가 있으면 생략한다.") { - val token = authUtil.defaultStoreAdminLogin() + val token = authUtil.defaultHqAdminLogin() val themeSize = 3 val themeIds = mutableListOf() @@ -359,11 +374,25 @@ class ThemeApiTest( expectedErrorCode = AuthErrorCode.ACCESS_DENIED ) } + + AdminPermissionLevel.entries.forEach { + test("관리자: Type=${AdminType.STORE} / Permission=${it}") { + val admin = AdminFixture.createStoreAdmin(permissionLevel = it) + + runExceptionTest( + token = authUtil.adminLogin(admin), + method = HttpMethod.POST, + requestBody = createRequest, + endpoint = endpoint, + expectedErrorCode = AuthErrorCode.ACCESS_DENIED + ) + } + } } test("비공개 테마까지 포함하여 간단한 정보만 조회된다.") { - val token = authUtil.defaultStoreAdminLogin() + val token = authUtil.defaultHqAdminLogin() requests.forEach { dummyInitializer.createTheme(token, it) } runTest( @@ -384,7 +413,7 @@ class ThemeApiTest( context("예약 페이지에서 테마를 조회한다.") { test("공개된 테마의 전체 정보가 조회된다.") { - val token = authUtil.defaultStoreAdminLogin() + val token = authUtil.defaultHqAdminLogin() listOf( createRequest.copy(name = "open", isOpen = true), createRequest.copy(name = "close", isOpen = false) @@ -434,20 +463,35 @@ class ThemeApiTest( ) } - test("권한이 ${AdminPermissionLevel.READ_SUMMARY}인 관리자") { - val admin = AdminFixture.create(permissionLevel = AdminPermissionLevel.READ_SUMMARY) + AdminPermissionLevel.entries.forEach { + test("관리자: Type=${AdminType.STORE} / Permission=${it}") { + val admin = AdminFixture.createStoreAdmin(permissionLevel = it) - runExceptionTest( - token = authUtil.adminLogin(admin), - method = HttpMethod.GET, - endpoint = endpoint, - expectedErrorCode = AuthErrorCode.ACCESS_DENIED - ) + runExceptionTest( + token = authUtil.adminLogin(admin), + method = HttpMethod.GET, + endpoint = endpoint, + expectedErrorCode = AuthErrorCode.ACCESS_DENIED + ) + } + + if (it == AdminPermissionLevel.READ_SUMMARY) { + test("관리자: Type=${AdminType.HQ} / Permission=${it}") { + val admin = AdminFixture.createHqAdmin(permissionLevel = it) + + runExceptionTest( + token = authUtil.adminLogin(admin), + method = HttpMethod.GET, + endpoint = endpoint, + expectedErrorCode = AuthErrorCode.ACCESS_DENIED + ) + } + } } } test("정상 응답") { - val token = authUtil.defaultStoreAdminLogin() + val token = authUtil.defaultHqAdminLogin() val createdTheme = dummyInitializer.createTheme( adminToken = token, request = createRequest @@ -475,7 +519,7 @@ class ThemeApiTest( test("테마가 없으면 실패한다.") { runExceptionTest( - token = authUtil.defaultStoreAdminLogin(), + token = authUtil.defaultHqAdminLogin(), method = HttpMethod.GET, endpoint = "/admin/themes/$INVALID_PK", expectedErrorCode = ThemeErrorCode.THEME_NOT_FOUND @@ -505,9 +549,9 @@ class ThemeApiTest( ) } - listOf(AdminPermissionLevel.READ_SUMMARY, AdminPermissionLevel.READ_ALL).forEach { - test("권한이 ${it}인 관리자") { - val admin = AdminFixture.create(permissionLevel = it) + AdminPermissionLevel.entries.forEach { + test("관리자: Type=${AdminType.STORE} / Permission=${it}") { + val admin = AdminFixture.createStoreAdmin(permissionLevel = it) runExceptionTest( token = authUtil.adminLogin(admin), @@ -516,11 +560,24 @@ class ThemeApiTest( expectedErrorCode = AuthErrorCode.ACCESS_DENIED ) } + + if (it == AdminPermissionLevel.READ_ALL || it == AdminPermissionLevel.READ_SUMMARY) { + test("관리자: Type=${AdminType.HQ} / Permission=${it}") { + val admin = AdminFixture.createHqAdmin(permissionLevel = it) + + runExceptionTest( + token = authUtil.adminLogin(admin), + method = HttpMethod.DELETE, + endpoint = endpoint, + expectedErrorCode = AuthErrorCode.ACCESS_DENIED + ) + } + } } } test("정상 삭제") { - val token = authUtil.defaultStoreAdminLogin() + val token = authUtil.defaultHqAdminLogin() val createdTheme = dummyInitializer.createTheme( adminToken = token, request = createRequest @@ -541,7 +598,7 @@ class ThemeApiTest( test("테마가 없으면 실패한다.") { runExceptionTest( - token = authUtil.defaultStoreAdminLogin(), + token = authUtil.defaultHqAdminLogin(), method = HttpMethod.DELETE, endpoint = "/admin/themes/$INVALID_PK", expectedErrorCode = ThemeErrorCode.THEME_NOT_FOUND @@ -573,9 +630,9 @@ class ThemeApiTest( ) } - listOf(AdminPermissionLevel.READ_SUMMARY, AdminPermissionLevel.READ_ALL).forEach { - test("권한이 ${it}인 관리자") { - val admin = AdminFixture.create(permissionLevel = it) + AdminPermissionLevel.entries.forEach { + test("관리자: Type=${AdminType.STORE} / Permission=${it}") { + val admin = AdminFixture.createStoreAdmin(permissionLevel = it) runExceptionTest( token = authUtil.adminLogin(admin), @@ -585,6 +642,20 @@ class ThemeApiTest( expectedErrorCode = AuthErrorCode.ACCESS_DENIED ) } + + if (it == AdminPermissionLevel.READ_ALL || it == AdminPermissionLevel.READ_SUMMARY) { + test("관리자: Type=${AdminType.HQ} / Permission=${it}") { + val admin = AdminFixture.createHqAdmin(permissionLevel = it) + + runExceptionTest( + token = authUtil.adminLogin(admin), + method = HttpMethod.PATCH, + endpoint = endpoint, + requestBody = request, + expectedErrorCode = AuthErrorCode.ACCESS_DENIED + ) + } + } } } @@ -592,11 +663,11 @@ class ThemeApiTest( test("정상 수정 및 감사 정보 변경 확인") { val createdTheme: ThemeEntity = dummyInitializer.createTheme( - adminToken = authUtil.defaultStoreAdminLogin(), + adminToken = authUtil.defaultHqAdminLogin(), request = createRequest.copy(name = "theme-${Random.nextInt()}") ) val otherAdminToken: String = authUtil.adminLogin( - AdminFixture.create(account = "hello", phone = "0101828402") + AdminFixture.createHqAdmin(permissionLevel = AdminPermissionLevel.WRITABLE) ) runTest( @@ -622,12 +693,12 @@ class ThemeApiTest( test("입력값이 없으면 수정하지 않는다.") { val createdTheme: ThemeEntity = dummyInitializer.createTheme( - adminToken = authUtil.defaultStoreAdminLogin(), + adminToken = authUtil.defaultHqAdminLogin(), request = createRequest.copy(name = "theme-${Random.nextInt()}") ) runTest( - token = authUtil.defaultStoreAdminLogin(), + token = authUtil.defaultHqAdminLogin(), using = { body(ThemeUpdateRequest()) }, @@ -647,7 +718,7 @@ class ThemeApiTest( test("테마가 없으면 실패한다.") { runExceptionTest( - token = authUtil.defaultStoreAdminLogin(), + token = authUtil.defaultHqAdminLogin(), method = HttpMethod.PATCH, endpoint = "/admin/themes/$INVALID_PK", requestBody = updateRequest, @@ -656,7 +727,7 @@ class ThemeApiTest( } test("금액이 ${MIN_PRICE}원 미만이면 실패한다.") { - val adminToken = authUtil.defaultStoreAdminLogin() + val adminToken = authUtil.defaultHqAdminLogin() val createdTheme: ThemeEntity = dummyInitializer.createTheme( adminToken = adminToken, request = createRequest.copy(name = "theme-${Random.nextInt()}") @@ -676,7 +747,7 @@ class ThemeApiTest( lateinit var createdTheme: ThemeEntity beforeTest { - adminToken = authUtil.defaultStoreAdminLogin() + adminToken = authUtil.defaultHqAdminLogin() createdTheme = dummyInitializer.createTheme( adminToken = adminToken, request = createRequest.copy(name = "theme-${Random.nextInt()}") @@ -719,7 +790,7 @@ class ThemeApiTest( lateinit var createdTheme: ThemeEntity beforeTest { - adminToken = authUtil.defaultStoreAdminLogin() + adminToken = authUtil.defaultHqAdminLogin() createdTheme = dummyInitializer.createTheme( adminToken = adminToken, request = createRequest.copy(name = "theme-${Random.nextInt()}") @@ -760,7 +831,7 @@ class ThemeApiTest( lateinit var createdTheme: ThemeEntity beforeTest { - adminToken = authUtil.defaultStoreAdminLogin() + adminToken = authUtil.defaultHqAdminLogin() createdTheme = dummyInitializer.createTheme( adminToken = adminToken, request = createRequest.copy(name = "theme-${Random.nextInt()}") @@ -793,7 +864,7 @@ class ThemeApiTest( lateinit var createdTheme: ThemeEntity beforeTest { - adminToken = authUtil.defaultStoreAdminLogin() + adminToken = authUtil.defaultHqAdminLogin() createdTheme = dummyInitializer.createTheme( adminToken = adminToken, request = createRequest.copy(name = "theme-${Random.nextInt()}")