Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ jobs:
os: ubuntu
- target: jsNode
os: ubuntu
# TODO: wasmJs times out on bulk tests
# - target: wasmJsBrowser
# os: ubuntu
- target: wasmJsBrowser
os: ubuntu
- target: wasmJsNode
os: ubuntu
- target: linuxX64
Expand Down
8 changes: 6 additions & 2 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ set windows-shell := ["C:\\Program Files\\Git\\bin\\sh.exe", "-c"]
_default:
just --list

test-server-cmd := "npx -y http-server src/commonTest/resources/data -e json -p 8080 --cors"

# Serve PokeAPI data from static files
test-server:
npx -y http-server src/commonTest/resources/data -e json -p 8080 --cors
{{ test-server-cmd }}

# Spawn a background job serving PokeAPI data from static files
test-server-background:
npx -y http-server src/commonTest/resources/data -e json -p 8080 --cors &
{{ test-server-cmd }} &
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.sargunv.pokekotlin.util
package dev.sargunv.pokekotlin.internal

import io.ktor.client.engine.darwin.Darwin

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package dev.sargunv.pokekotlin.client
@file:JvmName("PokeApiClient")

package dev.sargunv.pokekotlin

import de.jensklingenberg.ktorfit.Ktorfit.Builder
import de.jensklingenberg.ktorfit.http.GET
import de.jensklingenberg.ktorfit.http.Path
import de.jensklingenberg.ktorfit.http.Query
import dev.sargunv.pokekotlin.internal.PokeApiConverter
import dev.sargunv.pokekotlin.internal.PokeApiJson
import dev.sargunv.pokekotlin.internal.getDefaultEngine
import dev.sargunv.pokekotlin.model.Ability
import dev.sargunv.pokekotlin.model.ApiResourceList
import dev.sargunv.pokekotlin.model.Berry
Expand Down Expand Up @@ -55,14 +60,15 @@ import dev.sargunv.pokekotlin.model.SuperContestEffect
import dev.sargunv.pokekotlin.model.Type
import dev.sargunv.pokekotlin.model.Version
import dev.sargunv.pokekotlin.model.VersionGroup
import dev.sargunv.pokekotlin.util.getDefaultEngine
import io.ktor.client.HttpClient
import io.ktor.client.HttpClientConfig
import io.ktor.client.engine.HttpClientEngine
import io.ktor.client.plugins.cache.HttpCache
import io.ktor.client.plugins.cache.storage.CacheStorage
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.http.ContentType
import io.ktor.serialization.kotlinx.json.json
import kotlin.jvm.JvmName

interface PokeApi {

Expand Down Expand Up @@ -557,6 +563,7 @@ interface PokeApi {
companion object : PokeApi by PokeApi()
}

@JvmName("create")
fun PokeApi(
baseUrl: String = "https://pokeapi.co/api/v2/",
engine: HttpClientEngine = getDefaultEngine(),
Expand All @@ -567,10 +574,11 @@ fun PokeApi(
.baseUrl(baseUrl)
.httpClient(
HttpClient(engine) {
this.configure()
this.install(HttpCache) { cacheStorage?.let { privateStorage(it) } }
this.install(ContentNegotiation) { json(PokeApiJson) }
configure()
install(HttpCache) { cacheStorage?.let { privateStorage(it) } }
install(ContentNegotiation) { json(PokeApiJson, ContentType.Any) }
}
)
.converterFactories(PokeApiConverter.Factory)
.build()
.createPokeApi()
13 changes: 13 additions & 0 deletions src/commonMain/kotlin/dev/sargunv/pokekotlin/PokeApiException.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package dev.sargunv.pokekotlin

import io.ktor.http.HttpStatusCode

sealed class PokeApiException : Throwable {
constructor(message: String) : super(message)

constructor(cause: Throwable) : super(cause)

class HttpStatus(val status: HttpStatusCode) : PokeApiException(status.toString())

class UnknownException(cause: Throwable) : PokeApiException(cause)
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.sargunv.pokekotlin.util
package dev.sargunv.pokekotlin.internal

import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.SerialDescriptor
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package dev.sargunv.pokekotlin.internal

import de.jensklingenberg.ktorfit.Ktorfit
import de.jensklingenberg.ktorfit.converter.Converter
import de.jensklingenberg.ktorfit.converter.KtorfitResult
import de.jensklingenberg.ktorfit.converter.TypeData
import dev.sargunv.pokekotlin.PokeApiException
import io.ktor.client.call.body
import io.ktor.client.statement.HttpResponse
import io.ktor.http.isSuccess

internal class PokeApiConverter(private val typeData: TypeData) :
Converter.SuspendResponseConverter<HttpResponse, Any> {
override suspend fun convert(result: KtorfitResult): Any {
return when (result) {
is KtorfitResult.Failure -> throw PokeApiException.UnknownException(result.throwable)
is KtorfitResult.Success -> {
val status = result.response.status
when {
status.isSuccess() -> result.response.body<Any>(typeData.typeInfo)
else -> throw PokeApiException.HttpStatus(status)
}
}
}
}

internal object Factory : Converter.Factory {
override fun suspendResponseConverter(
typeData: TypeData,
ktorfit: Ktorfit,
): Converter.SuspendResponseConverter<HttpResponse, Any> = PokeApiConverter(typeData)
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package dev.sargunv.pokekotlin.client
package dev.sargunv.pokekotlin.internal

import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonNamingStrategy

@OptIn(ExperimentalSerializationApi::class)
val PokeApiJson = Json {
internal val PokeApiJson = Json {
prettyPrint = true
ignoreUnknownKeys = true
namingStrategy = JsonNamingStrategy.SnakeCase
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.sargunv.pokekotlin.util
package dev.sargunv.pokekotlin.internal

import io.ktor.client.engine.HttpClientEngine

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package dev.sargunv.pokekotlin.model

import dev.sargunv.pokekotlin.util.DelegatingSerializer
import dev.sargunv.pokekotlin.internal.DelegatingSerializer
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable

Expand Down
2 changes: 2 additions & 0 deletions src/commonTest/kotlin/dev/sargunv/pokekotlin/test/BulkTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package dev.sargunv.pokekotlin.test

import dev.sargunv.pokekotlin.model.ResourceSummary
import dev.sargunv.pokekotlin.model.ResourceSummaryList
import kotlin.test.Ignore
import kotlin.test.Test
import kotlin.test.fail
import kotlinx.coroutines.test.runTest

@Ignore
class BulkTest {

private suspend fun testCase(cat: String, ids: List<Int>, getObject: suspend (Int) -> Any) {
Expand Down
15 changes: 12 additions & 3 deletions src/commonTest/kotlin/dev/sargunv/pokekotlin/test/LiveTest.kt
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
package dev.sargunv.pokekotlin.test

import dev.sargunv.pokekotlin.client.PokeApi
import dev.sargunv.pokekotlin.PokeApi
import dev.sargunv.pokekotlin.PokeApiException
import io.ktor.http.HttpStatusCode.Companion.NotFound
import kotlin.test.Ignore
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlinx.coroutines.test.runTest

@Ignore
class LiveTest {

@Test fun liveObject() = runTest { assertEquals("sitrus", PokeApi.getBerry(10).name) }
@Test fun resource() = runTest { assertEquals("sitrus", PokeApi.getBerry(10).name) }

@Test
fun liveList() = runTest {
fun list() = runTest {
assertEquals(PokeApi.getMoveList(0, 50).results[25], PokeApi.getMoveList(25, 50).results[0])
}

@Test
fun notFound() = runTest {
val e = assertFailsWith(PokeApiException.HttpStatus::class) { PokeApi.getMove(-1) }
assertEquals(NotFound, e.status)
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package dev.sargunv.pokekotlin.test

import dev.sargunv.pokekotlin.client.PokeApi
import dev.sargunv.pokekotlin.client.PokeApiJson
import dev.sargunv.pokekotlin.PokeApi
import dev.sargunv.pokekotlin.internal.PokeApiJson
import dev.sargunv.pokekotlin.model.ApiResourceList
import dev.sargunv.pokekotlin.model.NamedApiResourceList
import io.ktor.client.plugins.api.createClientPlugin
Expand All @@ -13,7 +13,7 @@ import kotlinx.serialization.json.io.decodeFromSource

@OptIn(ExperimentalSerializationApi::class)
private val OffsetLimitPlugin =
createClientPlugin("OffsetLimitPlugin") {
createClientPlugin("OffsetLimit") {
transformResponseBody { response, content, requestedType ->
val offset = response.request.url.parameters["offset"]?.toIntOrNull() ?: 0
val limit = response.request.url.parameters["limit"]?.toIntOrNull() ?: 20
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package dev.sargunv.pokekotlin.test

import dev.sargunv.pokekotlin.PokeApi
import dev.sargunv.pokekotlin.PokeApiException
import io.ktor.http.HttpStatusCode.Companion.NotFound
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlinx.coroutines.test.runTest

class PokeApiExceptionTest {
@Test
fun notFoundError() = runTest {
val e = assertFailsWith(PokeApiException.HttpStatus::class) { LocalPokeApi.getMove(-1) }
assertEquals(NotFound, e.status)
}

@Test
fun badUrlError() = runTest {
assertFailsWith(PokeApiException.UnknownException::class) {
PokeApi("https://localhost:12345/").getBerry(10)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.sargunv.pokekotlin.util
package dev.sargunv.pokekotlin.internal

import io.ktor.client.engine.js.Js

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.sargunv.pokekotlin.util
package dev.sargunv.pokekotlin.internal

import io.ktor.client.engine.okhttp.OkHttp

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package dev.sargunv.pokekotlin.test

import dev.sargunv.pokekotlin.client.PokeApi
import dev.sargunv.pokekotlin.client.PokeApiJson
import dev.sargunv.pokekotlin.PokeApi
import dev.sargunv.pokekotlin.internal.PokeApiJson
import io.ktor.client.HttpClient
import io.ktor.client.request.get
import io.ktor.client.statement.bodyAsText
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.sargunv.pokekotlin.util
package dev.sargunv.pokekotlin.internal

import io.ktor.client.engine.curl.Curl

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.sargunv.pokekotlin.util
package dev.sargunv.pokekotlin.internal

import io.ktor.client.engine.winhttp.WinHttp

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.sargunv.pokekotlin.util
package dev.sargunv.pokekotlin.internal

import io.ktor.client.engine.js.Js

Expand Down