-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1879 from digitalfabrik/1864-integration-tests-fo…
…r-addeakapplication 1864: Integration tests for Verein360 applications
- Loading branch information
Showing
4 changed files
with
264 additions
and
7 deletions.
There are no files selected for viewing
208 changes: 208 additions & 0 deletions
208
...test/kotlin/app/ehrenamtskarte/backend/application/webservice/Verein360ApplicationTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
package app.ehrenamtskarte.backend.application.webservice | ||
|
||
import app.ehrenamtskarte.backend.GraphqlApiTest | ||
import app.ehrenamtskarte.backend.application.database.ApplicationEntity | ||
import app.ehrenamtskarte.backend.application.database.ApplicationVerificationEntity | ||
import app.ehrenamtskarte.backend.application.database.ApplicationVerificationExternalSource | ||
import app.ehrenamtskarte.backend.application.database.ApplicationVerifications | ||
import app.ehrenamtskarte.backend.application.database.Applications | ||
import app.ehrenamtskarte.backend.application.webservice.schema.create.Application | ||
import app.ehrenamtskarte.backend.application.webservice.schema.create.ApplicationType | ||
import app.ehrenamtskarte.backend.auth.database.ApiTokenType | ||
import app.ehrenamtskarte.backend.auth.database.ApiTokens | ||
import app.ehrenamtskarte.backend.helper.TestAdministrators | ||
import app.ehrenamtskarte.backend.helper.TestApplicationBuilder | ||
import app.ehrenamtskarte.backend.helper.TestData | ||
import app.ehrenamtskarte.backend.util.GraphQLRequestSerializer | ||
import io.javalin.testtools.JavalinTest | ||
import org.jetbrains.exposed.sql.deleteAll | ||
import org.jetbrains.exposed.sql.selectAll | ||
import org.jetbrains.exposed.sql.transactions.transaction | ||
import org.junit.jupiter.api.BeforeEach | ||
import org.junit.jupiter.api.Test | ||
import org.junit.jupiter.params.ParameterizedTest | ||
import org.junit.jupiter.params.provider.MethodSource | ||
import kotlin.test.assertEquals | ||
import kotlin.test.assertNotNull | ||
import kotlin.test.assertNull | ||
|
||
internal class Verein360ApplicationTest : GraphqlApiTest() { | ||
|
||
data class ValidationErrorTestCase(val application: Application, val error: String) | ||
|
||
companion object { | ||
@JvmStatic | ||
fun validationErrorTestCases(): List<ValidationErrorTestCase> { | ||
return listOf( | ||
ValidationErrorTestCase( | ||
application = TestApplicationBuilder.build( | ||
isAlreadyVerified = true, | ||
applicationType = ApplicationType.RENEWAL_APPLICATION | ||
), | ||
error = "Application type must be FIRST_APPLICATION if application is already verified" | ||
), | ||
ValidationErrorTestCase( | ||
application = TestApplicationBuilder.build( | ||
isAlreadyVerified = true, | ||
wantsDigitalCard = false, | ||
wantsPhysicalCard = true | ||
), | ||
error = "Digital card must be true if application is already verified" | ||
), | ||
ValidationErrorTestCase( | ||
application = TestApplicationBuilder.build( | ||
isAlreadyVerified = true, | ||
wantsPhysicalCard = true | ||
), | ||
error = "Physical card must be false if application is already verified" | ||
), | ||
ValidationErrorTestCase( | ||
application = TestApplicationBuilder.build( | ||
isAlreadyVerified = true, | ||
category = "Other" | ||
), | ||
error = "All organizations must be of category Sport if application is already verified" | ||
) | ||
) | ||
} | ||
} | ||
|
||
private val adminVerein360 = TestAdministrators.BAYERN_VEREIN_360 | ||
|
||
@BeforeEach | ||
fun cleanUp() { | ||
transaction { | ||
ApplicationVerifications.deleteAll() | ||
Applications.deleteAll() | ||
ApiTokens.deleteAll() | ||
} | ||
} | ||
|
||
@ParameterizedTest | ||
@MethodSource("validationErrorTestCases") | ||
fun `should return validation error when the request is not valid`(testCase: ValidationErrorTestCase) = JavalinTest.test(app) { _, client -> | ||
TestData.createApiToken(creatorId = adminVerein360.id, type = ApiTokenType.VERIFIED_APPLICATION) | ||
|
||
val mutation = createMutation(application = testCase.application) | ||
val response = post(client, mutation, token = "dummy") | ||
|
||
assertEquals(200, response.code) | ||
|
||
val jsonResponse = response.json() | ||
|
||
assertEquals("Error INVALID_JSON occurred.", jsonResponse.findValue("message").textValue()) | ||
assertEquals(testCase.error, jsonResponse.findValue("reason").textValue()) | ||
} | ||
|
||
@Test | ||
fun `should return an error when region not found`() = JavalinTest.test(app) { _, client -> | ||
val mutation = createMutation( | ||
regionId = 99, | ||
application = TestApplicationBuilder.build(true) | ||
) | ||
val response = post(client, mutation) | ||
|
||
assertEquals(200, response.code) | ||
|
||
val jsonResponse = response.json() | ||
|
||
assertEquals("Error REGION_NOT_FOUND occurred.", jsonResponse.findValue("message").textValue()) | ||
} | ||
|
||
@Test | ||
fun `should return an error when the application is pre-verified but auth token is missing`() = JavalinTest.test(app) { _, client -> | ||
val mutation = createMutation( | ||
application = TestApplicationBuilder.build(true) | ||
) | ||
val response = post(client, mutation) | ||
|
||
assertEquals(401, response.code) | ||
} | ||
|
||
@Test | ||
fun `should return an error when api token not found`() = JavalinTest.test(app) { _, client -> | ||
val mutation = createMutation( | ||
application = TestApplicationBuilder.build(true) | ||
) | ||
val response = post(client, mutation, token = "non-existent") | ||
|
||
assertEquals(403, response.code) | ||
} | ||
|
||
@Test | ||
fun `should return an error when api token has wrong type`() = JavalinTest.test(app) { _, client -> | ||
TestData.createApiToken(creatorId = adminVerein360.id, type = ApiTokenType.USER_IMPORT) | ||
|
||
val mutation = createMutation( | ||
application = TestApplicationBuilder.build(true) | ||
) | ||
val response = post(client, mutation, token = "dummy") | ||
|
||
assertEquals(403, response.code) | ||
} | ||
|
||
@Test | ||
fun `should create an application and approved verification if the request is pre-verified and valid`() = JavalinTest.test(app) { _, client -> | ||
TestData.createApiToken(creatorId = adminVerein360.id, type = ApiTokenType.VERIFIED_APPLICATION) | ||
|
||
val mutation = createMutation( | ||
application = TestApplicationBuilder.build(true) | ||
) | ||
val response = post(client, mutation, token = "dummy") | ||
|
||
assertEquals(200, response.code) | ||
|
||
transaction { | ||
assertEquals(1, Applications.selectAll().count()) | ||
assertEquals(1, ApplicationVerifications.selectAll().count()) | ||
|
||
val application = ApplicationEntity.all().single() | ||
|
||
ApplicationVerificationEntity.find { ApplicationVerifications.applicationId eq application.id }.single().let { | ||
assertNotNull(it.verifiedDate) | ||
assertNull(it.rejectedDate) | ||
assertEquals(ApplicationVerificationExternalSource.VEREIN360, it.automaticSource) | ||
} | ||
} | ||
} | ||
|
||
@Test | ||
fun `should create an application and pending verification if the request is not pre-verified`() = JavalinTest.test(app) { _, client -> | ||
val mutation = createMutation( | ||
application = TestApplicationBuilder.build(false) | ||
) | ||
val response = post(client, mutation) | ||
|
||
assertEquals(200, response.code) | ||
|
||
transaction { | ||
assertEquals(1, Applications.selectAll().count()) | ||
assertEquals(1, ApplicationVerifications.selectAll().count()) | ||
|
||
val application = ApplicationEntity.all().single() | ||
|
||
ApplicationVerificationEntity.find { ApplicationVerifications.applicationId eq application.id }.single().let { | ||
assertNull(it.verifiedDate) | ||
assertNull(it.rejectedDate) | ||
assertEquals(ApplicationVerificationExternalSource.NONE, it.automaticSource) | ||
} | ||
} | ||
} | ||
|
||
private fun createMutation( | ||
project: String = "bayern.ehrenamtskarte.app", | ||
regionId: Int = 1, | ||
application: Application | ||
): String { | ||
val applicationJson = GraphQLRequestSerializer.serializeObject(application) | ||
return """ | ||
mutation AddEakApplication { | ||
addEakApplication( | ||
project: "$project" | ||
regionId: $regionId | ||
application: $applicationJson | ||
) | ||
} | ||
""".trimIndent() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,7 +18,14 @@ import app.ehrenamtskarte.backend.application.webservice.schema.create.primitive | |
|
||
class TestApplicationBuilder { | ||
companion object { | ||
fun build(isAlreadyVerified: Boolean): Application { | ||
fun build( | ||
isAlreadyVerified: Boolean, | ||
applicationType: ApplicationType = ApplicationType.FIRST_APPLICATION, | ||
cardType: BavariaCardType = BavariaCardType.BLUE, | ||
wantsDigitalCard: Boolean = true, | ||
wantsPhysicalCard: Boolean = false, | ||
category: String = "Sport" | ||
): Application { | ||
return Application( | ||
personalData = PersonalData( | ||
forenames = ShortTextInput("John"), | ||
|
@@ -36,13 +43,13 @@ class TestApplicationBuilder { | |
emailAddress = EmailInput("[email protected]") | ||
), | ||
applicationDetails = ApplicationDetails( | ||
applicationType = ApplicationType.FIRST_APPLICATION, | ||
cardType = BavariaCardType.BLUE, | ||
applicationType = applicationType, | ||
cardType = cardType, | ||
givenInformationIsCorrectAndComplete = true, | ||
hasAcceptedEmailUsage = true, | ||
hasAcceptedPrivacyPolicy = true, | ||
wantsDigitalCard = true, | ||
wantsPhysicalCard = false, | ||
wantsDigitalCard = wantsDigitalCard, | ||
wantsPhysicalCard = wantsPhysicalCard, | ||
blueCardEntitlement = BlueCardEntitlement( | ||
juleicaEntitlement = null, | ||
militaryReserveEntitlement = null, | ||
|
@@ -61,7 +68,7 @@ class TestApplicationBuilder { | |
country = ShortTextInput("Deutschland"), | ||
addressSupplement = null | ||
), | ||
category = ShortTextInput("Sport"), | ||
category = ShortTextInput(category), | ||
contact = OrganizationContact( | ||
name = ShortTextInput("Jane Doe"), | ||
email = EmailInput("[email protected]"), | ||
|
42 changes: 42 additions & 0 deletions
42
backend/src/test/kotlin/app/ehrenamtskarte/backend/util/GraphQLRequestSerializer.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package app.ehrenamtskarte.backend.util | ||
|
||
import kotlin.reflect.KProperty1 | ||
import kotlin.reflect.KVisibility | ||
import kotlin.reflect.full.declaredMemberProperties | ||
import kotlin.reflect.full.declaredMembers | ||
|
||
object GraphQLRequestSerializer { | ||
|
||
/** | ||
* Serialize object into graphql request format | ||
* e.g. { stringProperty: "value", intProperty: 123, objectProperty: { booleanProperty: true } } | ||
*/ | ||
fun serializeObject(obj: Any): String { | ||
return obj::class.declaredMemberProperties.filter { it.visibility == KVisibility.PUBLIC } | ||
.joinToString(", ") { property -> | ||
val value = readInstanceProperty<Any>(obj, property.name) | ||
val serializedValue = "${property.name}: ${ | ||
when (value) { | ||
is String -> "\"$value\"" | ||
is Number, is Boolean -> value.toString() | ||
is Enum<*> -> value.name | ||
is List<*> -> serializeList(value) | ||
null -> null | ||
else -> serializeObject(value) | ||
} | ||
}" | ||
serializedValue | ||
}.let { "{ $it }" } | ||
} | ||
|
||
private fun serializeList(list: List<*>): String? { | ||
if (list.isEmpty()) return null | ||
return list.joinToString(", ", "[", "]") { serializeObject(it!!) } | ||
} | ||
|
||
@Suppress("UNCHECKED_CAST") | ||
private fun <R> readInstanceProperty(instance: Any, propertyName: String): R? { | ||
val property = instance::class.declaredMembers.first { it.name == propertyName } as KProperty1<Any, *> | ||
return property.get(instance) as R? | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters