implement mapAssertions with new infix API

Co-authored-by: alexjdz <alexdiaz.jdz@gmail.com>
Co-authored-by: jlundhol <jesper.a.lundholm@gmail.com>
Co-authored-by: ashgreyship <blackbird698@gmail.com>>
This commit is contained in:
Joar Ekelund
2020-02-20 12:08:46 +01:00
committed by jlundhol
parent ded28903c7
commit e135750aed
7 changed files with 599 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
package ch.tutteli.atrium.api.infix.en_GB.creating.map.get.builders
import ch.tutteli.atrium.api.infix.en_GB.creating.map.get.builders.impl.MapGetOptionImpl
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.creating.Assert
import ch.tutteli.atrium.creating.AssertionPlant
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.creating.SubjectProvider
/**
* Represents the extension point for another option after a `get key`-step within a
* sophisticated `get` assertion building process for [Map].
*
* @param K The key type of the [Map].
* @param V the value type of the [Map].
* @param T A subtype of [Map].
*/
interface MapGetOption<K, V, T : Map<out K, V>> {
/**
* The [AssertionPlant] for which this assertion is created
*/
val plant: Expect<T>
/**
* The given key which will be used to perform the [Map.get].
*/
val key: K
/**
* Makes the assertion that the [Assert.subject][SubjectProvider.subject] contains the previously specified [key] and that the
* corresponding value holds all assertions the given [assertionCreator] might create for it.
*
* @return This plant to support a fluent API.
* @throws AssertionError Might throw an [AssertionError] if a created [Assertion]s (by calling [assertionCreator])
* does not hold.
* @throws IllegalArgumentException in case the given [assertionCreator] did not create a single assertion.
*/
infix fun assertIt(assertionCreator: Expect<V>.() -> Unit): Expect<T>
companion object {
/**
* Creates a [MapGetOption] based on the given [plant] and [key].
*/
fun <K, V, T: Map<out K, V>> create(plant: Expect<T>, key: K): MapGetOption<K, V, T>
= MapGetOptionImpl(plant, key)
}
}

View File

@@ -0,0 +1,14 @@
package ch.tutteli.atrium.api.infix.en_GB.creating.map.get.builders.impl
import ch.tutteli.atrium.api.infix.en_GB.creating.map.get.builders.MapGetOption
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.builders.ExpectImpl
internal class MapGetOptionImpl<K, V, T: Map<out K, V>>(
override val plant: Expect<T>,
override val key: K
) : MapGetOption<K, V, T> {
override infix fun assertIt(assertionCreator: Expect<V>.() -> Unit): Expect<T>
= plant.addAssertion(ExpectImpl.map.getExisting(plant, key).collect(assertionCreator))
}

View File

@@ -0,0 +1,178 @@
package ch.tutteli.atrium.api.infix.en_GB
import ch.tutteli.atrium.api.infix.en_GB.creating.map.get.builders.MapGetOption
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.builders.ExpectImpl
/**
* Expects that the subject of the assertion (a [Map]) 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(keyValuePair)'.
*
* @return This assertion container to support a fluent API.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
infix fun <K, V, T: Map<out K, V>> Expect<T>.contains(keyValuePair: Pair<K, V>) =
contains(Pairs(keyValuePair))
/**
* Expects the subject of the assertion (a [Map]) contains for each entry in [keyValuePairs],
* a key as defined by that 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 of the [Pair]
* in [keyValuePairs] is defined as `'a' to 1` and another one is defined as `'a' to 1` as well, then both match,
* even though they match the same entry.
*
* @return This assertion container to support a fluent API.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
infix fun <K, V, T : Map<out K, V>> Expect<T>.contains(keyValuePairs: Pairs<K, V>) :Expect<T> =
addAssertion(ExpectImpl.map.contains(this, keyValuePairs.toList()))
/**
* Expects that the subject of the assertion (a [Map]) contains a key as defined by [keyValue]'s [KeyValue.key]
* with a corresponding value which either holds all assertions [keyValue]'s
* [KeyValue.valueAssertionCreatorOrNull] creates or needs to be `null` in case
* [KeyValue.valueAssertionCreatorOrNull] is defined as `null`
*
* @return This assertion container to support a fluent API.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
inline infix fun <K, reified V : Any, T : Map<out K, V?>> Expect<T>.contains(keyValue: KeyValue<K,V>) :Expect<T> =
contains(All(keyValue))
/**
* Expects that the subject of the assertion (a [Map]) contains for each [KeyValue] in [keyValues],
* a key as defined by [KeyValue.key] with a corresponding value which either holds all
* assertions [KeyValue]'s [KeyValue.valueAssertionCreatorOrNull] creates or needs to be `null` in case
* [KeyValue.valueAssertionCreatorOrNull] is defined as `null`
*
* Notice, that it does not search for unique matches. Meaning, if the map is `mapOf('a' to 1)` and one [KeyValue] in
* [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 assertion container to support a fluent API.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
inline infix fun <K, reified V : Any, T: Map<out K, V?>> Expect<T>.contains(keyValues: All<KeyValue<K, V>>)
= addAssertion(ExpectImpl.map.containsKeyWithValueAssertions(this, V::class, keyValues.toList().map { it.toPair() }))
/**
* Expects that the subject of the assertion (a [Map]) contains the given [key].
*
* @return This assertion container to support a fluent API.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
infix fun <K, T : Map<out K, *>> Expect<T>.containsKey(key: K) = addAssertion(ExpectImpl.map.containsKey(this, key))
/**
* Expects that the subject of the assertion (a [Map]) does not contain the given [key].
*
* @return This assertion container to support a fluent API.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
infix fun <K, T : Map<out K, *>> Expect<T>.containsNotKey(key: K) =
addAssertion(ExpectImpl.map.containsNotKey(this, key))
/**
* Expects that the subject of the assertion (a [Map]) contains the given [key],
* creates an [Expect] for the corresponding value and returns the newly created assertion container,
* so that further fluent calls are assertions about it.
*
* @return The newly created [Expect] for the feature.
* @throws AssertionError Might throw an [AssertionError] if the given [key] does not exist.
*/
infix fun <K, V, T : Map<out K, V>> Expect<T>.getExisting(key: K): Expect<V> =
ExpectImpl.map.getExisting(this, key).getExpectOfFeature()
/**
* Prepares the assertion about the return value of calling [get][Map.get] with the given [key].
*
* @return A fluent builder to finish the assertion.
* */
infix fun <K, V, T: Map<out K, V>> Expect<T>.getExisting(key: Key<K>): MapGetOption<K, V, T>
= MapGetOption.create(this, key.key)
/**
* Creates an [Expect] for the property [Map.keys] of the subject of the assertion,
* so that further fluent calls are assertions about it.
*
* @return The newly created [Expect] for the feature.
*/
val <K, T : Map<out K, *>> Expect<T>.keys: Expect<Set<K>>
get() = keys(this).getExpectOfFeature()
/**
* Expects that the property [Map.keys] of the subject of the assertion
* holds all assertions the given [assertionCreator] creates for it and returns this assertion container.
*
* @return This assertion container to support a fluent API.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
infix fun <K, V, T : Map<out K, V>> Expect<T>.keys(assertionCreator: Expect<Set<K>>.() -> Unit): Expect<T> =
keys(this).addToInitial(assertionCreator)
private fun <K, T : Map<out K, *>> keys(e: Expect<T>) = ExpectImpl.feature.property(e, Map<out K, *>::keys)
/**
* Expects that the subject of the assertion (a [Map]) is an empty [Map].
*
* @return This assertion container to support a fluent API.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
infix fun <T : Map<*, *>> Expect<T>.toBe(@Suppress("UNUSED_PARAMETER") Empty: Empty) = addAssertion(ExpectImpl.map.isEmpty(this))
/**
* Expects that the subject of the assertion (a [Map]) is not an empty [Map].
*
* @return This assertion container to support a fluent API.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
infix fun <T : Map<*, *>> Expect<T>.notToBe(@Suppress("UNUSED_PARAMETER") Empty: Empty) = addAssertion(ExpectImpl.map.isNotEmpty(this))
/**
* Creates an [Expect] for the property [Map.values] of the subject of the assertion,
* so that further fluent calls are assertions about it.
*
* @return The newly created [Expect] for the feature.
*/
val <V, T : Map<*, V>> Expect<T>.values: Expect<Collection<V>>
get() = values().getExpectOfFeature()
/**
* Expects that the property [Map.keys] of the subject of the assertion
* holds all assertions the given [assertionCreator] creates for it and returns this assertion container.
*
* @return This assertion container to support a fluent API.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
infix fun <K, V, T : Map<K, V>> Expect<T>.values(assertionCreator: Expect<Collection<V>>.() -> Unit): Expect<T> =
values().addToInitial(assertionCreator)
private fun <K, V, T : Map<out K, V>> Expect<T>.values() = ExpectImpl.feature.property(this, Map<out K, V>::values)
/**
* Turns `Expect<Map<K, V>>` into `Expect<Set<Map.Entry<K, V>>>`.
*
* The transformation as such is not reflected in reporting.
* Use `feature { f(it::entries) }` if you want to show the transformation in reporting.
*
* @return The newly created [Expect] for the transformed subject.
*/
fun <K, V, T : Map<out K, V>> Expect<T>.asEntries(): Expect<Set<Map.Entry<K, V>>> =
ExpectImpl.changeSubject(this).unreported { it.entries }
/**
* Turns `Expect<Map<K, V>>` into `Expect<Set<Map.Entry<K, V>>>` and expects that it holds all assertions the given
* [assertionCreator] creates.
*
* The transformation as such is not reflected in reporting.
* Use `feature { f(it::entries) }` if you want to show the transformation in reporting.
*
* @return The newly created [Expect] for the transformed subject.
*/
infix fun <K, V, T : Map<out K, V>> Expect<T>.asEntries(
assertionCreator: Expect<Set<Map.Entry<K, V>>>.() -> Unit
): Expect<T> = apply { asEntries().addAssertionsCreatedBy(assertionCreator) }

View File

@@ -1,6 +1,34 @@
package ch.tutteli.atrium.api.infix.en_GB
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.builders.utils.VarArgHelper
/**
* Wrapper for a single index -- can be used as distinguishable type for an overload where Int is already in use.
*/
data class Index(val index: Int)
data class Key<out K>(val key: K)
/**
* Parameter object to express `T, vararg T` in the infix-api.
*/
class All<out T>(override val expected: T, override vararg val otherExpected: T) : VarArgHelper<T>
/**
* Parameter object to express `Pair<K, V>, vararg Pair<K, V>` in the infix-api.
*/
class Pairs<out K, out V>(
override val expected: Pair<K, V>,
override vararg val otherExpected: Pair<K, V>
) : VarArgHelper<Pair<K, V>>
/**
* 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<out K, V : Any>(val key: K, val valueAssertionCreatorOrNull: (Expect<V>.() -> Unit)?) {
fun toPair(): Pair<K, (Expect<V>.() -> Unit)?> = key to valueAssertionCreatorOrNull
override fun toString(): String
= "KeyValue(key=$key, value=${if (valueAssertionCreatorOrNull == null) "null" else "lambda"})"
}

View File

@@ -0,0 +1,41 @@
package ch.tutteli.atrium.api.infix.en_GB
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.specs.feature0
import ch.tutteli.atrium.specs.fun1
import ch.tutteli.atrium.specs.notImplemented
object MapAsEntriesAssertionsSpec : ch.tutteli.atrium.specs.integration.MapAsEntriesAssertionsSpec(
feature0<Map<String, Int>, Set<Map.Entry<String, Int>>>(Expect<Map<String, Int>>::asEntries),
fun1<Map<String, Int>, Expect<Set<Map.Entry<String, Int>>>.() -> Unit>(Expect<Map<String, Int>>::asEntries)
) {
@Suppress("unused", "UNUSED_VALUE")
private fun ambiguityTest() {
var map: Expect<Map<Number, CharSequence>> = notImplemented()
var subMap: Expect<LinkedHashMap<out Number, String>> = notImplemented()
var nullableKeyMap: Expect<Map<Number?, CharSequence>> = notImplemented()
var nullableValueMap: Expect<Map<Number, CharSequence?>> = notImplemented()
var nullableKeyValueMap: Expect<Map<Number?, CharSequence?>> = notImplemented()
var readOnlyNullableKeyValueMap: Expect<Map<out Number?, CharSequence?>> = notImplemented()
var starKeyMap: Expect<Map<*, CharSequence?>> = notImplemented()
var starValueMap: Expect<Map<String, *>> = notImplemented()
map asEntries {}
subMap asEntries {}
nullableKeyMap asEntries {}
nullableValueMap asEntries {}
nullableKeyValueMap asEntries {}
readOnlyNullableKeyValueMap asEntries {}
map = map asEntries {}
subMap = subMap asEntries {}
nullableKeyMap = nullableKeyMap asEntries {}
nullableValueMap = nullableValueMap asEntries {}
nullableKeyValueMap = nullableKeyValueMap asEntries {}
readOnlyNullableKeyValueMap = readOnlyNullableKeyValueMap asEntries {}
starKeyMap = starKeyMap asEntries {}
starValueMap = starValueMap asEntries {}
}
}

View File

@@ -0,0 +1,240 @@
package ch.tutteli.atrium.api.infix.en_GB
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.builders.utils.mapArguments
import ch.tutteli.atrium.specs.*
class MapExpectionsSpec : ch.tutteli.atrium.specs.integration.MapAssertionsSpec(
fun2(Companion::contains),
fun2(Companion::contains).name to Companion::containsNullable,
"${fun2(Companion::contains).name} ${KeyValue::class.simpleName}" to Companion::containsKeyWithValueAssertions,
"${fun2(Companion::contains).name} ${KeyValue::class.simpleName}" to Companion::containsKeyWithNullableValueAssertions,
fun1(Companion::containsKey),
fun1(Companion::containsNullableKey),
fun1(Companion::containsNotKey),
fun1(Companion::containsNotNullableKey),
/* string toBe, notToBe to avoid ambiguity error */
"toBe ${Empty::class.simpleName}" to Companion::isEmpty,
"notToBe ${Empty::class.simpleName}" to Companion::isNotEmpty
) {
companion object {
private fun contains(plant: Expect<Map<out String, Int>>, pair: Pair<String, Int>, otherPairs: Array<out Pair<String, Int>>): Expect<Map<out String, Int>> {
return if (otherPairs.isEmpty()) {
plant contains (pair.first to pair.second)
} else {
plant contains Pairs(pair, *otherPairs)
}
}
private fun containsNullable(plant: Expect<Map<out String?, Int?>>, pair: Pair<String?, Int?>, otherPairs: Array<out Pair<String?, Int?>>): Expect<Map<out String?, Int?>> {
return if (otherPairs.isEmpty()) {
plant contains (pair.first to pair.second)
} else {
plant contains Pairs(pair, *otherPairs)
}
}
private fun containsKeyWithValueAssertions(plant: Expect<Map<out String, Int>>, keyValue: Pair<String, Expect<Int>.() -> Unit>, otherKeyValues: Array<out Pair<String, Expect<Int>.() -> Unit>>) : Expect<Map<out String, Int>> {
return if (otherKeyValues.isEmpty()) {
plant contains KeyValue(keyValue.first, keyValue.second)
} else {
mapArguments(keyValue, otherKeyValues).to { KeyValue(it.first, it.second) }.let { (first, others) ->
plant contains All(first, *others)
}
}
}
private fun containsKeyWithNullableValueAssertions(plant: Expect<Map<out String?, Int?>>, keyValue: Pair<String?, (Expect<Int>.() -> Unit)?>, otherKeyValues: Array<out Pair<String?, (Expect<Int>.() -> Unit)?>>): Expect<Map<out String?, Int?>> {
return if (otherKeyValues.isEmpty()) {
plant contains KeyValue(keyValue.first, keyValue.second)
} else {
mapArguments(keyValue, otherKeyValues).to { KeyValue(it.first, it.second) }.let { (first, others) ->
plant contains All(first, *others)
}
}
}
private fun containsKey(plant: Expect<Map<out String, *>>, key: String)
= plant containsKey key
private fun containsNullableKey(plant: Expect<Map<out String?, *>>, key: String?)
= plant containsKey key
private fun containsNotKey(plant: Expect<Map<out String, *>>, key: String)
= plant containsNotKey key
private fun containsNotNullableKey(plant: Expect<Map<out String?, *>>, key: String?)
= plant containsNotKey key
private fun isEmpty(plant: Expect<Map<*, *>>)
= plant toBe Empty
private fun isNotEmpty(plant: Expect<Map<*, *>>)
= plant notToBe Empty
}
@Suppress("unused", "UNUSED_VALUE")
private fun ambiguityTest() {
var map: Expect<Map<Number, CharSequence>> = notImplemented()
var subMap: Expect<LinkedHashMap<out Number, String>> = notImplemented()
var nullableKeyMap: Expect<Map<Number?, CharSequence>> = notImplemented()
var nullableValueMap: Expect<Map<Number, CharSequence?>> = notImplemented()
var nullableKeyValueMap: Expect<Map<Number?, CharSequence?>> = notImplemented()
var readOnlyNullableKeyValueMap: Expect<Map<out Number?, CharSequence?>> = notImplemented()
var starMap: Expect<Map<*, *>> = notImplemented()
map contains (1 to "a")
map contains Pairs(1 to "a", 2 to "b")
map contains (KeyValue(1) {})
map contains All(KeyValue(1) {}, KeyValue(2) {})
map contains Pairs(1.0 to StringBuilder("a"))
map contains Pairs(12f to "a", 2L to StringBuilder("b"))
map contains (KeyValue(1) {})
map contains All(KeyValue(1) {}, KeyValue(2) {})
subMap contains (1 to "a")
subMap contains Pairs(1 to "a", 2 to "b")
subMap contains (KeyValue(1) {})
subMap contains All(KeyValue(1) {}, KeyValue(2) {})
subMap contains (1.0 to StringBuilder("a"))
subMap contains Pairs(12f to "a", 2L to StringBuilder("b"))
subMap contains (KeyValue(1) {})
subMap contains All(KeyValue(1) {}, KeyValue(2) {})
nullableKeyMap contains (1 to "a")
nullableKeyMap contains Pairs(1 to "a", 2 to "b")
nullableKeyMap contains (KeyValue(1) {})
nullableKeyMap contains All(KeyValue(1) {}, KeyValue(2) {})
nullableKeyMap contains (null to "a")
nullableKeyMap contains Pairs(null to "a", null to "b")
nullableKeyMap contains Pairs(null to "a", 2 to "b")
nullableKeyMap contains (KeyValue(null) {})
nullableKeyMap contains All(KeyValue(null) {}, KeyValue(null) {})
nullableKeyMap contains All(KeyValue(null) {}, KeyValue(2) {})
nullableValueMap contains (1 to "a")
nullableValueMap contains Pairs(1 to "a", 2 to "b")
nullableValueMap contains (KeyValue(1) {})
nullableValueMap contains All(KeyValue(1) {}, KeyValue(2) {})
nullableValueMap contains (1 to null)
nullableValueMap contains Pairs(1 to null, 2 to null)
nullableValueMap contains Pairs(1 to null, 2 to "a")
nullableValueMap contains (KeyValue(1, null))
nullableValueMap contains All(KeyValue(1, null), KeyValue(2, null))
nullableValueMap contains All(KeyValue(1, null), KeyValue(2) {})
nullableKeyValueMap contains (1 to "a")
nullableKeyValueMap contains Pairs(1 to "a", 2 to "b")
nullableKeyValueMap contains (KeyValue(1) {})
nullableKeyValueMap contains All(KeyValue(1) {}, KeyValue(2) {})
nullableKeyValueMap contains (null to "a")
nullableKeyValueMap contains Pairs(null to "a", null to "b")
nullableKeyValueMap contains Pairs(null to "a", 2 to "b")
nullableKeyValueMap contains (KeyValue(null) {})
nullableKeyValueMap contains All(KeyValue(null) {}, KeyValue(null) {})
nullableKeyValueMap contains All(KeyValue(null) {}, KeyValue(2) {})
nullableKeyValueMap contains (1 to null)
nullableKeyValueMap contains Pairs(1 to null, 2 to null)
nullableKeyValueMap contains Pairs(1 to null, 2 to "a")
nullableKeyValueMap contains (KeyValue(1, null))
nullableKeyValueMap contains All(KeyValue(1, null), KeyValue(2, null))
nullableKeyValueMap contains All(KeyValue(1, null), KeyValue(2) {})
nullableKeyValueMap contains (null to null)
nullableKeyValueMap contains Pairs(null to null, null to null)
nullableKeyValueMap contains Pairs(1 to null, null to "a")
nullableKeyValueMap contains (KeyValue(null, null))
nullableKeyValueMap contains All(KeyValue(null, null), KeyValue(null, null))
nullableKeyValueMap contains All(KeyValue(1, null), KeyValue(null) {})
readOnlyNullableKeyValueMap contains (1 to "a")
readOnlyNullableKeyValueMap contains Pairs(1 to "a", 2 to "b")
readOnlyNullableKeyValueMap contains (KeyValue(1) {})
readOnlyNullableKeyValueMap contains All(KeyValue(1) {}, KeyValue(2) {})
readOnlyNullableKeyValueMap contains (null to "a")
readOnlyNullableKeyValueMap contains Pairs(null to "a", null to "b")
readOnlyNullableKeyValueMap contains Pairs(null to "a", 2 to "b")
readOnlyNullableKeyValueMap contains (KeyValue(null) {})
readOnlyNullableKeyValueMap contains All(KeyValue(null) {}, KeyValue(null) {})
readOnlyNullableKeyValueMap contains All(KeyValue(null) {}, KeyValue(2) {})
readOnlyNullableKeyValueMap contains (1 to null)
readOnlyNullableKeyValueMap contains Pairs(1 to null, 2 to null)
readOnlyNullableKeyValueMap contains Pairs(1 to null, 2 to "a")
readOnlyNullableKeyValueMap contains (KeyValue(1, null))
readOnlyNullableKeyValueMap contains All(KeyValue(1, null), KeyValue(2, null))
readOnlyNullableKeyValueMap contains All(KeyValue(1, null), KeyValue(2) {})
readOnlyNullableKeyValueMap contains (null to null)
readOnlyNullableKeyValueMap contains Pairs(null to null, null to null)
readOnlyNullableKeyValueMap contains Pairs(1 to null, null to "a")
readOnlyNullableKeyValueMap contains (KeyValue(null, null))
readOnlyNullableKeyValueMap contains All(KeyValue(null, null), KeyValue(null, null))
readOnlyNullableKeyValueMap contains All(KeyValue(1, null), KeyValue(null) {})
readOnlyNullableKeyValueMap contains (1 to "a")
readOnlyNullableKeyValueMap contains Pairs(1 to "a", 2 to "b")
readOnlyNullableKeyValueMap contains (KeyValue(1) {})
readOnlyNullableKeyValueMap contains All(KeyValue(1) {}, KeyValue(2) {})
starMap contains (null to "a")
starMap contains Pairs(null to "a", null to "b")
starMap contains Pairs(null to "a", 2 to "b")
starMap contains (KeyValue(null) {})
starMap contains All(KeyValue(null) {}, KeyValue(null) {})
starMap contains All(KeyValue(null) {}, KeyValue(2) {})
starMap contains (1 to null)
starMap contains Pairs(1 to null, 2 to null)
starMap contains Pairs(1 to null, 2 to "a")
starMap contains (KeyValue(1, null))
starMap contains All(KeyValue(1, null), KeyValue(2, null))
starMap contains All(KeyValue(1, null), KeyValue(2) {})
starMap contains (null to null)
starMap contains Pairs(null to null, null to null)
starMap contains Pairs(1 to null, null to "a")
starMap contains (KeyValue(null, null))
starMap contains All(KeyValue(null, null), KeyValue(null, null))
starMap contains All(KeyValue(1, null), KeyValue(null) {})
map containsKey 1
map containsKey 1f
subMap containsKey 1
subMap containsKey 1f
nullableKeyMap containsKey 1
nullableKeyMap containsKey 1f
readOnlyNullableKeyValueMap containsKey 1
readOnlyNullableKeyValueMap containsKey 1f
map containsNotKey 1
map containsNotKey 1f
subMap containsNotKey 1
subMap containsNotKey 1f
nullableKeyMap containsNotKey 1
nullableKeyMap containsNotKey 1f
readOnlyNullableKeyValueMap containsNotKey 1
readOnlyNullableKeyValueMap containsNotKey 1f
map = map toBe Empty
subMap = subMap toBe Empty
nullableKeyMap = nullableKeyMap toBe Empty
nullableValueMap = nullableValueMap toBe Empty
nullableKeyValueMap = nullableKeyValueMap toBe Empty
readOnlyNullableKeyValueMap = readOnlyNullableKeyValueMap toBe Empty
starMap = starMap toBe Empty
map = map notToBe Empty
subMap = subMap notToBe Empty
nullableKeyMap = nullableKeyMap notToBe Empty
nullableValueMap = nullableValueMap notToBe Empty
nullableKeyValueMap = nullableKeyValueMap notToBe Empty
readOnlyNullableKeyValueMap = readOnlyNullableKeyValueMap notToBe Empty
starMap = starMap notToBe Empty
}
}

View File

@@ -0,0 +1,50 @@
package ch.tutteli.atrium.api.infix.en_GB
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.specs.*
class MapFeatureAssertionsSpec : ch.tutteli.atrium.specs.integration.MapFeatureAssertionsSpec(
property<Map<String, Int>, Set<String>>(Expect<Map<String, Int>>::keys),
fun1<Map<String, Int>, Expect<Set<String>>.() -> Unit>(Expect<Map<String, Int>>::keys),
property<Map<String, Int>, Collection<Int>>(Expect<Map<String, Int>>::values),
fun1<Map<String, Int>, Expect<Collection<Int>>.() -> Unit>(Expect<Map<String, Int>>::values),
feature1<Map<String, Int>, String, Int>(Expect<Map<String, Int>>::getExisting),
fun2<Map<String, Int>, String, Expect<Int>.() -> Unit>(Companion::getExisting),
feature1<Map<String?, Int?>, String?, Int?>(Expect<Map<String?, Int?>>::getExisting).withNullableSuffix(),
fun2(Companion::getExisting).name to Companion::getExistingNullable
) {
companion object {
private fun getExisting(
plant: Expect<Map<String, Int>>,
key: String,
assertionCreator: Expect<Int>.() -> Unit
): Expect<Map<String, Int>>
= plant getExisting Key(key) assertIt { assertionCreator() }
private fun getExistingNullable(
plant: Expect<Map<String?, Int?>>,
key: String?,
assertionCreator: Expect<Int?>.() -> Unit
): Expect<Map<String?, Int?>>
= plant getExisting Key(key) assertIt { assertionCreator() }
}
@Suppress("unused", "UNUSED_VALUE")
private fun ambiguityTest() {
var a1: Expect<Map<String, Int>> = notImplemented()
var a2: Expect<Map<out String, Int>> = notImplemented()
var a3: Expect<Map<String?, Int?>> = notImplemented()
var star: Expect<Map<*, *>> = notImplemented()
//TODO ideally this would not work as the map has not defined the key to be out
a1 getExisting 1
a2 getExisting 1
a3 getExisting null as String?
star getExisting "a"
a1 = a1 getExisting Key("a") assertIt { }
a2 = a2 getExisting Key(1) assertIt { }
a3 = a3 getExisting Key(null) assertIt { }
star = star getExisting Key("a") assertIt { }
}
}