From 5a8a75d37e405ceba01c1526ac192c6939ebde4b Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Thu, 16 May 2024 15:25:24 +0200 Subject: [PATCH 1/6] Update to Kotlin RC3, and Arrow 2 Alpha 1 --- .github/workflows/build.yml | 4 -- .github/workflows/githubpages.yaml | 3 - .github/workflows/publish.yml | 2 - .github/workflows/pull_request.yaml | 23 +++++++ .gitignore | 3 +- build.gradle.kts | 54 +++++++++------ gradle.properties | 3 +- gradle/wrapper/gradle-wrapper.properties | 2 +- libs.versions.toml | 25 +++---- .../kotlin/io/github/nomisrev/JsonPath.kt | 21 +++--- .../io/github/nomisrev/JsonPathEvery.kt | 66 +++++++++---------- .../kotlin/io/github/nomisrev/optics.kt | 49 +++++++------- .../kotlin/io/github/nomisrev/JsonDSLSpec.kt | 2 +- 13 files changed, 139 insertions(+), 118 deletions(-) create mode 100644 .github/workflows/pull_request.yaml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5d04f2a..33070fd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,10 +8,6 @@ on: branches: - main -env: - JAVA_OPTS: -Xms512m -Xmx1024m - GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.configureondemand=true -Dorg.gradle.jvmargs=-Xmx3g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8" - jobs: check: runs-on: ubuntu-latest diff --git a/.github/workflows/githubpages.yaml b/.github/workflows/githubpages.yaml index ff32486..7a10c83 100644 --- a/.github/workflows/githubpages.yaml +++ b/.github/workflows/githubpages.yaml @@ -4,9 +4,6 @@ on: release: types: [published] -env: - GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.kotlin.dsl.internal.io.timeout=120000 -Dorg.gradle.jvmargs="-Xmx5g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8" - jobs: githubpages: runs-on: ubuntu-latest diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 0490dc3..4ee8e4c 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -10,8 +10,6 @@ on: type: string env: - JAVA_OPTS: -Xms1g -Xmx3g - GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.configureondemand=true -Dorg.gradle.jvmargs=-Xmx3g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8" ORG_GRADLE_PROJECT_mavenCentralUsername: '${{ secrets.SONATYPE_USER }}' ORG_GRADLE_PROJECT_mavenCentralPassword: '${{ secrets.SONATYPE_PWD }}' ORG_GRADLE_PROJECT_signingInMemoryKeyId: '${{ secrets.SIGNING_KEY_ID }}' diff --git a/.github/workflows/pull_request.yaml b/.github/workflows/pull_request.yaml new file mode 100644 index 0000000..6dfb596 --- /dev/null +++ b/.github/workflows/pull_request.yaml @@ -0,0 +1,23 @@ +name: "Pull Request" + +on: [pull_request] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Java + uses: actions/setup-java@v3 + with: + distribution: 'zulu' + java-version: 11 + + - name: Build + uses: gradle/gradle-build-action@v2 + with: + arguments: build diff --git a/.gitignore b/.gitignore index 32da301..1831c03 100644 --- a/.gitignore +++ b/.gitignore @@ -170,4 +170,5 @@ kotlin-js-store # End of https://www.toptal.com/developers/gitignore/api/intellij+all,kotlin,gradle,macos -gradle-build-scan.txt \ No newline at end of file +gradle-build-scan.txt +.kotlin/ \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index d62f929..bbc7a0f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,23 +2,21 @@ import kotlinx.knit.KnitPluginExtension import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import io.gitlab.arturbosch.detekt.Detekt import io.gitlab.arturbosch.detekt.extensions.DetektExtension -import kotlinx.kover.api.KoverTaskExtension -import org.gradle.api.JavaVersion.VERSION_1_8 -import org.gradle.api.Project +import org.gradle.api.JavaVersion.VERSION_11 import org.gradle.api.tasks.testing.logging.TestExceptionFormat import org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED -import org.gradle.api.tasks.testing.logging.TestLogEvent.PASSED import org.gradle.api.tasks.testing.logging.TestLogEvent.SKIPPED import org.gradle.api.tasks.testing.logging.TestLogEvent.STANDARD_ERROR import org.gradle.api.tasks.testing.logging.TestLogEvent.STANDARD_OUT import org.gradle.kotlin.dsl.configure import org.gradle.kotlin.dsl.withType import org.jetbrains.dokka.gradle.DokkaTask +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl plugins { application - alias(libs.plugins.kotlin.multiplatform) - alias(libs.plugins.arrow.kotlin) + alias(libs.plugins.kotlin) alias(libs.plugins.kotest.multiplatform) alias(libs.plugins.detekt) alias(libs.plugins.dokka) @@ -32,16 +30,14 @@ repositories { mavenCentral() } -group = property("projects.group").toString() - java { - sourceCompatibility = VERSION_1_8 - targetCompatibility = VERSION_1_8 + sourceCompatibility = VERSION_11 + targetCompatibility = VERSION_11 } tasks { withType().configureEach { - kotlinOptions.jvmTarget = "1.8" + this.compilerOptions.jvmTarget.set(JvmTarget.JVM_11) } withType().configureEach { @@ -49,7 +45,7 @@ tasks { useJUnitPlatform() testLogging { exceptionFormat = TestExceptionFormat.FULL - events = setOf(PASSED, SKIPPED, FAILED, STANDARD_OUT, STANDARD_ERROR) + events = setOf(SKIPPED, FAILED, STANDARD_OUT, STANDARD_ERROR) } } @@ -59,10 +55,36 @@ tasks { } kotlin { + explicitApi() + + jvm() + js(IR) { + browser() + nodejs() + } + + @OptIn(ExperimentalWasmDsl::class) + wasmJs() + linuxX64() + macosX64() + macosArm64() + iosSimulatorArm64() + iosX64() + linuxArm64() + watchosSimulatorArm64() + watchosX64() + watchosArm32() + watchosArm64() + tvosSimulatorArm64() + tvosX64() + tvosArm64() + iosArm64() + mingwX64() + sourceSets { commonMain { dependencies { - implementation(kotlin("stdlib-common")) + implementation(kotlin("stdlib")) api(libs.arrow.optics) api(libs.kotlinx.serialization.json) } @@ -118,12 +140,6 @@ tasks { getByName("knitPrepare").dependsOn(getTasksByName("dokka", true)) - register("cleanDocs") { - val folder = file("docs").also { it.mkdir() } - val docsContent = folder.listFiles().filter { it != folder } - delete(docsContent) - } - withType().configureEach { reports { html.required.set(true) diff --git a/gradle.properties b/gradle.properties index 8310438..68b827c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,6 @@ kotlin.code.style=official -projects.group=io.github.nomisrev -kotlin.mpp.stability.nowarn=true +GROUP=io.github.nomisrev SONATYPE_HOST=S01 RELEASE_SIGNING_ENABLED=true diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ac72c34..b82aa23 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/libs.versions.toml b/libs.versions.toml index 4eceae1..414b1b4 100644 --- a/libs.versions.toml +++ b/libs.versions.toml @@ -1,25 +1,19 @@ [versions] -arrow = "1.2.1" +arrow = "2.0.0-alpha.1" arrowGradle = "0.12.0-rc.6" -coroutines = "1.7.3" -dokka = "1.9.0" -kotlin = "1.9.10" -kotest = "5.7.2" -kotest-plugin = "5.7.2" -kover = "0.7.3" +dokka = "1.9.20" +kotlin = "2.0.0-RC3" +kotest = "5.9.0" +kover = "0.8.0" detekt = "1.23.1" kotest-arrow="1.4.0" -kotlinx-json="1.6.0" +kotlinx-json="1.6.3" kotlinx-knit="0.4.0" -publish="0.25.3" +publish="0.28.0" knit="0.4.0" [libraries] -arrow-core = { module = "io.arrow-kt:arrow-core", version.ref = "arrow" } arrow-optics = { module = "io.arrow-kt:arrow-optics", version.ref = "arrow" } -arrow-fx = { module = "io.arrow-kt:arrow-fx-coroutines", version.ref = "arrow" } -coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" } -coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" } dokka-core = { module = "org.jetbrains.dokka:dokka-core", version.ref = "dokka" } kotest-assertionsCore = { module = "io.kotest:kotest-assertions-core", version.ref = "kotest" } kotest-frameworkEngine = { module = "io.kotest:kotest-framework-engine", version.ref = "kotest" } @@ -32,11 +26,10 @@ kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serializa kotlinx-knit-test = { module = "org.jetbrains.kotlinx:kotlinx-knit-test", version.ref = "kotlinx-knit" } [plugins] -arrow-formatter = { id = "io.arrow-kt.arrow-gradle-config-formatter", version.ref = "arrowGradle" } -arrow-kotlin = { id = "io.arrow-kt.arrow-gradle-config-kotlin", version.ref = "arrowGradle" } +kotlin = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" } kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" } -kotest-multiplatform = { id = "io.kotest.multiplatform", version.ref = "kotest-plugin" } +kotest-multiplatform = { id = "io.kotest.multiplatform", version.ref = "kotest" } kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } kotlinx-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } diff --git a/src/commonMain/kotlin/io/github/nomisrev/JsonPath.kt b/src/commonMain/kotlin/io/github/nomisrev/JsonPath.kt index f910942..56952db 100644 --- a/src/commonMain/kotlin/io/github/nomisrev/JsonPath.kt +++ b/src/commonMain/kotlin/io/github/nomisrev/JsonPath.kt @@ -4,8 +4,8 @@ package io.github.nomisrev import arrow.core.Option import arrow.core.None import arrow.core.Some -import arrow.optics.Every import arrow.optics.Optional +import arrow.optics.Traversal import arrow.optics.typeclasses.At import arrow.optics.typeclasses.Index import arrow.optics.typeclasses.FilterIndex @@ -21,7 +21,6 @@ import kotlinx.serialization.serializer * Starting point of the JsonPath DSL * This represents the _root_ of the path you want to define in your `JsonElement` */ -@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE") public object JsonPath : Optional by Optional.id() /** Extract a [Boolean] value from a [JsonElement] */ @@ -63,8 +62,8 @@ public inline val Optional.`null`: Optional.every: Every - inline get() = this compose Every.jsonElement() +public inline val Optional.every: Traversal + inline get() = this compose Traversal.jsonElement() /** * Select value at [selector]. The following syntax is supported for [selector]: @@ -96,14 +95,14 @@ public fun Optional.select( */ public fun Optional.selectEvery( selector: String -): Every { +): Traversal { val inBrackets = matchNameInBrackets(selector) val ixs = matchIndicesInBrackets(selector) val startIx = matchStartIndex(selector) val startEndIx = matchStartEndIndex(selector) return when { inBrackets != null -> get(inBrackets) - selector == "*" -> this compose Every.jsonElement() // inline definition of [every] + selector == "*" -> this compose Traversal.jsonElement() // inline definition of [every] ixs != null -> filterIndex { it in ixs } startIx != null -> filterIndex { it >= startIx } startEndIx != null -> get(startEndIx.first until startEndIx.second) @@ -136,9 +135,9 @@ public fun Optional.pathEvery( path: String, fieldDelimiter: String = ".", indexDelimiter: String = "[" -): Every = +): Traversal = path.splitTwice(fieldDelimiter, indexDelimiter).fold(this) { - acc: Every, pathSelector -> acc.selectEvery(pathSelector) + acc: Traversal, pathSelector -> acc.selectEvery(pathSelector) } /** @@ -154,7 +153,7 @@ public fun Optional.at( /** Select keys out of an [JsonObject] with the given [predicate] */ public fun Optional.filterKeys( predicate: (keys: String) -> Boolean -): Every = +): Traversal = `object` compose FilterIndex.map().filter(predicate) /** Select a [property] out of a [JsonObject] */ @@ -172,13 +171,13 @@ public operator fun Optional.get( /** Select all indices from the [range] out of a [JsonArray] */ public operator fun Optional.get( range: ClosedRange -): Every = +): Traversal = filterIndex { it in range } /** Select an indices out of a [JsonArray] with the given [predicate] */ public fun Optional.filterIndex( predicate: (index: Int) -> Boolean -): Every = +): Traversal = array compose FilterIndex.list().filter(predicate) /** Extract a value of type [A] with an _implicit_ KotlinX Serializer */ diff --git a/src/commonMain/kotlin/io/github/nomisrev/JsonPathEvery.kt b/src/commonMain/kotlin/io/github/nomisrev/JsonPathEvery.kt index 8fa105f..22001f3 100644 --- a/src/commonMain/kotlin/io/github/nomisrev/JsonPathEvery.kt +++ b/src/commonMain/kotlin/io/github/nomisrev/JsonPathEvery.kt @@ -4,7 +4,7 @@ package io.github.nomisrev import arrow.core.None import arrow.core.Option import arrow.core.Some -import arrow.optics.Every +import arrow.optics.Traversal import arrow.optics.Optional import arrow.optics.typeclasses.At import arrow.optics.typeclasses.FilterIndex @@ -18,46 +18,46 @@ import kotlinx.serialization.json.JsonObject import kotlinx.serialization.serializer /** Extract a [Boolean] value from a [JsonElement] */ -public inline val Every.boolean: Every +public inline val Traversal.boolean: Traversal inline get() = this@boolean compose Optional.jsonBoolean() /** Extract a [String] value from a [JsonElement] */ -public inline val Every.string: Every +public inline val Traversal.string: Traversal inline get() = this compose Optional.jsonString() /** Extract a [Double] value from a [JsonElement] */ -public inline val Every.double: Every +public inline val Traversal.double: Traversal inline get() = this compose Optional.jsonDouble() /** Extract a [Float] value from a [JsonElement] */ -public inline val Every.float: Every +public inline val Traversal.float: Traversal inline get() = this compose Optional.jsonFloat() /** Extract a [Long] value from a [JsonElement] */ -public inline val Every.long: Every +public inline val Traversal.long: Traversal inline get() = this compose Optional.jsonLong() /** Extract a [Int] value from a [JsonElement] */ -public inline val Every.int: Every +public inline val Traversal.int: Traversal inline get() = this compose Optional.jsonInt() /** Extract a [List] of [JsonElement] from a [JsonElement] */ -public inline val Every.array: Every> +public inline val Traversal.array: Traversal> inline get() = this compose Optional.jsonArray() /** Extract a [Map] of [String] to [JsonElement] from a [JsonElement] */ @Suppress("TopLevelPropertyNaming") -public inline val Every.`object`: Every> +public inline val Traversal.`object`: Traversal> inline get() = this compose Optional.jsonObject() /** Extract `null` from a [JsonElement] */ @Suppress("TopLevelPropertyNaming") -public inline val Every.`null`: Every +public inline val Traversal.`null`: Traversal inline get() = this compose Optional.jsonNull() /** Select _every_ entry in [JsonArray] and [JsonObject] */ -public inline val Every.every: Every - inline get() = this compose Every.jsonElement() +public inline val Traversal.every: Traversal + inline get() = this compose Traversal.jsonElement() /** * Select value at [selector]. The following syntax is supported for [selector]: @@ -65,7 +65,7 @@ public inline val Every.every: Every.select(selector: String): Every { +public fun Traversal.select(selector: String): Traversal { val inBrackets = matchNameInBrackets(selector) val ix = matchIndexInBrackets(selector) return when { @@ -85,16 +85,16 @@ public fun Every.select(selector: String): Every.selectEvery( +public fun Traversal.selectEvery( selector: String -): Every { +): Traversal { val inBrackets = matchNameInBrackets(selector) val ixs = matchIndicesInBrackets(selector) val startIx = matchStartIndex(selector) val startEndIx = matchStartEndIndex(selector) return when { inBrackets != null -> get(inBrackets) - selector == "*" -> this compose Every.jsonElement() // inline definition of [every] + selector == "*" -> this compose Traversal.jsonElement() // inline definition of [every] ixs != null -> filterIndex { it in ixs } startIx != null -> filterIndex { it >= startIx } startEndIx != null -> get(startEndIx.first until startEndIx.second) @@ -109,11 +109,11 @@ public fun Every.selectEvery( * JsonPath.path("addresses[0].street.name") * ``` */ -public fun Every.path( +public fun Traversal.path( path: String, fieldDelimiter: String = ".", indexDelimiter: String = "[" -): Every = +): Traversal = path.splitTwice(fieldDelimiter, indexDelimiter).fold(this) { acc, pathSelector -> acc.select(pathSelector) } /** @@ -123,11 +123,11 @@ public fun Every.path( * JsonPath.path("addresses[0].*.street.name") * ``` */ -public fun Every.pathEvery( +public fun Traversal.pathEvery( path: String, fieldDelimiter: String = ".", indexDelimiter: String = "[" -): Every = +): Traversal = path.splitTwice(fieldDelimiter, indexDelimiter).fold(this) { acc, pathSelector -> acc.selectEvery(pathSelector) } /** @@ -135,41 +135,41 @@ public fun Every.pathEvery( * This allows you to erase the value by setting it to [None], * or allows you to overwrite it by setting a new [Some]. */ -public fun Every.at( +public fun Traversal.at( name: String -): Every> = +): Traversal> = `object` compose At.map().at(name) /** Select keys out of an [JsonObject] with the given [predicate] */ -public fun Every.filterKeys( +public fun Traversal.filterKeys( predicate: (keys: String) -> Boolean -): Every = +): Traversal = `object` compose FilterIndex.map().filter(predicate) /** Select a [property] out of a [JsonObject] */ -public operator fun Every.get(property: String): Every = +public operator fun Traversal.get(property: String): Traversal = `object` compose Index.map().index(property) /** Select an [index] out of a [JsonArray] */ -public operator fun Every.get(index: Int): Every = +public operator fun Traversal.get(index: Int): Traversal = array compose Index.list().index(index) /** Select all indices from the [range] out of a [JsonArray] */ -public operator fun Every.get(range: ClosedRange): Every = +public operator fun Traversal.get(range: ClosedRange): Traversal = filterIndex { it in range } /** Select an indices out of a [JsonArray] with the given [predicate] */ -public fun Every.filterIndex( +public fun Traversal.filterIndex( predicate: (index: Int) -> Boolean -): Every = array compose FilterIndex.list().filter(predicate) +): Traversal = array compose FilterIndex.list().filter(predicate) /** Extract a value of type [A] with an _implicit_ KotlinX Serializer */ -public inline fun Every.extract( +public inline fun Traversal.extract( parser: Json = Json -): Every = extract(serializer(), parser) +): Traversal = extract(serializer(), parser) /** Extract a value of type [A] given a [KSerializer] for [A] */ -public fun Every.extract( +public fun Traversal.extract( serializer: KSerializer, parser: Json = Json -): Every = this compose parse(serializer, parser) +): Traversal = this compose parse(serializer, parser) diff --git a/src/commonMain/kotlin/io/github/nomisrev/optics.kt b/src/commonMain/kotlin/io/github/nomisrev/optics.kt index 11162db..953eccc 100644 --- a/src/commonMain/kotlin/io/github/nomisrev/optics.kt +++ b/src/commonMain/kotlin/io/github/nomisrev/optics.kt @@ -2,21 +2,20 @@ package io.github.nomisrev -import arrow.core.Either -import arrow.core.Option -import arrow.core.foldLeft import arrow.core.left import arrow.core.right +import arrow.core.Option import arrow.core.toOption -import arrow.optics.Every +import arrow.core.Either +import arrow.core.fold +import arrow.optics.Prism import arrow.optics.Lens import arrow.optics.Optional -import arrow.optics.PEvery import arrow.optics.POptional -import arrow.optics.Prism +import arrow.optics.Traversal +import arrow.optics.PTraversal import arrow.optics.typeclasses.At import arrow.optics.typeclasses.Index -import arrow.typeclasses.Monoid import kotlinx.serialization.KSerializer import kotlinx.serialization.SerializationException import kotlinx.serialization.json.Json @@ -48,20 +47,20 @@ public fun POptional.Companion.jsonNull(): Optional = Jso public fun POptional.Companion.jsonArray(): Optional> = JsonElementToJsonArray -public fun PEvery.Companion.jsonArray(): Every = JsArrayEvery +public fun PTraversal.Companion.jsonArray(): Traversal = JsArrayTraversal public fun Index.Companion.jsonArray(): Index = JsArrayIndex public fun POptional.Companion.jsonObject(): Optional> = JsonElementToJsonObject -public fun PEvery.Companion.jsonObject(): Every = JsonObjectEvery +public fun PTraversal.Companion.jsonObject(): Traversal = JsonObjectTraversal public fun Index.Companion.jsonObject(): Index = JsonObjectIndex public fun At.Companion.jsonObject(): At> = JsonObjectAt -public fun PEvery.Companion.jsonElement(): Every = JsonElementEvery +public fun PTraversal.Companion.jsonElement(): Traversal = JsonElementTraversal private object JsonObjectIndex : Index { override fun index(i: String): Optional = @@ -81,17 +80,17 @@ private object JsonObjectAt : At> { ) } -private object JsonObjectEvery : Every { +private object JsonObjectTraversal : Traversal { override fun modify(source: JsonObject, map: (focus: JsonElement) -> JsonElement): JsonObject = JsonObject(source.mapValues { (_, focus) -> map(focus) }) - override fun foldMap(M: Monoid, source: JsonObject, map: (focus: JsonElement) -> R): R = - with(M) { source.foldLeft(empty()) { acc, (_, focus) -> acc.combine(map(focus)) } } + override fun foldMap(initial: R, combine: (R, R) -> R, source: JsonObject, map: (focus: JsonElement) -> R): R = + source.fold(initial) { acc, (_, focus) -> combine(acc, map(focus)) } } -private object JsArrayEvery : Every { - override fun foldMap(M: Monoid, source: JsonArray, map: (focus: JsonElement) -> R): R = - with(M) { source.fold(empty()) { acc, json -> acc.combine(map(json)) } } +private object JsArrayTraversal : Traversal { + override fun foldMap(initial: R, combine: (R, R) -> R, source: JsonArray, map: (focus: JsonElement) -> R): R = + source.fold(initial) { acc, json -> combine(acc, map(json)) } override fun modify(source: JsonArray, map: (focus: JsonElement) -> JsonElement): JsonArray = JsonArray(source.map(map)) @@ -217,15 +216,15 @@ private object JsonElementToJsonObject : Optional { - override fun foldMap(M: Monoid, source: JsonElement, map: (focus: JsonElement) -> R): R = - with(M) { - when (source) { - JsonNull -> map(JsonNull) - is JsonObject -> source.foldLeft(empty()) { acc, (_, focus) -> acc.combine(map(focus)) } - is JsonArray -> source.fold(empty()) { acc, json -> acc.combine(map(json)) } - is JsonPrimitive -> map(source) - } +private object JsonElementTraversal : Traversal { + override fun foldMap(initial: R, combine: (R, R) -> R, source: JsonElement, map: (focus: JsonElement) -> R): R = + when (source) { + JsonNull -> map(JsonNull) + is JsonObject -> + source.fold(initial) { acc, (_, focus) -> combine(acc, map(focus)) } + + is JsonArray -> source.fold(initial) { acc, json -> combine(acc, map(json)) } + is JsonPrimitive -> map(source) } override fun modify(source: JsonElement, map: (focus: JsonElement) -> JsonElement): JsonElement = diff --git a/src/commonTest/kotlin/io/github/nomisrev/JsonDSLSpec.kt b/src/commonTest/kotlin/io/github/nomisrev/JsonDSLSpec.kt index 08a38ce..3f54816 100644 --- a/src/commonTest/kotlin/io/github/nomisrev/JsonDSLSpec.kt +++ b/src/commonTest/kotlin/io/github/nomisrev/JsonDSLSpec.kt @@ -90,7 +90,7 @@ class JsonDSLSpec : StringSpec({ "at from object" { checkAll(Arb.json(Arb.city())) { cityJson -> - JsonPath.at("streets").getOrNull(cityJson)?.orNull() shouldBe (cityJson as? JsonObject)?.get("streets") + JsonPath.at("streets").getOrNull(cityJson)?.getOrNull() shouldBe (cityJson as? JsonObject)?.get("streets") } } From 770ceba5e59b8b1c3891049a24f40ad0998dd009 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Thu, 16 May 2024 15:28:27 +0200 Subject: [PATCH 2/6] .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 1831c03..14a866b 100644 --- a/.gitignore +++ b/.gitignore @@ -171,4 +171,4 @@ kotlin-js-store # End of https://www.toptal.com/developers/gitignore/api/intellij+all,kotlin,gradle,macos gradle-build-scan.txt -.kotlin/ \ No newline at end of file +.kotlin \ No newline at end of file From edeaba0428ecaef6858dd4356103e413fe9948a3 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Thu, 16 May 2024 15:51:07 +0200 Subject: [PATCH 3/6] Fix examples --- README.md | 12 ++++++------ src/jvmTest/kotlin/ReadMeSpec.kt | 7 ------- src/jvmTest/kotlin/example/example-readme-03.kt | 2 +- src/jvmTest/kotlin/example/example-readme-04.kt | 16 ++++++++-------- 4 files changed, 15 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 50e82d7..12c0022 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ In the example below we select the _employees_ `JsonArray`, and then we select _every_ `JsonElement` in the `JsonArray`. We then _select_ the _name_ out of _every_ `JsonElement`. -Instead of `Optional` it now returns `Every`, +Instead of `Optional` it now returns `Traversal`, since we selected _many properties_ instead of a _single property_. Just like before we can apply a function to it using _modify_, @@ -118,7 +118,7 @@ fun main(): Unit { --> ```kotlin val json: JsonElement = Json.decodeFromString(JSON_STRING) - val employeesName: Every = JsonPath.select("employees").every.select("name").string + val employeesName: Traversal = JsonPath.select("employees").every.select("name").string val res: JsonElement = employeesName.modify(json, String::uppercase).also(::println) employeesName.getAll(res).also(::println) ``` @@ -137,7 +137,7 @@ Like before, below we select the _employees_ `JsonArray`, and then we select _every_ `JsonElement` in the `JsonArray`. We then _select_ the _name_ out of _every_ `JsonElement`. -Again, instead of `Optional` it now returns `Every`, +Again, instead of `Optional` it now returns `Traversal`, since we selected _many properties_ instead of a _single property_. You can then, apply a function to it using _modify_ like before. @@ -151,13 +151,13 @@ fun main(): Unit { --> ```kotlin val json: JsonElement = Json.decodeFromString(JSON_STRING) - val employeesName: Every = JsonPath.pathEvery("employees.*.name").string + val employeesName: Traversal = JsonPath.pathEvery("employees.*.name").string val res: JsonElement = employeesName.modify(json, String::uppercase).also(::println) employeesName.getAll(res).also(::println) ``` -> You can get the full code [here](src/jvmTest/kotlin/example/example-readme-03.kt). +> You can get the full code [here](src/jvmTest/kotlin/example/example-readme-04.kt). ```text {"name":"Arrow","address":{"city":"Functional Town","street":{"number":1337,"name":"Functional street"}},"employees":[{"name":"JOHN","lastName":"doe"},{"name":"JANE","lastName":"doe"}]} [JOHN, JANE] -``` \ No newline at end of file +``` diff --git a/src/jvmTest/kotlin/ReadMeSpec.kt b/src/jvmTest/kotlin/ReadMeSpec.kt index 49b8395..1944ae8 100644 --- a/src/jvmTest/kotlin/ReadMeSpec.kt +++ b/src/jvmTest/kotlin/ReadMeSpec.kt @@ -26,11 +26,4 @@ class ReadMeSpec : StringSpec({ "[JOHN, JANE]" ) } - - "ExampleReadme04" { - captureOutput("ExampleReadme04") { com.example.exampleReadme04.main() }.verifyOutputLines( - "{\"name\":\"Arrow\",\"address\":{\"city\":\"Functional Town\",\"street\":{\"number\":1337,\"name\":\"Functional street\"}},\"employees\":[{\"name\":\"JOHN\",\"lastName\":\"doe\"},{\"name\":\"JANE\",\"lastName\":\"doe\"}]}", - "[JOHN, JANE]" - ) - } }) diff --git a/src/jvmTest/kotlin/example/example-readme-03.kt b/src/jvmTest/kotlin/example/example-readme-03.kt index 9518f68..7368253 100644 --- a/src/jvmTest/kotlin/example/example-readme-03.kt +++ b/src/jvmTest/kotlin/example/example-readme-03.kt @@ -33,7 +33,7 @@ private const val JSON_STRING = """ fun main(): Unit { val json: JsonElement = Json.decodeFromString(JSON_STRING) - val employeesName: Every = JsonPath.select("employees").every.select("name").string + val employeesName: Traversal = JsonPath.select("employees").every.select("name").string val res: JsonElement = employeesName.modify(json, String::uppercase).also(::println) employeesName.getAll(res).also(::println) } diff --git a/src/jvmTest/kotlin/example/example-readme-04.kt b/src/jvmTest/kotlin/example/example-readme-04.kt index 5051068..7c63221 100644 --- a/src/jvmTest/kotlin/example/example-readme-04.kt +++ b/src/jvmTest/kotlin/example/example-readme-04.kt @@ -2,12 +2,11 @@ @file:Suppress("InvalidPackageDeclaration") package com.example.exampleReadme04 -import arrow.optics.Every -import io.github.nomisrev.JsonPath -import io.github.nomisrev.pathEvery -import io.github.nomisrev.string -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.* +import kotlinx.serialization.json.* +import arrow.optics.* +import io.github.nomisrev.* +import arrow.optics.typeclasses.* private const val JSON_STRING = """ { @@ -31,9 +30,10 @@ private const val JSON_STRING = """ ] }""" -fun main() { +fun main(): Unit { + val json: JsonElement = Json.decodeFromString(JSON_STRING) - val employeesName: Every = JsonPath.pathEvery("employees.*.name").string + val employeesName: Traversal = JsonPath.pathEvery("employees.*.name").string val res: JsonElement = employeesName.modify(json, String::uppercase).also(::println) employeesName.getAll(res).also(::println) } From 075d3758e167c9479d7e0edb74ab576eb0357117 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Thu, 16 May 2024 16:06:39 +0200 Subject: [PATCH 4/6] Fix max line length --- build.gradle.kts | 7 +++++++ libs.versions.toml | 4 +++- src/commonMain/kotlin/io/github/nomisrev/JsonPathEvery.kt | 4 +++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index bbc7a0f..c8409fc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl plugins { application alias(libs.plugins.kotlin) + alias(libs.plugins.spotless) alias(libs.plugins.kotest.multiplatform) alias(libs.plugins.detekt) alias(libs.plugins.dokka) @@ -30,6 +31,12 @@ repositories { mavenCentral() } +spotless { + kotlin { + ktfmt().googleStyle() + } +} + java { sourceCompatibility = VERSION_11 targetCompatibility = VERSION_11 diff --git a/libs.versions.toml b/libs.versions.toml index 9d4462e..73ea11c 100644 --- a/libs.versions.toml +++ b/libs.versions.toml @@ -10,6 +10,7 @@ kotlinx-json="1.6.3" kotlinx-knit="0.5.0" publish="0.28.0" knit="0.5.0" +spotless="6.25.0" [libraries] arrow-optics = { module = "io.arrow-kt:arrow-optics", version.ref = "arrow" } @@ -33,4 +34,5 @@ kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } kotlinx-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } publish = { id = "com.vanniktech.maven.publish", version.ref="publish" } -knit = { id = "org.jetbrains.kotlinx.knit", version.ref="knit" } \ No newline at end of file +knit = { id = "org.jetbrains.kotlinx.knit", version.ref="knit" } +spotless = { id = "com.diffplug.spotless", version.ref ="spotless" } \ No newline at end of file diff --git a/src/commonMain/kotlin/io/github/nomisrev/JsonPathEvery.kt b/src/commonMain/kotlin/io/github/nomisrev/JsonPathEvery.kt index 22001f3..66d69bc 100644 --- a/src/commonMain/kotlin/io/github/nomisrev/JsonPathEvery.kt +++ b/src/commonMain/kotlin/io/github/nomisrev/JsonPathEvery.kt @@ -155,7 +155,9 @@ public operator fun Traversal.get(index: Int): Travers array compose Index.list().index(index) /** Select all indices from the [range] out of a [JsonArray] */ -public operator fun Traversal.get(range: ClosedRange): Traversal = +public operator fun Traversal.get( + range: ClosedRange +): Traversal = filterIndex { it in range } /** Select an indices out of a [JsonArray] with the given [predicate] */ From 447fb8163c4db12d3976fc15fd9a652e75fd1154 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Tue, 18 Feb 2025 15:15:52 +0100 Subject: [PATCH 5/6] Bump all dependencies --- .github/workflows/build.yml | 2 +- .github/workflows/githubpages.yaml | 2 +- .github/workflows/publish.yml | 4 +- .github/workflows/pull_request.yaml | 4 +- build.gradle.kts | 19 +- gradle.properties | 4 +- gradle/wrapper/gradle-wrapper.properties | 2 +- libs.versions.toml | 20 +- settings.gradle.kts | 11 - .../kotlin/io/github/nomisrev/Arb.kt | 160 ++++----- .../kotlin/io/github/nomisrev/JsonDSLSpec.kt | 330 +++++++++--------- .../kotlin/io/github/nomisrev/KotestConfig.kt | 42 ++- 12 files changed, 297 insertions(+), 303 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5a55aa3..aef50b2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,7 +26,7 @@ jobs: java-version: 11 - name: Build - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: arguments: build --scan --full-stacktrace diff --git a/.github/workflows/githubpages.yaml b/.github/workflows/githubpages.yaml index 7a10c83..3b22832 100644 --- a/.github/workflows/githubpages.yaml +++ b/.github/workflows/githubpages.yaml @@ -19,7 +19,7 @@ jobs: run: ./gradlew -Pversion=${{ github.event.release.tag_name }} dokkaHtml - name: Deploy to gh-pages - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./docs diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f09fd61..5069111 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -32,7 +32,7 @@ jobs: java-version: 11 - name: assemble - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: arguments: assemble -Pversion=${{ inputs.version }} @@ -44,6 +44,6 @@ jobs: path: '**/build/reports/**' - name: Publish final version - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: arguments: -Pversion=${{ inputs.version }} publishAllPublicationsToMavenCentralRepository diff --git a/.github/workflows/pull_request.yaml b/.github/workflows/pull_request.yaml index 6dfb596..c1c0f11 100644 --- a/.github/workflows/pull_request.yaml +++ b/.github/workflows/pull_request.yaml @@ -12,12 +12,12 @@ jobs: fetch-depth: 0 - name: Set up Java - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 11 - name: Build - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: arguments: build diff --git a/build.gradle.kts b/build.gradle.kts index c8409fc..2e90439 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,10 +12,9 @@ import org.gradle.kotlin.dsl.configure import org.gradle.kotlin.dsl.withType import org.jetbrains.dokka.gradle.DokkaTask import org.jetbrains.kotlin.gradle.dsl.JvmTarget -import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl plugins { - application alias(libs.plugins.kotlin) alias(libs.plugins.spotless) alias(libs.plugins.kotest.multiplatform) @@ -33,7 +32,12 @@ repositories { spotless { kotlin { - ktfmt().googleStyle() + ktfmt().kotlinlangStyle().configure { + it.setBlockIndent(2) + it.setContinuationIndent(2) + it.setRemoveUnusedImports(true) + it.setManageTrailingCommas(true) + } } } @@ -54,9 +58,6 @@ tasks { exceptionFormat = TestExceptionFormat.FULL events = setOf(SKIPPED, FAILED, STANDARD_OUT, STANDARD_ERROR) } - } - - test { useJUnitPlatform() } } @@ -71,7 +72,11 @@ kotlin { } @OptIn(ExperimentalWasmDsl::class) - wasmJs() + wasmJs { + browser() + nodejs() + d8() + } linuxX64() macosX64() macosArm64() diff --git a/gradle.properties b/gradle.properties index 68b827c..6840694 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,10 +1,12 @@ +org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=1g kotlin.code.style=official GROUP=io.github.nomisrev SONATYPE_HOST=S01 RELEASE_SIGNING_ENABLED=true -POM_NAME=kotlinx-serialization-jsonpath +POM_ARTIFACT_ID=kotlinx-serialization-jsonpath +POM_NAME=Kotlinx Serialization JsonPath POM_DESCRIPTION=JsonPath offers a simple DSL to work with JsonElement from Kotlinx Serialization Json, this allows you to easily work with JSON in Kotlin in a typed manner. POM_URL=https://github.com/nomisrev/kotlinx-serialization-jsonpath/ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b82aa23..e18bc25 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/libs.versions.toml b/libs.versions.toml index 73ea11c..76e2f01 100644 --- a/libs.versions.toml +++ b/libs.versions.toml @@ -1,16 +1,16 @@ [versions] -arrow = "2.0.0-alpha.1" -dokka = "1.9.20" -kotlin = "2.0.0-RC3" -kotest = "5.9.0" -kover = "0.8.0" -detekt = "1.23.5" -kotest-arrow="1.4.0" -kotlinx-json="1.6.3" +arrow = "2.0.1" +dokka = "2.0.0" +kotlin = "2.1.10" +kotest = "5.9.1" +kover = "0.9.1" +detekt = "1.23.7" +kotest-arrow="2.0.0" +kotlinx-json="1.8.0" kotlinx-knit="0.5.0" -publish="0.28.0" +publish="0.30.0" knit="0.5.0" -spotless="6.25.0" +spotless="7.0.2" [libraries] arrow-optics = { module = "io.arrow-kt:arrow-optics", version.ref = "arrow" } diff --git a/settings.gradle.kts b/settings.gradle.kts index ea75507..39b2f8e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,10 +7,6 @@ pluginManagement { } } -plugins { - id("com.gradle.enterprise") version "3.16.2" -} - dependencyResolutionManagement { versionCatalogs { create("libs") { @@ -23,10 +19,3 @@ dependencyResolutionManagement { gradlePluginPortal() } } - -gradleEnterprise { - buildScan { - termsOfServiceUrl = "https://gradle.com/terms-of-service" - termsOfServiceAgree = "yes" - } -} diff --git a/src/commonTest/kotlin/io/github/nomisrev/Arb.kt b/src/commonTest/kotlin/io/github/nomisrev/Arb.kt index f7ce65e..fb786b4 100644 --- a/src/commonTest/kotlin/io/github/nomisrev/Arb.kt +++ b/src/commonTest/kotlin/io/github/nomisrev/Arb.kt @@ -1,80 +1,80 @@ -package io.github.nomisrev - -import io.kotest.property.Arb -import io.kotest.property.arbitrary.boolean -import io.kotest.property.arbitrary.choice -import io.kotest.property.arbitrary.constant -import io.kotest.property.arbitrary.double -import io.kotest.property.arbitrary.filterNot -import io.kotest.property.arbitrary.float -import io.kotest.property.arbitrary.int -import io.kotest.property.arbitrary.list -import io.kotest.property.arbitrary.long -import io.kotest.property.arbitrary.map -import io.kotest.property.arbitrary.string -import kotlinx.serialization.SerializationStrategy -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonArray -import kotlinx.serialization.json.JsonElement -import kotlinx.serialization.json.JsonNull -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.JsonPrimitive -import kotlinx.serialization.serializer - -fun Arb.Companion.street(): Arb = - Arb.string().map(::Street) - -fun Arb.Companion.city(): Arb = - Arb.list(street()).map(::City) - -fun Arb.Companion.jsInt(): Arb = - int().map(::JsonPrimitive) - -fun Arb.Companion.jsLong(): Arb = - long().map(::JsonPrimitive) - -fun Arb.Companion.jsFloat(): Arb = - float().filterNot(Float::isNaN).map(::JsonPrimitive) - -fun Arb.Companion.jsDouble(): Arb = - double().filterNot(Double::isNaN).map(::JsonPrimitive) - -fun Arb.Companion.jsString(): Arb = - Arb.string().map(::JsonPrimitive) - -fun Arb.Companion.jsBoolean(): Arb = - boolean().map(::JsonPrimitive) - -fun Arb.Companion.jsNull(): Arb = - constant(JsonNull) - -private fun genJson(): Arb = - Arb.choice(Arb.jsInt(), Arb.jsLong(), Arb.jsDouble(), Arb.jsString(), Arb.jsNull()) - -fun Arb.Companion.jsArray(): Arb = - list(genJson()).map(::JsonArray) - -fun Arb.Companion.jsArray(valid: Arb, EN: SerializationStrategy): Arb = - list(valid).map { list -> JsonArray(list.map { elem -> Json.encodeToJsonElement(EN, elem) }) } - -inline fun Arb.Companion.jsArray(valid: Arb): Arb = - jsArray(valid, serializer()) - -fun Arb.Companion.jsObject(): Arb = - map(Arb.string(), genJson()).map(::JsonObject) - -fun Arb.Companion.json(valid: Arb, EN: SerializationStrategy): Arb = - valid.map { Json.encodeToJsonElement(EN, it) } - -inline fun Arb.Companion.json(valid: Arb): Arb = - json(valid, serializer()) - -fun Arb.Companion.json(): Arb = choice( - Arb.jsInt(), - Arb.jsLong(), - Arb.jsDouble(), - Arb.jsString(), - Arb.jsNull(), - Arb.jsArray(), - Arb.jsObject(), -) +//package io.github.nomisrev +// +//import io.kotest.property.Arb +//import io.kotest.property.arbitrary.boolean +//import io.kotest.property.arbitrary.choice +//import io.kotest.property.arbitrary.constant +//import io.kotest.property.arbitrary.double +//import io.kotest.property.arbitrary.filterNot +//import io.kotest.property.arbitrary.float +//import io.kotest.property.arbitrary.int +//import io.kotest.property.arbitrary.list +//import io.kotest.property.arbitrary.long +//import io.kotest.property.arbitrary.map +//import io.kotest.property.arbitrary.string +//import kotlinx.serialization.SerializationStrategy +//import kotlinx.serialization.json.Json +//import kotlinx.serialization.json.JsonArray +//import kotlinx.serialization.json.JsonElement +//import kotlinx.serialization.json.JsonNull +//import kotlinx.serialization.json.JsonObject +//import kotlinx.serialization.json.JsonPrimitive +//import kotlinx.serialization.serializer +// +//fun Arb.Companion.street(): Arb = +// Arb.string().map(::Street) +// +//fun Arb.Companion.city(): Arb = +// Arb.list(street()).map(::City) +// +//fun Arb.Companion.jsInt(): Arb = +// int().map(::JsonPrimitive) +// +//fun Arb.Companion.jsLong(): Arb = +// long().map(::JsonPrimitive) +// +//fun Arb.Companion.jsFloat(): Arb = +// float().filterNot(Float::isNaN).map(::JsonPrimitive) +// +//fun Arb.Companion.jsDouble(): Arb = +// double().filterNot(Double::isNaN).map(::JsonPrimitive) +// +//fun Arb.Companion.jsString(): Arb = +// Arb.string().map(::JsonPrimitive) +// +//fun Arb.Companion.jsBoolean(): Arb = +// boolean().map(::JsonPrimitive) +// +//fun Arb.Companion.jsNull(): Arb = +// constant(JsonNull) +// +//private fun genJson(): Arb = +// Arb.choice(Arb.jsInt(), Arb.jsLong(), Arb.jsDouble(), Arb.jsString(), Arb.jsNull()) +// +//fun Arb.Companion.jsArray(): Arb = +// list(genJson()).map(::JsonArray) +// +//fun Arb.Companion.jsArray(valid: Arb, EN: SerializationStrategy): Arb = +// list(valid).map { list -> JsonArray(list.map { elem -> Json.encodeToJsonElement(EN, elem) }) } +// +//inline fun Arb.Companion.jsArray(valid: Arb): Arb = +// jsArray(valid, serializer()) +// +//fun Arb.Companion.jsObject(): Arb = +// map(Arb.string(), genJson()).map(::JsonObject) +// +//fun Arb.Companion.json(valid: Arb, EN: SerializationStrategy): Arb = +// valid.map { Json.encodeToJsonElement(EN, it) } +// +//inline fun Arb.Companion.json(valid: Arb): Arb = +// json(valid, serializer()) +// +//fun Arb.Companion.json(): Arb = choice( +// Arb.jsInt(), +// Arb.jsLong(), +// Arb.jsDouble(), +// Arb.jsString(), +// Arb.jsNull(), +// Arb.jsArray(), +// Arb.jsObject(), +//) diff --git a/src/commonTest/kotlin/io/github/nomisrev/JsonDSLSpec.kt b/src/commonTest/kotlin/io/github/nomisrev/JsonDSLSpec.kt index 3f54816..7c349e8 100644 --- a/src/commonTest/kotlin/io/github/nomisrev/JsonDSLSpec.kt +++ b/src/commonTest/kotlin/io/github/nomisrev/JsonDSLSpec.kt @@ -1,165 +1,165 @@ -package io.github.nomisrev - -import io.kotest.common.Platform -import io.kotest.common.platform -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.nulls.shouldBeNull -import io.kotest.matchers.shouldBe -import io.kotest.property.Arb -import io.kotest.property.checkAll -import kotlinx.serialization.Serializable -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.JsonPrimitive -import kotlinx.serialization.json.boolean -import kotlinx.serialization.json.float -import kotlinx.serialization.json.int -import kotlinx.serialization.json.long - -@Serializable -data class City(val streets: List) - -@Serializable -data class Street(val name: String) - -class JsonDSLSpec : StringSpec({ - - "bool prism" { - checkAll(Arb.jsBoolean()) { jsBool -> - JsonPath.boolean.getOrNull(jsBool) shouldBe jsBool.boolean - } - - JsonPath.boolean.getOrNull(JsonPrimitive("text")).shouldBeNull() - } - - "string prism" { - checkAll(Arb.jsString()) { jsString -> - JsonPath.string.getOrNull(jsString) shouldBe jsString.content - } - - JsonPath.string.getOrNull(JsonPrimitive(false)).shouldBeNull() - } - - "long prism" { - checkAll(Arb.jsLong()) { jsLong -> - JsonPath.long.getOrNull(jsLong) shouldBe jsLong.long - } - - JsonPath.long.getOrNull(JsonPrimitive(false)).shouldBeNull() - } - - "float prism" { - checkAll(Arb.jsFloat()) { jsFloat -> - JsonPath.float.getOrNull(jsFloat) shouldBe jsFloat.float - } - - JsonPath.float.getOrNull(JsonPrimitive(false)).shouldBeNull() - } - - "int prism" { - checkAll(Arb.jsInt()) { jsInt -> - JsonPath.int.getOrNull(jsInt) shouldBe jsInt.int - } - - JsonPath.int.getOrNull(JsonPrimitive("text")).shouldBeNull() - } - - "array prism" { - checkAll(Arb.jsArray()) { jsArray -> - JsonPath.array.getOrNull(jsArray) shouldBe jsArray - } - - JsonPath.array.getOrNull(JsonPrimitive("5")).shouldBeNull() - } - - "object prism" { - checkAll(Arb.jsObject()) { jsObj -> - JsonPath.`object`.getOrNull(jsObj) shouldBe jsObj - } - - JsonPath.`object`.getOrNull(JsonPrimitive("5")).shouldBeNull() - } - - "null prism" { - checkAll(Arb.jsNull()) { jsNull -> - JsonPath.`null`.getOrNull(jsNull) shouldBe jsNull - } - - JsonPath.`null`.getOrNull(JsonPrimitive("5")).shouldBeNull() - } - - "at from object" { - checkAll(Arb.json(Arb.city())) { cityJson -> - JsonPath.at("streets").getOrNull(cityJson)?.getOrNull() shouldBe (cityJson as? JsonObject)?.get("streets") - } - } - - "select from object" { - checkAll(Arb.json(Arb.city())) { cityJson -> - JsonPath.select("streets").getOrNull(cityJson) shouldBe (cityJson as? JsonObject)?.get("streets") - } - } - - // See https://github.com/Kotlin/kotlinx.serialization/issues/1914 - "extract from object".config(enabled = platform != Platform.Native) { - checkAll(Arb.json(Arb.city())) { cityJson -> - JsonPath.extract(City.serializer()) - .getOrNull(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson) - } - } - - "get from array, using select and get".config(enabled = platform != Platform.Native) { - checkAll(Arb.json(Arb.city())) { cityJson -> - JsonPath.select("streets")[0] - .extract(Street.serializer()) - .getOrNull(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.getOrNull(0) - } - } - - "get from array, using get".config(enabled = platform != Platform.Native) { - checkAll(Arb.json(Arb.city())) { cityJson -> - JsonPath["streets"][0]["name"].string - .getOrNull(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.getOrNull(0)?.name - } - } - - "get from array, using get".config(enabled = platform != Platform.Native) { - checkAll(Arb.json(Arb.city())) { cityJson -> - JsonPath["streets"][0..0]["name"].string - .getAll(cityJson) - .getOrNull(0) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.getOrNull(0)?.name - } - } - - "get from array, using select with special syntax".config(enabled = platform != Platform.Native) { - checkAll(Arb.json(Arb.city())) { cityJson -> - JsonPath.select("['streets']").select("[0]") - .extract(Street.serializer()) - .getOrNull(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.getOrNull(0) - } - } - - "get from array, using path".config(enabled = platform != Platform.Native) { - checkAll(Arb.json(Arb.city())) { cityJson -> - JsonPath.path("streets[0]") - .extract(Street.serializer()) - .getOrNull(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.getOrNull(0) - } - } - - "get all elements from array".config(enabled = platform != Platform.Native) { - checkAll(Arb.json(Arb.city())) { cityJson -> - JsonPath.select("streets").selectEvery("*").select("name") - .string - .getAll(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.map { it.name } - } - } - - "get all elements from array, using path".config(enabled = platform != Platform.Native) { - checkAll(Arb.json(Arb.city())) { cityJson -> - JsonPath.pathEvery("streets.*.name") - .string - .getAll(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.map { it.name } - } - } -}) +//package io.github.nomisrev +// +//import io.kotest.common.Platform +//import io.kotest.common.platform +//import io.kotest.core.spec.style.StringSpec +//import io.kotest.matchers.nulls.shouldBeNull +//import io.kotest.matchers.shouldBe +//import io.kotest.property.Arb +//import io.kotest.property.checkAll +//import kotlinx.serialization.Serializable +//import kotlinx.serialization.json.Json +//import kotlinx.serialization.json.JsonObject +//import kotlinx.serialization.json.JsonPrimitive +//import kotlinx.serialization.json.boolean +//import kotlinx.serialization.json.float +//import kotlinx.serialization.json.int +//import kotlinx.serialization.json.long +// +//@Serializable +//data class City(val streets: List) +// +//@Serializable +//data class Street(val name: String) +// +//class JsonDSLSpec : StringSpec({ +// +// "bool prism" { +// checkAll(Arb.jsBoolean()) { jsBool -> +// JsonPath.boolean.getOrNull(jsBool) shouldBe jsBool.boolean +// } +// +// JsonPath.boolean.getOrNull(JsonPrimitive("text")).shouldBeNull() +// } +// +// "string prism" { +// checkAll(Arb.jsString()) { jsString -> +// JsonPath.string.getOrNull(jsString) shouldBe jsString.content +// } +// +// JsonPath.string.getOrNull(JsonPrimitive(false)).shouldBeNull() +// } +// +// "long prism" { +// checkAll(Arb.jsLong()) { jsLong -> +// JsonPath.long.getOrNull(jsLong) shouldBe jsLong.long +// } +// +// JsonPath.long.getOrNull(JsonPrimitive(false)).shouldBeNull() +// } +// +// "float prism" { +// checkAll(Arb.jsFloat()) { jsFloat -> +// JsonPath.float.getOrNull(jsFloat) shouldBe jsFloat.float +// } +// +// JsonPath.float.getOrNull(JsonPrimitive(false)).shouldBeNull() +// } +// +// "int prism" { +// checkAll(Arb.jsInt()) { jsInt -> +// JsonPath.int.getOrNull(jsInt) shouldBe jsInt.int +// } +// +// JsonPath.int.getOrNull(JsonPrimitive("text")).shouldBeNull() +// } +// +// "array prism" { +// checkAll(Arb.jsArray()) { jsArray -> +// JsonPath.array.getOrNull(jsArray) shouldBe jsArray +// } +// +// JsonPath.array.getOrNull(JsonPrimitive("5")).shouldBeNull() +// } +// +// "object prism" { +// checkAll(Arb.jsObject()) { jsObj -> +// JsonPath.`object`.getOrNull(jsObj) shouldBe jsObj +// } +// +// JsonPath.`object`.getOrNull(JsonPrimitive("5")).shouldBeNull() +// } +// +// "null prism" { +// checkAll(Arb.jsNull()) { jsNull -> +// JsonPath.`null`.getOrNull(jsNull) shouldBe jsNull +// } +// +// JsonPath.`null`.getOrNull(JsonPrimitive("5")).shouldBeNull() +// } +// +// "at from object" { +// checkAll(Arb.json(Arb.city())) { cityJson -> +// JsonPath.at("streets").getOrNull(cityJson)?.getOrNull() shouldBe (cityJson as? JsonObject)?.get("streets") +// } +// } +// +// "select from object" { +// checkAll(Arb.json(Arb.city())) { cityJson -> +// JsonPath.select("streets").getOrNull(cityJson) shouldBe (cityJson as? JsonObject)?.get("streets") +// } +// } +// +// // See https://github.com/Kotlin/kotlinx.serialization/issues/1914 +// "extract from object".config(enabled = platform != Platform.Native) { +// checkAll(Arb.json(Arb.city())) { cityJson -> +// JsonPath.extract(City.serializer()) +// .getOrNull(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson) +// } +// } +// +// "get from array, using select and get".config(enabled = platform != Platform.Native) { +// checkAll(Arb.json(Arb.city())) { cityJson -> +// JsonPath.select("streets")[0] +// .extract(Street.serializer()) +// .getOrNull(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.getOrNull(0) +// } +// } +// +// "get from array, using get".config(enabled = platform != Platform.Native) { +// checkAll(Arb.json(Arb.city())) { cityJson -> +// JsonPath["streets"][0]["name"].string +// .getOrNull(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.getOrNull(0)?.name +// } +// } +// +// "get from array, using get".config(enabled = platform != Platform.Native) { +// checkAll(Arb.json(Arb.city())) { cityJson -> +// JsonPath["streets"][0..0]["name"].string +// .getAll(cityJson) +// .getOrNull(0) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.getOrNull(0)?.name +// } +// } +// +// "get from array, using select with special syntax".config(enabled = platform != Platform.Native) { +// checkAll(Arb.json(Arb.city())) { cityJson -> +// JsonPath.select("['streets']").select("[0]") +// .extract(Street.serializer()) +// .getOrNull(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.getOrNull(0) +// } +// } +// +// "get from array, using path".config(enabled = platform != Platform.Native) { +// checkAll(Arb.json(Arb.city())) { cityJson -> +// JsonPath.path("streets[0]") +// .extract(Street.serializer()) +// .getOrNull(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.getOrNull(0) +// } +// } +// +// "get all elements from array".config(enabled = platform != Platform.Native) { +// checkAll(Arb.json(Arb.city())) { cityJson -> +// JsonPath.select("streets").selectEvery("*").select("name") +// .string +// .getAll(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.map { it.name } +// } +// } +// +// "get all elements from array, using path".config(enabled = platform != Platform.Native) { +// checkAll(Arb.json(Arb.city())) { cityJson -> +// JsonPath.pathEvery("streets.*.name") +// .string +// .getAll(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.map { it.name } +// } +// } +//}) diff --git a/src/commonTest/kotlin/io/github/nomisrev/KotestConfig.kt b/src/commonTest/kotlin/io/github/nomisrev/KotestConfig.kt index 938b004..83d6871 100644 --- a/src/commonTest/kotlin/io/github/nomisrev/KotestConfig.kt +++ b/src/commonTest/kotlin/io/github/nomisrev/KotestConfig.kt @@ -1,22 +1,20 @@ -package io.github.nomisrev - -import io.kotest.core.config.AbstractProjectConfig -import io.kotest.core.test.TestCaseOrder -import io.kotest.property.PropertyTesting -import kotlin.time.Duration -import kotlin.time.Duration.Companion.seconds - -object KotestConfig : AbstractProjectConfig() { - init { - PropertyTesting.defaultIterationCount = 50 - } - - override val timeout: Duration = - 30.seconds - - override val testCaseOrder: TestCaseOrder = - TestCaseOrder.Random - - - -} +//package io.github.nomisrev +// +//import io.kotest.core.config.AbstractProjectConfig +//import io.kotest.core.test.TestCaseOrder +//import io.kotest.property.PropertyTesting +//import kotlin.time.Duration +//import kotlin.time.Duration.Companion.seconds +// +//object KotestConfig : AbstractProjectConfig() { +// init { +// PropertyTesting.defaultIterationCount = 50 +// } +// +// override val timeout: Duration = +// 30.seconds +// +// override val testCaseOrder: TestCaseOrder = +// TestCaseOrder.Random +// +//} From b15c51692abd14231488b2fafb798597e181e6e8 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Tue, 18 Feb 2025 15:47:30 +0100 Subject: [PATCH 6/6] Bump Kotest to 6.0.0.M2 --- libs.versions.toml | 2 +- .../kotlin/io/github/nomisrev/Arb.kt | 160 ++++----- .../kotlin/io/github/nomisrev/JsonDSLSpec.kt | 327 +++++++++--------- .../kotlin/io/github/nomisrev/KotestConfig.kt | 40 +-- 4 files changed, 263 insertions(+), 266 deletions(-) diff --git a/libs.versions.toml b/libs.versions.toml index 76e2f01..903feeb 100644 --- a/libs.versions.toml +++ b/libs.versions.toml @@ -2,7 +2,7 @@ arrow = "2.0.1" dokka = "2.0.0" kotlin = "2.1.10" -kotest = "5.9.1" +kotest = "6.0.0.M2" kover = "0.9.1" detekt = "1.23.7" kotest-arrow="2.0.0" diff --git a/src/commonTest/kotlin/io/github/nomisrev/Arb.kt b/src/commonTest/kotlin/io/github/nomisrev/Arb.kt index fb786b4..f7ce65e 100644 --- a/src/commonTest/kotlin/io/github/nomisrev/Arb.kt +++ b/src/commonTest/kotlin/io/github/nomisrev/Arb.kt @@ -1,80 +1,80 @@ -//package io.github.nomisrev -// -//import io.kotest.property.Arb -//import io.kotest.property.arbitrary.boolean -//import io.kotest.property.arbitrary.choice -//import io.kotest.property.arbitrary.constant -//import io.kotest.property.arbitrary.double -//import io.kotest.property.arbitrary.filterNot -//import io.kotest.property.arbitrary.float -//import io.kotest.property.arbitrary.int -//import io.kotest.property.arbitrary.list -//import io.kotest.property.arbitrary.long -//import io.kotest.property.arbitrary.map -//import io.kotest.property.arbitrary.string -//import kotlinx.serialization.SerializationStrategy -//import kotlinx.serialization.json.Json -//import kotlinx.serialization.json.JsonArray -//import kotlinx.serialization.json.JsonElement -//import kotlinx.serialization.json.JsonNull -//import kotlinx.serialization.json.JsonObject -//import kotlinx.serialization.json.JsonPrimitive -//import kotlinx.serialization.serializer -// -//fun Arb.Companion.street(): Arb = -// Arb.string().map(::Street) -// -//fun Arb.Companion.city(): Arb = -// Arb.list(street()).map(::City) -// -//fun Arb.Companion.jsInt(): Arb = -// int().map(::JsonPrimitive) -// -//fun Arb.Companion.jsLong(): Arb = -// long().map(::JsonPrimitive) -// -//fun Arb.Companion.jsFloat(): Arb = -// float().filterNot(Float::isNaN).map(::JsonPrimitive) -// -//fun Arb.Companion.jsDouble(): Arb = -// double().filterNot(Double::isNaN).map(::JsonPrimitive) -// -//fun Arb.Companion.jsString(): Arb = -// Arb.string().map(::JsonPrimitive) -// -//fun Arb.Companion.jsBoolean(): Arb = -// boolean().map(::JsonPrimitive) -// -//fun Arb.Companion.jsNull(): Arb = -// constant(JsonNull) -// -//private fun genJson(): Arb = -// Arb.choice(Arb.jsInt(), Arb.jsLong(), Arb.jsDouble(), Arb.jsString(), Arb.jsNull()) -// -//fun Arb.Companion.jsArray(): Arb = -// list(genJson()).map(::JsonArray) -// -//fun Arb.Companion.jsArray(valid: Arb, EN: SerializationStrategy): Arb = -// list(valid).map { list -> JsonArray(list.map { elem -> Json.encodeToJsonElement(EN, elem) }) } -// -//inline fun Arb.Companion.jsArray(valid: Arb): Arb = -// jsArray(valid, serializer()) -// -//fun Arb.Companion.jsObject(): Arb = -// map(Arb.string(), genJson()).map(::JsonObject) -// -//fun Arb.Companion.json(valid: Arb, EN: SerializationStrategy): Arb = -// valid.map { Json.encodeToJsonElement(EN, it) } -// -//inline fun Arb.Companion.json(valid: Arb): Arb = -// json(valid, serializer()) -// -//fun Arb.Companion.json(): Arb = choice( -// Arb.jsInt(), -// Arb.jsLong(), -// Arb.jsDouble(), -// Arb.jsString(), -// Arb.jsNull(), -// Arb.jsArray(), -// Arb.jsObject(), -//) +package io.github.nomisrev + +import io.kotest.property.Arb +import io.kotest.property.arbitrary.boolean +import io.kotest.property.arbitrary.choice +import io.kotest.property.arbitrary.constant +import io.kotest.property.arbitrary.double +import io.kotest.property.arbitrary.filterNot +import io.kotest.property.arbitrary.float +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.list +import io.kotest.property.arbitrary.long +import io.kotest.property.arbitrary.map +import io.kotest.property.arbitrary.string +import kotlinx.serialization.SerializationStrategy +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonNull +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.serializer + +fun Arb.Companion.street(): Arb = + Arb.string().map(::Street) + +fun Arb.Companion.city(): Arb = + Arb.list(street()).map(::City) + +fun Arb.Companion.jsInt(): Arb = + int().map(::JsonPrimitive) + +fun Arb.Companion.jsLong(): Arb = + long().map(::JsonPrimitive) + +fun Arb.Companion.jsFloat(): Arb = + float().filterNot(Float::isNaN).map(::JsonPrimitive) + +fun Arb.Companion.jsDouble(): Arb = + double().filterNot(Double::isNaN).map(::JsonPrimitive) + +fun Arb.Companion.jsString(): Arb = + Arb.string().map(::JsonPrimitive) + +fun Arb.Companion.jsBoolean(): Arb = + boolean().map(::JsonPrimitive) + +fun Arb.Companion.jsNull(): Arb = + constant(JsonNull) + +private fun genJson(): Arb = + Arb.choice(Arb.jsInt(), Arb.jsLong(), Arb.jsDouble(), Arb.jsString(), Arb.jsNull()) + +fun Arb.Companion.jsArray(): Arb = + list(genJson()).map(::JsonArray) + +fun Arb.Companion.jsArray(valid: Arb, EN: SerializationStrategy): Arb = + list(valid).map { list -> JsonArray(list.map { elem -> Json.encodeToJsonElement(EN, elem) }) } + +inline fun Arb.Companion.jsArray(valid: Arb): Arb = + jsArray(valid, serializer()) + +fun Arb.Companion.jsObject(): Arb = + map(Arb.string(), genJson()).map(::JsonObject) + +fun Arb.Companion.json(valid: Arb, EN: SerializationStrategy): Arb = + valid.map { Json.encodeToJsonElement(EN, it) } + +inline fun Arb.Companion.json(valid: Arb): Arb = + json(valid, serializer()) + +fun Arb.Companion.json(): Arb = choice( + Arb.jsInt(), + Arb.jsLong(), + Arb.jsDouble(), + Arb.jsString(), + Arb.jsNull(), + Arb.jsArray(), + Arb.jsObject(), +) diff --git a/src/commonTest/kotlin/io/github/nomisrev/JsonDSLSpec.kt b/src/commonTest/kotlin/io/github/nomisrev/JsonDSLSpec.kt index 7c349e8..5c5b31a 100644 --- a/src/commonTest/kotlin/io/github/nomisrev/JsonDSLSpec.kt +++ b/src/commonTest/kotlin/io/github/nomisrev/JsonDSLSpec.kt @@ -1,165 +1,162 @@ -//package io.github.nomisrev -// -//import io.kotest.common.Platform -//import io.kotest.common.platform -//import io.kotest.core.spec.style.StringSpec -//import io.kotest.matchers.nulls.shouldBeNull -//import io.kotest.matchers.shouldBe -//import io.kotest.property.Arb -//import io.kotest.property.checkAll -//import kotlinx.serialization.Serializable -//import kotlinx.serialization.json.Json -//import kotlinx.serialization.json.JsonObject -//import kotlinx.serialization.json.JsonPrimitive -//import kotlinx.serialization.json.boolean -//import kotlinx.serialization.json.float -//import kotlinx.serialization.json.int -//import kotlinx.serialization.json.long -// -//@Serializable -//data class City(val streets: List) -// -//@Serializable -//data class Street(val name: String) -// -//class JsonDSLSpec : StringSpec({ -// -// "bool prism" { -// checkAll(Arb.jsBoolean()) { jsBool -> -// JsonPath.boolean.getOrNull(jsBool) shouldBe jsBool.boolean -// } -// -// JsonPath.boolean.getOrNull(JsonPrimitive("text")).shouldBeNull() -// } -// -// "string prism" { -// checkAll(Arb.jsString()) { jsString -> -// JsonPath.string.getOrNull(jsString) shouldBe jsString.content -// } -// -// JsonPath.string.getOrNull(JsonPrimitive(false)).shouldBeNull() -// } -// -// "long prism" { -// checkAll(Arb.jsLong()) { jsLong -> -// JsonPath.long.getOrNull(jsLong) shouldBe jsLong.long -// } -// -// JsonPath.long.getOrNull(JsonPrimitive(false)).shouldBeNull() -// } -// -// "float prism" { -// checkAll(Arb.jsFloat()) { jsFloat -> -// JsonPath.float.getOrNull(jsFloat) shouldBe jsFloat.float -// } -// -// JsonPath.float.getOrNull(JsonPrimitive(false)).shouldBeNull() -// } -// -// "int prism" { -// checkAll(Arb.jsInt()) { jsInt -> -// JsonPath.int.getOrNull(jsInt) shouldBe jsInt.int -// } -// -// JsonPath.int.getOrNull(JsonPrimitive("text")).shouldBeNull() -// } -// -// "array prism" { -// checkAll(Arb.jsArray()) { jsArray -> -// JsonPath.array.getOrNull(jsArray) shouldBe jsArray -// } -// -// JsonPath.array.getOrNull(JsonPrimitive("5")).shouldBeNull() -// } -// -// "object prism" { -// checkAll(Arb.jsObject()) { jsObj -> -// JsonPath.`object`.getOrNull(jsObj) shouldBe jsObj -// } -// -// JsonPath.`object`.getOrNull(JsonPrimitive("5")).shouldBeNull() -// } -// -// "null prism" { -// checkAll(Arb.jsNull()) { jsNull -> -// JsonPath.`null`.getOrNull(jsNull) shouldBe jsNull -// } -// -// JsonPath.`null`.getOrNull(JsonPrimitive("5")).shouldBeNull() -// } -// -// "at from object" { -// checkAll(Arb.json(Arb.city())) { cityJson -> -// JsonPath.at("streets").getOrNull(cityJson)?.getOrNull() shouldBe (cityJson as? JsonObject)?.get("streets") -// } -// } -// -// "select from object" { -// checkAll(Arb.json(Arb.city())) { cityJson -> -// JsonPath.select("streets").getOrNull(cityJson) shouldBe (cityJson as? JsonObject)?.get("streets") -// } -// } -// -// // See https://github.com/Kotlin/kotlinx.serialization/issues/1914 -// "extract from object".config(enabled = platform != Platform.Native) { -// checkAll(Arb.json(Arb.city())) { cityJson -> -// JsonPath.extract(City.serializer()) -// .getOrNull(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson) -// } -// } -// -// "get from array, using select and get".config(enabled = platform != Platform.Native) { -// checkAll(Arb.json(Arb.city())) { cityJson -> -// JsonPath.select("streets")[0] -// .extract(Street.serializer()) -// .getOrNull(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.getOrNull(0) -// } -// } -// -// "get from array, using get".config(enabled = platform != Platform.Native) { -// checkAll(Arb.json(Arb.city())) { cityJson -> -// JsonPath["streets"][0]["name"].string -// .getOrNull(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.getOrNull(0)?.name -// } -// } -// -// "get from array, using get".config(enabled = platform != Platform.Native) { -// checkAll(Arb.json(Arb.city())) { cityJson -> -// JsonPath["streets"][0..0]["name"].string -// .getAll(cityJson) -// .getOrNull(0) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.getOrNull(0)?.name -// } -// } -// -// "get from array, using select with special syntax".config(enabled = platform != Platform.Native) { -// checkAll(Arb.json(Arb.city())) { cityJson -> -// JsonPath.select("['streets']").select("[0]") -// .extract(Street.serializer()) -// .getOrNull(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.getOrNull(0) -// } -// } -// -// "get from array, using path".config(enabled = platform != Platform.Native) { -// checkAll(Arb.json(Arb.city())) { cityJson -> -// JsonPath.path("streets[0]") -// .extract(Street.serializer()) -// .getOrNull(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.getOrNull(0) -// } -// } -// -// "get all elements from array".config(enabled = platform != Platform.Native) { -// checkAll(Arb.json(Arb.city())) { cityJson -> -// JsonPath.select("streets").selectEvery("*").select("name") -// .string -// .getAll(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.map { it.name } -// } -// } -// -// "get all elements from array, using path".config(enabled = platform != Platform.Native) { -// checkAll(Arb.json(Arb.city())) { cityJson -> -// JsonPath.pathEvery("streets.*.name") -// .string -// .getAll(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.map { it.name } -// } -// } -//}) +package io.github.nomisrev + +import io.kotest.core.spec.style.StringSpec +import io.kotest.matchers.nulls.shouldBeNull +import io.kotest.matchers.shouldBe +import io.kotest.property.Arb +import io.kotest.property.checkAll +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.boolean +import kotlinx.serialization.json.float +import kotlinx.serialization.json.int +import kotlinx.serialization.json.long + +@Serializable +data class City(val streets: List) + +@Serializable +data class Street(val name: String) + +class JsonDSLSpec : StringSpec({ + + "bool prism" { + checkAll(Arb.jsBoolean()) { jsBool -> + JsonPath.boolean.getOrNull(jsBool) shouldBe jsBool.boolean + } + + JsonPath.boolean.getOrNull(JsonPrimitive("text")).shouldBeNull() + } + + "string prism" { + checkAll(Arb.jsString()) { jsString -> + JsonPath.string.getOrNull(jsString) shouldBe jsString.content + } + + JsonPath.string.getOrNull(JsonPrimitive(false)).shouldBeNull() + } + + "long prism" { + checkAll(Arb.jsLong()) { jsLong -> + JsonPath.long.getOrNull(jsLong) shouldBe jsLong.long + } + + JsonPath.long.getOrNull(JsonPrimitive(false)).shouldBeNull() + } + + "float prism" { + checkAll(Arb.jsFloat()) { jsFloat -> + JsonPath.float.getOrNull(jsFloat) shouldBe jsFloat.float + } + + JsonPath.float.getOrNull(JsonPrimitive(false)).shouldBeNull() + } + + "int prism" { + checkAll(Arb.jsInt()) { jsInt -> + JsonPath.int.getOrNull(jsInt) shouldBe jsInt.int + } + + JsonPath.int.getOrNull(JsonPrimitive("text")).shouldBeNull() + } + + "array prism" { + checkAll(Arb.jsArray()) { jsArray -> + JsonPath.array.getOrNull(jsArray) shouldBe jsArray + } + + JsonPath.array.getOrNull(JsonPrimitive("5")).shouldBeNull() + } + + "object prism" { + checkAll(Arb.jsObject()) { jsObj -> + JsonPath.`object`.getOrNull(jsObj) shouldBe jsObj + } + + JsonPath.`object`.getOrNull(JsonPrimitive("5")).shouldBeNull() + } + + "null prism" { + checkAll(Arb.jsNull()) { jsNull -> + JsonPath.`null`.getOrNull(jsNull) shouldBe jsNull + } + + JsonPath.`null`.getOrNull(JsonPrimitive("5")).shouldBeNull() + } + + "at from object" { + checkAll(Arb.json(Arb.city())) { cityJson -> + JsonPath.at("streets").getOrNull(cityJson)?.getOrNull() shouldBe (cityJson as? JsonObject)?.get("streets") + } + } + + "select from object" { + checkAll(Arb.json(Arb.city())) { cityJson -> + JsonPath.select("streets").getOrNull(cityJson) shouldBe (cityJson as? JsonObject)?.get("streets") + } + } + + "extract from object" { + checkAll(Arb.json(Arb.city())) { cityJson -> + JsonPath.extract(City.serializer()) + .getOrNull(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson) + } + } + + "get from array, using select and get" { + checkAll(Arb.json(Arb.city())) { cityJson -> + JsonPath.select("streets")[0] + .extract(Street.serializer()) + .getOrNull(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.getOrNull(0) + } + } + + "get from array, using get" { + checkAll(Arb.json(Arb.city())) { cityJson -> + JsonPath["streets"][0]["name"].string + .getOrNull(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.getOrNull(0)?.name + } + } + + "get from array, using get range" { + checkAll(Arb.json(Arb.city())) { cityJson -> + JsonPath["streets"][0..0]["name"].string + .getAll(cityJson) + .getOrNull(0) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.getOrNull(0)?.name + } + } + + "get from array, using select with special syntax" { + checkAll(Arb.json(Arb.city())) { cityJson -> + JsonPath.select("['streets']").select("[0]") + .extract(Street.serializer()) + .getOrNull(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.getOrNull(0) + } + } + + "get from array, using path" { + checkAll(Arb.json(Arb.city())) { cityJson -> + JsonPath.path("streets[0]") + .extract(Street.serializer()) + .getOrNull(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.getOrNull(0) + } + } + + "get all elements from array" { + checkAll(Arb.json(Arb.city())) { cityJson -> + JsonPath.select("streets").selectEvery("*").select("name") + .string + .getAll(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.map { it.name } + } + } + + "get all elements from array, using path" { + checkAll(Arb.json(Arb.city())) { cityJson -> + JsonPath.pathEvery("streets.*.name") + .string + .getAll(cityJson) shouldBe Json.decodeFromJsonElement(City.serializer(), cityJson).streets.map { it.name } + } + } +}) diff --git a/src/commonTest/kotlin/io/github/nomisrev/KotestConfig.kt b/src/commonTest/kotlin/io/github/nomisrev/KotestConfig.kt index 83d6871..0796d24 100644 --- a/src/commonTest/kotlin/io/github/nomisrev/KotestConfig.kt +++ b/src/commonTest/kotlin/io/github/nomisrev/KotestConfig.kt @@ -1,20 +1,20 @@ -//package io.github.nomisrev -// -//import io.kotest.core.config.AbstractProjectConfig -//import io.kotest.core.test.TestCaseOrder -//import io.kotest.property.PropertyTesting -//import kotlin.time.Duration -//import kotlin.time.Duration.Companion.seconds -// -//object KotestConfig : AbstractProjectConfig() { -// init { -// PropertyTesting.defaultIterationCount = 50 -// } -// -// override val timeout: Duration = -// 30.seconds -// -// override val testCaseOrder: TestCaseOrder = -// TestCaseOrder.Random -// -//} +package io.github.nomisrev + +import io.kotest.core.config.AbstractProjectConfig +import io.kotest.core.test.TestCaseOrder +import io.kotest.property.PropertyTesting +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds + +object KotestConfig : AbstractProjectConfig() { + init { + PropertyTesting.defaultIterationCount = 50 + } + + override val timeout: Duration = + 30.seconds + + override val testCaseOrder: TestCaseOrder = + TestCaseOrder.Random + +}