From 87c6d6ea059dcbd413deefb143692b172f82fda1 Mon Sep 17 00:00:00 2001 From: Robert Stoll Date: Thu, 23 May 2024 22:23:16 +0200 Subject: [PATCH] introduce ifNotEmpty, drop own Atrium verb --- .../kotlin/ch/tutteli/kbox/ifNotEmpty.kt | 25 +++++++++++ .../tutteli/kbox/AppendToStringBuilderSpec.kt | 2 +- .../kotlin/ch/tutteli/kbox/BlankToNullSpec.kt | 2 +- .../tutteli/kbox/DynamicTreeTraversalSpec.kt | 2 +- .../kotlin/ch/tutteli/kbox/FailIfTest.kt | 2 +- .../kotlin/ch/tutteli/kbox/ForEachInSpec.kt | 2 +- .../ch/tutteli/kbox/ForEachRemainingSpec.kt | 2 +- .../tutteli/kbox/ForElementAndForEachSpec.kt | 2 +- .../kotlin/ch/tutteli/kbox/IfNotEmptyTest.kt | 42 +++++++++++++++++++ .../ch/tutteli/kbox/IfWithinBoundSpec.kt | 2 +- .../ch/tutteli/kbox/IsNotNullAndNotSpec.kt | 2 +- .../ch/tutteli/kbox/JoinToStringSpec.kt | 2 +- .../kotlin/ch/tutteli/kbox/MapParentsSpec.kt | 2 +- .../ch/tutteli/kbox/MapRemainingSpec.kt | 2 +- .../ch/tutteli/kbox/MapWithIndexSpec.kt | 2 +- .../ch/tutteli/kbox/PeekingIteratorSpec.kt | 2 +- .../kotlin/ch/tutteli/kbox/TakeIfSpec.kt | 21 ---------- .../kotlin/ch/tutteli/kbox/TakeIfTest.kt | 20 +++++++++ .../ch/tutteli/kbox/atrium/atriumVerbs.kt | 20 --------- 19 files changed, 101 insertions(+), 55 deletions(-) create mode 100644 src/commonMain/kotlin/ch/tutteli/kbox/ifNotEmpty.kt create mode 100644 src/commonTest/kotlin/ch/tutteli/kbox/IfNotEmptyTest.kt delete mode 100644 src/commonTest/kotlin/ch/tutteli/kbox/TakeIfSpec.kt create mode 100644 src/commonTest/kotlin/ch/tutteli/kbox/TakeIfTest.kt delete mode 100644 src/commonTest/kotlin/ch/tutteli/kbox/atrium/atriumVerbs.kt diff --git a/src/commonMain/kotlin/ch/tutteli/kbox/ifNotEmpty.kt b/src/commonMain/kotlin/ch/tutteli/kbox/ifNotEmpty.kt new file mode 100644 index 0000000..55d7d72 --- /dev/null +++ b/src/commonMain/kotlin/ch/tutteli/kbox/ifNotEmpty.kt @@ -0,0 +1,25 @@ +package ch.tutteli.kbox + +/** + * Checks if this collection is empty and if not applies the given [transformation]. + * + * @param transformation the function which transforms this collection into [SuperTypeOfT] (at least an + * [Iterable]) + * + * @param T The type of the receiver -- a [Collection] or one of its subtypes + * @param SuperTypeOfT The result type can also be a super type of [T] as long as it doesn't go + * beyond [Iterable]. In theory, we would not need to establish this constraint but in all cases we came across + * so far we never wanted to end up with [Any]. E.g. if [T] = [List] then we don't want that the + * [transformation] returns an [Array] as otherwise we have a [List] in case it is empty and an [Array] otherwise and + * the least upper bound of those two types is [Any], i.e. we would end up with [SuperTypeOfT] = [Any]. + * + * @return `this` if the given collection is empty, otherwise the result of applying this collection to the given + * [transformation]. + * + * @since 1.2.0 + */ +@Suppress("BOUNDS_NOT_ALLOWED_IF_BOUNDED_BY_TYPE_PARAMETER") +inline fun T.ifNotEmpty( + transformation: (T) -> SuperTypeOfT +): SuperTypeOfT where T : Collection<*>, SuperTypeOfT : Iterable<*>, T : SuperTypeOfT = + if (this.isNotEmpty()) transformation(this) else this diff --git a/src/commonTest/kotlin/ch/tutteli/kbox/AppendToStringBuilderSpec.kt b/src/commonTest/kotlin/ch/tutteli/kbox/AppendToStringBuilderSpec.kt index 5ae990a..493fb18 100644 --- a/src/commonTest/kotlin/ch/tutteli/kbox/AppendToStringBuilderSpec.kt +++ b/src/commonTest/kotlin/ch/tutteli/kbox/AppendToStringBuilderSpec.kt @@ -2,7 +2,7 @@ package ch.tutteli.kbox import ch.tutteli.atrium.api.fluent.en_GB.toBeEmpty import ch.tutteli.atrium.api.fluent.en_GB.toEqual -import ch.tutteli.kbox.atrium.expect +import ch.tutteli.atrium.api.verbs.expect import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.describe import kotlin.reflect.KFunction4 diff --git a/src/commonTest/kotlin/ch/tutteli/kbox/BlankToNullSpec.kt b/src/commonTest/kotlin/ch/tutteli/kbox/BlankToNullSpec.kt index d92ea17..382bf1d 100644 --- a/src/commonTest/kotlin/ch/tutteli/kbox/BlankToNullSpec.kt +++ b/src/commonTest/kotlin/ch/tutteli/kbox/BlankToNullSpec.kt @@ -1,7 +1,7 @@ package ch.tutteli.kbox import ch.tutteli.atrium.api.fluent.en_GB.toEqual -import ch.tutteli.kbox.atrium.expect +import ch.tutteli.atrium.api.verbs.expect import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.describe diff --git a/src/commonTest/kotlin/ch/tutteli/kbox/DynamicTreeTraversalSpec.kt b/src/commonTest/kotlin/ch/tutteli/kbox/DynamicTreeTraversalSpec.kt index 44183f7..afeb39d 100644 --- a/src/commonTest/kotlin/ch/tutteli/kbox/DynamicTreeTraversalSpec.kt +++ b/src/commonTest/kotlin/ch/tutteli/kbox/DynamicTreeTraversalSpec.kt @@ -1,7 +1,7 @@ package ch.tutteli.kbox import ch.tutteli.atrium.api.fluent.en_GB.* -import ch.tutteli.kbox.atrium.expect +import ch.tutteli.atrium.api.verbs.expect import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.describe diff --git a/src/commonTest/kotlin/ch/tutteli/kbox/FailIfTest.kt b/src/commonTest/kotlin/ch/tutteli/kbox/FailIfTest.kt index 49aa8c5..bc48f62 100644 --- a/src/commonTest/kotlin/ch/tutteli/kbox/FailIfTest.kt +++ b/src/commonTest/kotlin/ch/tutteli/kbox/FailIfTest.kt @@ -3,7 +3,7 @@ package ch.tutteli.kbox import ch.tutteli.atrium.api.fluent.en_GB.messageToContain import ch.tutteli.atrium.api.fluent.en_GB.notToThrow import ch.tutteli.atrium.api.fluent.en_GB.toThrow -import ch.tutteli.kbox.atrium.expect +import ch.tutteli.atrium.api.verbs.expect import kotlin.test.Test class FailIfTest { diff --git a/src/commonTest/kotlin/ch/tutteli/kbox/ForEachInSpec.kt b/src/commonTest/kotlin/ch/tutteli/kbox/ForEachInSpec.kt index 2abfea4..4c2610a 100644 --- a/src/commonTest/kotlin/ch/tutteli/kbox/ForEachInSpec.kt +++ b/src/commonTest/kotlin/ch/tutteli/kbox/ForEachInSpec.kt @@ -1,7 +1,7 @@ package ch.tutteli.kbox import ch.tutteli.atrium.api.fluent.en_GB.toEqual -import ch.tutteli.kbox.atrium.expect +import ch.tutteli.atrium.api.verbs.expect import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.describe diff --git a/src/commonTest/kotlin/ch/tutteli/kbox/ForEachRemainingSpec.kt b/src/commonTest/kotlin/ch/tutteli/kbox/ForEachRemainingSpec.kt index 540e525..3e250e1 100644 --- a/src/commonTest/kotlin/ch/tutteli/kbox/ForEachRemainingSpec.kt +++ b/src/commonTest/kotlin/ch/tutteli/kbox/ForEachRemainingSpec.kt @@ -2,7 +2,7 @@ package ch.tutteli.kbox import ch.tutteli.atrium.api.fluent.en_GB.toContainExactly import ch.tutteli.atrium.api.fluent.en_GB.toBeEmpty -import ch.tutteli.kbox.atrium.expect +import ch.tutteli.atrium.api.verbs.expect import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.describe import kotlin.reflect.KFunction2 diff --git a/src/commonTest/kotlin/ch/tutteli/kbox/ForElementAndForEachSpec.kt b/src/commonTest/kotlin/ch/tutteli/kbox/ForElementAndForEachSpec.kt index 4b38418..82ef0b9 100644 --- a/src/commonTest/kotlin/ch/tutteli/kbox/ForElementAndForEachSpec.kt +++ b/src/commonTest/kotlin/ch/tutteli/kbox/ForElementAndForEachSpec.kt @@ -1,7 +1,7 @@ package ch.tutteli.kbox import ch.tutteli.atrium.api.fluent.en_GB.toEqual -import ch.tutteli.kbox.atrium.expect +import ch.tutteli.atrium.api.verbs.expect import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.describe import kotlin.reflect.KFunction3 diff --git a/src/commonTest/kotlin/ch/tutteli/kbox/IfNotEmptyTest.kt b/src/commonTest/kotlin/ch/tutteli/kbox/IfNotEmptyTest.kt new file mode 100644 index 0000000..b9e9ac3 --- /dev/null +++ b/src/commonTest/kotlin/ch/tutteli/kbox/IfNotEmptyTest.kt @@ -0,0 +1,42 @@ +package ch.tutteli.kbox + +import ch.tutteli.atrium.api.fluent.en_GB.* +import ch.tutteli.atrium.api.verbs.expect +import ch.tutteli.atrium.api.verbs.expectGrouped +import kotlin.test.Test + +class IfNotEmptyTest { + + @Test + fun it_returns_the_collection_itself_if_empty() { + expectGrouped { + listOf>( + emptyList(), + emptySet(), + ).forEach { collection -> + group("check it works with ${collection::class.simpleName}") { + expect(collection.ifNotEmpty { nonEmptyCollection -> + nonEmptyCollection.map { it + 1 } + }).toBeTheInstance(collection) + } + } + } + } + + @Test + fun it_returns_the_result_of_the_transformation_if_not_empty() { + expectGrouped { + listOf( + listOf(1), + setOf(1), + ).forEach { collection -> + group("check it works with ${collection::class.simpleName}") { + expect(collection.ifNotEmpty { nonEmptyCollection -> + nonEmptyCollection.map { it + 1 } + }).toContainExactly(2) + } + } + } + } +} + diff --git a/src/commonTest/kotlin/ch/tutteli/kbox/IfWithinBoundSpec.kt b/src/commonTest/kotlin/ch/tutteli/kbox/IfWithinBoundSpec.kt index afe8e55..b731c65 100644 --- a/src/commonTest/kotlin/ch/tutteli/kbox/IfWithinBoundSpec.kt +++ b/src/commonTest/kotlin/ch/tutteli/kbox/IfWithinBoundSpec.kt @@ -1,7 +1,7 @@ package ch.tutteli.kbox import ch.tutteli.atrium.api.fluent.en_GB.toEqual -import ch.tutteli.kbox.atrium.expect +import ch.tutteli.atrium.api.verbs.expect import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.describe diff --git a/src/commonTest/kotlin/ch/tutteli/kbox/IsNotNullAndNotSpec.kt b/src/commonTest/kotlin/ch/tutteli/kbox/IsNotNullAndNotSpec.kt index 3bee0fa..7653f5d 100644 --- a/src/commonTest/kotlin/ch/tutteli/kbox/IsNotNullAndNotSpec.kt +++ b/src/commonTest/kotlin/ch/tutteli/kbox/IsNotNullAndNotSpec.kt @@ -1,7 +1,7 @@ package ch.tutteli.kbox import ch.tutteli.atrium.api.fluent.en_GB.toEqual -import ch.tutteli.kbox.atrium.expect +import ch.tutteli.atrium.api.verbs.expect import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.describe diff --git a/src/commonTest/kotlin/ch/tutteli/kbox/JoinToStringSpec.kt b/src/commonTest/kotlin/ch/tutteli/kbox/JoinToStringSpec.kt index e4dc3d4..8337dd9 100644 --- a/src/commonTest/kotlin/ch/tutteli/kbox/JoinToStringSpec.kt +++ b/src/commonTest/kotlin/ch/tutteli/kbox/JoinToStringSpec.kt @@ -2,7 +2,7 @@ package ch.tutteli.kbox import ch.tutteli.atrium.api.fluent.en_GB.toBeEmpty import ch.tutteli.atrium.api.fluent.en_GB.toEqual -import ch.tutteli.kbox.atrium.expect +import ch.tutteli.atrium.api.verbs.expect import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.describe import kotlin.reflect.KFunction3 diff --git a/src/commonTest/kotlin/ch/tutteli/kbox/MapParentsSpec.kt b/src/commonTest/kotlin/ch/tutteli/kbox/MapParentsSpec.kt index 85b0360..ec3fd21 100644 --- a/src/commonTest/kotlin/ch/tutteli/kbox/MapParentsSpec.kt +++ b/src/commonTest/kotlin/ch/tutteli/kbox/MapParentsSpec.kt @@ -1,7 +1,7 @@ package ch.tutteli.kbox import ch.tutteli.atrium.api.fluent.en_GB.* -import ch.tutteli.kbox.atrium.expect +import ch.tutteli.atrium.api.verbs.expect import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.Suite import org.spekframework.spek2.style.specification.describe diff --git a/src/commonTest/kotlin/ch/tutteli/kbox/MapRemainingSpec.kt b/src/commonTest/kotlin/ch/tutteli/kbox/MapRemainingSpec.kt index ac0b3c8..f6650b8 100644 --- a/src/commonTest/kotlin/ch/tutteli/kbox/MapRemainingSpec.kt +++ b/src/commonTest/kotlin/ch/tutteli/kbox/MapRemainingSpec.kt @@ -2,7 +2,7 @@ package ch.tutteli.kbox import ch.tutteli.atrium.api.fluent.en_GB.toContainExactly import ch.tutteli.atrium.api.fluent.en_GB.toBeEmpty -import ch.tutteli.kbox.atrium.expect +import ch.tutteli.atrium.api.verbs.expect import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.describe diff --git a/src/commonTest/kotlin/ch/tutteli/kbox/MapWithIndexSpec.kt b/src/commonTest/kotlin/ch/tutteli/kbox/MapWithIndexSpec.kt index 406115b..6444014 100644 --- a/src/commonTest/kotlin/ch/tutteli/kbox/MapWithIndexSpec.kt +++ b/src/commonTest/kotlin/ch/tutteli/kbox/MapWithIndexSpec.kt @@ -2,7 +2,7 @@ package ch.tutteli.kbox import ch.tutteli.atrium.api.fluent.en_GB.toContainExactly import ch.tutteli.atrium.api.fluent.en_GB.toBeEmpty -import ch.tutteli.kbox.atrium.expect +import ch.tutteli.atrium.api.verbs.expect import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.describe diff --git a/src/commonTest/kotlin/ch/tutteli/kbox/PeekingIteratorSpec.kt b/src/commonTest/kotlin/ch/tutteli/kbox/PeekingIteratorSpec.kt index 7e16293..06f0584 100644 --- a/src/commonTest/kotlin/ch/tutteli/kbox/PeekingIteratorSpec.kt +++ b/src/commonTest/kotlin/ch/tutteli/kbox/PeekingIteratorSpec.kt @@ -3,7 +3,7 @@ package ch.tutteli.kbox import ch.tutteli.atrium.api.fluent.en_GB.toBeTheInstance import ch.tutteli.atrium.api.fluent.en_GB.toEqual import ch.tutteli.atrium.api.fluent.en_GB.toThrow -import ch.tutteli.kbox.atrium.expect +import ch.tutteli.atrium.api.verbs.expect import org.spekframework.spek2.Spek import org.spekframework.spek2.lifecycle.CachingMode import org.spekframework.spek2.style.specification.describe diff --git a/src/commonTest/kotlin/ch/tutteli/kbox/TakeIfSpec.kt b/src/commonTest/kotlin/ch/tutteli/kbox/TakeIfSpec.kt deleted file mode 100644 index 2423b5b..0000000 --- a/src/commonTest/kotlin/ch/tutteli/kbox/TakeIfSpec.kt +++ /dev/null @@ -1,21 +0,0 @@ -package ch.tutteli.kbox - -import ch.tutteli.atrium.api.fluent.en_GB.toEqual -import ch.tutteli.kbox.atrium.expect -import org.spekframework.spek2.Spek -import org.spekframework.spek2.style.specification.describe - -object TakeIfSpec : Spek({ - - describe("fun ${::takeIf.name}}") { - it("it returns null if predicate doesn't hold") { - expect( - takeIf(false) { throw IllegalArgumentException("bla") } - ).toEqual(null) - } - - it("it returns null if predicate doesn't hold") { - expect(takeIf(true) { 1 }).toEqual(1) - } - } -}) diff --git a/src/commonTest/kotlin/ch/tutteli/kbox/TakeIfTest.kt b/src/commonTest/kotlin/ch/tutteli/kbox/TakeIfTest.kt new file mode 100644 index 0000000..b89c195 --- /dev/null +++ b/src/commonTest/kotlin/ch/tutteli/kbox/TakeIfTest.kt @@ -0,0 +1,20 @@ +package ch.tutteli.kbox + +import ch.tutteli.atrium.api.fluent.en_GB.toEqual +import ch.tutteli.atrium.api.verbs.expect +import kotlin.test.Test + +class TakeIfTest { + + @Test + fun `it_returns_null_if_predicate_doesnt_hold`() { + expect( + takeIf(false) { throw IllegalArgumentException("bla") } + ).toEqual(null) + } + + @Test + fun it_returns_lambda_result_if_predicate_holds() { + expect(takeIf(true) { 1 }).toEqual(1) + } +} diff --git a/src/commonTest/kotlin/ch/tutteli/kbox/atrium/atriumVerbs.kt b/src/commonTest/kotlin/ch/tutteli/kbox/atrium/atriumVerbs.kt deleted file mode 100644 index ea8e148..0000000 --- a/src/commonTest/kotlin/ch/tutteli/kbox/atrium/atriumVerbs.kt +++ /dev/null @@ -1,20 +0,0 @@ -package ch.tutteli.kbox.atrium - -import ch.tutteli.atrium.creating.Expect -import ch.tutteli.atrium.logic._logic -import ch.tutteli.atrium.logic.creating.RootExpectBuilder -import ch.tutteli.atrium.reporting.translating.StringBasedTranslatable -import ch.tutteli.kbox.atrium.AssertionVerb.ASSERT - -internal fun expect(subject: T): Expect = - RootExpectBuilder.forSubject(subject) - .withVerb(ASSERT) - .withoutOptions() - .build() - -internal fun expect(subject: T, createAssertions: Expect.() -> Unit) = - expect(subject)._logic.appendAsGroup(createAssertions) - -internal enum class AssertionVerb(override val value: String) : StringBasedTranslatable { - ASSERT("assert"), -}