diff --git a/api/src/commonMain/kotlin/Parameters.kt b/api/src/commonMain/kotlin/Parameters.kt index 0bbecc5..864d893 100644 --- a/api/src/commonMain/kotlin/Parameters.kt +++ b/api/src/commonMain/kotlin/Parameters.kt @@ -112,6 +112,22 @@ abstract class Parameters( */ protected fun parameter(name: String) = Parameter(name, null) + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other == null || this::class != other::class) return false + + other as Parameters + + return data == other.data + } + + override fun hashCode(): Int { + return data.hashCode() + } + + override fun toString(): String = + "${this::class.toString().removePrefix("class ")}$data" + /** * Internal type used by the parameter declaration syntax. * -- 2.51.2 From 2eadadec96d6e7b6b04876e3501a2df206fd39d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 29 May 2025 10:59:24 +0200 Subject: [PATCH 2/7] test(api): Migrate from Kotest to Power Assert --- api/src/commonTest/kotlin/ParametersTest.kt | 45 +++++++++------------ api/src/commonTest/kotlin/PathTest.kt | 10 ++--- 2 files changed, 24 insertions(+), 31 deletions(-) diff --git a/api/src/commonTest/kotlin/ParametersTest.kt b/api/src/commonTest/kotlin/ParametersTest.kt index d2858f9..2154694 100644 --- a/api/src/commonTest/kotlin/ParametersTest.kt +++ b/api/src/commonTest/kotlin/ParametersTest.kt @@ -1,6 +1,5 @@ package opensavvy.spine.api -import io.kotest.assertions.assertSoftly import io.kotest.assertions.throwables.shouldThrow import io.kotest.matchers.shouldBe import opensavvy.prepared.suite.SuiteDsl @@ -16,10 +15,8 @@ fun SuiteDsl.parameters() = suite("Endpoint parameters") { archived = true } - assertSoftly { - params.archived shouldBe true - shouldThrow { params.private } - } + check(params.archived) + shouldThrow { params.private } params.data shouldBe mapOf( "archived" to "true", @@ -36,10 +33,8 @@ fun SuiteDsl.parameters() = suite("Endpoint parameters") { archived = true } - assertSoftly { - params.archived shouldBe true - params.private shouldBe null - } + check(params.archived == true) + check(params.private == null) params.data shouldBe mapOf( "archived" to "true", @@ -56,8 +51,8 @@ fun SuiteDsl.parameters() = suite("Endpoint parameters") { archived = true } - params.archived shouldBe true - params.private shouldBe false + check(params.archived) + check(!params.private) params.data shouldBe mapOf( "archived" to "true", @@ -100,23 +95,23 @@ fun SuiteDsl.parameters() = suite("Endpoint parameters") { double = 10.0 } - params.string shouldBe "thing" - params.bool shouldBe true + check(params.string == "thing") + check(params.bool) - params.byte shouldBe 1 - params.short shouldBe 2 - params.int shouldBe 3 - params.long shouldBe 4 + check(params.byte == 1.toByte()) + check(params.short == 2.toShort()) + check(params.int == 3) + check(params.long == 4.toLong()) - params.ubyte shouldBe 5u - params.ushort shouldBe 6u - params.uint shouldBe 7u - params.ulong shouldBe 8u + check(params.ubyte == 5.toUByte()) + check(params.ushort == 6.toUShort()) + check(params.uint == 7.toUInt()) + check(params.ulong == 8.toULong()) - params.float shouldBe 9f - params.double shouldBe 10.0 + check(params.float == 9f) + check(params.double == 10.0) - params.data shouldBe mapOf( + check(params.data == mapOf( "string" to "thing", "bool" to "true", @@ -132,6 +127,6 @@ fun SuiteDsl.parameters() = suite("Endpoint parameters") { "float" to "${9.0}", // JVM: "9.0" — JS: "9" "double" to "${10.0}", - ) + )) } } diff --git a/api/src/commonTest/kotlin/PathTest.kt b/api/src/commonTest/kotlin/PathTest.kt index 64a6dca..c78725b 100644 --- a/api/src/commonTest/kotlin/PathTest.kt +++ b/api/src/commonTest/kotlin/PathTest.kt @@ -1,18 +1,16 @@ package opensavvy.spine.api import io.kotest.assertions.throwables.shouldThrow -import io.kotest.assertions.withClue -import io.kotest.matchers.shouldBe import opensavvy.prepared.suite.SuiteDsl -infix fun Addressed.shouldBeAddressedBy(path: String) = withClue("Expecting $this to be addressed by $path") { - this.path.toString() shouldBe path +infix fun Addressed.shouldBeAddressedBy(expectedPath: String) { + check(this.path.toString() == expectedPath) } fun SuiteDsl.paths() = suite("Paths") { test("Valid segments") { - Path.Segment("test").text shouldBe "test" - Path.Segment("test-other2").text shouldBe "test-other2" + check(Path.Segment("test").text == "test") + check(Path.Segment("test-other2").text == "test-other2") } test("A segment shouldn't be empty") { -- 2.51.2 From b95681bf59a04a5a1175884f02c12df0c2488245 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 29 May 2025 11:10:31 +0200 Subject: [PATCH 3/7] test(server): Migrate from Kotest to Power Assert --- server/src/commonTest/kotlin/RouteTest.kt | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/server/src/commonTest/kotlin/RouteTest.kt b/server/src/commonTest/kotlin/RouteTest.kt index b91b4ec..528f89c 100644 --- a/server/src/commonTest/kotlin/RouteTest.kt +++ b/server/src/commonTest/kotlin/RouteTest.kt @@ -1,6 +1,5 @@ package opensavvy.spine.typed.server -import io.kotest.matchers.shouldBe import io.ktor.client.* import io.ktor.http.HttpStatusCode.Companion.Created import io.ktor.http.HttpStatusCode.Companion.NotFound @@ -11,8 +10,12 @@ import kotlinx.coroutines.sync.withLock import kotlinx.serialization.Serializable import opensavvy.prepared.compat.ktor.preparedClient import opensavvy.prepared.compat.ktor.preparedServer -import opensavvy.prepared.suite.random.* -import opensavvy.prepared.suite.* +import opensavvy.prepared.suite.SuiteDsl +import opensavvy.prepared.suite.map +import opensavvy.prepared.suite.prepared +import opensavvy.prepared.suite.random.nextInt +import opensavvy.prepared.suite.random.random +import opensavvy.prepared.suite.random.randomInt import opensavvy.spine.api.* import opensavvy.spine.client.bodyOrThrow import opensavvy.spine.client.request @@ -129,11 +132,11 @@ fun SuiteDsl.routeTest() = suite("Route test") { val userId by randomInt(0, 999).map { it.toString() } test("Listing users when there are no users should return an empty list") { - client().listUsers(includeDisabled = false) shouldBe emptyList() + check(client().listUsers(includeDisabled = false) == emptyList()) } test("Listing users when there are no users should return an empty list, even if we want to access disabled users") { - client().listUsers(includeDisabled = true) shouldBe emptyList() + check(client().listUsers(includeDisabled = true) == emptyList()) } test("Creating a user") { @@ -154,26 +157,26 @@ fun SuiteDsl.routeTest() = suite("Route test") { enabledUser() disabledUser() - client().listUsers(includeDisabled = false) shouldBe listOf(enabledUser()) + check(client().listUsers(includeDisabled = false) == listOf(enabledUser())) } test("Listing all users") { enabledUser() disabledUser() - client().listUsers(includeDisabled = true) shouldBe listOf(enabledUser(), disabledUser()) + check(client().listUsers(includeDisabled = true) == listOf(enabledUser(), disabledUser())) } test("Accessing the details of a user") { val user = enabledUser() - client().getUser(user.id) shouldBe user + check(client().getUser(user.id) == user) } test("Deleting a user") { val user = enabledUser() client().deleteUser(user.id) - client().listUsers() shouldBe emptyList() + check(client().listUsers() == emptyList()) } } -- 2.51.2 From ddd741cc16f4e2e905722a52de45c2c9971898e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 29 May 2025 11:13:28 +0200 Subject: [PATCH 4/7] test(server-arrow-independent): Migrate from Kotest to Power Assert --- .../src/commonTest/kotlin/ServerRaiseTest.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/server-arrow-independent/src/commonTest/kotlin/ServerRaiseTest.kt b/server-arrow-independent/src/commonTest/kotlin/ServerRaiseTest.kt index 1fbbe6a..8047b0d 100644 --- a/server-arrow-independent/src/commonTest/kotlin/ServerRaiseTest.kt +++ b/server-arrow-independent/src/commonTest/kotlin/ServerRaiseTest.kt @@ -1,12 +1,10 @@ package opensavvy.spine.server.arrow.independent import arrow.core.raise.ensureNotNull -import io.kotest.matchers.shouldBe import io.ktor.client.call.* import io.ktor.client.request.* import io.ktor.http.* import io.ktor.serialization.kotlinx.json.* -import io.ktor.server.application.* import io.ktor.server.response.* import io.ktor.server.routing.* import opensavvy.prepared.compat.ktor.preparedClient @@ -48,7 +46,7 @@ class ServerRaiseTest : PreparedSpec({ } test("Product of two integers") { - client().put("/product?first=6&second=2").body() shouldBe 12 + check(client().put("/product?first=6&second=2").body() == 12) } }) -- 2.51.2 From 841dc1f7284bc9126eb7faa904ce50bc532fe2ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 29 May 2025 11:16:00 +0200 Subject: [PATCH 5/7] style(api): Suppress pointless warning --- api/src/commonMain/kotlin/Resource.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/api/src/commonMain/kotlin/Resource.kt b/api/src/commonMain/kotlin/Resource.kt index c19d441..452a093 100644 --- a/api/src/commonMain/kotlin/Resource.kt +++ b/api/src/commonMain/kotlin/Resource.kt @@ -310,6 +310,7 @@ private suspend fun SequenceScope.hierarchy(self: Resource) { * - `Api.Users`: `[Api, Users]` * - `Api.Users.User`: `[Api, Users, User]` */ +@Suppress("KDocUnresolvedReference") // `[Api]` is not a link, it's just text val Resource.hierarchy: Sequence get() { val self = this -- 2.51.2 From 505987fba75599a8e8578d64e386658861bc4d26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 29 May 2025 11:24:23 +0200 Subject: [PATCH 6/7] style(server): Removed pointless qualifications --- server/src/commonTest/kotlin/RouteTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/commonTest/kotlin/RouteTest.kt b/server/src/commonTest/kotlin/RouteTest.kt index 528f89c..854bc40 100644 --- a/server/src/commonTest/kotlin/RouteTest.kt +++ b/server/src/commonTest/kotlin/RouteTest.kt @@ -122,9 +122,9 @@ private suspend fun HttpClient.listUsers(includeDisabled: Boolean = false) = req private suspend fun HttpClient.createUser(user: UserDto) = request(Routes / Users / Users.create, user).bodyOrThrow() -private suspend fun HttpClient.getUser(id: String) = request(Routes / Users / Users.User(id) / User.get).bodyOrThrow() +private suspend fun HttpClient.getUser(id: String) = request(Routes / Users / User(id) / User.get).bodyOrThrow() -private suspend fun HttpClient.deleteUser(id: String) = request(Routes / Users / Users.User(id) / User.delete).bodyOrThrow() +private suspend fun HttpClient.deleteUser(id: String) = request(Routes / Users / User(id) / User.delete).bodyOrThrow() // endregion -- 2.51.2 From 64212a1bb77f4866aa834c4c3092fc7d9cf7a5c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 29 May 2025 11:26:19 +0200 Subject: [PATCH 7/7] test(api): Add examples of 'patch' and 'head' --- api/src/commonTest/kotlin/UsersAndDepartments.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/src/commonTest/kotlin/UsersAndDepartments.kt b/api/src/commonTest/kotlin/UsersAndDepartments.kt index d209400..1a7cf92 100644 --- a/api/src/commonTest/kotlin/UsersAndDepartments.kt +++ b/api/src/commonTest/kotlin/UsersAndDepartments.kt @@ -14,6 +14,8 @@ object Root : RootResource("api") { object User : DynamicResource("user", Users) { val get by get() + val head by head() + val update by patch() val preferences by get("preferences") object Departments : StaticResource("departments", User) {