From 6c654ef39885c1e108fa5114260f721ebed631d4 Mon Sep 17 00:00:00 2001 From: Robert Stoll Date: Mon, 18 Mar 2019 21:21:37 +0100 Subject: [PATCH] open up non-nullable overloads for Map assertions ...and delete the once which have been used for nullable --- .../atrium/api/cc/de_CH/mapAssertions.kt | 49 ++---------- .../atrium/api/cc/de_CH/parameterObjects.kt | 4 +- .../atrium/api/cc/de_CH/MapAssertionsSpec.kt | 65 ++++++++++++++- .../atrium/api/cc/en_GB/mapAssertions.kt | 46 ++--------- .../atrium/api/cc/en_GB/parameterObjects.kt | 6 +- .../atrium/api/cc/en_GB/MapAssertionsSpec.kt | 67 +++++++++++++++- .../api/cc/infix/en_GB/mapAssertions.kt | 80 +++---------------- .../api/cc/infix/en_GB/parameterObjects.kt | 4 +- .../api/cc/infix/en_GB/MapAssertionsSpec.kt | 68 +++++++++++++++- .../atrium/domain/creating/MapAssertions.kt | 7 +- .../builders/creating/MapAssertionsBuilder.kt | 14 +--- .../robstoll/lib/creating/mapAssertions.kt | 55 +++++++------ .../robstoll/creating/MapAssertionsImpl.kt | 17 +--- 13 files changed, 255 insertions(+), 227 deletions(-) diff --git a/apis/cc-de_CH/atrium-api-cc-de_CH-common/src/main/kotlin/ch/tutteli/atrium/api/cc/de_CH/mapAssertions.kt b/apis/cc-de_CH/atrium-api-cc-de_CH-common/src/main/kotlin/ch/tutteli/atrium/api/cc/de_CH/mapAssertions.kt index bd8bdd36b..3f6ab63d8 100644 --- a/apis/cc-de_CH/atrium-api-cc-de_CH-common/src/main/kotlin/ch/tutteli/atrium/api/cc/de_CH/mapAssertions.kt +++ b/apis/cc-de_CH/atrium-api-cc-de_CH-common/src/main/kotlin/ch/tutteli/atrium/api/cc/de_CH/mapAssertions.kt @@ -7,12 +7,11 @@ import ch.tutteli.atrium.creating.AssertionPlantNullable import ch.tutteli.atrium.domain.builders.AssertImpl import ch.tutteli.kbox.glue import kotlin.js.JsName -import kotlin.jvm.JvmName /** - * Makes the assertion that the [Assert.subject][AssertionPlant.subject] contains a key as defined by [entry]'s [Pair.first] - * with a corresponding value as defined by [entry]'s [Pair.second] -- optionally the same assertions are created - * for the [otherEntries]. + * Makes the assertion that the [Assert.subject][AssertionPlant.subject] contains a key as defined by + * [entry]'s [Pair.first] with a corresponding value as defined by [entry]'s [Pair.second] + * -- optionally the same assertions are created for the [otherEntries]. * * Notice, that it does not search for unique matches. Meaning, if the map is `mapOf('a' to 1)` and [entry] is * defined as `'a' to 1` and one of the [otherEntries] is defined as `'a' to 1` as well, then both match, @@ -21,41 +20,9 @@ import kotlin.jvm.JvmName * @return This plant to support a fluent API. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ -@JsName("enthaelt") -fun > Assert.enthaelt(entry: Pair, vararg otherEntries: Pair) +fun > Assert.enthaelt(entry: Pair, vararg otherEntries: Pair) = addAssertion(AssertImpl.map.contains(this, entry glue otherEntries)) -/** - * Makes the assertion that the [Assert.subject][AssertionPlant.subject] contains a key as defined by [entry]'s [Pair.first] - * with a corresponding value as defined by [entry]'s [Pair.second] -- optionally the same assertions are created - * for the [otherEntries]. - * - * Notice, that it does not search for unique matches. Meaning, if the map is `mapOf('a' to 1)` and [entry] is - * defined as `'a' to 1` and one of the [otherEntries] is defined as `'a' to 1` as well, then both match, - * even though they match the same entry. - * - * @return This plant to support a fluent API. - * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. - */ -@JvmName("enthaeltNullable") -inline fun > Assert.enthaelt(entry: Pair, vararg otherEntries: Pair) - = addAssertion(AssertImpl.map.containsNullable(this, V::class, entry glue otherEntries)) - -/** - * Makes the assertion that the [Assert.subject][AssertionPlant.subject] contains a key as defined by [keyValue]'s [KeyValue.key] - * with a corresponding value which holds all assertions [keyValue]'s [valueAssertionCreator][KeyValue.valueAssertionCreatorOrNull] might create. - * -- optionally the same assertions are created for the [otherKeyValues]. - * - * Notice, that it does not search for unique matches. Meaning, if the map is `mapOf('a' to 1)` and [keyValue] is - * defined as `Key('a') { isGreaterThan(0) }` and one of the [otherKeyValues] is defined as `Key('a') { isLessThan(2) }` - * then both match, even though they match the same entry. - * - * @return This plant to support a fluent API. - * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. - */ -fun > Assert.enthaelt(keyValue: KeyValue.() -> Unit>, vararg otherKeyValues: KeyValue.() -> Unit>) - = addAssertion(AssertImpl.map.containsKeyWithValueAssertions(this, (keyValue glue otherKeyValues).map { it.toPair() })) - /** * Makes the assertion that the [Assert.subject][AssertionPlant.subject] contains a key as defined by [keyValue]'s [KeyValue.key] * with a corresponding value which either holds all assertions [keyValue]'s @@ -70,9 +37,10 @@ fun > Assert.enthaelt(keyValue: KeyValue> Assert.enthaelt(keyValue: KeyValue.() -> Unit)?>, vararg otherKeyValues: KeyValue.() -> Unit)?>) - = addAssertion(AssertImpl.map.containsKeyWithNullableValueAssertions(this, V::class, (keyValue glue otherKeyValues).map { it.toPair() })) +fun > Assert.enthaelt( + keyValue: KeyValue, + vararg otherKeyValues: KeyValue +) = addAssertion(AssertImpl.map.containsKeyWithValueAssertions(this, (keyValue glue otherKeyValues).map { it.toPair() })) /** @@ -94,7 +62,6 @@ fun Assert>.enthaeltNichtKey(key: K) = addAssertion(AssertImpl.map.containsNotKey(this, key)) - /** * Makes the assertion that the [Assert.subject][AssertionPlant.subject] contains the given [key], creates a feature * assertion plant for corresponding value and returns the newly created plant. diff --git a/apis/cc-de_CH/atrium-api-cc-de_CH-common/src/main/kotlin/ch/tutteli/atrium/api/cc/de_CH/parameterObjects.kt b/apis/cc-de_CH/atrium-api-cc-de_CH-common/src/main/kotlin/ch/tutteli/atrium/api/cc/de_CH/parameterObjects.kt index e7fe3d57c..62374649b 100644 --- a/apis/cc-de_CH/atrium-api-cc-de_CH-common/src/main/kotlin/ch/tutteli/atrium/api/cc/de_CH/parameterObjects.kt +++ b/apis/cc-de_CH/atrium-api-cc-de_CH-common/src/main/kotlin/ch/tutteli/atrium/api/cc/de_CH/parameterObjects.kt @@ -57,8 +57,8 @@ class Eintraege( * Parameter object to express a key/value [Pair] whose value type is a lambda with an * [Assert][AssertionPlant] receiver, which means one can either pass a lambda or `null`. */ -data class KeyValue) -> Unit)?>(val key: K, val valueAssertionCreatorOrNull: A) { - fun toPair(): Pair = key to valueAssertionCreatorOrNull +data class KeyValue(val key: K, val valueAssertionCreatorOrNull: (Assert.() -> Unit)?) { + fun toPair(): Pair.() -> Unit)?> = key to valueAssertionCreatorOrNull override fun toString(): String = "KeyValue(key=$key, value=${if (valueAssertionCreatorOrNull == null) "null" else "lambda"})" } diff --git a/apis/cc-de_CH/atrium-api-cc-de_CH-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/de_CH/MapAssertionsSpec.kt b/apis/cc-de_CH/atrium-api-cc-de_CH-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/de_CH/MapAssertionsSpec.kt index ebc96842a..d7037cda7 100644 --- a/apis/cc-de_CH/atrium-api-cc-de_CH-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/de_CH/MapAssertionsSpec.kt +++ b/apis/cc-de_CH/atrium-api-cc-de_CH-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/de_CH/MapAssertionsSpec.kt @@ -3,6 +3,7 @@ package ch.tutteli.atrium.api.cc.de_CH import ch.tutteli.atrium.AssertionVerbFactory import ch.tutteli.atrium.creating.Assert import ch.tutteli.atrium.domain.builders.utils.mapArguments +import ch.tutteli.atrium.esGilt import kotlin.reflect.KFunction3 class MapAssertionsSpec : ch.tutteli.atrium.spec.integration.MapAssertionsSpec( @@ -22,8 +23,8 @@ class MapAssertionsSpec : ch.tutteli.atrium.spec.integration.MapAssertionsSpec( companion object { private val containsFun : KFunction3>, Pair, Array>, Assert>> = Assert>::enthaelt private val containsNullableFun : KFunction3>, Pair, Array>, Assert>> = Assert>::enthaelt - private val containsKeyWithValueAssertionsFun : KFunction3>, KeyValue) -> Unit>, Array) -> Unit>>, Assert>> = Assert>::enthaelt - private val containsKeyWithNullableValueAssertionsFun : KFunction3>, KeyValue) -> Unit)?>, Array) -> Unit)?>>, Assert>> = Assert>::enthaelt + private val containsKeyWithValueAssertionsFun : KFunction3>, KeyValue, Array>, Assert>> = Assert>::enthaelt + private val containsKeyWithNullableValueAssertionsFun : KFunction3>, KeyValue, Array>, Assert>> = Assert>::enthaelt fun contains(plant: Assert>, keyValue: Pair.() -> Unit>, otherKeyValues: Array.() -> Unit>>) = mapArguments(keyValue, otherKeyValues).to { KeyValue(it.first, it.second) }.let { (first, others) -> @@ -35,5 +36,65 @@ class MapAssertionsSpec : ch.tutteli.atrium.spec.integration.MapAssertionsSpec( plant.enthaelt(first, *others) } } + + @Suppress("unused") + private fun ambiguityTest() { + val map = mapOf(1 to "a") + val nullableKeyMap = mapOf(1 as Int? to "a") + val nullableValueMap = mapOf(1 to "a" as String?) + val nullableKeyValueMap = mapOf(1 as Int? to "a" as String?) + esGilt(map).enthaelt(1 to "a") + esGilt(map).enthaelt(1 to "a", 2 to "b") + esGilt(map).enthaelt(KeyValue(1){}) + esGilt(map).enthaelt(KeyValue(1){}, KeyValue(2){}) + + esGilt(nullableKeyMap).enthaelt(1 to "a") + esGilt(nullableKeyMap).enthaelt(1 to "a", 2 to "b") + esGilt(nullableKeyMap).enthaelt(KeyValue(1){}) + esGilt(nullableKeyMap).enthaelt(KeyValue(1){}, KeyValue(2){}) + esGilt(nullableKeyMap).enthaelt(null to "a") + esGilt(nullableKeyMap).enthaelt(null to "a", null to "b") + esGilt(nullableKeyMap).enthaelt(null to "a", 2 to "b") + esGilt(nullableKeyMap).enthaelt(KeyValue(null){}) + esGilt(nullableKeyMap).enthaelt(KeyValue(null){}, KeyValue(null){}) + esGilt(nullableKeyMap).enthaelt(KeyValue(null){}, KeyValue(2){}) + + esGilt(nullableValueMap).enthaelt(1 to "a") + esGilt(nullableValueMap).enthaelt(1 to "a", 2 to "b") + esGilt(nullableValueMap).enthaelt(KeyValue(1){}) + esGilt(nullableValueMap).enthaelt(KeyValue(1){}, KeyValue(2){}) + esGilt(nullableValueMap).enthaelt(1 to null) + esGilt(nullableValueMap).enthaelt(1 to null, 2 to null) + esGilt(nullableValueMap).enthaelt(1 to null, 2 to "a") + esGilt(nullableValueMap).enthaelt(KeyValue(1, null)) + esGilt(nullableValueMap).enthaelt(KeyValue(1, null), KeyValue(2, null)) + esGilt(nullableValueMap).enthaelt(KeyValue(1, null), KeyValue(2){}) + + esGilt(nullableKeyValueMap).enthaelt(1 to "a") + esGilt(nullableKeyValueMap).enthaelt(1 to "a", 2 to "b") + esGilt(nullableKeyValueMap).enthaelt(KeyValue(1){}) + esGilt(nullableKeyValueMap).enthaelt(KeyValue(1){}, KeyValue(2){}) + + esGilt(nullableKeyValueMap).enthaelt(null to "a") + esGilt(nullableKeyValueMap).enthaelt(null to "a", null to "b") + esGilt(nullableKeyValueMap).enthaelt(null to "a", 2 to "b") + esGilt(nullableKeyValueMap).enthaelt(KeyValue(null){}) + esGilt(nullableKeyValueMap).enthaelt(KeyValue(null){}, KeyValue(null){}) + esGilt(nullableKeyValueMap).enthaelt(KeyValue(null){}, KeyValue(2){}) + + esGilt(nullableKeyValueMap).enthaelt(1 to null) + esGilt(nullableKeyValueMap).enthaelt(1 to null, 2 to null) + esGilt(nullableKeyValueMap).enthaelt(1 to null, 2 to "a") + esGilt(nullableKeyValueMap).enthaelt(KeyValue(1, null)) + esGilt(nullableKeyValueMap).enthaelt(KeyValue(1, null), KeyValue(2, null)) + esGilt(nullableKeyValueMap).enthaelt(KeyValue(1, null), KeyValue(2){}) + + esGilt(nullableKeyValueMap).enthaelt(null to null) + esGilt(nullableKeyValueMap).enthaelt(null to null, null to null) + esGilt(nullableKeyValueMap).enthaelt(1 to null, null to "a") + esGilt(nullableKeyValueMap).enthaelt(KeyValue(null, null)) + esGilt(nullableKeyValueMap).enthaelt(KeyValue(null, null), KeyValue(null, null)) + esGilt(nullableKeyValueMap).enthaelt(KeyValue(1, null), KeyValue(null){}) + } } diff --git a/apis/cc-en_GB/atrium-api-cc-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/en_GB/mapAssertions.kt b/apis/cc-en_GB/atrium-api-cc-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/en_GB/mapAssertions.kt index 02c93eadc..ca5c1df3a 100644 --- a/apis/cc-en_GB/atrium-api-cc-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/en_GB/mapAssertions.kt +++ b/apis/cc-en_GB/atrium-api-cc-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/en_GB/mapAssertions.kt @@ -7,7 +7,6 @@ import ch.tutteli.atrium.creating.AssertionPlantNullable import ch.tutteli.atrium.domain.builders.AssertImpl import ch.tutteli.kbox.glue import kotlin.js.JsName -import kotlin.jvm.JvmName /** * Makes the assertion that the [Assert.subject][AssertionPlant.subject] contains a key as defined by [keyValuePair]'s [Pair.first] @@ -21,43 +20,9 @@ import kotlin.jvm.JvmName * @return This plant to support a fluent API. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ -@JsName("contains") -fun > Assert.contains(keyValuePair: Pair, vararg otherPairs: Pair) +fun > Assert.contains(keyValuePair: Pair, vararg otherPairs: Pair) = addAssertion(AssertImpl.map.contains(this, keyValuePair glue otherPairs)) -/** - * Makes the assertion that the [Assert.subject][AssertionPlant.subject] contains a key as defined by [keyNullableValuePair]'s [Pair.first] - * with a corresponding value as defined by [keyNullableValuePair]'s [Pair.second] -- optionally the same assertions - * are created for the [otherEntries]. - * - * Notice, that it does not search for unique matches. Meaning, if the map is `mapOf('a' to 1)` and [keyNullableValuePair] is - * defined as `'a' to 1` and one of the [otherEntries] is defined as `'a' to 1` as well, then both match, - * even though they match the same entry. - * - * @return This plant to support a fluent API. - * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. - */ -@JvmName("containsNullable") -inline fun > Assert.contains(keyNullableValuePair: Pair, vararg otherEntries: Pair) - = addAssertion(AssertImpl.map.containsNullable(this, V::class, keyNullableValuePair glue otherEntries)) - -/** - * Makes the assertion that the [Assert.subject][AssertionPlant.subject] contains a key as defined by [keyValue]'s [KeyValue.key] - * with a corresponding value which holds all assertions [keyValue]'s [KeyValue.valueAssertionCreatorOrNull] might create. - * -- optionally the same assertions are created for the [otherKeyValues]. - * - * Notice, that it does not search for unique matches. Meaning, if the map is `mapOf('a' to 1)` and [keyValue] is - * defined as `Key('a') { isGreaterThan(0) }` and one of the [otherKeyValues] is defined as `Key('a') { isLessThan(2) }` - * , then both match, even though they match the same entry. - * - * @return This plant to support a fluent API. - * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. - */ -fun > Assert.contains( - keyValue: KeyValue.() -> Unit>, - vararg otherKeyValues: KeyValue.() -> Unit> -) = addAssertion(AssertImpl.map.containsKeyWithValueAssertions(this, (keyValue glue otherKeyValues).map { it.toPair() })) - /** * Makes the assertion that the [Assert.subject][AssertionPlant.subject] contains a key as defined by [keyValue]'s [KeyValue.key] * with a corresponding value which either holds all assertions [keyValue]'s @@ -72,11 +37,10 @@ fun > Assert.contains( * @return This plant to support a fluent API. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ -@JvmName("containsNullable") -inline fun > Assert.contains( - keyValue: KeyValue.() -> Unit)?>, - vararg otherKeyValues: KeyValue.() -> Unit)?> -) = addAssertion(AssertImpl.map.containsKeyWithNullableValueAssertions(this, V::class, (keyValue glue otherKeyValues).map { it.toPair() })) +fun > Assert.contains( + keyValue: KeyValue, + vararg otherKeyValues: KeyValue +) = addAssertion(AssertImpl.map.containsKeyWithValueAssertions(this, (keyValue glue otherKeyValues).map { it.toPair() })) /** * Makes the assertion that the [Assert.subject][AssertionPlant.subject] contains the given [key]. diff --git a/apis/cc-en_GB/atrium-api-cc-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/en_GB/parameterObjects.kt b/apis/cc-en_GB/atrium-api-cc-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/en_GB/parameterObjects.kt index 052eff5e9..fdf12d601 100644 --- a/apis/cc-en_GB/atrium-api-cc-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/en_GB/parameterObjects.kt +++ b/apis/cc-en_GB/atrium-api-cc-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/en_GB/parameterObjects.kt @@ -14,7 +14,7 @@ import ch.tutteli.kbox.glue /** * Parameter object to express a [Group] with a single identification lambda. * - In case `null` is used for the identification lambda then it is expected that the corresponding entry +In case `null` is used for the identification lambda then it is expected that the corresponding entry * is `null` as well. * * @param assertionCreatorOrNull The identification lambda identifying the entry where an entry is considered @@ -53,8 +53,8 @@ class Entries( * Parameter object to express a key/value [Pair] whose value type is a nullable lambda with an * [Assert][AssertionPlant] receiver, which means one can either pass a lambda or `null`. */ -data class KeyValue) -> Unit)?>(val key: K, val valueAssertionCreatorOrNull: A) { - fun toPair(): Pair = key to valueAssertionCreatorOrNull +data class KeyValue(val key: K, val valueAssertionCreatorOrNull: (Assert.() -> Unit)?) { + fun toPair(): Pair.() -> Unit)?> = key to valueAssertionCreatorOrNull override fun toString(): String = "KeyValue(key=$key, value=${if (valueAssertionCreatorOrNull == null) "null" else "lambda"})" } diff --git a/apis/cc-en_GB/atrium-api-cc-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/en_GB/MapAssertionsSpec.kt b/apis/cc-en_GB/atrium-api-cc-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/en_GB/MapAssertionsSpec.kt index 18ba2593d..6b4f173f4 100644 --- a/apis/cc-en_GB/atrium-api-cc-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/en_GB/MapAssertionsSpec.kt +++ b/apis/cc-en_GB/atrium-api-cc-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/en_GB/MapAssertionsSpec.kt @@ -3,6 +3,7 @@ package ch.tutteli.atrium.api.cc.en_GB import ch.tutteli.atrium.creating.Assert import ch.tutteli.atrium.domain.builders.utils.mapArguments import ch.tutteli.atrium.verbs.internal.AssertionVerbFactory +import ch.tutteli.atrium.verbs.internal.assert import kotlin.reflect.KFunction3 class MapAssertionsSpec : ch.tutteli.atrium.spec.integration.MapAssertionsSpec( @@ -10,7 +11,7 @@ class MapAssertionsSpec : ch.tutteli.atrium.spec.integration.MapAssertionsSpec( containsFun.name to Assert>::contains, containsNullableFun.name to Assert>::contains, "${containsKeyWithValueAssertionsFun.name} ${KeyValue::class.simpleName}" to Companion::contains, - "${containsKeyWithNullableValueAssertionsFun.name} ${KeyNullableValue::class.simpleName}" to Companion::containsNullable, + "${containsKeyWithNullableValueAssertionsFun.name} ${KeyValue::class.simpleName}" to Companion::containsNullable, Assert>::containsKey.name to Assert>::containsKey, Assert>::containsKey.name to Assert>::containsKey, Assert>::containsKey.name to Assert>::containsNotKey, @@ -22,8 +23,8 @@ class MapAssertionsSpec : ch.tutteli.atrium.spec.integration.MapAssertionsSpec( companion object { private val containsFun : KFunction3>, Pair, Array>, Assert>> = Assert>::contains private val containsNullableFun : KFunction3>, Pair, Array>, Assert>> = Assert>::contains - private val containsKeyWithValueAssertionsFun : KFunction3>, KeyValue.() -> Unit>, Array.() -> Unit>>, Assert>> = Assert>::contains - private val containsKeyWithNullableValueAssertionsFun : KFunction3>, KeyValue.() -> Unit)?>, Array.() -> Unit)?>>, Assert>> = Assert>::contains + private val containsKeyWithValueAssertionsFun : KFunction3>, KeyValue, Array>, Assert>> = Assert>::contains + private val containsKeyWithNullableValueAssertionsFun : KFunction3>, KeyValue, Array>, Assert>> = Assert>::contains fun contains(plant: Assert>, keyValue: Pair.() -> Unit>, otherKeyValues: Array.() -> Unit>>) = mapArguments(keyValue, otherKeyValues).to { KeyValue(it.first, it.second) }.let { (first, others) -> @@ -35,4 +36,64 @@ class MapAssertionsSpec : ch.tutteli.atrium.spec.integration.MapAssertionsSpec( plant.contains(first, *others) } } + + @Suppress("unused") + private fun ambiguityTest() { + val map = mapOf(1 to "a") + val nullableKeyMap = mapOf(1 as Int? to "a") + val nullableValueMap = mapOf(1 to "a" as String?) + val nullableKeyValueMap = mapOf(1 as Int? to "a" as String?) + assert(map).contains(1 to "a") + assert(map).contains(1 to "a", 2 to "b") + assert(map).contains(KeyValue(1){}) + assert(map).contains(KeyValue(1){}, KeyValue(2){}) + + assert(nullableKeyMap).contains(1 to "a") + assert(nullableKeyMap).contains(1 to "a", 2 to "b") + assert(nullableKeyMap).contains(KeyValue(1){}) + assert(nullableKeyMap).contains(KeyValue(1){}, KeyValue(2){}) + assert(nullableKeyMap).contains(null to "a") + assert(nullableKeyMap).contains(null to "a", null to "b") + assert(nullableKeyMap).contains(null to "a", 2 to "b") + assert(nullableKeyMap).contains(KeyValue(null){}) + assert(nullableKeyMap).contains(KeyValue(null){}, KeyValue(null){}) + assert(nullableKeyMap).contains(KeyValue(null){}, KeyValue(2){}) + + assert(nullableValueMap).contains(1 to "a") + assert(nullableValueMap).contains(1 to "a", 2 to "b") + assert(nullableValueMap).contains(KeyValue(1){}) + assert(nullableValueMap).contains(KeyValue(1){}, KeyValue(2){}) + assert(nullableValueMap).contains(1 to null) + assert(nullableValueMap).contains(1 to null, 2 to null) + assert(nullableValueMap).contains(1 to null, 2 to "a") + assert(nullableValueMap).contains(KeyValue(1, null)) + assert(nullableValueMap).contains(KeyValue(1, null), KeyValue(2, null)) + assert(nullableValueMap).contains(KeyValue(1, null), KeyValue(2){}) + + assert(nullableKeyValueMap).contains(1 to "a") + assert(nullableKeyValueMap).contains(1 to "a", 2 to "b") + assert(nullableKeyValueMap).contains(KeyValue(1){}) + assert(nullableKeyValueMap).contains(KeyValue(1){}, KeyValue(2){}) + + assert(nullableKeyValueMap).contains(null to "a") + assert(nullableKeyValueMap).contains(null to "a", null to "b") + assert(nullableKeyValueMap).contains(null to "a", 2 to "b") + assert(nullableKeyValueMap).contains(KeyValue(null){}) + assert(nullableKeyValueMap).contains(KeyValue(null){}, KeyValue(null){}) + assert(nullableKeyValueMap).contains(KeyValue(null){}, KeyValue(2){}) + + assert(nullableKeyValueMap).contains(1 to null) + assert(nullableKeyValueMap).contains(1 to null, 2 to null) + assert(nullableKeyValueMap).contains(1 to null, 2 to "a") + assert(nullableKeyValueMap).contains(KeyValue(1, null)) + assert(nullableKeyValueMap).contains(KeyValue(1, null), KeyValue(2, null)) + assert(nullableKeyValueMap).contains(KeyValue(1, null), KeyValue(2){}) + + assert(nullableKeyValueMap).contains(null to null) + assert(nullableKeyValueMap).contains(null to null, null to null) + assert(nullableKeyValueMap).contains(1 to null, null to "a") + assert(nullableKeyValueMap).contains(KeyValue(null, null)) + assert(nullableKeyValueMap).contains(KeyValue(null, null), KeyValue(null, null)) + assert(nullableKeyValueMap).contains(KeyValue(1, null), KeyValue(null){}) + } } diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/mapAssertions.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/mapAssertions.kt index 629d2f625..b5f9816f8 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/mapAssertions.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/mapAssertions.kt @@ -8,85 +8,29 @@ import ch.tutteli.atrium.creating.Assert import ch.tutteli.atrium.creating.AssertionPlant import ch.tutteli.atrium.domain.builders.AssertImpl import kotlin.js.JsName -import kotlin.jvm.JvmName /** - * Makes the assertion that the [Assert.subject][AssertionPlant.subject] contains a key as defined by [keyValuePair]'s [Pair.first] - * with a corresponding value as defined by [keyValuePair]'s [Pair.second]. + * Makes the assertion that the [Assert.subject][AssertionPlant.subject] contains a key as defined by + * [keyValuePair]'s [Pair.first] with a corresponding value as defined by [keyValuePair]'s [Pair.second]. * - * Delegates to `contains Pairs(entry)`. + * Delegates to `contains Pairs(keyValuePair)`. * * @return This plant to support a fluent API. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ -@JsName("contains") -infix fun > Assert.contains(keyValuePair: Pair) +infix fun > Assert.contains(keyValuePair: Pair) = this contains Pairs(keyValuePair) /** - * Makes the assertion that the [Assert.subject][AssertionPlant.subject] contains for each entry in [keyValuePairs], a key as defined by - * entry's [Pair.first] with a corresponding value as defined by entry's [Pair.second]. - * - * Notice, that it does not search for unique matches. Meaning, if the map is `mapOf('a' to 1)` and one pair in [keyValuePairs] - * is defined as `'a' to 1` and another pair in [Pairs] is defined as `'a' to 1` as well, then both match, - * even though they match the same entry. + * Makes the assertion that the [Assert.subject][AssertionPlant.subject] contains for each entry in [keyValuePairs], + * a key as defined by entry's [Pair.first] with a corresponding value as defined by entry's [Pair.second]. * * @return This plant to support a fluent API. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ -@JsName("containsPairs") -infix fun > Assert.contains(keyValuePairs: Pairs) +infix fun > Assert.contains(keyValuePairs: Pairs) = addAssertion(AssertImpl.map.contains(this, keyValuePairs.toList())) -/** - * Makes the assertion that the [Assert.subject][AssertionPlant.subject] contains a key as defined by [keyValuePair]'s [Pair.first] - * with a corresponding value as defined by [keyValuePair]'s [Pair.second]. - * - * Delegates to `contains Pairs(entry)`. - * - * @return This plant to support a fluent API. - * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. - */ -@JvmName("containsNullable") -inline infix fun > Assert.contains(keyValuePair: Pair) - = this contains Pairs(keyValuePair) - -/** - * Makes the assertion that the [Assert.subject][AssertionPlant.subject] contains for each entry in [keyValuePairs], a key as defined by - * entry's [Pair.first] with a corresponding value as defined by entry's [Pair.second]. - * - * @return This plant to support a fluent API. - * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. - */ -@JvmName("containsNullable") -inline infix fun > Assert.contains(keyValuePairs: Pairs) - = addAssertion(AssertImpl.map.containsNullable(this, V::class, keyValuePairs.toList())) - -/** - * Makes the assertion that the [Assert.subject][AssertionPlant.subject] contains a key as defined by [keyValue]'s [KeyValue.key] - * with a corresponding value which holds all assertions [keyValue]'s [KeyValue.valueAssertionCreator] might create. - * - * @return This plant to support a fluent API. - * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. - */ -infix fun > Assert.contains(keyValue: KeyValue.() -> Unit>) - = contains(All(keyValue)) - -/** - * Makes the assertion that for each of the [KeyValue] in [keyValues], the [Assert.subject][AssertionPlant.subject] contains a key - * as defined by keyValue's [KeyValue.key] with a corresponding value which holds all assertions keyValues's - * [KeyValue.valueAssertionCreatorOrNull] might create. - * - * Notice, that it does not search for unique matches. Meaning, if the map is `mapOf('a' to 1)` and one of the - * [keyValues] is defined as `Key('a') { isGreaterThan(0) }` and another one is defined as `Key('a') { isLessThan(2) }` - * then both match, even though they match the same entry. - * - * @return This plant to support a fluent API. - * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. - */ -infix fun > Assert.contains(keyValues: All.() -> Unit>>) - = addAssertion(AssertImpl.map.containsKeyWithValueAssertions(this, keyValues.toList().map { it.toPair() })) - /** * Makes the assertion that the [Assert.subject][AssertionPlant.subject] contains a key as defined by [keyValue]'s [KeyValue.key] * with a corresponding value which either holds all assertions [keyValue]'s @@ -96,8 +40,7 @@ infix fun > Assert.contains(keyValues: All> Assert.contains(keyValue: KeyValue.() -> Unit)?>) +infix fun > Assert.contains(keyValue: KeyValue) = contains(All(keyValue)) /** @@ -113,9 +56,8 @@ inline infix fun > Assert.contains(keyV * @return This plant to support a fluent API. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ -@JvmName("containsNullable") -inline infix fun > Assert.contains(keyValues: All.() -> Unit)?>>) - = addAssertion(AssertImpl.map.containsKeyWithNullableValueAssertions(this, V::class, keyValues.toList().map { it.toPair() })) +infix fun > Assert.contains(keyValues: All>) + = addAssertion(AssertImpl.map.containsKeyWithValueAssertions(this, keyValues.toList().map { it.toPair() })) /** * Makes the assertion that the [Assert.subject][AssertionPlant.subject] contains the given [key]. @@ -136,7 +78,6 @@ infix fun Assert>.containsNotKey(key: K) = addAssertion(AssertImpl.map.containsNotKey(this, key)) - /** * Makes the assertion that the [Assert.subject][AssertionPlant.subject] contains the given [key], creates a feature * assertion plant for the corresponding value and returns the newly created plant. @@ -178,7 +119,6 @@ infix fun > Assert.getExisting(key: Key): MapGetNul = MapGetNullableOption.create(this, key.key) - /** * Makes the assertion that the [Assert.subject][AssertionPlant.subject]'s [Map.size] is [size]. * diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/parameterObjects.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/parameterObjects.kt index 668f77471..cb1e7c17d 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/parameterObjects.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/parameterObjects.kt @@ -68,8 +68,8 @@ data class Key(val key: K) * Parameter object to express a key/value [Pair] whose value type is a lambda with an * [Assert][AssertionPlant] receiver, which means one can either pass a lambda or `null`. */ -data class KeyValue) -> Unit)?>(val key: K, val valueAssertionCreatorOrNull: A) { - fun toPair(): Pair = key to valueAssertionCreatorOrNull +data class KeyValue(val key: K, val valueAssertionCreatorOrNull: (Assert.() -> Unit)?) { + fun toPair(): Pair.() -> Unit)?> = key to valueAssertionCreatorOrNull override fun toString(): String = "KeyValue(key=$key, value=${if (valueAssertionCreatorOrNull == null) "null" else "lambda"})" } diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapAssertionsSpec.kt index 86f8e76d7..973b63e01 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapAssertionsSpec.kt @@ -4,6 +4,7 @@ import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.Empty import ch.tutteli.atrium.creating.Assert import ch.tutteli.atrium.domain.builders.utils.mapArguments import ch.tutteli.atrium.verbs.internal.AssertionVerbFactory +import ch.tutteli.atrium.verbs.internal.assert import kotlin.reflect.KFunction2 class MapAssertionsSpec : ch.tutteli.atrium.spec.integration.MapAssertionsSpec( @@ -11,7 +12,7 @@ class MapAssertionsSpec : ch.tutteli.atrium.spec.integration.MapAssertionsSpec( containsFun.name to Companion::contains, containsNullableFun.name to Companion::containsNullable, "${containsKeyWithValueAssertionsFun.name} ${KeyValue::class.simpleName}" to Companion::containsKeyWithValueAssertions, - "${containsKeyWithNullableValueAssertionsFun.name} ${KeyNullableValue::class.simpleName}" to Companion::containsKeyWithNullableValueAssertions, + "${containsKeyWithNullableValueAssertionsFun.name} ${KeyValue::class.simpleName}" to Companion::containsKeyWithNullableValueAssertions, Assert>::containsKey.name to Companion::containsKey, Assert>::containsKey.name to Companion::containsNullableKey, Assert>::containsNotKey.name to Companion::containsNotKey, @@ -39,7 +40,7 @@ class MapAssertionsSpec : ch.tutteli.atrium.spec.integration.MapAssertionsSpec( } } - private val containsKeyWithValueAssertionsFun : KFunction2>, KeyValue.() -> Unit>, Assert>> = Assert>::contains + private val containsKeyWithValueAssertionsFun : KFunction2>, KeyValue, Assert>> = Assert>::contains private fun containsKeyWithValueAssertions(plant: Assert>, keyValue: Pair.() -> Unit>, otherKeyValues: Array.() -> Unit>>) : Assert> { return if (otherKeyValues.isEmpty()) { plant contains KeyValue(keyValue.first, keyValue.second) @@ -50,7 +51,7 @@ class MapAssertionsSpec : ch.tutteli.atrium.spec.integration.MapAssertionsSpec( } } - private val containsKeyWithNullableValueAssertionsFun : KFunction2>, KeyValue.() -> Unit)?>, Assert>> = Assert>::contains + private val containsKeyWithNullableValueAssertionsFun : KFunction2>, KeyValue, Assert>> = Assert>::contains private fun containsKeyWithNullableValueAssertions(plant: Assert>, keyValue: Pair.() -> Unit)?>, otherKeyValues: Array.() -> Unit)?>>): Assert> { return if (otherKeyValues.isEmpty()) { plant contains KeyValue(keyValue.first, keyValue.second) @@ -82,5 +83,66 @@ class MapAssertionsSpec : ch.tutteli.atrium.spec.integration.MapAssertionsSpec( private fun isNotEmpty(plant: Assert>) = plant notToBe Empty } + + @Suppress("unused") + private fun ambiguityTest() { + val map = mapOf(1 to "a") + val nullableKeyMap = mapOf(1 as Int? to "a") + val nullableValueMap = mapOf(1 to "a" as String?) + val nullableKeyValueMap = mapOf(1 as Int? to "a" as String?) + assert(map) contains (1 to "a") + assert(map) contains Pairs(1 to "a", 2 to "b") + assert(map) contains KeyValue(1){} + assert(map) contains All(KeyValue(1){}, KeyValue(2){}) + + assert(nullableKeyMap) contains (1 to "a") + assert(nullableKeyMap) contains Pairs(1 to "a", 2 to "b") + assert(nullableKeyMap) contains KeyValue(1){} + assert(nullableKeyMap) contains All(KeyValue(1){}, KeyValue(2){}) + assert(nullableKeyMap) contains (null to "a") + assert(nullableKeyMap) contains Pairs(null to "a", null to "b") + assert(nullableKeyMap) contains Pairs(null to "a", 2 to "b") + assert(nullableKeyMap) contains KeyValue(null){} + assert(nullableKeyMap) contains All(KeyValue(null){}, KeyValue(null){}) + assert(nullableKeyMap) contains All(KeyValue(null){}, KeyValue(2){}) + + assert(nullableValueMap) contains (1 to "a") + assert(nullableValueMap) contains Pairs(1 to "a", 2 to "b") + assert(nullableValueMap) contains KeyValue(1){} + assert(nullableValueMap) contains All(KeyValue(1){}, KeyValue(2){}) + assert(nullableValueMap) contains (1 to null) + assert(nullableValueMap) contains Pairs(1 to null, 2 to null) + assert(nullableValueMap) contains Pairs(1 to null, 2 to "a") + assert(nullableValueMap) contains KeyValue(1, null) + assert(nullableValueMap) contains All(KeyValue(1, null), KeyValue(2, null)) + assert(nullableValueMap) contains All(KeyValue(1, null), KeyValue(2){}) + + assert(nullableKeyValueMap) contains (1 to "a") + assert(nullableKeyValueMap) contains Pairs(1 to "a", 2 to "b") + assert(nullableKeyValueMap) contains All(KeyValue(1){}) + assert(nullableKeyValueMap) contains All(KeyValue(1){}, KeyValue(2){}) + + assert(nullableKeyValueMap) contains (null to "a") + assert(nullableKeyValueMap) contains Pairs(null to "a", null to "b") + assert(nullableKeyValueMap) contains Pairs(null to "a", 2 to "b") + assert(nullableKeyValueMap) contains KeyValue(null){} + assert(nullableKeyValueMap) contains All(KeyValue(null){}, KeyValue(null){}) + assert(nullableKeyValueMap) contains All(KeyValue(null){}, KeyValue(2){}) + + assert(nullableKeyValueMap) contains (1 to null) + assert(nullableKeyValueMap) contains Pairs(1 to null, 2 to null) + assert(nullableKeyValueMap) contains Pairs(1 to null, 2 to "a") + assert(nullableKeyValueMap) contains KeyValue(1, null) + assert(nullableKeyValueMap) contains All(KeyValue(1, null), KeyValue(2, null)) + assert(nullableKeyValueMap) contains All(KeyValue(1, null), KeyValue(2){}) + + //TODO don't use Pair but null to null as soon as https://youtrack.jetbrains.com/issue/KT-30496 is fiex + assert(nullableKeyValueMap) contains Pair(null, null) + assert(nullableKeyValueMap) contains Pairs(Pair(null, null), null to null as String?) + assert(nullableKeyValueMap) contains Pairs(1 to null, null to "a") + assert(nullableKeyValueMap) contains KeyValue(null, null) + assert(nullableKeyValueMap) contains All(KeyValue(null, null), KeyValue(null, null)) + assert(nullableKeyValueMap) contains All(KeyValue(1, null), KeyValue(null){}) + } } diff --git a/domain/api/atrium-domain-api-common/src/main/kotlin/ch/tutteli/atrium/domain/creating/MapAssertions.kt b/domain/api/atrium-domain-api-common/src/main/kotlin/ch/tutteli/atrium/domain/creating/MapAssertions.kt index f0cc66a41..a92246635 100644 --- a/domain/api/atrium-domain-api-common/src/main/kotlin/ch/tutteli/atrium/domain/creating/MapAssertions.kt +++ b/domain/api/atrium-domain-api-common/src/main/kotlin/ch/tutteli/atrium/domain/creating/MapAssertions.kt @@ -5,7 +5,6 @@ import ch.tutteli.atrium.core.polyfills.loadSingleService import ch.tutteli.atrium.creating.Assert import ch.tutteli.atrium.creating.AssertionPlant import ch.tutteli.atrium.creating.AssertionPlantNullable -import kotlin.reflect.KClass /** * The access point to an implementation of [MapAssertions]. @@ -20,10 +19,8 @@ val mapAssertions by lazy { loadSingleService(MapAssertions::class) } * which an implementation of the domain of Atrium has to provide. */ interface MapAssertions { - fun contains(plant: AssertionPlant>, keyValuePairs: List>): Assertion - fun containsNullable(plant: AssertionPlant>, type: KClass, keyValuePairs: List>): Assertion - fun containsKeyWithValueAssertions(plant: AssertionPlant>, keyValues: List.() -> Unit>>): Assertion - fun containsKeyWithNullableValueAssertions(plant: AssertionPlant>, type: KClass, keyValues: List.() -> Unit)?>>): Assertion + fun contains(plant: AssertionPlant>, keyValuePairs: List>): Assertion + fun containsKeyWithValueAssertions(plant: AssertionPlant>, keyValues: List.() -> Unit)?>>): Assertion fun containsKey(plant: AssertionPlant>, key: K): Assertion fun containsNotKey(plant: AssertionPlant>, key: K): Assertion diff --git a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/MapAssertionsBuilder.kt b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/MapAssertionsBuilder.kt index 29b52df0e..e58fd862a 100644 --- a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/MapAssertionsBuilder.kt +++ b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/MapAssertionsBuilder.kt @@ -9,7 +9,6 @@ import ch.tutteli.atrium.creating.AssertionPlantNullable import ch.tutteli.atrium.domain.creating.MapAssertions import ch.tutteli.atrium.domain.creating.MapEntryAssertions import ch.tutteli.atrium.domain.creating.mapAssertions -import kotlin.reflect.KClass /** * Delegates inter alia to the implementation of [MapAssertions]. @@ -24,22 +23,13 @@ object MapAssertionsBuilder : MapAssertions { */ inline val entry get() : MapEntryAssertionsBuilder = MapEntryAssertionsBuilder - override inline fun contains(plant: AssertionPlant>, keyValuePairs: List>): Assertion + override inline fun contains(plant: AssertionPlant>, keyValuePairs: List>): Assertion = mapAssertions.contains(plant, keyValuePairs) - override inline fun containsNullable(plant: AssertionPlant>, type: KClass, keyValuePairs: List>): Assertion - = mapAssertions.containsNullable(plant, type, keyValuePairs) - override inline fun containsKeyWithValueAssertions( - plant: AssertionPlant>, - keyValues: List.() -> Unit>> - ) = mapAssertions.containsKeyWithValueAssertions(plant, keyValues) - - override inline fun containsKeyWithNullableValueAssertions( plant: AssertionPlant>, - type: KClass, keyValues: List.() -> Unit)?>> - ) = mapAssertions.containsKeyWithNullableValueAssertions(plant, type, keyValues) + ) = mapAssertions.containsKeyWithValueAssertions(plant, keyValues) override inline fun containsKey(plant: AssertionPlant>, key: K) = mapAssertions.containsKey(plant, key) diff --git a/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/mapAssertions.kt b/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/mapAssertions.kt index 7362b9249..b4048b767 100644 --- a/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/mapAssertions.kt +++ b/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/mapAssertions.kt @@ -3,8 +3,10 @@ package ch.tutteli.atrium.domain.robstoll.lib.creating import ch.tutteli.atrium.api.cc.en_GB.property import ch.tutteli.atrium.api.cc.en_GB.toBe import ch.tutteli.atrium.assertions.Assertion +import ch.tutteli.atrium.core.trueProvider import ch.tutteli.atrium.creating.* import ch.tutteli.atrium.domain.builders.AssertImpl +import ch.tutteli.atrium.domain.builders.utils.subAssert import ch.tutteli.atrium.domain.creating.feature.extract.FeatureExtractor import ch.tutteli.atrium.domain.robstoll.lib.assertions.LazyThreadUnsafeAssertionGroup import ch.tutteli.atrium.reporting.RawString @@ -12,42 +14,39 @@ import ch.tutteli.atrium.reporting.translating.TranslatableWithArgs import ch.tutteli.atrium.translations.DescriptionBasic import ch.tutteli.atrium.translations.DescriptionCollectionAssertion.EMPTY import ch.tutteli.atrium.translations.DescriptionMapAssertion -import kotlin.reflect.KClass -fun _contains(plant: AssertionPlant>, pairs: List>): Assertion - = containsNonNullable(plant, pairs) { value -> toBe(value) } - -fun _containsNullable( - plant: AssertionPlant>, - type: KClass, - pairs: List> -): Assertion = containsNullable(plant, pairs) { value -> - addAssertion(AssertImpl.any.isNullable(this, type, value)) -} +fun _contains( + plant: AssertionPlant>, + pairs: List> +): Assertion = _containsKeyWithValueAssertion(plant, pairs.map { + it.first to it.second?.let { expected -> subAssert { toBe(expected as Any) } } +}) fun _containsKeyWithValueAssertion( - plant: AssertionPlant>, - keyValues: List.() -> Unit>> -): Assertion = containsNonNullable(plant, keyValues.map { it }) { assertionCreator -> assertionCreator() } - -fun _containsKeyWithNullableValueAssertions( plant: AssertionPlant>, - type: KClass, keyValues: List.() -> Unit)?>> ): Assertion = containsNullable(plant, keyValues.map{ it }) { assertionCreator -> - addAssertion(AssertImpl.any.isNullIfNullGivenElse(this, type, assertionCreator)) + val subjectIsNull = try { + this.subject == null + } catch (t: PlantHasNoSubjectException) { + true + } + if (assertionCreator != null && !subjectIsNull) { + AssertImpl.changeSubject(this) { this.subject as V }.assertionCreator() + } else if (subjectIsNull && assertionCreator == null){ + addAssertion(AssertImpl.builder.createDescriptive(DescriptionBasic.IS, RawString.NULL, trueProvider)) + } else { + addAssertion(AssertImpl.builder.explanatoryGroup + .withDefaultType + .withAssertions(AssertImpl.collector.forExplanation.throwIfNoAssertionIsCollected.collect( + DescriptionMapAssertion.CANNOT_EVALUATE_KEY_DOES_NOT_EXIST, + MaybeSubject.Absent, + assertionCreator) + ) + .build()) + } } -private fun containsNonNullable( - plant: AssertionPlant>, - pairs: List>, - assertionCreator: AssertionPlant.(M) -> Unit -) = contains( - pairs, - { option, key -> option.withParameterObject(createGetParameterObject(plant, key)) }, - assertionCreator -) - private fun containsNullable( plant: AssertionPlant>, pairs: List>, diff --git a/domain/robstoll/atrium-domain-robstoll-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/creating/MapAssertionsImpl.kt b/domain/robstoll/atrium-domain-robstoll-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/creating/MapAssertionsImpl.kt index 66e7867ec..f8cbbc09e 100644 --- a/domain/robstoll/atrium-domain-robstoll-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/creating/MapAssertionsImpl.kt +++ b/domain/robstoll/atrium-domain-robstoll-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/creating/MapAssertionsImpl.kt @@ -6,32 +6,19 @@ import ch.tutteli.atrium.creating.AssertionPlant import ch.tutteli.atrium.creating.AssertionPlantNullable import ch.tutteli.atrium.domain.creating.MapAssertions import ch.tutteli.atrium.domain.robstoll.lib.creating.* -import kotlin.reflect.KClass /** * Robstoll's implementation of [MapAssertions]. */ class MapAssertionsImpl : MapAssertions { - override fun contains(plant: AssertionPlant>, keyValuePairs: List>) + override fun contains(plant: AssertionPlant>, keyValuePairs: List>) = _contains(plant, keyValuePairs) - override fun containsNullable( - plant: AssertionPlant>, - type: KClass, - keyValuePairs: List> - ) = _containsNullable(plant, type, keyValuePairs) - override fun containsKeyWithValueAssertions( - plant: AssertionPlant>, - keyValues: List.() -> Unit>> - ) = _containsKeyWithValueAssertion(plant, keyValues) - - override fun containsKeyWithNullableValueAssertions( plant: AssertionPlant>, - type: KClass, keyValues: List.() -> Unit)?>> - ) = _containsKeyWithNullableValueAssertions(plant, type, keyValues) + ) = _containsKeyWithValueAssertion(plant, keyValues) override fun containsKey(plant: AssertionPlant>, key: K) = _containsKey(plant, key)