diff --git a/build.gradle b/build.gradle index df079f48..07085eed 100644 --- a/build.gradle +++ b/build.gradle @@ -426,7 +426,7 @@ dependencies { testImplementation("io.insert-koin:koin-test:$koin_version") testImplementation "io.insert-koin:koin-test-junit5:$koin_version" testImplementation("org.junit.jupiter:junit-jupiter-api:$junit_version") - testImplementation('io.mockk:mockk:1.13.4') + testImplementation('io.mockk:mockk:1.13.10') testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$junit_version") testImplementation 'org.testcontainers:junit-jupiter:1.19.7' diff --git a/src/test/kotlin/com/hypto/iam/server/apis/ActionApiTest.kt b/src/test/kotlin/com/hypto/iam/server/apis/ActionApiTest.kt index 68798315..112e75df 100644 --- a/src/test/kotlin/com/hypto/iam/server/apis/ActionApiTest.kt +++ b/src/test/kotlin/com/hypto/iam/server/apis/ActionApiTest.kt @@ -1,8 +1,7 @@ package com.hypto.iam.server.apis -import com.google.gson.Gson import com.hypto.iam.server.Constants -import com.hypto.iam.server.helpers.AbstractContainerBaseTest +import com.hypto.iam.server.helpers.BaseSingleAppTest import com.hypto.iam.server.helpers.DataSetupHelper.deleteOrganization import com.hypto.iam.server.helpers.DataSetupHelperV3.createAction import com.hypto.iam.server.helpers.DataSetupHelperV3.createOrganization @@ -23,39 +22,11 @@ import io.ktor.http.ContentType import io.ktor.http.HttpHeaders import io.ktor.http.HttpStatusCode import io.ktor.http.contentType -import io.ktor.server.config.ApplicationConfig -import io.ktor.server.testing.TestApplication import io.ktor.test.dispatcher.testSuspend -import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.Test -import org.koin.test.inject - -class ActionApiTest : AbstractContainerBaseTest() { - private val gson: Gson by inject() - - companion object { - lateinit var testApp: TestApplication - - @JvmStatic - @BeforeAll - fun setupTest() { - testApp = - TestApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - } - } - - @JvmStatic - @AfterAll - fun teardownTest() { - testApp.stop() - } - } +class ActionApiTest : BaseSingleAppTest() { @Test fun `create action success case1`() { testSuspend { diff --git a/src/test/kotlin/com/hypto/iam/server/apis/CredentialApiKtTest.kt b/src/test/kotlin/com/hypto/iam/server/apis/CredentialApiKtTest.kt index ba0e9663..779a3fb1 100644 --- a/src/test/kotlin/com/hypto/iam/server/apis/CredentialApiKtTest.kt +++ b/src/test/kotlin/com/hypto/iam/server/apis/CredentialApiKtTest.kt @@ -1,11 +1,10 @@ package com.hypto.iam.server.apis -import com.google.gson.Gson import com.hypto.iam.server.Constants -import com.hypto.iam.server.helpers.AbstractContainerBaseTest -import com.hypto.iam.server.helpers.DataSetupHelperV2.createCredential -import com.hypto.iam.server.helpers.DataSetupHelperV2.createOrganization -import com.hypto.iam.server.helpers.DataSetupHelperV2.deleteOrganization +import com.hypto.iam.server.helpers.BaseSingleAppTest +import com.hypto.iam.server.helpers.DataSetupHelper.deleteOrganization +import com.hypto.iam.server.helpers.DataSetupHelperV3.createCredential +import com.hypto.iam.server.helpers.DataSetupHelperV3.createOrganization import com.hypto.iam.server.models.CreateCredentialRequest import com.hypto.iam.server.models.Credential import com.hypto.iam.server.models.ListCredentialResponse @@ -19,14 +18,12 @@ import io.ktor.http.ContentType.Application.Json import io.ktor.http.HttpHeaders import io.ktor.http.HttpStatusCode import io.ktor.http.contentType -import io.ktor.server.config.ApplicationConfig -import io.ktor.server.testing.testApplication +import io.ktor.test.dispatcher.testSuspend import io.mockk.coEvery import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test -import org.koin.test.inject import software.amazon.awssdk.services.cognitoidentityprovider.model.AdminGetUserRequest import software.amazon.awssdk.services.cognitoidentityprovider.model.UserNotFoundException import java.time.LocalDateTime @@ -34,19 +31,14 @@ import java.time.format.DateTimeFormatter import java.time.temporal.ChronoUnit import java.util.UUID -internal class CredentialApiKtTest : AbstractContainerBaseTest() { - private val gson: Gson by inject() - +internal class CredentialApiKtTest : BaseSingleAppTest() { @Nested @DisplayName("Create credential API tests") inner class CreateCredentialTest { @Test fun `without expiry - success`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (createdOrganizationResponse, createdUser) = createOrganization() + testSuspend { + val (createdOrganizationResponse, createdUser) = testApp.createOrganization() val createdOrganization = createdOrganizationResponse.organization val rootUserToken = createdOrganizationResponse.rootUserToken @@ -55,7 +47,7 @@ internal class CredentialApiKtTest : AbstractContainerBaseTest() { // Actual test val requestBody = CreateCredentialRequest() val response = - client.post( + testApp.client.post( "/organizations/${createdOrganization.id}/users/$userName/credentials", ) { header(HttpHeaders.ContentType, Json.toString()) @@ -80,11 +72,8 @@ internal class CredentialApiKtTest : AbstractContainerBaseTest() { @Test fun `with expiry - success`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (createdOrganizationResponse, createdUser) = createOrganization() + testSuspend { + val (createdOrganizationResponse, createdUser) = testApp.createOrganization() val createdOrganization = createdOrganizationResponse.organization val rootUserToken = createdOrganizationResponse.rootUserToken val userName = createdOrganizationResponse.organization.rootUser.username @@ -94,7 +83,7 @@ internal class CredentialApiKtTest : AbstractContainerBaseTest() { val requestBody = CreateCredentialRequest(expiry.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)) val response = - client.post( + testApp.client.post( "/organizations/${createdOrganization.id}/users/$userName/credentials", ) { header(HttpHeaders.ContentType, Json.toString()) @@ -122,11 +111,8 @@ internal class CredentialApiKtTest : AbstractContainerBaseTest() { @Test fun `expiry date in past - failure`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (createdOrganizationResponse, createdUser) = createOrganization() + testSuspend { + val (createdOrganizationResponse, createdUser) = testApp.createOrganization() val createdOrganization = createdOrganizationResponse.organization val rootUserToken = createdOrganizationResponse.rootUserToken val userName = createdOrganizationResponse.organization.rootUser.username @@ -136,7 +122,7 @@ internal class CredentialApiKtTest : AbstractContainerBaseTest() { val requestBody = CreateCredentialRequest(now.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)) val response = - client.post( + testApp.client.post( "/organizations/${createdOrganization.id}/users/$userName/credentials", ) { header(HttpHeaders.ContentType, Json.toString()) @@ -165,18 +151,15 @@ internal class CredentialApiKtTest : AbstractContainerBaseTest() { ) } throws UserNotFoundException.builder().message("User does not exist.").build() - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (createdOrganizationResponse, _) = createOrganization() + testSuspend { + val (createdOrganizationResponse, _) = testApp.createOrganization() val createdOrganization = createdOrganizationResponse.organization val rootUserToken = createdOrganizationResponse.rootUserToken val expiry = LocalDateTime.now().plusDays(1) val requestBody = CreateCredentialRequest(expiry.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)) val response = - client.post( + testApp.client.post( "/organizations/${createdOrganization.id}/users/$invalidUserName/credentials", ) { header(HttpHeaders.ContentType, Json.toString()) @@ -198,17 +181,14 @@ internal class CredentialApiKtTest : AbstractContainerBaseTest() { inner class DeleteCredentialTest { @Test fun `delete existing credential`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (createdOrganizationResponse, createdUser) = createOrganization() + testSuspend { + val (createdOrganizationResponse, createdUser) = testApp.createOrganization() val createdOrganization = createdOrganizationResponse.organization val rootUserToken = createdOrganizationResponse.rootUserToken val userName = createdOrganizationResponse.organization.rootUser.username val createCredentialCall = - client.post( + testApp.client.post( "/organizations/${createdOrganization.id}/users/$userName/credentials", ) { header(HttpHeaders.ContentType, Json.toString()) @@ -221,7 +201,7 @@ internal class CredentialApiKtTest : AbstractContainerBaseTest() { // Delete Credential var response = - client.delete( + testApp.client.delete( "/organizations/${createdOrganization.id}/users/" + "$userName/credentials/${credentialsToDelete.id}", ) { @@ -233,7 +213,7 @@ internal class CredentialApiKtTest : AbstractContainerBaseTest() { // Validate that credential has been deleted response = - client.get( + testApp.client.get( "/organizations/${createdOrganization.id}/users/" + "$userName/credentials/${credentialsToDelete.id}", ) { @@ -244,7 +224,7 @@ internal class CredentialApiKtTest : AbstractContainerBaseTest() { // Validate that using deleted credentials returns 401 response = - client.get( + testApp.client.get( "/organizations/${createdOrganization.id}/users/" + "$userName/credentials/${credentialsToDelete.id}", ) { @@ -259,11 +239,8 @@ internal class CredentialApiKtTest : AbstractContainerBaseTest() { @Test fun `credential not found`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (createdOrganizationResponse, createdUser) = createOrganization() + testSuspend { + val (createdOrganizationResponse, createdUser) = testApp.createOrganization() val createdOrganization = createdOrganizationResponse.organization val rootUserToken = createdOrganizationResponse.rootUserToken val userName = createdOrganizationResponse.organization.rootUser.username @@ -272,7 +249,7 @@ internal class CredentialApiKtTest : AbstractContainerBaseTest() { // Delete Credential val response = - client.delete( + testApp.client.delete( "/organizations/${createdOrganization.id}/users/$userName/credentials/$nonExistentCredentialId", ) { header(HttpHeaders.ContentType, Json.toString()) @@ -287,23 +264,20 @@ internal class CredentialApiKtTest : AbstractContainerBaseTest() { @Test fun `unauthorized access`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (organizationResponse1, user1) = createOrganization() - val (organizationResponse2, _) = createOrganization() + testSuspend { + val (organizationResponse1, user1) = testApp.createOrganization() + val (organizationResponse2, _) = testApp.createOrganization() val user1Name = organizationResponse1.organization.rootUser.username val organization1 = organizationResponse1.organization val rootUserToken1 = organizationResponse1.rootUserToken - val credential1 = createCredential(organization1.id, user1Name, rootUserToken1) + val credential1 = testApp.createCredential(organization1.id, user1Name, rootUserToken1) val rootUserToken2 = organizationResponse2.rootUserToken // Delete Credential val response = - client.delete( + testApp.client.delete( "/organizations/${organization1.id}/users/$user1Name/credentials/${credential1.id}", ) { header(HttpHeaders.ContentType, Json.toString()) @@ -322,19 +296,16 @@ internal class CredentialApiKtTest : AbstractContainerBaseTest() { inner class GetCredentialTest { @Test fun `success - response does not have secret`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (createdOrganizationResponse, createdUser) = createOrganization() + testSuspend { + val (createdOrganizationResponse, createdUser) = testApp.createOrganization() val createdOrganization = createdOrganizationResponse.organization val rootUserToken = createdOrganizationResponse.rootUserToken val userName = createdOrganizationResponse.organization.rootUser.username - val createdCredentials = createCredential(createdOrganization.id, userName, rootUserToken) + val createdCredentials = testApp.createCredential(createdOrganization.id, userName, rootUserToken) val response = - client.get( + testApp.client.get( "/organizations/${createdOrganization.id}/users/$userName/credentials/${createdCredentials.id}", ) { header(HttpHeaders.ContentType, Json.toString()) @@ -354,18 +325,15 @@ internal class CredentialApiKtTest : AbstractContainerBaseTest() { @Test fun `not found`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (createdOrganizationResponse, createdUser) = createOrganization() + testSuspend { + val (createdOrganizationResponse, createdUser) = testApp.createOrganization() val createdOrganization = createdOrganizationResponse.organization val rootUserToken = createdOrganizationResponse.rootUserToken val userName = createdOrganizationResponse.organization.rootUser.username val nonExistentCredentialId = UUID.randomUUID().toString() val response = - client.get( + testApp.client.get( "/organizations/${createdOrganization.id}/users/$userName/credentials/$nonExistentCredentialId", ) { header(HttpHeaders.ContentType, Json.toString()) @@ -380,17 +348,14 @@ internal class CredentialApiKtTest : AbstractContainerBaseTest() { @Test fun `invalid credential id`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (createdOrganizationResponse, createdUser) = createOrganization() + testSuspend { + val (createdOrganizationResponse, createdUser) = testApp.createOrganization() val createdOrganization = createdOrganizationResponse.organization val rootUserToken = createdOrganizationResponse.rootUserToken val userName = createdOrganizationResponse.organization.rootUser.username val response = - client.get( + testApp.client.get( "/organizations/${createdOrganization.id}/users/$userName/credentials/inValid_credential_id", ) { header(HttpHeaders.ContentType, Json.toString()) @@ -408,22 +373,19 @@ internal class CredentialApiKtTest : AbstractContainerBaseTest() { inner class ListCredentialTest { @Test fun `list credentials of a user`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (createdOrganizationResponse, createdUser) = createOrganization() + testSuspend { + val (createdOrganizationResponse, createdUser) = testApp.createOrganization() val createdOrganization = createdOrganizationResponse.organization val rootUserToken = createdOrganizationResponse.rootUserToken val userName = createdOrganizationResponse.organization.rootUser.username val credential1 = - createCredential(createdOrganization.id, userName, rootUserToken) + testApp.createCredential(createdOrganization.id, userName, rootUserToken) val credential2 = - createCredential(createdOrganization.id, userName, rootUserToken) + testApp.createCredential(createdOrganization.id, userName, rootUserToken) val response = - client.get( + testApp.client.get( "/organizations/${createdOrganization.id}/users/$userName/credentials", ) { header(HttpHeaders.ContentType, Json.toString()) @@ -441,11 +403,8 @@ internal class CredentialApiKtTest : AbstractContainerBaseTest() { @Test fun `list credentials for unknown user`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (createdOrganizationResponse, _) = createOrganization() + testSuspend { + val (createdOrganizationResponse, _) = testApp.createOrganization() val createdOrganization = createdOrganizationResponse.organization val rootUserToken = createdOrganizationResponse.rootUserToken @@ -454,7 +413,7 @@ internal class CredentialApiKtTest : AbstractContainerBaseTest() { } throws UserNotFoundException.builder().message("User does not exist.").build() val response = - client.get( + testApp.client.get( "/organizations/${createdOrganization.id}/users/unknown_user/credentials", ) { header(HttpHeaders.ContentType, Json.toString()) @@ -467,17 +426,14 @@ internal class CredentialApiKtTest : AbstractContainerBaseTest() { @Test fun `return empty list for credentials list api`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (createdOrganizationResponse, createdUser) = createOrganization() + testSuspend { + val (createdOrganizationResponse, createdUser) = testApp.createOrganization() val createdOrganization = createdOrganizationResponse.organization val rootUserToken = createdOrganizationResponse.rootUserToken val userName = createdOrganizationResponse.organization.rootUser.username val response = - client.get( + testApp.client.get( "/organizations/${createdOrganization.id}/users/$userName/credentials", ) { header(HttpHeaders.ContentType, Json.toString()) diff --git a/src/test/kotlin/com/hypto/iam/server/apis/KeyApiTest.kt b/src/test/kotlin/com/hypto/iam/server/apis/KeyApiTest.kt index e49d62d4..21c8b5ba 100644 --- a/src/test/kotlin/com/hypto/iam/server/apis/KeyApiTest.kt +++ b/src/test/kotlin/com/hypto/iam/server/apis/KeyApiTest.kt @@ -1,8 +1,7 @@ package com.hypto.iam.server.apis -import com.google.gson.Gson -import com.hypto.iam.server.helpers.AbstractContainerBaseTest -import com.hypto.iam.server.helpers.DataSetupHelperV2.createOrganization +import com.hypto.iam.server.helpers.BaseSingleAppTest +import com.hypto.iam.server.helpers.DataSetupHelperV3.createOrganization import com.hypto.iam.server.models.KeyResponse import com.hypto.iam.server.models.TokenResponse import com.hypto.iam.server.service.TokenServiceImpl @@ -15,30 +14,23 @@ import io.ktor.http.ContentType.Application.Json import io.ktor.http.HttpHeaders import io.ktor.http.HttpStatusCode import io.ktor.http.contentType -import io.ktor.server.config.ApplicationConfig -import io.ktor.server.testing.testApplication +import io.ktor.test.dispatcher.testSuspend import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertDoesNotThrow -import org.koin.test.inject import java.security.KeyFactory import java.security.PublicKey import java.security.spec.X509EncodedKeySpec import java.util.Base64 -class KeyApiTest : AbstractContainerBaseTest() { - private val gson: Gson by inject() - +class KeyApiTest : BaseSingleAppTest() { @Test fun `validate token using public key`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (organizationResponse, _) = createOrganization() + testSuspend { + val (organizationResponse, _) = testApp.createOrganization() val createTokenCall = - client.post("/organizations/${organizationResponse.organization.id}/token") { + testApp.client.post("/organizations/${organizationResponse.organization.id}/token") { header(HttpHeaders.ContentType, Json.toString()) header(HttpHeaders.Authorization, "Bearer ${organizationResponse.rootUserToken}") } @@ -55,7 +47,7 @@ class KeyApiTest : AbstractContainerBaseTest() { val kid = jwt.header.getValue(TokenServiceImpl.KEY_ID) as String val response = - client.get( + testApp.client.get( "/keys/$kid?format=der", ) { header(HttpHeaders.Authorization, "Bearer ${organizationResponse.rootUserToken}") diff --git a/src/test/kotlin/com/hypto/iam/server/apis/OrganizationApiKtTest.kt b/src/test/kotlin/com/hypto/iam/server/apis/OrganizationApiKtTest.kt index 6d3ffe97..87ec69a6 100644 --- a/src/test/kotlin/com/hypto/iam/server/apis/OrganizationApiKtTest.kt +++ b/src/test/kotlin/com/hypto/iam/server/apis/OrganizationApiKtTest.kt @@ -1,6 +1,5 @@ package com.hypto.iam.server.apis -import com.google.gson.Gson import com.hypto.iam.server.Constants import com.hypto.iam.server.ROOT_ORG import com.hypto.iam.server.authProviders.GoogleAuthProvider @@ -9,8 +8,8 @@ import com.hypto.iam.server.db.repositories.OrganizationRepo import com.hypto.iam.server.db.repositories.PasscodeRepo import com.hypto.iam.server.db.tables.pojos.Organizations import com.hypto.iam.server.db.tables.records.PasscodesRecord -import com.hypto.iam.server.helpers.AbstractContainerBaseTest -import com.hypto.iam.server.helpers.DataSetupHelperV2.deleteOrganization +import com.hypto.iam.server.helpers.BaseSingleAppTest +import com.hypto.iam.server.helpers.DataSetupHelper.deleteOrganization import com.hypto.iam.server.models.CreateOrganizationRequest import com.hypto.iam.server.models.CreateOrganizationResponse import com.hypto.iam.server.models.Organization @@ -37,6 +36,7 @@ import io.ktor.http.HttpStatusCode import io.ktor.http.contentType import io.ktor.server.config.ApplicationConfig import io.ktor.server.testing.testApplication +import io.ktor.test.dispatcher.testSuspend import io.mockk.coEvery import io.mockk.mockkObject import org.junit.jupiter.api.Assertions @@ -51,16 +51,12 @@ import kotlin.test.assertFalse import kotlin.test.assertNull @Testcontainers -internal class OrganizationApiKtTest : AbstractContainerBaseTest() { - private val gson: Gson by inject() +internal class OrganizationApiKtTest : BaseSingleAppTest() { private val passcodeService: PasscodeService by inject() @Test fun `create organization with valid root credentials`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } + testSuspend { val orgName = "test-org" + IdGenerator.randomId() val preferredUsername = "user" + IdGenerator.randomId() val name = "test name" @@ -79,7 +75,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { ), ) val response = - client.post("/organizations") { + testApp.client.post("/organizations") { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) header("X-Api-Key", rootToken) setBody(gson.toJson(requestBody)) @@ -96,7 +92,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { // Assert root user creation val listUsersResponse = - client.get("/organizations/$orgId/users") { + testApp.client.get("/organizations/$orgId/users") { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) header(HttpHeaders.Authorization, "Bearer ${responseBody.rootUserToken}") } @@ -111,7 +107,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { // Assert policy creation val actResponse = - client.get( + testApp.client.get( "/organizations/$orgId/policies?pageSize=50", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -133,7 +129,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { // Assert policy association val userPoliciesResponse = - client.get( + testApp.client.get( "/organizations/$orgId/users/${responseBody.organization.rootUser.username}/policies", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -201,10 +197,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { @Test fun `create organization with verify email method`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } + testSuspend { val orgName = "test-org" + IdGenerator.randomId() val preferredUsername = "user" + IdGenerator.randomId() val name = "test name" @@ -219,7 +212,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { email = testEmail, purpose = VerifyEmailRequest.Purpose.signup, ) - client.post("/verifyEmail") { + testApp.client.post("/verifyEmail") { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) setBody(gson.toJson(verifyRequestBody)) } @@ -235,7 +228,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { ), ) val response = - client.post("/organizations") { + testApp.client.post("/organizations") { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) header("X-Api-Key", testPasscode) setBody(gson.toJson(requestBody)) @@ -323,10 +316,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { @Test fun `create organization using google authorization - success`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } + testSuspend { // Arrange val googleToken = "test-google-token" val name = "test-name" @@ -349,7 +339,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { // Act val response = - client.post("/organizations") { + testApp.client.post("/organizations") { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) header("x-issuer", "google") header(HttpHeaders.Authorization, "Bearer $googleToken") @@ -374,10 +364,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { @Test fun `create organization using microsoft authorization - fail`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } + testSuspend { // Arrange val microsoftToken = "test-microsoft-token" val name = "test-name" @@ -401,7 +388,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { // Act val response = - client.post("/organizations") { + testApp.client.post("/organizations") { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) header("x-issuer", "microsoft") header(HttpHeaders.Authorization, "Bearer $microsoftToken") @@ -421,10 +408,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { } } - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } + testSuspend { val orgName = "test-org" + IdGenerator.randomId() val preferredUsername = "user" + IdGenerator.randomId() val name = "test-name" + IdGenerator.randomId() @@ -444,7 +428,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { ), ) val response = - client.post("/organizations") { + testApp.client.post("/organizations") { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) header("X-Api-Key", rootToken) setBody(gson.toJson(requestBody)) @@ -455,10 +439,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { @Test fun `get organization with invalid credentials`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } + testSuspend { val orgName = "test-org" + IdGenerator.randomId() val preferredUsername = "user" + IdGenerator.randomId() val name = "test name" @@ -467,7 +448,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { val testPassword = "testPassword@Hash1" val createOrganizationCall = - client.post("/organizations") { + testApp.client.post("/organizations") { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) header("X-Api-Key", rootToken) setBody( @@ -489,7 +470,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { gson.fromJson(createOrganizationCall.bodyAsText(), CreateOrganizationResponse::class.java) val response = - client.get("/organizations/${createdOrganization.organization.id}") { + testApp.client.get("/organizations/${createdOrganization.organization.id}") { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) header(HttpHeaders.Authorization, "Bearer test-bearer-token") } @@ -503,10 +484,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { @Test fun `get organization success`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } + testSuspend { val orgName = "test-org" + IdGenerator.randomId() val preferredUsername = "user" + IdGenerator.randomId() val name = "test name" @@ -515,7 +493,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { val testPassword = "testPassword@Hash1" val createOrganizationCall = - client.post("/organizations") { + testApp.client.post("/organizations") { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) header("X-Api-Key", rootToken) setBody( @@ -537,7 +515,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { gson.fromJson(createOrganizationCall.bodyAsText(), CreateOrganizationResponse::class.java) val response = - client.get("/organizations/${createdOrganization.organization.id}") { + testApp.client.get("/organizations/${createdOrganization.organization.id}") { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) header(HttpHeaders.Authorization, "Bearer ${createdOrganization.rootUserToken}") } @@ -553,10 +531,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { @Test fun `get organization not found`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } + testSuspend { val orgName = "test-org" + IdGenerator.randomId() val preferredUsername = "user" + IdGenerator.randomId() val name = "test name" @@ -566,7 +541,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { // Create organization val createOrganizationCall = - client.post("/organizations") { + testApp.client.post("/organizations") { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) header("X-Api-Key", rootToken) setBody( @@ -588,7 +563,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { gson.fromJson(createOrganizationCall.bodyAsText(), CreateOrganizationResponse::class.java) val response = - client.get("/organizations/inValidOrganizationId") { + testApp.client.get("/organizations/inValidOrganizationId") { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) header( HttpHeaders.Authorization, @@ -603,10 +578,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { @Test fun `update organization name success`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } + testSuspend { val orgName = "test-org" + IdGenerator.randomId() val orgDescription = "test-org-description" val preferredUsername = "user" + IdGenerator.randomId() @@ -616,7 +588,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { val testPassword = "testPassword@Hash1" val createOrganizationCall = - client.post("/organizations") { + testApp.client.post("/organizations") { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) header("X-Api-Key", rootToken) setBody( @@ -640,7 +612,7 @@ internal class OrganizationApiKtTest : AbstractContainerBaseTest() { val updatedOrgName = "updated-org" + IdGenerator.randomId() val response = - client.patch("/organizations/${createdOrganization.organization.id}") { + testApp.client.patch("/organizations/${createdOrganization.organization.id}") { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) header(HttpHeaders.Authorization, "Bearer ${createdOrganization.rootUserToken}") setBody( diff --git a/src/test/kotlin/com/hypto/iam/server/apis/PasscodeApiTest.kt b/src/test/kotlin/com/hypto/iam/server/apis/PasscodeApiTest.kt index 5bcb03a6..43801c02 100644 --- a/src/test/kotlin/com/hypto/iam/server/apis/PasscodeApiTest.kt +++ b/src/test/kotlin/com/hypto/iam/server/apis/PasscodeApiTest.kt @@ -1,8 +1,7 @@ package com.hypto.iam.server.apis -import com.google.gson.Gson import com.hypto.iam.server.db.tables.records.PasscodesRecord -import com.hypto.iam.server.helpers.AbstractContainerBaseTest +import com.hypto.iam.server.helpers.BaseSingleAppTest import com.hypto.iam.server.helpers.DataSetupHelperV2.createOrganization import com.hypto.iam.server.helpers.DataSetupHelperV2.deleteOrganization import com.hypto.iam.server.idp.CognitoConstants @@ -24,7 +23,6 @@ import io.mockk.coEvery import io.mockk.mockk import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.koin.test.inject import software.amazon.awssdk.services.cognitoidentityprovider.model.AttributeType import software.amazon.awssdk.services.cognitoidentityprovider.model.ListUsersRequest import software.amazon.awssdk.services.cognitoidentityprovider.model.ListUsersResponse @@ -32,9 +30,7 @@ import software.amazon.awssdk.services.cognitoidentityprovider.model.UserType import java.time.Instant import java.time.LocalDateTime -internal class PasscodeApiTest : AbstractContainerBaseTest() { - private val gson: Gson by inject() - +internal class PasscodeApiTest : BaseSingleAppTest() { @Test fun `test verifyEmail api for signup purpose - success`() { testApplication { diff --git a/src/test/kotlin/com/hypto/iam/server/apis/PolicyApiTest.kt b/src/test/kotlin/com/hypto/iam/server/apis/PolicyApiTest.kt index 79866512..9207d1c4 100644 --- a/src/test/kotlin/com/hypto/iam/server/apis/PolicyApiTest.kt +++ b/src/test/kotlin/com/hypto/iam/server/apis/PolicyApiTest.kt @@ -1,15 +1,14 @@ package com.hypto.iam.server.apis -import com.google.gson.Gson import com.hypto.iam.server.Constants import com.hypto.iam.server.db.repositories.PolicyTemplatesRepo import com.hypto.iam.server.db.tables.records.PolicyTemplatesRecord -import com.hypto.iam.server.helpers.AbstractContainerBaseTest -import com.hypto.iam.server.helpers.DataSetupHelperV2.createAndAttachPolicy -import com.hypto.iam.server.helpers.DataSetupHelperV2.createOrganization -import com.hypto.iam.server.helpers.DataSetupHelperV2.createResourceActionHrn -import com.hypto.iam.server.helpers.DataSetupHelperV2.createUser -import com.hypto.iam.server.helpers.DataSetupHelperV2.deleteOrganization +import com.hypto.iam.server.helpers.BaseSingleAppTest +import com.hypto.iam.server.helpers.DataSetupHelper.deleteOrganization +import com.hypto.iam.server.helpers.DataSetupHelperV3.createAndAttachPolicy +import com.hypto.iam.server.helpers.DataSetupHelperV3.createOrganization +import com.hypto.iam.server.helpers.DataSetupHelperV3.createResourceActionHrn +import com.hypto.iam.server.helpers.DataSetupHelperV3.createUser import com.hypto.iam.server.models.CreatePolicyFromTemplateRequest import com.hypto.iam.server.models.CreatePolicyRequest import com.hypto.iam.server.models.CreateUserRequest @@ -34,8 +33,7 @@ import io.ktor.http.ContentType import io.ktor.http.HttpHeaders import io.ktor.http.HttpStatusCode import io.ktor.http.contentType -import io.ktor.server.config.ApplicationConfig -import io.ktor.server.testing.testApplication +import io.ktor.test.dispatcher.testSuspend import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Nested @@ -43,19 +41,14 @@ import org.junit.jupiter.api.Test import org.koin.test.inject import java.time.LocalDateTime -class PolicyApiTest : AbstractContainerBaseTest() { - private val gson: Gson by inject() - +internal class PolicyApiTest : BaseSingleAppTest() { @Nested @DisplayName("Create policy API tests") inner class CreatePolicyTest { @Test fun `valid policy - success`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (createdOrganizationResponse, _) = createOrganization() + testSuspend { + val (createdOrganizationResponse, _) = testApp.createOrganization() val createdOrganization = createdOrganizationResponse.organization val rootUserToken = createdOrganizationResponse.rootUserToken @@ -64,7 +57,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { val resourceName = "resource" val (resourceHrn, actionHrn) = - createResourceActionHrn( + testApp.createResourceActionHrn( createdOrganization.id, null, resourceName, @@ -74,7 +67,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { val requestBody = CreatePolicyRequest(policyName, policyStatements) val response = - client.post( + testApp.client.post( "/organizations/${createdOrganization.id}/policies", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -113,18 +106,15 @@ class PolicyApiTest : AbstractContainerBaseTest() { @Test fun `policy name already in use`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } + testSuspend { // Arrange - val (createOrganizationResponse, _) = createOrganization() + val (createOrganizationResponse, _) = testApp.createOrganization() val createdOrganization = createOrganizationResponse.organization val policyName = "samplePolicy" val resourceName = "resource" val (resourceHrn, actionHrn) = - createResourceActionHrn( + testApp.createResourceActionHrn( createdOrganization.id, null, resourceName, @@ -133,7 +123,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { val policyStatements = listOf(PolicyStatement(resourceHrn, actionHrn, PolicyStatement.Effect.allow)) val requestBody = CreatePolicyRequest(policyName, policyStatements) - client.post( + testApp.client.post( "/organizations/${createOrganizationResponse.organization.id}/policies", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -146,7 +136,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { // Act val response = - client.post( + testApp.client.post( "/organizations/${createOrganizationResponse.organization.id}/policies", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -167,17 +157,14 @@ class PolicyApiTest : AbstractContainerBaseTest() { @Test fun `policy without statements - failure`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (createOrganizationResponse, _) = createOrganization() + testSuspend { + val (createOrganizationResponse, _) = testApp.createOrganization() val policyName = "SamplePolicy" val requestBody = CreatePolicyRequest(policyName, listOf()) val response = - client.post( + testApp.client.post( "/organizations/${createOrganizationResponse.organization.id}/policies", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -197,11 +184,8 @@ class PolicyApiTest : AbstractContainerBaseTest() { @Test fun `policy with too many policy statements - failure`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (createOrganizationResponse, _) = createOrganization() + testSuspend { + val (createOrganizationResponse, _) = testApp.createOrganization() val policyName = "SamplePolicy" // val policyStatements = mutableListOf() @@ -215,7 +199,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { ) val response = - client.post( + testApp.client.post( "/organizations/${createOrganizationResponse.organization.id}/policies", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -235,11 +219,8 @@ class PolicyApiTest : AbstractContainerBaseTest() { @Test fun `create policy with different org in principal - failure`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (createdOrganizationResponse, _) = createOrganization() + testSuspend { + val (createdOrganizationResponse, _) = testApp.createOrganization() val createdOrganization = createdOrganizationResponse.organization val rootUserToken = createdOrganizationResponse.rootUserToken @@ -248,7 +229,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { val resourceName = "resource" val (resourceHrn, actionHrn) = - createResourceActionHrn( + testApp.createResourceActionHrn( "randomId", null, resourceName, @@ -258,7 +239,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { val requestBody = CreatePolicyRequest(policyName, policyStatements) val response = - client.post( + testApp.client.post( "/organizations/${createdOrganization.id}/policies", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -277,12 +258,8 @@ class PolicyApiTest : AbstractContainerBaseTest() { @Test fun `create policy from template - success`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - - val (createdOrganizationResponse, _) = createOrganization() + testSuspend { + val (createdOrganizationResponse, _) = testApp.createOrganization() val createdOrganization = createdOrganizationResponse.organization val rootUserToken = createdOrganizationResponse.rootUserToken @@ -292,7 +269,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { val resourceName = "resource" val (resourceHrn, actionHrn) = - createResourceActionHrn( + testApp.createResourceActionHrn( createdOrganization.id, null, resourceName, @@ -322,7 +299,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { val requestBody = CreatePolicyFromTemplateRequest(policyName, policyTemplateName) val response = - client.post( + testApp.client.post( "/organizations/${createdOrganization.id}/policy_from_template", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -367,18 +344,15 @@ class PolicyApiTest : AbstractContainerBaseTest() { inner class GetPolicyTest { @Test fun `existing policy - success`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } + testSuspend { // Arrange - val (createOrganizationResponse, _) = createOrganization() + val (createOrganizationResponse, _) = testApp.createOrganization() val createdOrganization = createOrganizationResponse.organization val policyName = "samplePolicy" val resourceName = "resource" val (resourceHrn, actionHrn) = - createResourceActionHrn( + testApp.createResourceActionHrn( createdOrganization.id, null, resourceName, @@ -388,7 +362,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { val requestBody = CreatePolicyRequest(policyName, policyStatements) val createPolicyCall = - client.post( + testApp.client.post( "/organizations/${createOrganizationResponse.organization.id}/policies", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -403,7 +377,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { // Act val response = - client.get( + testApp.client.get( "/organizations/${createOrganizationResponse.organization.id}/policies/${createdPolicy.name}", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -439,16 +413,13 @@ class PolicyApiTest : AbstractContainerBaseTest() { @Test fun `non existing policy`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } + testSuspend { // Arrange - val (createOrganizationResponse, _) = createOrganization() + val (createOrganizationResponse, _) = testApp.createOrganization() // Act val response = - client.get( + testApp.client.get( "/organizations/${createOrganizationResponse.organization.id}/policies/non_existing_policy", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -472,17 +443,14 @@ class PolicyApiTest : AbstractContainerBaseTest() { inner class ListPoliciesTest { @Test fun `existing policy - first page, more pages available`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } + testSuspend { // Arrange - val (createOrganizationResponse, _) = createOrganization() + val (createOrganizationResponse, _) = testApp.createOrganization() val createdOrganization = createOrganizationResponse.organization val resourceName = "resource" val (resourceHrn, actionHrn) = - createResourceActionHrn( + testApp.createResourceActionHrn( createdOrganization.id, null, resourceName, @@ -493,7 +461,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { // We create 2 policies in addition to 1 ADMIN_ROOT_POLICY. // So, list API must return 3 policies in total. (1..2).forEach { - client.post( + testApp.client.post( "/organizations/${createOrganizationResponse.organization.id}/policies", ) { val requestBody = CreatePolicyRequest("SamplePolicy$it", policyStatements) @@ -508,7 +476,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { // Act val actResponse = - client.get( + testApp.client.get( "/organizations/${createOrganizationResponse.organization.id}/policies?pageSize=2", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -533,7 +501,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { // Assert - Last page val lastPageResponse = - client.get( + testApp.client.get( "/organizations/${createOrganizationResponse.organization.id}/policies?" + "pageSize=3&nextToken=${responseBody.nextToken}", ) { @@ -563,7 +531,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { // Assert - Empty page val emptyPageResponse = - client.get( + testApp.client.get( "/organizations/${createOrganizationResponse.organization.id}/policies?" + "pageSize=2&nextToken=${responseBody2.nextToken}", ) { @@ -594,16 +562,13 @@ class PolicyApiTest : AbstractContainerBaseTest() { @Test fun `no policies available (Just root policy)`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } + testSuspend { // Arrange - val (createOrganizationResponse, _) = createOrganization() + val (createOrganizationResponse, _) = testApp.createOrganization() // Act val actResponse = - client.get( + testApp.client.get( "/organizations/${createOrganizationResponse.organization.id}/policies?pageSize=2", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -628,7 +593,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { // Assert - Empty page val emptyPageResponse = - client.get( + testApp.client.get( "/organizations/${createOrganizationResponse.organization.id}/policies?" + "pageSize=2&nextToken=${responseBody.nextToken}", ) { @@ -663,12 +628,9 @@ class PolicyApiTest : AbstractContainerBaseTest() { inner class UpdatePoliciesTest { @Test fun `update policy`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } + testSuspend { // Arrange - val (createdOrganizationResponse, _) = createOrganization() + val (createdOrganizationResponse, _) = testApp.createOrganization() // Create a policy val createdOrganization = createdOrganizationResponse.organization @@ -676,7 +638,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { val policyName = "samplePolicy" val resourceName = "resource" val (resourceHrn, actionHrn) = - createResourceActionHrn( + testApp.createResourceActionHrn( createdOrganization.id, null, resourceName, @@ -684,7 +646,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { ) val actResponse = - client.post( + testApp.client.post( "/organizations/${createdOrganization.id}/policies", ) { val policyStatements = @@ -713,7 +675,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { ), ) val updatedCreatedPolicyResponse = - client.patch( + testApp.client.patch( "/organizations/${createdOrganization.id}/policies/$policyName", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -739,12 +701,9 @@ class PolicyApiTest : AbstractContainerBaseTest() { @Test fun `update non-existent policy`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } + testSuspend { // Arrange - val (createdOrganizationResponse, _) = createOrganization() + val (createdOrganizationResponse, _) = testApp.createOrganization() // Act @@ -752,7 +711,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { val createdOrganization = createdOrganizationResponse.organization val resourceName = "resource" val (resourceHrn, actionHrn) = - createResourceActionHrn( + testApp.createResourceActionHrn( createdOrganization.id, null, resourceName, @@ -767,7 +726,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { ), ) val response = - client.patch( + testApp.client.patch( "/organizations/${createdOrganization.id}/policies/non_existent_policy", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -793,19 +752,16 @@ class PolicyApiTest : AbstractContainerBaseTest() { inner class DeletePolicyTest { @Test fun `delete existing policy`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } + testSuspend { // Arrange - val (createOrganizationResponse, _) = createOrganization() + val (createOrganizationResponse, _) = testApp.createOrganization() val createdOrganization = createOrganizationResponse.organization val policyName = "samplePolicy" val resourceName = "resource" val (resourceHrn, actionHrn) = - createResourceActionHrn( + testApp.createResourceActionHrn( createdOrganization.id, null, resourceName, @@ -816,7 +772,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { val requestBody = CreatePolicyRequest(policyName, policyStatements) val createPolicyCall = - client.post( + testApp.client.post( "/organizations/${createOrganizationResponse.organization.id}/policies", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -831,7 +787,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { // Act val response = - client.delete( + testApp.client.delete( "/organizations/${createOrganizationResponse.organization.id}/policies/${createdPolicy.name}", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -851,16 +807,13 @@ class PolicyApiTest : AbstractContainerBaseTest() { @Test fun `delete non existent policy`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } + testSuspend { // Arrange - val (createOrganizationResponse, _) = createOrganization() + val (createOrganizationResponse, _) = testApp.createOrganization() // Act val response = - client.delete( + testApp.client.delete( "/organizations/${createOrganizationResponse.organization.id}/policies/non_existent+policy", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -884,23 +837,20 @@ class PolicyApiTest : AbstractContainerBaseTest() { inner class GetPoliciesByUserTest { @Test fun `get policies of a user`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } + testSuspend { // Arrange - val (createdOrganizationResponse, createdUser) = createOrganization() + val (createdOrganizationResponse, createdUser) = testApp.createOrganization() val createdOrganization = createdOrganizationResponse.organization val username = createdOrganizationResponse.organization.rootUser.username (1..2).forEach { val response = - client.post( + testApp.client.post( "/organizations/${createdOrganization.id}/policies", ) { val resourceName = "resource" val (resourceHrn, actionHrn) = - createResourceActionHrn( + testApp.createResourceActionHrn( createdOrganization.id, null, resourceName, @@ -922,7 +872,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { // Associate policy to a user val associatedResponse = - client.patch( + testApp.client.patch( "/organizations/${createdOrganization.id}/users/" + "${createdOrganizationResponse.organization.rootUser.username}/attach_policies", ) { @@ -943,7 +893,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { // First page val firstResponse = - client.get( + testApp.client.get( "/organizations/${createdOrganization.id}/users/$username" + "/policies?pageSize=$pageSize", ) { @@ -968,7 +918,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { // Second and last page with results val secondAndLastResponse = - client.get( + testApp.client.get( "/organizations/${createdOrganization.id}/users/$username" + "/policies?pageSize=$pageSize${nextToken?.let { "&nextToken=$it" }}", ) { @@ -997,7 +947,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { // Empty page val emptyPageResponse = - client.get( + testApp.client.get( "/organizations/${createdOrganization.id}/users/$username" + "/policies?pageSize=$pageSize${nextToken?.let { "&nextToken=$it" }}", ) { @@ -1028,11 +978,8 @@ class PolicyApiTest : AbstractContainerBaseTest() { @Test fun `user to list policies of other user without permission - failure`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (organizationResponse, _) = createOrganization() + testSuspend { + val (organizationResponse, _) = testApp.createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken @@ -1049,7 +996,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { ) val (user1, _) = - createUser( + testApp.createUser( organization.id, rootUserToken, createUser1Request, @@ -1067,12 +1014,12 @@ class PolicyApiTest : AbstractContainerBaseTest() { loginAccess = true, ) val (user2, credential) = - createUser( + testApp.createUser( organization.id, rootUserToken, createUser2Request, ) - createAndAttachPolicy( + testApp.createAndAttachPolicy( orgId = organization.id, username = user2.username, bearerToken = rootUserToken, @@ -1083,7 +1030,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { resourceInstance = user2.username, ) val response = - client.get( + testApp.client.get( "/organizations/${organization.id}/users/${user1.username}/policies", ) { header(HttpHeaders.Authorization, "Bearer ${credential.secret}") @@ -1096,11 +1043,8 @@ class PolicyApiTest : AbstractContainerBaseTest() { @Test fun `user to list policy of a user with permission - success`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (organizationResponse, _) = createOrganization() + testSuspend { + val (organizationResponse, _) = testApp.createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken @@ -1117,7 +1061,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { ) val (user1, _) = - createUser( + testApp.createUser( organization.id, rootUserToken, createUser1Request, @@ -1134,12 +1078,12 @@ class PolicyApiTest : AbstractContainerBaseTest() { loginAccess = true, ) val (user2, credential) = - createUser( + testApp.createUser( organization.id, rootUserToken, createUser2Request, ) - createAndAttachPolicy( + testApp.createAndAttachPolicy( orgId = organization.id, username = user2.username, bearerToken = rootUserToken, @@ -1150,7 +1094,7 @@ class PolicyApiTest : AbstractContainerBaseTest() { resourceInstance = user1.username, ) val response = - client.get( + testApp.client.get( "/organizations/${organization.id}/users/${user1.username}/policies", ) { header(HttpHeaders.Authorization, "Bearer ${credential.secret}") diff --git a/src/test/kotlin/com/hypto/iam/server/apis/ResourceApiTest.kt b/src/test/kotlin/com/hypto/iam/server/apis/ResourceApiTest.kt index 3be15e6a..3a7ab227 100644 --- a/src/test/kotlin/com/hypto/iam/server/apis/ResourceApiTest.kt +++ b/src/test/kotlin/com/hypto/iam/server/apis/ResourceApiTest.kt @@ -1,10 +1,9 @@ package com.hypto.iam.server.apis -import com.google.gson.Gson -import com.hypto.iam.server.helpers.AbstractContainerBaseTest -import com.hypto.iam.server.helpers.DataSetupHelperV2.createOrganization -import com.hypto.iam.server.helpers.DataSetupHelperV2.createResource -import com.hypto.iam.server.helpers.DataSetupHelperV2.deleteOrganization +import com.hypto.iam.server.helpers.BaseSingleAppTest +import com.hypto.iam.server.helpers.DataSetupHelper.deleteOrganization +import com.hypto.iam.server.helpers.DataSetupHelperV3.createOrganization +import com.hypto.iam.server.helpers.DataSetupHelperV3.createResource import com.hypto.iam.server.models.BaseSuccessResponse import com.hypto.iam.server.models.CreateResourceRequest import com.hypto.iam.server.models.Resource @@ -21,31 +20,24 @@ import io.ktor.http.ContentType import io.ktor.http.HttpHeaders import io.ktor.http.HttpStatusCode import io.ktor.http.contentType -import io.ktor.server.config.ApplicationConfig -import io.ktor.server.testing.testApplication +import io.ktor.test.dispatcher.testSuspend import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.koin.test.inject import org.testcontainers.junit.jupiter.Testcontainers @Testcontainers -internal class ResourceApiTest : AbstractContainerBaseTest() { - private val gson: Gson by inject() - +internal class ResourceApiTest : BaseSingleAppTest() { @Test fun `create resource success case`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (organizationResponse, _) = createOrganization() + testSuspend { + val (organizationResponse, _) = testApp.createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken val resourceName = "resource-name" val response = - client.post("/organizations/${organization.id}/resources") { + testApp.client.post("/organizations/${organization.id}/resources") { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) header(HttpHeaders.Authorization, "Bearer $rootUserToken") setBody(gson.toJson(CreateResourceRequest(name = resourceName))) @@ -64,19 +56,16 @@ internal class ResourceApiTest : AbstractContainerBaseTest() { @Test fun `get resource`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (organizationResponse, _) = createOrganization() + testSuspend { + val (organizationResponse, _) = testApp.createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken val resourceName = "resource-name" - createResource(organization.id, rootUserToken, resourceName) + testApp.createResource(organization.id, rootUserToken, resourceName) val response = - client.get("/organizations/${organization.id}/resources/$resourceName") { + testApp.client.get("/organizations/${organization.id}/resources/$resourceName") { header(HttpHeaders.Authorization, "Bearer $rootUserToken") } assertEquals(HttpStatusCode.OK, response.status) @@ -91,22 +80,19 @@ internal class ResourceApiTest : AbstractContainerBaseTest() { @Test fun `get resource failure for unauthorized user access`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (organizationResponse1, _) = createOrganization() + testSuspend { + val (organizationResponse1, _) = testApp.createOrganization() val organization1 = organizationResponse1.organization val rootUserToken1 = organizationResponse1.rootUserToken - val (organizationResponse2, _) = createOrganization() + val (organizationResponse2, _) = testApp.createOrganization() val organization2 = organizationResponse2.organization val rootUserToken2 = organizationResponse2.rootUserToken - val resource = createResource(organization1.id, rootUserToken1) + val resource = testApp.createResource(organization1.id, rootUserToken1) val response = - client.get("/organizations/${organization1.id}/resources/${resource.name}") { + testApp.client.get("/organizations/${organization1.id}/resources/${resource.name}") { header(HttpHeaders.Authorization, "Bearer $rootUserToken2") } assertEquals(HttpStatusCode.Forbidden, response.status) @@ -119,18 +105,15 @@ internal class ResourceApiTest : AbstractContainerBaseTest() { @Test fun `delete resource`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (organizationResponse, _) = createOrganization() + testSuspend { + val (organizationResponse, _) = testApp.createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken - val resource = createResource(organization.id, rootUserToken) + val resource = testApp.createResource(organization.id, rootUserToken) val response = - client.delete("/organizations/${organization.id}/resources/${resource.name}") { + testApp.client.delete("/organizations/${organization.id}/resources/${resource.name}") { header(HttpHeaders.Authorization, "Bearer $rootUserToken") } assertEquals(HttpStatusCode.OK, response.status) @@ -140,7 +123,7 @@ internal class ResourceApiTest : AbstractContainerBaseTest() { // Check that the resource is no longer available val getResourceResponse = - client.get("/organizations/${organization.id}/resources/${resource.name}") { + testApp.client.get("/organizations/${organization.id}/resources/${resource.name}") { header(HttpHeaders.Authorization, "Bearer $rootUserToken") } assertEquals(HttpStatusCode.NotFound, getResourceResponse.status) @@ -151,19 +134,16 @@ internal class ResourceApiTest : AbstractContainerBaseTest() { @Test fun `list resources within a organization`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (organizationResponse, _) = createOrganization() + testSuspend { + val (organizationResponse, _) = testApp.createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken - val resource1 = createResource(organization.id, rootUserToken) - val resource2 = createResource(organization.id, rootUserToken) + val resource1 = testApp.createResource(organization.id, rootUserToken) + val resource2 = testApp.createResource(organization.id, rootUserToken) val response = - client.get("/organizations/${organization.id}/resources") { + testApp.client.get("/organizations/${organization.id}/resources") { header(HttpHeaders.Authorization, "Bearer $rootUserToken") } @@ -181,19 +161,16 @@ internal class ResourceApiTest : AbstractContainerBaseTest() { @Test fun `update resource`() { - testApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - val (organizationResponse, _) = createOrganization() + testSuspend { + val (organizationResponse, _) = testApp.createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken - val resource = createResource(organization.id, rootUserToken) + val resource = testApp.createResource(organization.id, rootUserToken) val newDescription = "new description" val response = - client.patch("/organizations/${organization.id}/resources/${resource.name}") { + testApp.client.patch("/organizations/${organization.id}/resources/${resource.name}") { header(HttpHeaders.Authorization, "Bearer $rootUserToken") header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) setBody(gson.toJson(UpdateResourceRequest(description = "new description"))) diff --git a/src/test/kotlin/com/hypto/iam/server/apis/SubOrganizationUserApiTest.kt b/src/test/kotlin/com/hypto/iam/server/apis/SubOrganizationUserApiTest.kt index 19b7ee0a..dc8f7c21 100644 --- a/src/test/kotlin/com/hypto/iam/server/apis/SubOrganizationUserApiTest.kt +++ b/src/test/kotlin/com/hypto/iam/server/apis/SubOrganizationUserApiTest.kt @@ -3,14 +3,14 @@ package com.hypto.iam.server.apis import com.google.gson.Gson import com.hypto.iam.server.Constants import com.hypto.iam.server.helpers.AbstractContainerBaseTest -import com.hypto.iam.server.helpers.DataSetupHelperV3.createAndAttachPolicy -import com.hypto.iam.server.helpers.DataSetupHelperV3.createOrganization -import com.hypto.iam.server.helpers.DataSetupHelperV3.createPolicy -import com.hypto.iam.server.helpers.DataSetupHelperV3.createResource -import com.hypto.iam.server.helpers.DataSetupHelperV3.createSubOrganization -import com.hypto.iam.server.helpers.DataSetupHelperV3.createSubOrganizationUser -import com.hypto.iam.server.helpers.DataSetupHelperV3.createUser -import com.hypto.iam.server.helpers.DataSetupHelperV3.deleteOrganization +import com.hypto.iam.server.helpers.DataSetupHelperV2.createAndAttachPolicy +import com.hypto.iam.server.helpers.DataSetupHelperV2.createOrganization +import com.hypto.iam.server.helpers.DataSetupHelperV2.createPolicy +import com.hypto.iam.server.helpers.DataSetupHelperV2.createResource +import com.hypto.iam.server.helpers.DataSetupHelperV2.createSubOrganization +import com.hypto.iam.server.helpers.DataSetupHelperV2.createSubOrganizationUser +import com.hypto.iam.server.helpers.DataSetupHelperV2.createUser +import com.hypto.iam.server.helpers.DataSetupHelperV2.deleteOrganization import com.hypto.iam.server.idp.CognitoConstants import com.hypto.iam.server.models.BaseSuccessResponse import com.hypto.iam.server.models.ChangeUserPasswordRequest @@ -38,14 +38,11 @@ import io.ktor.http.HttpHeaders import io.ktor.http.HttpStatusCode import io.ktor.http.contentType import io.ktor.server.config.ApplicationConfig -import io.ktor.server.testing.TestApplication -import io.ktor.test.dispatcher.testSuspend +import io.ktor.server.testing.testApplication import io.mockk.coEvery import io.mockk.slot import io.mockk.verify -import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @@ -68,30 +65,9 @@ import kotlin.test.assertTrue class SubOrganizationUserApiTest : AbstractContainerBaseTest() { private val gson: Gson by inject() - companion object { - lateinit var testApp: TestApplication - - @JvmStatic - @BeforeAll - fun setupTest() { - testApp = - TestApplication { - environment { - config = ApplicationConfig("application-custom.conf") - } - } - } - - @JvmStatic - @AfterAll - fun teardownTest() { - testApp.stop() - } - } - @Nested @DisplayName("Create sub organization user API tests") - inner class CreateSubOrganizationUserTest { + inner class CreateSuborganizationUserTest { @Test fun `create user success case`() { val testEmail = "test-user-email" + IdGenerator.randomId() + "@hypto.in" @@ -106,11 +82,14 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { verified = true, loginAccess = true, ) - testSuspend { - val (organizationResponse, _) = testApp.createOrganization() + testApplication { + environment { + config = ApplicationConfig("application-custom.conf") + } + val (organizationResponse, _) = createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken - val subOrganizationResponse = testApp.createSubOrganization(organization.id, rootUserToken) + val subOrganizationResponse = createSubOrganization(organization.id, rootUserToken) coEvery { cognitoClient.adminGetUser(any()) @@ -127,10 +106,10 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { .userCreateDate(Instant.now()) .build() - testApp.createResource(organization.id, rootUserToken) + createResource(organization.id, rootUserToken) val response = - testApp.client.post( + client.post( "/organizations/${organization .id}/sub_organizations/${subOrganizationResponse.subOrganization.name}/users", ) { @@ -154,7 +133,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { assertEquals(User.Status.enabled.toString(), responseBody.user.status.toString()) assertEquals(createUserRequest.verified, responseBody.user.verified) - testApp.deleteOrganization(organization.id) + deleteOrganization(organization.id) } } @@ -171,11 +150,14 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { verified = true, loginAccess = true, ) - testSuspend { - val (organizationResponse, _) = testApp.createOrganization() + testApplication { + environment { + config = ApplicationConfig("application-custom.conf") + } + val (organizationResponse, _) = createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken - val subOrganizationResponse = testApp.createSubOrganization(organization.id, rootUserToken) + val subOrganizationResponse = createSubOrganization(organization.id, rootUserToken) coEvery { cognitoClient.adminGetUser(any()) @@ -192,10 +174,10 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { .userCreateDate(Instant.now()) .build() - testApp.createResource(organization.id, rootUserToken) + createResource(organization.id, rootUserToken) val response = - testApp.client.post( + client.post( "/organizations/${organization .id}/sub_organizations/${subOrganizationResponse.subOrganization.name}/users", ) { @@ -219,7 +201,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { assertEquals(User.Status.enabled.toString(), responseBody.user.status.toString()) assertEquals(createUserRequest.verified, responseBody.user.verified) - testApp.deleteOrganization(organization.id) + deleteOrganization(organization.id) } } @@ -241,10 +223,10 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { // environment { // config = ApplicationConfig("application-custom.conf") // } -// val (organizationResponse, _) = testApp.createOrganization(preferredUsername) +// val (organizationResponse, _) = createOrganization(preferredUsername) // val organization = organizationResponse.organization // val rootUserToken = organizationResponse.rootUserToken -// val subOrganizationResponse = testApp.createSubOrganization(organization.id, rootUserToken) +// val subOrganizationResponse = createSubOrganization(organization.id, rootUserToken) // // coEvery { // cognitoClient.adminCreateUser(any()) @@ -255,9 +237,9 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { // } throws UserNotFoundException.builder() // .build() // -// testApp.createResource(organization.id, rootUserToken) +// createResource(organization.id, rootUserToken) // -// val response = testApp.client.post( +// val response = client.post( // "/organizations/${organization // .id}/sub_organizations/${subOrganizationResponse.subOrganization.name}/users" // ) { @@ -271,7 +253,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { // response.contentType() // ) // -// testApp.deleteOrganization(organization.id) +// deleteOrganization(organization.id) // } // } @@ -288,15 +270,18 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { phone = "+919999999999", loginAccess = true, ) - testSuspend { - val (organizationResponse, _) = testApp.createOrganization() + testApplication { + environment { + config = ApplicationConfig("application-custom.conf") + } + val (organizationResponse, _) = createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken - testApp.createResource(organization.id, rootUserToken) - val subOrganizationResponse = testApp.createSubOrganization(organization.id, rootUserToken) + createResource(organization.id, rootUserToken) + val subOrganizationResponse = createSubOrganization(organization.id, rootUserToken) val response = - testApp.client.post( + client.post( "/organizations/${organization .id}/sub_organizations/${subOrganizationResponse.subOrganization.name}/users", ) { @@ -306,7 +291,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { } assertEquals(HttpStatusCode.BadRequest, response.status) - testApp.deleteOrganization(organization.id) + deleteOrganization(organization.id) } } @@ -321,16 +306,19 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { verified = true, loginAccess = false, ) - testSuspend { - val (organizationResponse, rootUser) = testApp.createOrganization() + testApplication { + environment { + config = ApplicationConfig("application-custom.conf") + } + val (organizationResponse, rootUser) = createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken - val subOrganizationResponse = testApp.createSubOrganization(organization.id, rootUserToken) + val subOrganizationResponse = createSubOrganization(organization.id, rootUserToken) - testApp.createResource(organization.id, rootUserToken) + createResource(organization.id, rootUserToken) val response = - testApp.client.post( + client.post( "/organizations/${organization .id}/sub_organizations/${subOrganizationResponse.subOrganization.name}/users", ) { @@ -356,7 +344,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { assertEquals(createUserRequest.verified, responseBody.user.verified) assertEquals(createUserRequest.loginAccess, responseBody.user.loginAccess) - testApp.deleteOrganization(organization.id) + deleteOrganization(organization.id) } } @@ -372,16 +360,19 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { password = "testPassword@ash", loginAccess = false, ) - testSuspend { - val (organizationResponse, rootUser) = testApp.createOrganization() + testApplication { + environment { + config = ApplicationConfig("application-custom.conf") + } + val (organizationResponse, rootUser) = createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken - val subOrganizationResponse = testApp.createSubOrganization(organization.id, rootUserToken) + val subOrganizationResponse = createSubOrganization(organization.id, rootUserToken) - testApp.createResource(organization.id, rootUserToken) + createResource(organization.id, rootUserToken) val response = - testApp.client.post( + client.post( "/organizations/${organization .id}/sub_organizations/${subOrganizationResponse.subOrganization.name}/users", ) { @@ -395,7 +386,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { response.contentType(), ) - testApp.deleteOrganization(organization.id) + deleteOrganization(organization.id) } } } @@ -406,13 +397,16 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { @Test fun `get user request success case`() { val testEmail = "test-user-email" + IdGenerator.randomId() + "@hypto.in" - testSuspend { - val (organizationResponse, _) = testApp.createOrganization() + testApplication { + environment { + config = ApplicationConfig("application-custom.conf") + } + val (organizationResponse, _) = createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken - val subOrganizationResponse = testApp.createSubOrganization(organization.id, rootUserToken) + val subOrganizationResponse = createSubOrganization(organization.id, rootUserToken) val (subOrgUser, subOrgUserCreds) = - testApp.createSubOrganizationUser( + createSubOrganizationUser( organization.id, subOrganizationResponse.subOrganization.name, rootUserToken, @@ -436,7 +430,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { // Get user val response = - testApp.client.get( + client.get( "/organizations/${organization.id}" + "/sub_organizations/${subOrganizationResponse.subOrganization.name}" + "/users/${subOrgUser.username}", @@ -453,7 +447,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { assertEquals(subOrgUser.preferredUsername, responseBody.preferredUsername) assertEquals(true, responseBody.verified) - testApp.deleteOrganization(organization.id) + deleteOrganization(organization.id) } } @@ -470,14 +464,17 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { phone = "+919626012778", loginAccess = true, ) - testSuspend { - val (organizationResponse, _) = testApp.createOrganization() + testApplication { + environment { + config = ApplicationConfig("application-custom.conf") + } + val (organizationResponse, _) = createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken - val subOrganizationResponse = testApp.createSubOrganization(organization.id, rootUserToken) + val subOrganizationResponse = createSubOrganization(organization.id, rootUserToken) // Create user val (user1, _) = - testApp.createUser( + createUser( orgId = organization.id, bearerToken = rootUserToken, createUserRequest = createUserRequest, @@ -485,7 +482,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { // Get user val response = - testApp.client.get( + client.get( "/organizations/${organization .id}/sub_organizations/${subOrganizationResponse.subOrganization.name}/users/${user1.username}", ) { @@ -493,7 +490,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { header(HttpHeaders.Authorization, "Bearer badSecret") } assertEquals(HttpStatusCode.Unauthorized, response.status) - testApp.deleteOrganization(organization.id) + deleteOrganization(organization.id) } } } @@ -503,13 +500,27 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { inner class DeleteUserTest { @Test fun `delete user success case`() { - testSuspend { - val (organizationResponse, _) = testApp.createOrganization() + val testEmail = "test-user-email" + IdGenerator.randomId() + "@hypto.in" + val createUserRequest = + CreateUserRequest( + preferredUsername = "testUserName", + name = "lorem ipsum", + password = "testPassword@Hash1", + email = testEmail, + status = CreateUserRequest.Status.enabled, + phone = "+919626012778", + loginAccess = true, + ) + testApplication { + environment { + config = ApplicationConfig("application-custom.conf") + } + val (organizationResponse, _) = createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken - val subOrganizationResponse = testApp.createSubOrganization(organization.id, rootUserToken) - val (subOrgUser, _) = - testApp.createSubOrganizationUser( + val subOrganizationResponse = createSubOrganization(organization.id, rootUserToken) + val (subOrgUser, subOrgUserCreds) = + createSubOrganizationUser( organization.id, subOrganizationResponse.subOrganization.name, rootUserToken, @@ -518,7 +529,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { // Delete user val response = - testApp.client.delete( + client.delete( "/organizations/${organization.id}" + "/sub_organizations/${subOrganizationResponse.subOrganization.name}" + "/users/${subOrgUser.username}", @@ -533,7 +544,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { verify { get().adminDeleteUser(capture(slot)) } val adminUserRequest = slot.captured assertEquals(subOrgUser.username, adminUserRequest.username()) - testApp.deleteOrganization(organization.id) + deleteOrganization(organization.id) } } } @@ -565,15 +576,18 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { phone = "+919626012778", loginAccess = true, ) - testSuspend { - val (organizationResponse, _) = testApp.createOrganization() + testApplication { + environment { + config = ApplicationConfig("application-custom.conf") + } + val (organizationResponse, _) = createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken - val subOrganizationResponse = testApp.createSubOrganization(organization.id, rootUserToken) - testApp.createResource(organization.id, rootUserToken) + val subOrganizationResponse = createSubOrganization(organization.id, rootUserToken) + createResource(organization.id, rootUserToken) // Create user1 - testApp.client.post( + client.post( "/organizations/${organization .id}/sub_organizations/${subOrganizationResponse.subOrganization.name}/users", ) { @@ -583,7 +597,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { } // Create user2 - testApp.client.post( + client.post( "/organizations/${organization .id}/sub_organizations/${subOrganizationResponse.subOrganization.name}/users", ) { @@ -594,7 +608,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { // List users val listUsersResponse = - testApp.client.get( + client.get( "/organizations/${organization .id}/sub_organizations/${subOrganizationResponse.subOrganization.name}/users", ) { @@ -609,7 +623,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { val responseBody = gson.fromJson(listUsersResponse.bodyAsText(), UserPaginatedResponse::class.java) assertEquals(responseBody.data!!.size, 2) - testApp.deleteOrganization(organization.id) + deleteOrganization(organization.id) } } } @@ -619,16 +633,19 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { inner class UpdateUserTest { @Test fun `update user`() { - testSuspend { - val (organizationResponse, _) = testApp.createOrganization() + testApplication { + environment { + config = ApplicationConfig("application-custom.conf") + } + val (organizationResponse, _) = createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken - val subOrganizationResponse = testApp.createSubOrganization(organization.id, rootUserToken) + val subOrganizationResponse = createSubOrganization(organization.id, rootUserToken) val testEmail = "test-user-email" + IdGenerator.randomId() + "@hypto.in" // Create sub org user val (subOrgUser, _) = - testApp.createSubOrganizationUser( + createSubOrganizationUser( organization.id, subOrganizationResponse.subOrganization.name, rootUserToken, @@ -659,7 +676,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { .build() val response = - testApp.client.patch( + client.patch( "/organizations/${organization.id}" + "/sub_organizations/${subOrganizationResponse.subOrganization.name}" + "/users/${subOrgUser.username}", @@ -674,7 +691,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { response.contentType(), ) - testApp.deleteOrganization(organization.id) + deleteOrganization(organization.id) } } } @@ -684,28 +701,33 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { inner class ChangeUserPasswordTest { @Test fun `change password with wrong old password - failure`() { - testSuspend { - val (organizationResponse, _) = testApp.createOrganization() + testApplication { + environment { + config = ApplicationConfig("application-custom.conf") + } + val (organizationResponse, rootUser) = createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken - val subOrganizationResponse = testApp.createSubOrganization(organization.id, rootUserToken) + val subOrganizationResponse = createSubOrganization(organization.id, rootUserToken) val (subOrgUser, subOrgUserCreds) = - testApp.createSubOrganizationUser( + createSubOrganizationUser( organization.id, subOrganizationResponse.subOrganization.name, rootUserToken, cognitoClient, ) - testApp.createAndAttachPolicy( - orgId = organization.id, - username = subOrgUser.username, - bearerToken = rootUserToken, - policyName = "sample-policy2", - subOrgName = subOrganizationResponse.subOrganization.name, - resourceName = "iam-user", - actionName = "changePassword", - resourceInstance = subOrgUser.username, - ) + val username = organizationResponse.organization.rootUser.username + val samplePolicy = + createAndAttachPolicy( + orgId = organization.id, + username = subOrgUser.username, + bearerToken = rootUserToken, + policyName = "sample-policy2", + subOrgName = subOrganizationResponse.subOrganization.name, + resourceName = "iam-user", + actionName = "changePassword", + resourceInstance = subOrgUser.username, + ) coEvery { cognitoClient.adminInitiateAuth(any()) @@ -717,7 +739,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { newPassword = "testPassword@Hash2", ) val response = - testApp.client.post( + client.post( "/organizations/${organization .id}/sub_organizations/${subOrganizationResponse.subOrganization .name}/users/${subOrgUser.username}/change_password", @@ -731,26 +753,29 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { ContentType.Application.Json, response.contentType(), ) - testApp.deleteOrganization(organization.id) + deleteOrganization(organization.id) } } @Test fun `user to change password on their own with permission - success`() { - testSuspend { - val (organizationResponse, _) = testApp.createOrganization() + testApplication { + environment { + config = ApplicationConfig("application-custom.conf") + } + val (organizationResponse, _) = createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken - val subOrganizationResponse = testApp.createSubOrganization(organization.id, rootUserToken) + val subOrganizationResponse = createSubOrganization(organization.id, rootUserToken) val (subOrgUser, subOrgUserCred) = - testApp.createSubOrganizationUser( + createSubOrganizationUser( organization.id, subOrganizationResponse.subOrganization.name, rootUserToken, cognitoClient, ) - testApp.createAndAttachPolicy( + createAndAttachPolicy( orgId = organization.id, username = subOrgUser.username, bearerToken = rootUserToken, @@ -767,7 +792,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { newPassword = "testPassword@Hash2", ) val response = - testApp.client.post( + client.post( "/organizations/${organization .id}/sub_organizations/${subOrganizationResponse.subOrganization .name}/users/${subOrgUser.username}/change_password", @@ -781,33 +806,36 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { ContentType.Application.Json, response.contentType(), ) - testApp.deleteOrganization(organization.id) + deleteOrganization(organization.id) } } @Test fun `change password of different user without permission - failure`() { - testSuspend { - val (organizationResponse, _) = testApp.createOrganization() + testApplication { + environment { + config = ApplicationConfig("application-custom.conf") + } + val (organizationResponse, _) = createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken - val subOrganizationResponse = testApp.createSubOrganization(organization.id, rootUserToken) + val subOrganizationResponse = createSubOrganization(organization.id, rootUserToken) val (subOrgUser1, subOrgUser1Creds) = - testApp.createSubOrganizationUser( + createSubOrganizationUser( organization.id, subOrganizationResponse.subOrganization.name, rootUserToken, cognitoClient, ) val (subOrgUser2, subOrgUser2Creds) = - testApp.createSubOrganizationUser( + createSubOrganizationUser( organization.id, subOrganizationResponse.subOrganization.name, rootUserToken, cognitoClient, ) - testApp.createAndAttachPolicy( + createAndAttachPolicy( orgId = organization.id, username = subOrgUser2.username, bearerToken = subOrgUser2Creds.secret, @@ -824,7 +852,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { newPassword = "testPassword@Hash2", ) val response = - testApp.client.post( + client.post( "/organizations/${organization .id}/sub_organizations/${subOrganizationResponse.subOrganization .name}/users/${subOrgUser1.username}/change_password", @@ -834,26 +862,29 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { setBody(gson.toJson(changePasswordRequest)) } assertEquals(HttpStatusCode.Forbidden, response.status) - testApp.deleteOrganization(organization.id) + deleteOrganization(organization.id) } } @Test fun `generate token after changing password - success`() { - testSuspend { - val (organizationResponse, rootUser) = testApp.createOrganization() + testApplication { + environment { + config = ApplicationConfig("application-custom.conf") + } + val (organizationResponse, rootUser) = createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken - val subOrganizationResponse = testApp.createSubOrganization(organization.id, rootUserToken) + val subOrganizationResponse = createSubOrganization(organization.id, rootUserToken) val (subOrgUser, subOrgUserCreds) = - testApp.createSubOrganizationUser( + createSubOrganizationUser( organization.id, subOrganizationResponse.subOrganization.name, rootUserToken, cognitoClient, ) val samplePolicy = - testApp.createAndAttachPolicy( + createAndAttachPolicy( orgId = organization.id, username = subOrgUser.username, bearerToken = rootUserToken, @@ -872,7 +903,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { newPassword = "testPassword@Hash2", ) val response = - testApp.client.post( + client.post( "/organizations/${organization .id}/sub_organizations/${subOrganizationResponse.subOrganization .name}/users/${subOrgUser.username}/change_password", @@ -891,7 +922,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { val authHeader = "Basic ${Base64.getEncoder().encodeToString(authString.encodeToByteArray())}" val tokenResponse = - testApp.client.post( + client.post( "/organizations/${organization.id}/sub_organizations/token", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -906,7 +937,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { ContentType.Application.Json, tokenResponse.contentType(), ) - testApp.deleteOrganization(organization.id) + deleteOrganization(organization.id) } } } @@ -916,12 +947,15 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { inner class ResetUserPasswordTest { @Test fun `reset Password - success`() { - testSuspend { - val (organizationResponse, createdUser) = testApp.createOrganization() + testApplication { + environment { + config = ApplicationConfig("application-custom.conf") + } + val (organizationResponse, createdUser) = createOrganization() val organizationId = organizationResponse.organization.id - val subOrganizationResponse = testApp.createSubOrganization(organizationId, organizationResponse.rootUserToken) - val (subOrgUser, _) = - testApp.createSubOrganizationUser( + val subOrganizationResponse = createSubOrganization(organizationId, organizationResponse.rootUserToken) + val (subOrgUser, subOrgUserCreds) = + createSubOrganizationUser( organizationResponse.organization.id, subOrganizationResponse.subOrganization.name, organizationResponse.rootUserToken, @@ -959,7 +993,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { cognitoClient.listUsers(any()) } returns listUsersResponse - testApp.client.post("/verifyEmail") { + client.post("/verifyEmail") { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) setBody( gson.toJson( @@ -974,7 +1008,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { } val resetPasswordResponse = - testApp.client.post( + client.post( "/organizations/$organizationId/sub_organizations/${subOrganizationResponse.subOrganization .name}/users/resetPassword", ) { @@ -994,7 +1028,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { val response = gson.fromJson(resetPasswordResponse.bodyAsText(), BaseSuccessResponse::class.java) assertTrue(response.success) - testApp.deleteOrganization(organizationId) + deleteOrganization(organizationId) } } } @@ -1004,20 +1038,23 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { inner class UserAttachPolicyTest { @Test fun `user to attach policy to a different user with permission - success`() { - testSuspend { - val (organizationResponse, _) = testApp.createOrganization() + testApplication { + environment { + config = ApplicationConfig("application-custom.conf") + } + val (organizationResponse, _) = createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken - val subOrganizationResponse = testApp.createSubOrganization(organization.id, rootUserToken) + val subOrganizationResponse = createSubOrganization(organization.id, rootUserToken) val (subOrgUser, subOrgUserCreds) = - testApp.createSubOrganizationUser( + createSubOrganizationUser( organization.id, subOrganizationResponse.subOrganization.name, rootUserToken, cognitoClient, ) - testApp.createAndAttachPolicy( + createAndAttachPolicy( orgId = organization.id, username = subOrgUser.username, bearerToken = rootUserToken, @@ -1029,7 +1066,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { ) val samplePolicy = - testApp.createPolicy( + createPolicy( orgId = organization.id, bearerToken = rootUserToken, policyName = "sample-policy", @@ -1040,7 +1077,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { ) assertEquals(1, samplePolicy.statements.size) val response = - testApp.client.patch( + client.patch( "/organizations/${organization .id}/sub_organizations/${subOrganizationResponse.subOrganization .name}/users/${subOrgUser.username}/attach_policies", @@ -1054,19 +1091,22 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { ContentType.Application.Json, response.contentType(), ) - testApp.deleteOrganization(organization.id) + deleteOrganization(organization.id) } } @Test fun `user to attach policies to a different user without permission - failure`() { - testSuspend { - val (organizationResponse, _) = testApp.createOrganization() + testApplication { + environment { + config = ApplicationConfig("application-custom.conf") + } + val (organizationResponse, _) = createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken - val subOrganizationResponse = testApp.createSubOrganization(organization.id, rootUserToken) + val subOrganizationResponse = createSubOrganization(organization.id, rootUserToken) val (subOrgUser, subOrgUserCreds) = - testApp.createSubOrganizationUser( + createSubOrganizationUser( organization.id, subOrganizationResponse.subOrganization.name, rootUserToken, @@ -1074,7 +1114,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { ) val samplePolicy = - testApp.createPolicy( + createPolicy( orgId = organization.id, bearerToken = rootUserToken, policyName = "sample-policy", @@ -1085,7 +1125,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { ) assertEquals(1, samplePolicy.statements.size) val response = - testApp.client.patch( + client.patch( "/organizations/${organization .id}/sub_organizations/${subOrganizationResponse.subOrganization .name}/users/${subOrgUser.username}/attach_policies", @@ -1099,7 +1139,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { ContentType.Application.Json, response.contentType(), ) - testApp.deleteOrganization(organization.id) + deleteOrganization(organization.id) } } } @@ -1109,13 +1149,16 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { inner class CreatePasswordForSubOrganizationUserTest { @Test fun `create password for sub org user - success`() { - testSuspend { - val (organizationResponse, _) = testApp.createOrganization() + testApplication { + environment { + config = ApplicationConfig("application-custom.conf") + } + val (organizationResponse, _) = createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken - val subOrganizationResponse = testApp.createSubOrganization(organization.id, rootUserToken) + val subOrganizationResponse = createSubOrganization(organization.id, rootUserToken) val (subOrgUser, _) = - testApp.createSubOrganizationUser( + createSubOrganizationUser( organization.id, subOrganizationResponse.subOrganization.name, rootUserToken, @@ -1123,7 +1166,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { false, ) - testApp.createAndAttachPolicy( + createAndAttachPolicy( orgId = organization.id, username = subOrgUser.username, bearerToken = rootUserToken, @@ -1136,7 +1179,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { // Create password for sub org user val response = - testApp.client.post( + client.post( "/organizations/${organization .id}" + "/sub_organizations/${subOrganizationResponse.subOrganization.name}" + "/users/${subOrgUser.username}/create_password", @@ -1160,7 +1203,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { val createPasswordResponse = gson.fromJson(response.bodyAsText(), TokenResponse::class.java) - testApp.client.post( + client.post( "/organizations/${organization.id}/sub_organizations/token", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -1197,7 +1240,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { val authHeader = "Basic ${Base64.getEncoder().encodeToString(authString.encodeToByteArray())}" val tokenResponse = - testApp.client.post( + client.post( "/organizations/${organization.id}/sub_organizations/token", ) { header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) @@ -1212,19 +1255,22 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { organization.id, tokenResponse.headers[Constants.X_ORGANIZATION_HEADER], ) - testApp.deleteOrganization(organization.id) + deleteOrganization(organization.id) } } @Test fun `create password for sub org user - failure`() { - testSuspend { - val (organizationResponse, _) = testApp.createOrganization() + testApplication { + environment { + config = ApplicationConfig("application-custom.conf") + } + val (organizationResponse, _) = createOrganization() val organization = organizationResponse.organization val rootUserToken = organizationResponse.rootUserToken - val subOrganizationResponse = testApp.createSubOrganization(organization.id, rootUserToken) + val subOrganizationResponse = createSubOrganization(organization.id, rootUserToken) val (subOrgUser, _) = - testApp.createSubOrganizationUser( + createSubOrganizationUser( organization.id, subOrganizationResponse.subOrganization.name, rootUserToken, @@ -1232,7 +1278,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { false, ) - testApp.createAndAttachPolicy( + createAndAttachPolicy( orgId = organization.id, username = subOrgUser.username, bearerToken = rootUserToken, @@ -1245,7 +1291,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { // Create password for sub org user val response = - testApp.client.post( + client.post( "/organizations/${organization .id}" + "/sub_organizations/dummySubOrg" + "/users/${subOrgUser.username}/create_password", @@ -1260,7 +1306,7 @@ class SubOrganizationUserApiTest : AbstractContainerBaseTest() { contentType(), ) } - testApp.deleteOrganization(organization.id) + deleteOrganization(organization.id) } } } diff --git a/src/test/kotlin/com/hypto/iam/server/helpers/BaseSingleAppTest.kt b/src/test/kotlin/com/hypto/iam/server/helpers/BaseSingleAppTest.kt new file mode 100644 index 00000000..77a53a89 --- /dev/null +++ b/src/test/kotlin/com/hypto/iam/server/helpers/BaseSingleAppTest.kt @@ -0,0 +1,33 @@ +package com.hypto.iam.server.helpers + +import com.google.gson.Gson +import io.ktor.server.config.ApplicationConfig +import io.ktor.server.testing.TestApplication +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.BeforeAll +import org.koin.test.inject + +abstract class BaseSingleAppTest : AbstractContainerBaseTest() { + protected val gson: Gson by inject() + + companion object { + lateinit var testApp: TestApplication + + @JvmStatic + @BeforeAll + fun setupTest() { + testApp = + TestApplication { + environment { + config = ApplicationConfig("application-custom.conf") + } + } + } + + @JvmStatic + @AfterAll + fun teardownTest() { + testApp.stop() + } + } +}