From 95c030d9817950641493d5f231b4fa5397d3ab10 Mon Sep 17 00:00:00 2001 From: Christoph Sturm Date: Mon, 24 Jan 2022 17:33:12 +0100 Subject: [PATCH] experimental any dsl --- .../src/test/kotlin/strikt/exp/ClearlyTest.kt | 55 +++++++++++++++ .../kotlin/strikt/exp/HasWithReceiverTest.kt | 68 +++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 strikt-core/src/test/kotlin/strikt/exp/ClearlyTest.kt create mode 100644 strikt-core/src/test/kotlin/strikt/exp/HasWithReceiverTest.kt diff --git a/strikt-core/src/test/kotlin/strikt/exp/ClearlyTest.kt b/strikt-core/src/test/kotlin/strikt/exp/ClearlyTest.kt new file mode 100644 index 00000000..601b301c --- /dev/null +++ b/strikt-core/src/test/kotlin/strikt/exp/ClearlyTest.kt @@ -0,0 +1,55 @@ +package strikt.exp + +import failgood.Test +import failgood.describe +import strikt.api.DescribeableBuilder +import strikt.api.expectThat +import strikt.assertions.endsWith +import strikt.assertions.isEqualTo +import strikt.internal.AssertionBuilder +import strikt.internal.AssertionStrategy +import strikt.internal.AssertionSubject + + +@Test +class ClearlyTest { + val context = describe("experimental Any receiver syntax") { + describe("has") { + + it("works with simple asserts") { + val kiddo = "jakob" + // instead of + expectThat(kiddo).isEqualTo("jakob") + // we could also write + kiddo.clearly.isEqualTo("jakob") + // or likely, doubtless, withoutADoubt, promisesIt, saysIt, you get the idea + + // or using the nested syntax: + kiddo.has { this.that.isEqualTo("jakob") } + } + it("works with nested asserts") { + data class User(val name: String, val email: String) + + val user = User("chris", "chris@example.com") + user.has { + name.that.isEqualTo("chris") + email.that.endsWith("example.com") + } + } + } + } + private val T.clearly: DescribeableBuilder + get() = AssertionBuilder( + AssertionSubject(this), AssertionStrategy.Throwing + ) + + private val T.that: DescribeableBuilder + get() = AssertionBuilder( + AssertionSubject(this), AssertionStrategy.Throwing + ) + + fun T.has(function: T.() -> Unit) { + this.function() + } +} + diff --git a/strikt-core/src/test/kotlin/strikt/exp/HasWithReceiverTest.kt b/strikt-core/src/test/kotlin/strikt/exp/HasWithReceiverTest.kt new file mode 100644 index 00000000..d2aecafc --- /dev/null +++ b/strikt-core/src/test/kotlin/strikt/exp/HasWithReceiverTest.kt @@ -0,0 +1,68 @@ +package strikt.exp + +import failgood.Test +import failgood.describe +import strikt.api.Assertion +import strikt.api.DescribeableBuilder +import strikt.assertions.endsWith +import strikt.assertions.isEqualTo +import strikt.assertions.isNotNull +import strikt.internal.AssertionBuilder +import strikt.internal.AssertionStrategy +import strikt.internal.AssertionSubject + +@Suppress("NAME_SHADOWING") +@Test +class HasWithReceiverTest { + inline fun T.has(function: DSL.(T) -> Unit) { + DSL().function(this) + } + + class DSL { + val errors = mutableListOf() + + @Suppress("UNUSED_VARIABLE") + val T.that: DescribeableBuilder + get() { + val errors = this@DSL.errors // we can access the errors collection in the dsl collector + return AssertionBuilder( + AssertionSubject(this), AssertionStrategy.Throwing + ) + } + fun Assertion.Builder.andHas(block: DSL.(T) -> Unit) { + this@DSL.block(this.subject) + } + } + + + val context = describe("has with receiver") { + it("works with nested asserts") { + data class Nested(val field: String) + data class Role(val nested: Nested) + data class User(val name: String, val email: String, val role: Role?) + + val user = User("chris", "chris@example.com", Role(Nested("field"))) + + + user.has { a -> + a.name.that.isEqualTo("chris") + a.email.that.endsWith("example.com") + a.role.that.isNotNull().andHas { a -> + a.nested.field.that.isEqualTo("field") + } + } + } + it("can call suspend methods") { + class Coroutine { + @Suppress("RedundantSuspendModifier") + suspend fun otto() = 8 + } + Coroutine().has { a -> + a.otto().that.isEqualTo(8) + } + } + } + +} + +