diff options
author | Torsten Grote <t@grobox.de> | 2020-07-06 09:58:14 -0300 |
---|---|---|
committer | Torsten Grote <t@grobox.de> | 2020-07-06 09:58:14 -0300 |
commit | bdfbb18fe62e93cdabfa779866d8c04a67585145 (patch) | |
tree | 7a50b87294f464af862f22c273bdb1fa295447b2 /src | |
parent | c8791545fe56f84a54d6700e833000ec379b7ee0 (diff) | |
download | wallet-kotlin-bdfbb18fe62e93cdabfa779866d8c04a67585145.tar.gz wallet-kotlin-bdfbb18fe62e93cdabfa779866d8c04a67585145.tar.bz2 wallet-kotlin-bdfbb18fe62e93cdabfa779866d8c04a67585145.zip |
Use custom serializer for Amount and improve withdrawal info test
Diffstat (limited to 'src')
4 files changed, 91 insertions, 53 deletions
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/Amount.kt b/src/commonMain/kotlin/net/taler/wallet/kotlin/Amount.kt index a078089..87c147d 100644 --- a/src/commonMain/kotlin/net/taler/wallet/kotlin/Amount.kt +++ b/src/commonMain/kotlin/net/taler/wallet/kotlin/Amount.kt @@ -16,6 +16,11 @@ package net.taler.wallet.kotlin +import kotlinx.serialization.Decoder +import kotlinx.serialization.Encoder +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.Serializer import net.taler.wallet.kotlin.crypto.CryptoImpl.Companion.toByteArray import kotlin.math.floor import kotlin.math.pow @@ -24,6 +29,7 @@ import kotlin.math.roundToInt class AmountParserException(msg: String? = null, cause: Throwable? = null) : Exception(msg, cause) class AmountOverflowException(msg: String? = null, cause: Throwable? = null) : Exception(msg, cause) +@Serializable data class Amount( /** * name of the currency using either a three-character ISO 4217 currency code, @@ -48,7 +54,8 @@ data class Amount( val fraction: Int ) : Comparable<Amount> { - companion object { + @Serializer(forClass = Amount::class) + companion object : KSerializer<Amount> { private const val FRACTIONAL_BASE: Int = 100000000 // 1e8 @@ -114,6 +121,13 @@ data class Amount( return fraction } + override fun serialize(encoder: Encoder, value: Amount) { + encoder.encodeString(value.toJSONString()) + } + + override fun deserialize(decoder: Decoder): Amount { + return fromJSONString(decoder.decodeString()) + } } val amountStr: String diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/operations/Withdraw.kt b/src/commonMain/kotlin/net/taler/wallet/kotlin/operations/Withdraw.kt index 3fc4321..b002e32 100644 --- a/src/commonMain/kotlin/net/taler/wallet/kotlin/operations/Withdraw.kt +++ b/src/commonMain/kotlin/net/taler/wallet/kotlin/operations/Withdraw.kt @@ -15,6 +15,7 @@ */ package net.taler.wallet.kotlin.operations + import io.ktor.client.HttpClient import io.ktor.client.features.json.JsonFeature import io.ktor.client.features.json.serializer.KotlinxSerializer @@ -28,13 +29,24 @@ class Withdraw( private val httpClient: HttpClient = HttpClient { install(JsonFeature) { serializer = KotlinxSerializer() } } ) { + data class BankDetails( + val amount: Amount, + val selectionDone: Boolean, + val transferDone: Boolean, + val senderWire: String?, + val suggestedExchange: String?, + val confirmTransferUrl: String?, + val wireTypes: List<String>, + val extractedStatusUrl: String + ) + @Serializable - data class Response( + private data class Response( @SerialName("selection_done") val selectionDone: Boolean, @SerialName("transfer_done") val transferDone: Boolean, - val amount: String, // TODO Amount + val amount: Amount, @SerialName("wire_types") val wireTypes: List<String>, @SerialName("sender_wire") @@ -43,32 +55,23 @@ class Withdraw( val suggestedExchange: String?, @SerialName("confirm_transfer_url") val confirmTransferUrl: String? - ) - - data class BankDetails( - val selectionDone: Boolean, - val transferDone: Boolean, - val amount: Amount, - val senderWire: String?, - val suggestedExchange: String?, - val confirmTransferUrl: String?, - val wireTypes: List<String>, - val extractedStatusUrl: String - ) + ) { + fun toBankDetails(extractedStatusUrl: String) = BankDetails( + amount = amount, + confirmTransferUrl = confirmTransferUrl, + extractedStatusUrl = extractedStatusUrl, + selectionDone = selectionDone, + senderWire = senderWire, + suggestedExchange = suggestedExchange, + transferDone = transferDone, + wireTypes = wireTypes + ) + } suspend fun getBankInfo(talerWithdrawUri: String): BankDetails { val url = parseWithdrawUri(talerWithdrawUri) ?: throw Error("Can't parse URI $talerWithdrawUri") val response: Response = httpClient.get(url) - return BankDetails( - amount = Amount.fromJSONString(response.amount), - confirmTransferUrl = response.confirmTransferUrl, - extractedStatusUrl = url, - selectionDone = response.selectionDone, - senderWire = response.senderWire, - suggestedExchange = response.suggestedExchange, - transferDone = response.transferDone, - wireTypes = response.wireTypes - ) + return response.toBankDetails(url) } } diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt b/src/commonTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt index ec12556..857c56c 100644 --- a/src/commonTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt +++ b/src/commonTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt @@ -16,9 +16,44 @@ package net.taler.wallet.kotlin +import io.ktor.client.HttpClient +import io.ktor.client.engine.mock.MockEngine +import io.ktor.client.engine.mock.MockEngineConfig +import io.ktor.client.engine.mock.respond +import io.ktor.client.engine.mock.respondError +import io.ktor.client.features.json.JsonFeature +import io.ktor.http.ContentType.Application +import io.ktor.http.HttpStatusCode.Companion.InternalServerError +import io.ktor.http.Url +import io.ktor.http.fullPath +import io.ktor.http.headersOf +import io.ktor.http.hostWithPort import kotlinx.coroutines.CoroutineScope /** * Workaround to use suspending functions in unit tests */ -expect fun runCoroutine(block: suspend (scope : CoroutineScope) -> Unit) +expect fun runCoroutine(block: suspend (scope: CoroutineScope) -> Unit) + +fun getMockHttpClient(): HttpClient = HttpClient(MockEngine) { + install(JsonFeature) + engine { + addHandler { error("No test handler added") } + } +} + +fun HttpClient.giveJsonResponse(url: String, jsonProducer: () -> String) { + val httpConfig = engineConfig as MockEngineConfig + httpConfig.requestHandlers.removeAt(0) + httpConfig.requestHandlers.add { request -> + if (request.url.fullUrl == url) { + val headers = headersOf("Content-Type" to listOf(Application.Json.toString())) + respond(jsonProducer(), headers = headers) + } else { + respondError(InternalServerError, "Unexpected URL: ${request.url.fullUrl}") + } + } +} + +private val Url.hostWithPortIfRequired: String get() = if (port == protocol.defaultPort) host else hostWithPort +private val Url.fullUrl: String get() = "${protocol.name}://$hostWithPortIfRequired$fullPath" diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/operations/WithdrawTest.kt b/src/commonTest/kotlin/net/taler/wallet/kotlin/operations/WithdrawTest.kt index 83c55a6..b5f8553 100644 --- a/src/commonTest/kotlin/net/taler/wallet/kotlin/operations/WithdrawTest.kt +++ b/src/commonTest/kotlin/net/taler/wallet/kotlin/operations/WithdrawTest.kt @@ -16,14 +16,9 @@ package net.taler.wallet.kotlin.operations -import io.ktor.client.HttpClient -import io.ktor.client.engine.mock.MockEngine -import io.ktor.client.engine.mock.MockEngineConfig -import io.ktor.client.engine.mock.respond -import io.ktor.client.features.json.JsonFeature -import io.ktor.http.ContentType -import io.ktor.http.headersOf import net.taler.wallet.kotlin.Amount +import net.taler.wallet.kotlin.getMockHttpClient +import net.taler.wallet.kotlin.giveJsonResponse import net.taler.wallet.kotlin.operations.Withdraw.BankDetails import net.taler.wallet.kotlin.runCoroutine import kotlin.test.Test @@ -31,13 +26,7 @@ import kotlin.test.assertEquals internal class WithdrawTest { - private val httpClient = HttpClient(MockEngine) { - install(JsonFeature) - engine { - addHandler { error("No test handler added") } - } - } - private val httpConfig = httpClient.engineConfig as MockEngineConfig + private val httpClient = getMockHttpClient() private val withdraw = Withdraw(httpClient) @Test @@ -52,19 +41,16 @@ internal class WithdrawTest { transferDone = false, wireTypes = listOf("x-taler-bank") ) - val json = """{ - "selection_done": ${bankDetails.selectionDone}, - "transfer_done": ${bankDetails.transferDone}, - "amount": "${bankDetails.amount.toJSONString()}", - "wire_types": ["${bankDetails.wireTypes[0]}"], - "sender_wire": "${bankDetails.senderWire}", - "suggested_exchange": "${bankDetails.suggestedExchange}", - "confirm_transfer_url": "${bankDetails.confirmTransferUrl}" - }""".trimIndent() - httpConfig.requestHandlers.removeAt(0) - httpConfig.requestHandlers.add { - val headers = headersOf("Content-Type" to listOf(ContentType.Application.Json.toString())) - respond(json, headers = headers) + httpClient.giveJsonResponse(bankDetails.extractedStatusUrl) { + """{ + "selection_done": ${bankDetails.selectionDone}, + "transfer_done": ${bankDetails.transferDone}, + "amount": "${bankDetails.amount.toJSONString()}", + "wire_types": ["${bankDetails.wireTypes[0]}"], + "sender_wire": "${bankDetails.senderWire}", + "suggested_exchange": "${bankDetails.suggestedExchange}", + "confirm_transfer_url": "${bankDetails.confirmTransferUrl}" + }""".trimIndent() } runCoroutine { val details = |