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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
20 changes: 16 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,26 @@ on:
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest
test:
strategy:
matrix:
include:
- runner: ubuntu-latest
target: jvm
- runner: macos-latest
target: macosArm64
- runner: ubuntu-latest
target: linuxX64
- runner: windows-latest
target: mingwX64
runs-on: "${{ matrix.runner }}"
name: "test (${{ matrix.target }})"
steps:
- uses: "actions/checkout@v4"
with:
fetch-depth: 0
- uses: "./.github/actions/setup"
- run: "./gradlew build"
- run: "./gradlew ${{ matrix.target }}Test"

build-docs:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -49,7 +61,7 @@ jobs:

all-good:
needs:
- "build"
- "test"
- "check-format"
- "build-docs"
runs-on: "ubuntu-latest"
Expand Down
40 changes: 37 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,58 @@ kotlin {

jvm()

// native tier 1
macosX64()
macosArm64()
iosSimulatorArm64()
iosX64()
iosArm64()

// native tier 2
linuxX64()
linuxArm64()
watchosSimulatorArm64()
watchosX64()
watchosArm32()
watchosArm64()
tvosSimulatorArm64()
tvosX64()
tvosArm64()

// native tier 3
mingwX64()
watchosDeviceArm64()

// native tier 3 - but no suitable Ktor engine available
// androidNativeArm32()
// androidNativeArm64()
// androidNativeX86()
// androidNativeX64()

applyDefaultHierarchyTemplate()

sourceSets {
jvmMain.dependencies {
commonMain.dependencies {
implementation(kotlin("stdlib"))
implementation(libs.kotlinx.serialization.json)
implementation(libs.ktor.client.content.negotiation)
implementation(libs.ktor.serialization.kotlinx.json)
implementation(libs.ktorfit)
}

jvmTest.dependencies {
jvmMain.dependencies { implementation(libs.ktor.client.okhttp) }
appleMain.dependencies { implementation(libs.ktor.client.darwin) }
linuxMain.dependencies { implementation(libs.ktor.client.curl) }
mingwMain.dependencies { implementation(libs.ktor.client.winhttp) }

commonTest.dependencies {
implementation(kotlin("test"))
implementation(kotlin("reflect"))
implementation(libs.kotlinx.coroutines.test)
implementation(libs.kotlinx.io)
implementation(libs.ktor.client.mock)
}

jvmTest.dependencies { implementation(kotlin("reflect")) }
}
}

Expand Down
2 changes: 2 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
kotlin.code.style=official
kotlin.incremental.wasm=true
kotlin.daemon.jvmargs=-Xmx2048M
org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled
org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true
org.gradle.configuration-cache=false
org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8
6 changes: 6 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-t
kotlinx-io = { module = "org.jetbrains.kotlinx:kotlinx-io-core", version.ref = "kotlinx-io" }
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
ktorfit = { module = "de.jensklingenberg.ktorfit:ktorfit-lib", version.ref = "gradle-ktorfit" }
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" }
ktor-client-winhttp = { module = "io.ktor:ktor-client-winhttp", version.ref = "ktor" }
ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" }
ktor-client-curl = { module = "io.ktor:ktor-client-curl", version.ref = "ktor" }
ktor-client-js = { module = "io.ktor:ktor-client-js", version.ref = "ktor" }
ktor-client-mock = { module = "io.ktor:ktor-client-mock", version.ref = "ktor" }
ktor-client-content-negotiation = { module = "io.ktor:ktor-client-content-negotiation", version.ref = "ktor" }
ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package dev.sargunv.pokekotlin.util

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

internal actual fun getDefaultEngine() = Darwin.create()
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.sargunv.pokekotlin.client

import de.jensklingenberg.ktorfit.Ktorfit.Builder
import dev.sargunv.pokekotlin.util.getDefaultEngine
import io.ktor.client.HttpClient
import io.ktor.client.HttpClientConfig
import io.ktor.client.engine.HttpClientEngine
Expand All @@ -9,7 +10,7 @@ import io.ktor.serialization.kotlinx.json.json

class PokeApiClient(
baseUrl: String = "https://pokeapi.co/api/v2/",
engine: HttpClientEngine? = null,
engine: HttpClientEngine = getDefaultEngine(),
configure: HttpClientConfig<*>.() -> Unit = {},
) : PokeApi by getInstance(baseUrl, engine, configure) {
private companion object {
Expand All @@ -20,16 +21,12 @@ class PokeApiClient(

private fun getInstance(
baseUrl: String,
engine: HttpClientEngine?,
engine: HttpClientEngine,
configure: HttpClientConfig<*>.() -> Unit,
) =
Builder()
.baseUrl(baseUrl)
.httpClient(
client =
if (engine == null) HttpClient { configureWithJson(configure) }
else HttpClient(engine) { configureWithJson(configure) }
)
.httpClient(HttpClient(engine) { configureWithJson(configure) })
.build()
.createPokeApi()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package dev.sargunv.pokekotlin.util

import io.ktor.client.engine.HttpClientEngine

internal expect fun getDefaultEngine(): HttpClientEngine
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ class BulkTest {
ids.forEachIndexed { i, id ->
print("$cat ${i + 1}/$count (id=$id) ... ")
try {
val o = getObject(id)
getObject(id)
println("deserialized!")
} catch (e: Throwable) {
println("ERROR: ${e.javaClass.simpleName}: ${e.message}")
println("ERROR: ${e::class.simpleName}: ${e.message}")
pass = false
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import io.ktor.client.request.HttpRequestData
import io.ktor.client.request.HttpResponseData
import io.ktor.http.HttpStatusCode
import io.ktor.http.headersOf
import kotlin.io.path.Path
import kotlin.io.path.exists
import kotlin.io.path.readText
import io.ktor.utils.io.readText
import kotlinx.io.IOException
import kotlinx.io.buffered
import kotlinx.io.files.Path
import kotlinx.io.files.SystemFileSystem
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.buildJsonArray
Expand All @@ -35,14 +37,23 @@ object MockServer {
return PokeApiJson.encodeToString(newObj)
}

fun readFile(path: Path) =
try {
SystemFileSystem.source(path).buffered().use { it.readText() }
} catch (e: IOException) {
println("Error reading file: ${e.message}")
null
}

private fun MockRequestHandleScope.dispatch(request: HttpRequestData): HttpResponseData {
val basePath = request.url.encodedPath
val limit = request.url.parameters["limit"]?.toInt()
val file = Path("src/jvmTest/resources/data" + basePath + "index.json")
return if (file.exists()) {
val text = file.readText()
val content = if (limit != null) limit(text, limit) else text
respond(content = content, headers = headersOf("content-type", "application/json"))
} else respondError(HttpStatusCode.NotFound)
val file = Path("src/commonTest/resources/data" + basePath + "index.json")
val text = readFile(file) ?: return respondError(HttpStatusCode.NotFound)
val responseContent = if (limit != null) limit(text, limit) else text
return respond(
content = responseContent,
headers = headersOf("content-type", "application/json"),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import dev.sargunv.pokekotlin.model.Name
import dev.sargunv.pokekotlin.model.NamedApiResource
import dev.sargunv.pokekotlin.test.MockServer
import kotlin.test.Test
import kotlin.test.assertContains
import kotlin.test.assertEquals
import kotlin.test.assertNotEquals
import kotlinx.coroutines.test.runTest

class BerryTest {
Expand All @@ -22,7 +24,7 @@ class BerryTest {
assertEquals(35, smoothness)
assertEquals(8, soilDryness)
assertEquals(NamedApiResource("hard", "berry-firmness", 3), firmness)
assert(flavors.isNotEmpty())
assertNotEquals(0, flavors.size)
assertEquals(NamedApiResource("durin-berry", "item", 159), item)
assertEquals(NamedApiResource("water", "type", 11), naturalGiftType)
}
Expand All @@ -33,8 +35,8 @@ class BerryTest {
MockServer.client.getBerryFirmness(3).apply {
assertEquals(3, id)
assertEquals("hard", name)
assert(NamedApiResource("rawst", "berry", 4) in berries)
assert(Name(name = "Hard", language = NamedApiResource("en", "language", 9)) in names)
assertContains(berries, NamedApiResource("rawst", "berry", 4))
assertContains(names, Name(name = "Hard", language = NamedApiResource("en", "language", 9)))
}
}

Expand All @@ -44,8 +46,11 @@ class BerryTest {
assertEquals(3, id)
assertEquals("sweet", name)
assertEquals(NamedApiResource("cute", "contest-type", 3), contestType)
assert(FlavorBerryMap(potency = 10, berry = NamedApiResource("leppa", "berry", 6)) in berries)
assert(Name(name = "Sweet", language = NamedApiResource("en", "language", 9)) in names)
assertContains(
berries,
FlavorBerryMap(potency = 10, berry = NamedApiResource("leppa", "berry", 6)),
)
assertContains(names, Name(name = "Sweet", language = NamedApiResource("en", "language", 9)))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import dev.sargunv.pokekotlin.model.FlavorText
import dev.sargunv.pokekotlin.model.NamedApiResource
import dev.sargunv.pokekotlin.test.MockServer
import kotlin.test.Test
import kotlin.test.assertContains
import kotlin.test.assertEquals
import kotlinx.coroutines.test.runTest

Expand All @@ -17,12 +18,13 @@ class ContestTest {
assertEquals(4, id)
assertEquals("smart", name)
assertEquals(NamedApiResource("bitter", "berry-flavor", 4), berryFlavor)
assert(
assertContains(
names,
ContestName(
name = "Smart",
color = "Green",
language = NamedApiResource("en", "language", 9),
) in names
),
)
}
}
Expand All @@ -33,17 +35,19 @@ class ContestTest {
assertEquals(27, id)
assertEquals(2, appeal)
assertEquals(0, jam)
assert(
assertContains(
effectEntries,
Effect(
effect = "If user appeals first this turn, earns six points instead of two.",
language = NamedApiResource("en", "language", 9),
) in effectEntries
),
)
assert(
assertContains(
flavorTextEntries,
FlavorText(
flavorText = "The appeal works great if performed first.",
language = NamedApiResource("en", "language", 9),
) in flavorTextEntries
),
)
}
}
Expand All @@ -53,13 +57,14 @@ class ContestTest {
MockServer.client.getSuperContestEffect(14).apply {
assertEquals(14, id)
assertEquals(2, appeal)
assert(
assertContains(
flavorTextEntries,
FlavorText(
flavorText = "Makes the order of contestants random in the next turn.",
language = NamedApiResource("en", "language", 9),
) in flavorTextEntries
),
)
assert(NamedApiResource("assist", "move", 274) in moves)
assertContains(moves, NamedApiResource("assist", "move", 274))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import dev.sargunv.pokekotlin.model.Name
import dev.sargunv.pokekotlin.model.NamedApiResource
import dev.sargunv.pokekotlin.test.MockServer
import kotlin.test.Test
import kotlin.test.assertContains
import kotlin.test.assertEquals
import kotlinx.coroutines.test.runTest

Expand All @@ -15,7 +16,10 @@ class EncounterTest {
assertEquals(5, id)
assertEquals("surf", name)
assertEquals(14, order)
assert(Name(name = "Surfing", language = NamedApiResource("en", "language", 9)) in names)
assertContains(
names,
Name(name = "Surfing", language = NamedApiResource("en", "language", 9)),
)
}
}

Expand All @@ -24,8 +28,8 @@ class EncounterTest {
MockServer.client.getEncounterCondition(5).apply {
assertEquals(5, id)
assertEquals("radio", name)
assert(NamedApiResource("radio-hoenn", "encounter-condition-value", 15) in values)
assert(Name(name = "Radio", language = NamedApiResource("en", "language", 9)) in names)
assertContains(values, NamedApiResource("radio-hoenn", "encounter-condition-value", 15))
assertContains(names, Name(name = "Radio", language = NamedApiResource("en", "language", 9)))
}
}

Expand All @@ -35,7 +39,10 @@ class EncounterTest {
assertEquals(5, id)
assertEquals("time-night", name)
assertEquals(NamedApiResource("time", "encounter-condition", 2), condition)
assert(Name(name = "At night", language = NamedApiResource("en", "language", 9)) in names)
assertContains(
names,
Name(name = "At night", language = NamedApiResource("en", "language", 9)),
)
}
}
}
Loading