api-fluent excluding bcc-tests and deprecation

This commit is contained in:
Robert Stoll
2020-09-08 21:04:24 +02:00
parent 24c810093d
commit 26b6f626e1
94 changed files with 2377 additions and 261 deletions

View File

@@ -5,7 +5,7 @@
package ch.tutteli.atrium.api.fluent.en_GB
import ch.tutteli.atrium.logic._logic
import ch.tutteli.atrium.logic.creating.charsequence.contains.CharSequenceContains
import ch.tutteli.atrium.logic.creating.charsequence.contains.CharSequenceContains.EntryPointStep
import ch.tutteli.atrium.logic.creating.charsequence.contains.searchbehaviours.IgnoringCaseSearchBehaviour
import ch.tutteli.atrium.logic.creating.charsequence.contains.searchbehaviours.NoOpSearchBehaviour
import ch.tutteli.atrium.logic.creating.charsequence.contains.searchbehaviours.NotSearchBehaviour
@@ -20,8 +20,8 @@ import kotlin.jvm.JvmName
*
* @return The newly created builder.
*/
val <T : CharSequence> CharSequenceContains.EntryPointStep<T, NoOpSearchBehaviour>.ignoringCase: CharSequenceContains.EntryPointStep<T, IgnoringCaseSearchBehaviour>
get() : CharSequenceContains.EntryPointStep<T, IgnoringCaseSearchBehaviour> = _logic.ignoringCase
val <T : CharSequence> EntryPointStep<T, NoOpSearchBehaviour>.ignoringCase: EntryPointStep<T, IgnoringCaseSearchBehaviour>
get() = _logic.ignoringCase
/**
* Defines that the search behaviour `ignore case` shall be applied to this sophisticated `contains not` assertion.
@@ -32,5 +32,4 @@ val <T : CharSequence> CharSequenceContains.EntryPointStep<T, NoOpSearchBehaviou
// only keep the above so that we have contains.ignoringCase.not -- seems like a better fit
// as we don't have to re-create the containsBuilder but use NotChecker only as checker as all other checkers
val <T : CharSequence> NotCheckerStep<T, NotSearchBehaviour>.ignoringCase: NotCheckerStep<T, IgnoringCaseSearchBehaviour>
get() : NotCheckerStep<T, IgnoringCaseSearchBehaviour> =
_logic.entryPointStepLogic.ignoringCase._logic.notCheckerStep()
get() = _logic.entryPointStepLogic.ignoringCase._logic.notCheckerStep()

View File

@@ -1,6 +1,5 @@
package ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.impl
import ch.tutteli.atrium.api.fluent.en_GB.atLeast
import ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.AtLeastCheckerOption
import ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.impl.StaticName.nameContainsNotValuesFun
import ch.tutteli.atrium.domain.builders.creating.iterable.contains.builders.AtLeastCheckerOptionBase
@@ -26,5 +25,5 @@ internal class AtLeastCheckerOptionImpl<out E, out T : Iterable<E>, out S : InAn
times,
containsBuilder,
nameContainsNotValuesFun,
{ "${containsBuilder::atLeast.name}($it)" }
{ "atLeast($it)" }
), AtLeastCheckerOption<E, T, S>

View File

@@ -1,10 +1,7 @@
package ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.impl
import ch.tutteli.atrium.api.fluent.en_GB.atLeast
import ch.tutteli.atrium.api.fluent.en_GB.atMost
import ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.AtMostCheckerOption
import ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.impl.StaticName.nameContainsNotValuesFun
import ch.tutteli.atrium.api.fluent.en_GB.exactly
import ch.tutteli.atrium.domain.builders.creating.iterable.contains.builders.AtMostCheckerOptionBase
import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains
import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour
@@ -28,7 +25,7 @@ internal class AtMostCheckerOptionImpl<out E, out T : Iterable<E>, out S : InAny
times,
containsBuilder,
nameContainsNotValuesFun,
{ "${containsBuilder::atMost.name}($it)" },
{ "${containsBuilder::atLeast.name}($it)" },
{ "${containsBuilder::exactly.name}($it)" }
{ "atMost($it)" },
{ "atLeast($it)" },
{ "exactly($it)" }
), AtMostCheckerOption<E, T, S>

View File

@@ -1,12 +1,8 @@
package ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.impl
import ch.tutteli.atrium.api.fluent.en_GB.atLeast
import ch.tutteli.atrium.api.fluent.en_GB.atMost
import ch.tutteli.atrium.api.fluent.en_GB.butAtMost
import ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.AtLeastCheckerOption
import ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.ButAtMostCheckerOption
import ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.impl.StaticName.nameContainsNotValuesFun
import ch.tutteli.atrium.api.fluent.en_GB.exactly
import ch.tutteli.atrium.domain.builders.creating.iterable.contains.builders.ButAtMostCheckerOptionBase
import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains
import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour
@@ -32,9 +28,9 @@ internal class ButAtMostCheckerOptionImpl<out E, out T : Iterable<E>, out S : In
atLeastBuilder,
containsBuilder,
nameContainsNotValuesFun,
{ l, u -> "${containsBuilder::atLeast.name}($l).${atLeastBuilder::butAtMost.name}($u)" },
{ "${containsBuilder::atMost.name}($it)" },
{ "${containsBuilder::atLeast.name}($it)" },
{ "${atLeastBuilder::butAtMost.name}($it)" },
{ "${containsBuilder::exactly.name}($it)" }
{ l, u -> "atLeast($l).butAtMost($u)" },
{ "atMost($it)" },
{ "atLeast($it)" },
{ "butAtMost($it)" },
{ "exactly($it)" }
), ButAtMostCheckerOption<E, T, S>

View File

@@ -2,7 +2,6 @@ package ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.i
import ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.ExactlyCheckerOption
import ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.impl.StaticName.nameContainsNotValuesFun
import ch.tutteli.atrium.api.fluent.en_GB.exactly
import ch.tutteli.atrium.domain.builders.creating.iterable.contains.builders.ExactlyCheckerOptionBase
import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains
import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour
@@ -26,5 +25,5 @@ internal class ExactlyCheckerOptionImpl<out E, out T : Iterable<E>, out S : InAn
times,
containsBuilder,
nameContainsNotValuesFun,
{ "${containsBuilder::exactly.name}($it)" }
{ "exactly($it)" }
), ExactlyCheckerOption<E, T, S>

View File

@@ -2,7 +2,6 @@ package ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.i
import ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.NotOrAtMostCheckerOption
import ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.impl.StaticName.nameContainsNotValuesFun
import ch.tutteli.atrium.api.fluent.en_GB.notOrAtMost
import ch.tutteli.atrium.domain.builders.creating.iterable.contains.builders.NotOrAtMostCheckerOptionBase
import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains
import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour
@@ -26,5 +25,5 @@ internal class NotOrAtMostCheckerOptionImpl<out E, out T : Iterable<E>, out S :
times,
containsBuilder,
nameContainsNotValuesFun,
{ "${containsBuilder::notOrAtMost.name}($it)" }
{ "notOrAtMost($it)" }
), NotOrAtMostCheckerOption<E, T, S>

View File

@@ -1,4 +1,5 @@
@file:Suppress("DEPRECATION" /* will be removed with 1.0.0 */)
package ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.impl
import ch.tutteli.atrium.api.fluent.en_GB.containsNot

View File

@@ -0,0 +1,22 @@
package ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.impl
import ch.tutteli.atrium.api.fluent.en_GB.*
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.AtLeastCheckerStep
import kotlin.reflect.KFunction3
internal object StaticName {
val containsNotValuesFun = {
val f: KFunction3<Expect<Iterable<Double>>, Double, Array<out Double>, Expect<Iterable<Double>>> =
Expect<Iterable<Double>>::containsNot
f.name
}()
val atLeast = IterableLikeContains.EntryPointStep<*, *, InAnyOrderSearchBehaviour>::atLeast.name
val butAtMost = AtLeastCheckerStep<*, *, InAnyOrderSearchBehaviour>::butAtMost.name
val atMost = IterableLikeContains.EntryPointStep<*, *, InAnyOrderSearchBehaviour>::atMost.name
val exactly = IterableLikeContains.EntryPointStep<*, *, InAnyOrderSearchBehaviour>::exactly.name
val notOrAtMost = IterableLikeContains.EntryPointStep<*, *, InAnyOrderSearchBehaviour>::notOrAtMost.name
}

View File

@@ -1,33 +1,30 @@
package ch.tutteli.atrium.api.fluent.en_GB
import ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.NotCheckerOption
import ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.impl.NotCheckerOptionImpl
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.builders.ExpectImpl
import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains
import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.NoOpSearchBehaviour
import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.NotSearchBehaviour
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.*
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.NoOpSearchBehaviour
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.NotSearchBehaviour
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.NotCheckerStep
import ch.tutteli.kbox.identity
/**
* Creates an [IterableContains.Builder] based on this [Expect] which allows to define
* more sophisticated `contains` assertions.
* Starts a sophisticated `contains` assertion building process based on this [Expect].
*
* @return The newly created builder.
*/
val <E, T : Iterable<E>> Expect<T>.contains: IterableContains.Builder<E, T, NoOpSearchBehaviour>
get() = ExpectImpl.iterable.containsBuilder(this)
val <E, T : Iterable<E>> Expect<T>.contains: IterableLikeContains.EntryPointStep<E, T, NoOpSearchBehaviour>
get() = _logic.containsBuilder(::identity)
/**
* Creates an [IterableContains.Builder] based on this [Expect] which allows to define
* more sophisticated `contains not` assertions.
* Starts a sophisticated `contains` assertion building process based on this [Expect] and already chooses a
* [NotCheckerStep].
*
* @return The newly created builder.
*/
val <E, T : Iterable<E>> Expect<T>.containsNot: NotCheckerOption<E, T, NotSearchBehaviour>
get() = NotCheckerOptionImpl(ExpectImpl.iterable.containsNotBuilder(this))
val <E, T : Iterable<E>> Expect<T>.containsNot: NotCheckerStep<E, T, NotSearchBehaviour>
get() = _logic.containsNotBuilder(::identity)
/**
* Expects that the subject of the assertion (an [Iterable]) contains the

View File

@@ -1,9 +1,10 @@
package ch.tutteli.atrium.api.fluent.en_GB
import ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.*
import ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.impl.*
import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains
import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour
import ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.impl.StaticName
import ch.tutteli.atrium.logic._logic
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.*
/**
* Restricts a `contains` assertion by specifying that the number of occurrences of the entry which we are looking
@@ -16,9 +17,10 @@ import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InAn
* @throws IllegalArgumentException In case [times] is smaller than zero.
* @throws IllegalArgumentException In case [times] equals to zero; use [containsNot] instead.
*/
fun <E, T : Iterable<E>, S : InAnyOrderSearchBehaviour> IterableContains.Builder<E, T, S>.atLeast(
fun <E, T : Any, S : InAnyOrderSearchBehaviour> IterableLikeContains.EntryPointStep<E, T, S>.atLeast(
times: Int
): AtLeastCheckerOption<E, T, S> = AtLeastCheckerOptionImpl(times, this)
): AtLeastCheckerStep<E, T, S> =
_logic.atLeastCheckerStep(times, StaticName.containsNotValuesFun) { "${StaticName.atLeast}($it)" }
/**
* Restricts a `contains at least` assertion by specifying that the number of occurrences of the entry which we
@@ -35,9 +37,18 @@ fun <E, T : Iterable<E>, S : InAnyOrderSearchBehaviour> IterableContains.Builder
* @throws IllegalArgumentException In case [times] of this `at most` restriction equals to the number of the
* `at least` restriction; use the [exactly] restriction instead.
*/
fun <E, T : Iterable<E>, S : InAnyOrderSearchBehaviour> AtLeastCheckerOption<E, T, S>.butAtMost(
fun <E, T : Any, S : InAnyOrderSearchBehaviour> AtLeastCheckerStep<E, T, S>.butAtMost(
times: Int
): ButAtMostCheckerOption<E, T, S> = ButAtMostCheckerOptionImpl(times, this, containsBuilder)
): ButAtMostCheckerStep<E, T, S> = _logic.butAtMostCheckerStep(
times,
StaticName.containsNotValuesFun,
{ l, u -> "${StaticName.atLeast}($l).${StaticName.butAtMost}($u)" },
{ "${StaticName.atLeast}($it)" },
{ "${StaticName.butAtMost}($it)" },
{ "${StaticName.exactly}($it)" },
{ "${StaticName.atMost}($it)" }
)
/**
* Restricts a `contains` assertion by specifying that the number of occurrences of the entry which we
@@ -50,9 +61,10 @@ fun <E, T : Iterable<E>, S : InAnyOrderSearchBehaviour> AtLeastCheckerOption<E,
* @throws IllegalArgumentException In case [times] is smaller than zero.
* @throws IllegalArgumentException In case [times] equals to zero; use [containsNot] instead.
*/
fun <E, T : Iterable<E>, S : InAnyOrderSearchBehaviour> IterableContains.Builder<E, T, S>.exactly(
fun <E, T : Any, S : InAnyOrderSearchBehaviour> IterableLikeContains.EntryPointStep<E, T, S>.exactly(
times: Int
): ExactlyCheckerOption<E, T, S> = ExactlyCheckerOptionImpl(times, this)
): ExactlyCheckerStep<E, T, S> =
_logic.exactlyCheckerStep(times, StaticName.containsNotValuesFun) { "${StaticName.exactly}($it)" }
/**
* Restricts a `contains` assertion by specifying that the number of occurrences of the entry which we
@@ -70,9 +82,15 @@ fun <E, T : Iterable<E>, S : InAnyOrderSearchBehaviour> IterableContains.Builder
* @throws IllegalArgumentException In case [times] equals to zero; use [containsNot] instead.
* @throws IllegalArgumentException In case [times] equals to one; use [exactly] instead.
*/
fun <E, T : Iterable<E>, S : InAnyOrderSearchBehaviour> IterableContains.Builder<E, T, S>.atMost(
fun <E, T : Any, S : InAnyOrderSearchBehaviour> IterableLikeContains.EntryPointStep<E, T, S>.atMost(
times: Int
): AtMostCheckerOption<E, T, S> = AtMostCheckerOptionImpl(times, this)
): AtMostCheckerStep<E, T, S> = _logic.atMostCheckerStep(
times,
StaticName.containsNotValuesFun,
{ "${StaticName.atMost}($it)" },
{ "${StaticName.atLeast}($it)" },
{ "${StaticName.exactly}($it)" }
)
/**
* Restricts a `contains` assertion by specifying that the number of occurrences of the entry which we
@@ -85,6 +103,7 @@ fun <E, T : Iterable<E>, S : InAnyOrderSearchBehaviour> IterableContains.Builder
* @throws IllegalArgumentException In case [times] is smaller than zero.
* @throws IllegalArgumentException In case [times] equals to zero; use [containsNot] instead.
*/
fun <E, T : Iterable<E>, S : InAnyOrderSearchBehaviour> IterableContains.Builder<E, T, S>.notOrAtMost(
fun <E, T : Any, S : InAnyOrderSearchBehaviour> IterableLikeContains.EntryPointStep<E, T, S>.notOrAtMost(
times: Int
): NotOrAtMostCheckerOption<E, T, S> = NotOrAtMostCheckerOptionImpl(times, this)
): NotOrAtMostCheckerStep<E, T, S> =
_logic.notOrAtMostCheckerStep(times, StaticName.containsNotValuesFun) { "${StaticName.notOrAtMost}($it)" }

View File

@@ -1,12 +1,13 @@
package ch.tutteli.atrium.api.fluent.en_GB
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.builders.ExpectImpl
import ch.tutteli.atrium.domain.builders.creating.basic.contains.addAssertion
import ch.tutteli.atrium.domain.builders.utils.toVarArg
import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains.CheckerOption
import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic._logicAppend
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains.CheckerStep
import ch.tutteli.atrium.logic.creating.iterable.contains.creators.entries
import ch.tutteli.atrium.logic.creating.iterable.contains.creators.values
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour
import ch.tutteli.kbox.glue
/**
@@ -20,7 +21,7 @@ import ch.tutteli.kbox.glue
* @return An [Expect] for the current subject of the assertion.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
fun <E, T : Iterable<E>> CheckerOption<E, T, InAnyOrderSearchBehaviour>.value(expected: E): Expect<T> =
fun <E, T : Any> CheckerStep<E, T, InAnyOrderSearchBehaviour>.value(expected: E): Expect<T> =
values(expected)
/**
@@ -43,10 +44,10 @@ fun <E, T : Iterable<E>> CheckerOption<E, T, InAnyOrderSearchBehaviour>.value(ex
* @return An [Expect] for the current subject of the assertion.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
fun <E, T : Iterable<E>> CheckerOption<E, T, InAnyOrderSearchBehaviour>.values(
fun <E, T : Any> CheckerStep<E, T, InAnyOrderSearchBehaviour>.values(
expected: E,
vararg otherExpected: E
): Expect<T> = addAssertion(ExpectImpl.iterable.contains.valuesInAnyOrder(this, expected glue otherExpected))
): Expect<T> = _logicAppend { values(expected glue otherExpected) }
/**
* Finishes the specification of the sophisticated `contains` assertion where an entry shall be searched which either
@@ -62,7 +63,7 @@ fun <E, T : Iterable<E>> CheckerOption<E, T, InAnyOrderSearchBehaviour>.values(
* @return An [Expect] for the current subject of the assertion.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
fun <E : Any, T : Iterable<E?>> CheckerOption<E?, T, InAnyOrderSearchBehaviour>.entry(
fun <E : Any, T : Any> CheckerStep<out E?, T, InAnyOrderSearchBehaviour>.entry(
assertionCreatorOrNull: (Expect<E>.() -> Unit)?
): Expect<T> = entries(assertionCreatorOrNull)
@@ -81,15 +82,10 @@ fun <E : Any, T : Iterable<E?>> CheckerOption<E?, T, InAnyOrderSearchBehaviour>.
* @return An [Expect] for the current subject of the assertion.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
fun <E : Any, T : Iterable<E?>> CheckerOption<E?, T, InAnyOrderSearchBehaviour>.entries(
fun <E : Any, T : Any> CheckerStep<out E?, T, InAnyOrderSearchBehaviour>.entries(
assertionCreatorOrNull: (Expect<E>.() -> Unit)?,
vararg otherAssertionCreatorsOrNulls: (Expect<E>.() -> Unit)?
): Expect<T> = addAssertion(
ExpectImpl.iterable.contains.entriesInAnyOrder(
this,
assertionCreatorOrNull glue otherAssertionCreatorsOrNulls
)
)
): Expect<T> = _logicAppend { entries(assertionCreatorOrNull glue otherAssertionCreatorsOrNulls) }
/**
* Finishes the specification of the sophisticated `contains` assertion where all elements of the [expectedIterable]
@@ -107,7 +103,7 @@ fun <E : Any, T : Iterable<E?>> CheckerOption<E?, T, InAnyOrderSearchBehaviour>.
* @since 0.9.0
* TODO remove with 1.0.0
*/
inline fun <reified E, T : Iterable<E>> CheckerOption<E, T, InAnyOrderSearchBehaviour>.elementsOf(
inline fun <reified E, T : Any> CheckerStep<E, T, InAnyOrderSearchBehaviour>.elementsOf(
expectedIterable: Iterable<E>
): Expect<T> {
val (first, rest) = toVarArg<E>(expectedIterable)
@@ -133,7 +129,7 @@ inline fun <reified E, T : Iterable<E>> CheckerOption<E, T, InAnyOrderSearchBeha
*
* @since 0.13.0
*/
inline fun <reified E, T : Iterable<E>> CheckerOption<E, T, InAnyOrderSearchBehaviour>.elementsOf(
inline fun <reified E, T : Any> CheckerStep<E, T, InAnyOrderSearchBehaviour>.elementsOf(
expectedIterableLike: IterableLike
): Expect<T> {
val (first, rest) = toVarArg<E>(expectedIterableLike)

View File

@@ -1,12 +1,15 @@
package ch.tutteli.atrium.api.fluent.en_GB
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.builders.ExpectImpl
import ch.tutteli.atrium.domain.builders.creating.basic.contains.addAssertion
import ch.tutteli.atrium.domain.builders.utils.toVarArg
import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains.Builder
import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InAnyOrderOnlySearchBehaviour
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic._logicAppend
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains.EntryPointStep
import ch.tutteli.atrium.logic.creating.iterable.contains.creators.entries
import ch.tutteli.atrium.logic.creating.iterable.contains.creators.entriesInAnyOrderOnly
import ch.tutteli.atrium.logic.creating.iterable.contains.creators.values
import ch.tutteli.atrium.logic.creating.iterable.contains.creators.valuesInAnyOrderOnly
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InAnyOrderOnlySearchBehaviour
import ch.tutteli.kbox.glue
/**
@@ -24,7 +27,7 @@ import ch.tutteli.kbox.glue
* @return An [Expect] for the current subject of the assertion.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
fun <E, T : Iterable<E>> Builder<E, T, InAnyOrderOnlySearchBehaviour>.value(expected: E): Expect<T> =
fun <E, T : Iterable<E>> EntryPointStep<E, T, InAnyOrderOnlySearchBehaviour>.value(expected: E): Expect<T> =
values(expected)
/**
@@ -43,10 +46,10 @@ fun <E, T : Iterable<E>> Builder<E, T, InAnyOrderOnlySearchBehaviour>.value(expe
* @return An [Expect] for the current subject of the assertion.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
fun <E, T : Iterable<E>> Builder<E, T, InAnyOrderOnlySearchBehaviour>.values(
fun <E, T : Iterable<E>> EntryPointStep<E, T, InAnyOrderOnlySearchBehaviour>.values(
expected: E,
vararg otherExpected: E
): Expect<T> = addAssertion(ExpectImpl.iterable.contains.valuesInAnyOrderOnly(this, expected glue otherExpected))
): Expect<T> = _logicAppend { valuesInAnyOrderOnly(expected glue otherExpected) }
/**
* Finishes the specification of the sophisticated `contains` assertion where the [Iterable] needs to contain only one
@@ -66,7 +69,7 @@ fun <E, T : Iterable<E>> Builder<E, T, InAnyOrderOnlySearchBehaviour>.values(
* @return An [Expect] for the current subject of the assertion.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
fun <E : Any, T : Iterable<E?>> Builder<E?, T, InAnyOrderOnlySearchBehaviour>.entry(
fun <E : Any, T : Iterable<E?>> EntryPointStep<out E?, T, InAnyOrderOnlySearchBehaviour>.entry(
assertionCreatorOrNull: (Expect<E>.() -> Unit)?
): Expect<T> = entries(assertionCreatorOrNull)
@@ -98,15 +101,10 @@ fun <E : Any, T : Iterable<E?>> Builder<E?, T, InAnyOrderOnlySearchBehaviour>.en
* @return An [Expect] for the current subject of the assertion.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
fun <E : Any, T : Iterable<E?>> Builder<E?, T, InAnyOrderOnlySearchBehaviour>.entries(
fun <E : Any, T : Iterable<E?>> EntryPointStep<out E?, T, InAnyOrderOnlySearchBehaviour>.entries(
assertionCreatorOrNull: (Expect<E>.() -> Unit)?,
vararg otherAssertionCreatorsOrNulls: (Expect<E>.() -> Unit)?
): Expect<T> = addAssertion(
ExpectImpl.iterable.contains.entriesInAnyOrderOnly(
this,
assertionCreatorOrNull glue otherAssertionCreatorsOrNulls
)
)
): Expect<T> = _logicAppend { entriesInAnyOrderOnly(assertionCreatorOrNull glue otherAssertionCreatorsOrNulls) }
/**
* Finishes the specification of the sophisticated `contains` assertion where all elements in
@@ -128,7 +126,7 @@ fun <E : Any, T : Iterable<E?>> Builder<E?, T, InAnyOrderOnlySearchBehaviour>.en
* @since 0.9.0
* TODO remove with 1.0.0
*/
inline fun <reified E, T : Iterable<E>> Builder<E, T, InAnyOrderOnlySearchBehaviour>.elementsOf(
inline fun <reified E, T : Iterable<E>> EntryPointStep<E, T, InAnyOrderOnlySearchBehaviour>.elementsOf(
expectedIterable: Iterable<E>
): Expect<T> {
val (first, rest) = toVarArg<E>(expectedIterable)
@@ -158,7 +156,7 @@ inline fun <reified E, T : Iterable<E>> Builder<E, T, InAnyOrderOnlySearchBehavi
*
* @since 0.13.0
*/
inline fun <reified E, T : Iterable<E>> Builder<E, T, InAnyOrderOnlySearchBehaviour>.elementsOf(
inline fun <reified E, T : Iterable<E>> EntryPointStep<E, T, InAnyOrderOnlySearchBehaviour>.elementsOf(
expectedIterableLike: IterableLike
): Expect<T> {
val (first, rest) = toVarArg<E>(expectedIterableLike)

View File

@@ -1,12 +1,15 @@
package ch.tutteli.atrium.api.fluent.en_GB
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.builders.ExpectImpl
import ch.tutteli.atrium.domain.builders.creating.basic.contains.addAssertion
import ch.tutteli.atrium.domain.builders.utils.toVarArg
import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains.Builder
import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InOrderOnlySearchBehaviour
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains.EntryPointStep
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InOrderOnlySearchBehaviour
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic._logicAppend
import ch.tutteli.atrium.logic.creating.iterable.contains.creators.entriesInAnyOrderOnly
import ch.tutteli.atrium.logic.creating.iterable.contains.creators.entriesInOrderOnly
import ch.tutteli.atrium.logic.creating.iterable.contains.creators.valuesInAnyOrderOnly
import ch.tutteli.atrium.logic.creating.iterable.contains.creators.valuesInOrderOnly
import ch.tutteli.kbox.glue
/**
@@ -24,7 +27,7 @@ import ch.tutteli.kbox.glue
* @return An [Expect] for the current subject of the assertion.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
fun <E, T : Iterable<E>> Builder<E, T, InOrderOnlySearchBehaviour>.value(expected: E): Expect<T> =
fun <E, T : Iterable<E>> EntryPointStep<E, T, InOrderOnlySearchBehaviour>.value(expected: E): Expect<T> =
values(expected)
/**
@@ -42,10 +45,10 @@ fun <E, T : Iterable<E>> Builder<E, T, InOrderOnlySearchBehaviour>.value(expecte
* @return An [Expect] for the current subject of the assertion.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
fun <E, T : Iterable<E>> Builder<E, T, InOrderOnlySearchBehaviour>.values(
fun <E, T : Iterable<E>> EntryPointStep<E, T, InOrderOnlySearchBehaviour>.values(
expected: E,
vararg otherExpected: E
): Expect<T> = addAssertion(ExpectImpl.iterable.contains.valuesInOrderOnly(this, expected glue otherExpected))
): Expect<T> = _logicAppend { valuesInOrderOnly(expected glue otherExpected) }
/**
* Finishes the specification of the sophisticated `contains` assertion where the [Iterable] needs to contain only a
@@ -65,7 +68,7 @@ fun <E, T : Iterable<E>> Builder<E, T, InOrderOnlySearchBehaviour>.values(
* @return An [Expect] for the current subject of the assertion.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
fun <E : Any, T : Iterable<E?>> Builder<E?, T, InOrderOnlySearchBehaviour>.entry(
fun <E : Any, T : Iterable<E?>> EntryPointStep<out E?, T, InOrderOnlySearchBehaviour>.entry(
assertionCreatorOrNull: (Expect<E>.() -> Unit)?
): Expect<T> = entries(assertionCreatorOrNull)
@@ -88,15 +91,10 @@ fun <E : Any, T : Iterable<E?>> Builder<E?, T, InOrderOnlySearchBehaviour>.entry
* @return An [Expect] for the current subject of the assertion.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
fun <E : Any, T : Iterable<E?>> Builder<E?, T, InOrderOnlySearchBehaviour>.entries(
fun <E : Any, T : Iterable<E?>> EntryPointStep<out E?, T, InOrderOnlySearchBehaviour>.entries(
assertionCreatorOrNull: (Expect<E>.() -> Unit)?,
vararg otherAssertionCreatorsOrNulls: (Expect<E>.() -> Unit)?
): Expect<T> = addAssertion(
ExpectImpl.iterable.contains.entriesInOrderOnly(
this,
assertionCreatorOrNull glue otherAssertionCreatorsOrNulls
)
)
): Expect<T> = _logicAppend { entriesInOrderOnly(assertionCreatorOrNull glue otherAssertionCreatorsOrNulls) }
/**
* Finishes the specification of the sophisticated `contains` assertion where all elements of the [expectedIterable]
@@ -118,7 +116,7 @@ fun <E : Any, T : Iterable<E?>> Builder<E?, T, InOrderOnlySearchBehaviour>.entri
* @since 0.9.0
* TODO remove with 1.0.0
*/
inline fun <reified E, T : Iterable<E>> Builder<E, T, InOrderOnlySearchBehaviour>.elementsOf(
inline fun <reified E, T : Iterable<E>> EntryPointStep<E, T, InOrderOnlySearchBehaviour>.elementsOf(
expectedIterable: Iterable<E>
): Expect<T> {
val (first, rest) = toVarArg<E>(expectedIterable)
@@ -148,7 +146,7 @@ inline fun <reified E, T : Iterable<E>> Builder<E, T, InOrderOnlySearchBehaviour
*
* @since 0.13.0
*/
inline fun <reified E, T : Iterable<E>> Builder<E, T, InOrderOnlySearchBehaviour>.elementsOf(
inline fun <reified E, T : Iterable<E>> EntryPointStep<E, T, InOrderOnlySearchBehaviour>.elementsOf(
expectedIterableLike: IterableLike
): Expect<T> {
val (first, rest) = toVarArg<E>(expectedIterableLike)

View File

@@ -1,12 +1,13 @@
package ch.tutteli.atrium.api.fluent.en_GB
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.builders.ExpectImpl
import ch.tutteli.atrium.domain.builders.creating.basic.contains.addAssertion
import ch.tutteli.atrium.domain.builders.utils.Group
import ch.tutteli.atrium.domain.builders.utils.groupsToList
import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains.Builder
import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InOrderOnlyGroupedWithinSearchBehaviour
import ch.tutteli.atrium.logic._logicAppend
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains.EntryPointStep
import ch.tutteli.atrium.logic.creating.iterable.contains.creators.entriesInOrderOnlyGrouped
import ch.tutteli.atrium.logic.creating.iterable.contains.creators.valuesInOrderOnlyGrouped
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InOrderOnlyGroupedWithinSearchBehaviour
import kotlin.jvm.JvmName
/**
@@ -22,16 +23,11 @@ import kotlin.jvm.JvmName
* @return An [Expect] for the current subject of the assertion.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
fun <E, T : Iterable<E>> Builder<E, T, InOrderOnlyGroupedWithinSearchBehaviour>.inAnyOrder(
fun <E, T : Iterable<E>> EntryPointStep<E, T, InOrderOnlyGroupedWithinSearchBehaviour>.inAnyOrder(
firstGroup: Group<E>,
secondGroup: Group<E>,
vararg otherExpectedGroups: Group<E>
): Expect<T> = addAssertion(
ExpectImpl.iterable.contains.valuesInOrderOnlyGrouped(
this,
groupsToList(firstGroup, secondGroup, otherExpectedGroups)
)
)
): Expect<T> = _logicAppend { valuesInOrderOnlyGrouped(groupsToList(firstGroup, secondGroup, otherExpectedGroups)) }
/**
* Finishes the specification of the sophisticated `contains` assertion where the expected [firstGroup] as well as
@@ -52,13 +48,8 @@ fun <E, T : Iterable<E>> Builder<E, T, InOrderOnlyGroupedWithinSearchBehaviour>.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
*/
@JvmName("inAnyOrderEntries")
fun <E : Any, T : Iterable<E?>> Builder<E?, T, InOrderOnlyGroupedWithinSearchBehaviour>.inAnyOrder(
fun <E : Any, T : Iterable<E?>> EntryPointStep<out E?, T, InOrderOnlyGroupedWithinSearchBehaviour>.inAnyOrder(
firstGroup: Group<(Expect<E>.() -> Unit)?>,
secondGroup: Group<(Expect<E>.() -> Unit)?>,
vararg otherExpectedGroups: Group<(Expect<E>.() -> Unit)?>
): Expect<T> = addAssertion(
ExpectImpl.iterable.contains.entriesInOrderOnlyGrouped(
this,
groupsToList(firstGroup, secondGroup, otherExpectedGroups)
)
)
): Expect<T> = _logicAppend { entriesInOrderOnlyGrouped(groupsToList(firstGroup, secondGroup, otherExpectedGroups)) }

View File

@@ -1,8 +1,9 @@
package ch.tutteli.atrium.api.fluent.en_GB
import ch.tutteli.atrium.domain.builders.ExpectImpl
import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains.Builder
import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.*
import ch.tutteli.atrium.logic._logic
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains.EntryPointStep
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.*
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.*
import kotlin.jvm.JvmName
/**
@@ -11,8 +12,8 @@ import kotlin.jvm.JvmName
*
* @return The newly created builder.
*/
val <E, T : Iterable<E>> Builder<E, T, NoOpSearchBehaviour>.inAnyOrder: Builder<E, T, InAnyOrderSearchBehaviour>
get() = ExpectImpl.iterable.contains.searchBehaviours.inAnyOrder(this)
val <E, T : Iterable<E>> EntryPointStep<E, T, NoOpSearchBehaviour>.inAnyOrder: EntryPointStep<E, T, InAnyOrderSearchBehaviour>
get() = _logic.inAnyOrder
/**
* Defines that the constraint "`only` the specified entries exist in the [Iterable]" shall be applied to this
@@ -20,10 +21,9 @@ val <E, T : Iterable<E>> Builder<E, T, NoOpSearchBehaviour>.inAnyOrder: Builder<
*
* @return The newly created builder.
*/
val <E, T : Iterable<E>> Builder<E, T, InAnyOrderSearchBehaviour>.only: Builder<E, T, InAnyOrderOnlySearchBehaviour>
val <E, T : Iterable<E>> EntryPointStep<E, T, InAnyOrderSearchBehaviour>.only: EntryPointStep<E, T, InAnyOrderOnlySearchBehaviour>
@JvmName("butOnly")
get() = ExpectImpl.iterable.contains.searchBehaviours.inAnyOrderOnly(this)
get() = _logic.butOnly
/**
* Defines that the search behaviour "find entries `in order` in the [Iterable]" shall be applied to this
@@ -31,8 +31,8 @@ val <E, T : Iterable<E>> Builder<E, T, InAnyOrderSearchBehaviour>.only: Builder<
*
* @return The newly created builder.
*/
val <E, T : Iterable<E>> Builder<E, T, NoOpSearchBehaviour>.inOrder: Builder<E, T, InOrderSearchBehaviour>
get() = ExpectImpl.iterable.contains.searchBehaviours.inOrder(this)
val <E, T : Iterable<E>> EntryPointStep<E, T, NoOpSearchBehaviour>.inOrder: EntryPointStep<E, T, InOrderSearchBehaviour>
get() = _logic.inOrder
/**
* Defines that the constraint "`only` the specified entries exist in the [Iterable]" shall be applied to this
@@ -40,9 +40,9 @@ val <E, T : Iterable<E>> Builder<E, T, NoOpSearchBehaviour>.inOrder: Builder<E,
*
* @return The newly created builder.
*/
val <E, T : Iterable<E>> Builder<E, T, InOrderSearchBehaviour>.only: Builder<E, T, InOrderOnlySearchBehaviour>
val <E, T : Iterable<E>> EntryPointStep<E, T, InOrderSearchBehaviour>.only: EntryPointStep<E, T, InOrderOnlySearchBehaviour>
@JvmName("andOnly")
get() = ExpectImpl.iterable.contains.searchBehaviours.inOrderOnly(this)
get() = _logic.andOnly
/**
* Defines that the [Iterable] contains `in order only` groups of entries
@@ -50,13 +50,13 @@ val <E, T : Iterable<E>> Builder<E, T, InOrderSearchBehaviour>.only: Builder<E,
*
* @return The newly created builder.
*/
val <E, T : Iterable<E>> Builder<E, T, InOrderOnlySearchBehaviour>.grouped: Builder<E, T, InOrderOnlyGroupedSearchBehaviour>
get() = ExpectImpl.iterable.contains.searchBehaviours.inOrderOnlyGrouped(this)
val <E, T : Iterable<E>> EntryPointStep<E, T, InOrderOnlySearchBehaviour>.grouped: EntryPointStep<E, T, InOrderOnlyGroupedSearchBehaviour>
get() = _logic.grouped
/**
* A filler word to emphasis that the next step defines the order within expected groups of values.
*
* @return The newly created builder.
*/
val <E, T : Iterable<E>> Builder<E, T, InOrderOnlyGroupedSearchBehaviour>.within: Builder<E, T, InOrderOnlyGroupedWithinSearchBehaviour>
get() = ExpectImpl.iterable.contains.searchBehaviours.inOrderOnlyGroupedWithin(this)
val <E, T : Iterable<E>> EntryPointStep<E, T, InOrderOnlyGroupedSearchBehaviour>.within: EntryPointStep<E, T, InOrderOnlyGroupedWithinSearchBehaviour>
get() = _logic.within

View File

@@ -1,10 +1,10 @@
package ch.tutteli.atrium.api.fluent.en_GB
import ch.tutteli.atrium.api.fluent.en_GB.creating.iterable.contains.builders.AtLeastCheckerOption
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.builders.utils.Group
import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains
import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.*
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.*
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.AtLeastCheckerStep
import ch.tutteli.atrium.specs.notImplemented
import kotlin.reflect.KFunction4
import kotlin.reflect.KProperty
@@ -16,27 +16,27 @@ abstract class IterableContainsSpecBase {
protected val containsNot = containsNotProp.name
//@formatter:off
protected val atLeast = IterableContains.Builder<*, *, InAnyOrderSearchBehaviour>::atLeast.name
protected val butAtMost = AtLeastCheckerOption<*, *, InAnyOrderSearchBehaviour>::butAtMost.name
protected val exactly = IterableContains.Builder<*, *, InAnyOrderSearchBehaviour>::exactly.name
protected val atMost = IterableContains.Builder<*, *, InAnyOrderSearchBehaviour>::atMost.name
protected val notOrAtMost = IterableContains.Builder<*, *, InAnyOrderSearchBehaviour>::notOrAtMost.name
protected val inAnyOrder = IterableContains.Builder<*, *, NoOpSearchBehaviour>::inAnyOrder.name
protected val inAnyOrderValues = IterableContains.CheckerOption<Int, Iterable<Int>, InAnyOrderSearchBehaviour>::values.name
protected val inAnyOrderEntries = IterableContains.CheckerOption<Int, Iterable<Int>, InAnyOrderSearchBehaviour>::entries.name
protected val inAnyOrderElementsOf = IterableContains.CheckerOption<Int, Iterable<Int>, InAnyOrderSearchBehaviour>::elementsOf.name
protected val inAnyOrderOnlyValues = IterableContains.Builder<Int, Iterable<Int>, InAnyOrderOnlySearchBehaviour>::values.name
protected val inAnyOrderOnlyEntries = IterableContains.Builder<Int, Iterable<Int>, InAnyOrderOnlySearchBehaviour>::entries.name
protected val inAnyOrderOnlyElementsOf = IterableContains.Builder<Int, Iterable<Int>, InAnyOrderOnlySearchBehaviour>::elementsOf.name
protected val inOrder = IterableContains.Builder<*, *, NoOpSearchBehaviour>::inOrder.name
protected val only = IterableContains.Builder<*, *, InAnyOrderSearchBehaviour>::only.name
protected val inOrderOnlyValues = IterableContains.Builder<Int, Iterable<Int>, InOrderOnlySearchBehaviour>::values.name
protected val inOrderOnlyEntries = IterableContains.Builder<Int, Iterable<Int>, InOrderOnlySearchBehaviour>::entries.name
protected val inOrderElementsOf = IterableContains.Builder<Int, Iterable<Int>, InOrderOnlySearchBehaviour>::elementsOf.name
protected val grouped = IterableContains.Builder<*, *, InOrderOnlySearchBehaviour>::grouped.name
protected val within = IterableContains.Builder<*, *, InOrderOnlyGroupedSearchBehaviour>::within.name
private val withinInAnyOrderFun: KFunction4<IterableContains.Builder<Int, Iterable<Int>, InOrderOnlyGroupedWithinSearchBehaviour>, Group<Int>, Group<Int>, Array<out Group<Int>>, Expect<Iterable<Int>>> =
IterableContains.Builder<Int, Iterable<Int>, InOrderOnlyGroupedWithinSearchBehaviour>::inAnyOrder
protected val atLeast = IterableLikeContains.EntryPointStep<*, *, InAnyOrderSearchBehaviour>::atLeast.name
protected val butAtMost = AtLeastCheckerStep<*, *, InAnyOrderSearchBehaviour>::butAtMost.name
protected val exactly = IterableLikeContains.EntryPointStep<*, *, InAnyOrderSearchBehaviour>::exactly.name
protected val atMost = IterableLikeContains.EntryPointStep<*, *, InAnyOrderSearchBehaviour>::atMost.name
protected val notOrAtMost = IterableLikeContains.EntryPointStep<*, *, InAnyOrderSearchBehaviour>::notOrAtMost.name
protected val inAnyOrder = IterableLikeContains.EntryPointStep<Int, List<Int>, NoOpSearchBehaviour>::inAnyOrder.name
protected val inAnyOrderValues = IterableLikeContains.CheckerStep<Int, Iterable<Int>, InAnyOrderSearchBehaviour>::values.name
protected val inAnyOrderEntries = IterableLikeContains.CheckerStep<Int, Iterable<Int>, InAnyOrderSearchBehaviour>::entries.name
protected val inAnyOrderElementsOf = IterableLikeContains.CheckerStep<Int, Iterable<Int>, InAnyOrderSearchBehaviour>::elementsOf.name
protected val inAnyOrderOnlyValues = IterableLikeContains.EntryPointStep<Int, Iterable<Int>, InAnyOrderOnlySearchBehaviour>::values.name
protected val inAnyOrderOnlyEntries = IterableLikeContains.EntryPointStep<Int, Iterable<Int>, InAnyOrderOnlySearchBehaviour>::entries.name
protected val inAnyOrderOnlyElementsOf = IterableLikeContains.EntryPointStep<Int, Iterable<Int>, InAnyOrderOnlySearchBehaviour>::elementsOf.name
protected val inOrder = IterableLikeContains.EntryPointStep<Int, List<Int>, NoOpSearchBehaviour>::inOrder.name
protected val only = IterableLikeContains.EntryPointStep<Int, List<Int>, InAnyOrderSearchBehaviour>::only.name
protected val inOrderOnlyValues = IterableLikeContains.EntryPointStep<Int, Iterable<Int>, InOrderOnlySearchBehaviour>::values.name
protected val inOrderOnlyEntries = IterableLikeContains.EntryPointStep<Int, Iterable<Int>, InOrderOnlySearchBehaviour>::entries.name
protected val inOrderElementsOf = IterableLikeContains.EntryPointStep<Int, Iterable<Int>, InOrderOnlySearchBehaviour>::elementsOf.name
protected val grouped = IterableLikeContains.EntryPointStep<Int, List<Int>, InOrderOnlySearchBehaviour>::grouped.name
protected val within = IterableLikeContains.EntryPointStep<Int, List<Int>, InOrderOnlyGroupedSearchBehaviour>::within.name
private val withinInAnyOrderFun: KFunction4<IterableLikeContains.EntryPointStep<Int, Iterable<Int>, InOrderOnlyGroupedWithinSearchBehaviour>, Group<Int>, Group<Int>, Array<out Group<Int>>, Expect<Iterable<Int>>> =
IterableLikeContains.EntryPointStep<Int, Iterable<Int>, InOrderOnlyGroupedWithinSearchBehaviour>::inAnyOrder
protected val withinInAnyOrder = withinInAnyOrderFun.name
//@formatter:on
@@ -46,6 +46,7 @@ abstract class IterableContainsSpecBase {
val nullableList: Expect<Set<Number?>> = notImplemented()
val subList: Expect<ArrayList<out Number>> = notImplemented()
val star: Expect<Collection<*>> = notImplemented()
val any: Expect<Collection<Any>> = notImplemented()
list.contains(1)
list.contains(1f)
@@ -116,7 +117,7 @@ abstract class IterableContainsSpecBase {
subList.containsExactly {}
subList.containsExactly({}, {})
nullableList.containsExactly(1)
nullableList.containsExactly(1, 1)
nullableList.containsExactly(1, 1f)
nullableList.containsExactly {}
nullableList.containsExactly(null)
nullableList.containsExactly({}, null)
@@ -124,33 +125,33 @@ abstract class IterableContainsSpecBase {
nullableList.containsExactly(null, {})
list.contains.inAnyOrder.atLeast(1).value(1)
list.contains.inAnyOrder.atLeast(1).values(2, 1)
list.contains.inAnyOrder.atLeast(1).values(2, 1f)
list.contains.inAnyOrder.atLeast(1).entry {}
list.contains.inAnyOrder.atLeast(1).entries({}, {})
list.contains.inAnyOrder.atLeast(1).elementsOf(listOf(1, 2))
list.contains.inAnyOrder.atLeast(1).elementsOf(listOf(1, 2f))
subList.contains.inAnyOrder.atLeast(1).value(1)
subList.contains.inAnyOrder.atLeast(1).values(2, 1)
subList.contains.inAnyOrder.atLeast(1).entry {}
subList.contains.inAnyOrder.atLeast(1).entries({}, {})
subList.contains.inAnyOrder.atLeast(1).elementsOf(listOf(1, 2))
subList.contains.inAnyOrder.atLeast(1).elementsOf(listOf(1, 2f))
nullableList.contains.inAnyOrder.atLeast(1).value(1)
nullableList.contains.inAnyOrder.atLeast(1).values(2, 1)
nullableList.contains.inAnyOrder.atLeast(1).values(2, 1f)
nullableList.contains.inAnyOrder.atLeast(1).entry {}
nullableList.contains.inAnyOrder.atLeast(1).entries({}, {})
nullableList.contains.inAnyOrder.atLeast(1).elementsOf(listOf(1, 2))
nullableList.contains.inAnyOrder.atLeast(1).elementsOf(listOf(1, 2f))
nullableList.contains.inAnyOrder.atLeast(1).value(null)
nullableList.contains.inAnyOrder.atLeast(1).values(null, 1)
nullableList.contains.inAnyOrder.atLeast(1).values(2, null)
nullableList.contains.inAnyOrder.atLeast(1).values(2f, null)
nullableList.contains.inAnyOrder.atLeast(1).values(null, null)
nullableList.contains.inAnyOrder.atLeast(1).entry(null)
nullableList.contains.inAnyOrder.atLeast(1).entries(null, {})
nullableList.contains.inAnyOrder.atLeast(1).entries({}, null)
nullableList.contains.inAnyOrder.atLeast(1).entries(null, null)
star.contains.inAnyOrder.atLeast(1).value(1)
star.contains.inAnyOrder.atLeast(1).values(2, 1)
star.contains.inAnyOrder.atLeast(1).values(2, 1f)
star.contains.inAnyOrder.atLeast(1).entry {}
star.contains.inAnyOrder.atLeast(1).entries({}, {})
star.contains.inAnyOrder.atLeast(1).elementsOf(listOf(1, 2))
star.contains.inAnyOrder.atLeast(1).elementsOf(listOf(1, 2f))
star.contains.inAnyOrder.atLeast(1).value(null)
star.contains.inAnyOrder.atLeast(1).values(null, 1)
star.contains.inAnyOrder.atLeast(1).values(2, null)
@@ -164,33 +165,33 @@ abstract class IterableContainsSpecBase {
list.contains.inAnyOrder.only.values(2, 1)
list.contains.inAnyOrder.only.entry {}
list.contains.inAnyOrder.only.entries({}, {})
list.contains.inAnyOrder.only.elementsOf(listOf(1, 2))
list.contains.inAnyOrder.only.elementsOf(listOf(1, 2f))
subList.contains.inAnyOrder.only.value(1)
subList.contains.inAnyOrder.only.values(2, 1)
subList.contains.inAnyOrder.only.entry {}
subList.contains.inAnyOrder.only.entries({}, {})
subList.contains.inAnyOrder.only.elementsOf(listOf(1, 2))
subList.contains.inAnyOrder.only.elementsOf(listOf(1, 2f))
nullableList.contains.inAnyOrder.only.value(1)
nullableList.contains.inAnyOrder.only.values(2, 1)
nullableList.contains.inAnyOrder.only.values(2, 1f)
nullableList.contains.inAnyOrder.only.entry {}
nullableList.contains.inAnyOrder.only.entries({}, {})
nullableList.contains.inAnyOrder.only.elementsOf(listOf(1, 2))
nullableList.contains.inAnyOrder.only.elementsOf(listOf(1, 2f))
nullableList.contains.inAnyOrder.only.value(null)
nullableList.contains.inAnyOrder.only.values(null, 1)
nullableList.contains.inAnyOrder.only.values(2, null)
nullableList.contains.inAnyOrder.only.values(2f, null)
nullableList.contains.inAnyOrder.only.values(null, null)
nullableList.contains.inAnyOrder.only.entry(null)
nullableList.contains.inAnyOrder.only.entries(null, {})
nullableList.contains.inAnyOrder.only.entries({}, null)
nullableList.contains.inAnyOrder.only.entries(null, null)
star.contains.inAnyOrder.only.value(1)
star.contains.inAnyOrder.only.values(2, 1)
star.contains.inAnyOrder.only.values(2, 1f)
star.contains.inAnyOrder.only.entry {}
star.contains.inAnyOrder.only.entries({}, {})
star.contains.inAnyOrder.only.elementsOf(listOf(1, 2))
star.contains.inAnyOrder.only.elementsOf(listOf(1, 2f))
star.contains.inAnyOrder.only.value(null)
star.contains.inAnyOrder.only.values(null, 1)
star.contains.inAnyOrder.only.values(2, null)
star.contains.inAnyOrder.only.values(2f, null)
star.contains.inAnyOrder.only.values(null, null)
star.contains.inAnyOrder.only.entry(null)
star.contains.inAnyOrder.only.entries(null, {})
@@ -201,48 +202,49 @@ abstract class IterableContainsSpecBase {
list.contains.inOrder.only.values(2, 1)
list.contains.inOrder.only.entry {}
list.contains.inOrder.only.entries({}, {})
list.contains.inOrder.only.elementsOf(listOf(1, 2))
list.contains.inOrder.only.elementsOf(listOf(1, 2f))
subList.contains.inOrder.only.value(1)
subList.contains.inOrder.only.values(2, 1)
subList.contains.inOrder.only.values(2, 1f)
subList.contains.inOrder.only.entry {}
subList.contains.inOrder.only.entries({}, {})
subList.contains.inOrder.only.elementsOf(listOf(1, 2))
subList.contains.inOrder.only.elementsOf(listOf(1, 2f))
nullableList.contains.inOrder.only.value(1)
nullableList.contains.inOrder.only.values(2, 1)
nullableList.contains.inOrder.only.entry {}
nullableList.contains.inOrder.only.entries({}, {})
nullableList.contains.inOrder.only.elementsOf(listOf(1, 2))
nullableList.contains.inOrder.only.elementsOf(listOf(1, 2f))
nullableList.contains.inOrder.only.value(null)
nullableList.contains.inOrder.only.values(null, 1)
nullableList.contains.inOrder.only.values(2, null)
nullableList.contains.inOrder.only.values(2f, null)
nullableList.contains.inOrder.only.values(null, null)
nullableList.contains.inOrder.only.entry(null)
nullableList.contains.inOrder.only.entries(null, {})
nullableList.contains.inOrder.only.entries({}, null)
nullableList.contains.inOrder.only.entries(null, null)
star.contains.inOrder.only.value(1)
star.contains.inOrder.only.values(2, 1)
star.contains.inOrder.only.values(2, 1f)
star.contains.inOrder.only.entry {}
star.contains.inOrder.only.entries({}, {})
star.contains.inOrder.only.elementsOf(listOf(1, 2))
star.contains.inOrder.only.elementsOf(listOf(1, 2f))
star.contains.inOrder.only.value(null)
star.contains.inOrder.only.values(null, 1)
star.contains.inOrder.only.values(2, null)
star.contains.inOrder.only.values(2f, null)
star.contains.inOrder.only.values(null, null)
star.contains.inOrder.only.entry(null)
star.contains.inOrder.only.entries(null, {})
star.contains.inOrder.only.entries({}, null)
star.contains.inOrder.only.entries(null, null)
star.contains.inOrder.only.entries(null, null)
list.contains.inOrder.only.grouped.within.inAnyOrder(
Value(1),
Values(1f),
Values(1f, 1)
Values<Number>(1f, 1)
)
subList.contains.inOrder.only.grouped.within.inAnyOrder(
Value(1),
Values(1f),
Values(1f, 1)
Values<Number>(1f, 1)
)
nullableList.contains.inOrder.only.grouped.within.inAnyOrder(
Value(null),
@@ -258,6 +260,13 @@ abstract class IterableContainsSpecBase {
Values(1, null),
Values(null, null)
)
any.contains.inOrder.only.grouped.within.inAnyOrder(
Value(1),
Values(2),
Values(1f, 2),
Values(1, 1),
Values("je", 'a')
)
list.contains.inOrder.only.grouped.within.inAnyOrder(
Entry {},
@@ -276,7 +285,14 @@ abstract class IterableContainsSpecBase {
Entries({}, null),
Entries(null, null)
)
star.contains.inOrder.only.grouped.within.inAnyOrder(
star.contains.inOrder.only.grouped.within.inAnyOrder<Any, Collection<Any?>>(
Entry(null),
Entries(null),
Entries(null, {}),
Entries({}, null),
Entries(null, null)
)
any.contains.inOrder.only.grouped.within.inAnyOrder(
Entry(null),
Entries(null),
Entries(null, {}),

View File

@@ -12,14 +12,35 @@ dependencies {
apply from: "$project.projectDir/../generateLogic.gradle"
def generateLogic = createGenerateLogicTask(project, "impls", '',
['/creating/charsequence/contains/creators' : new Tuple5(
'CharSequenceContains.CheckerStepLogic',
'ch.tutteli.atrium.logic.creating.charsequence.contains.CharSequenceContains',
/checkerStepLogic: (CharSequenceContains.CheckerStepLogic<T, [^>]+>)/,
'<T : CharSequence, S : CharSequenceContains.SearchBehaviour> CharSequenceContains.CheckerStepLogic<T, S>',
'entryPointStepLogic.container.getImpl'
)])
Map<String, Closure<Tuple4<String, String, String, String>>> map = [
'/creating/charsequence/contains/creators': {
new Tuple3(
'import ch.tutteli.atrium.logic.creating.charsequence.contains.CharSequenceContains',
'<T : CharSequence, S : CharSequenceContains.SearchBehaviour> CharSequenceContains.CheckerStepLogic<T, S>',
'entryPointStepLogic.container.getImpl'
)
},
'/creating/iterable/contains/creators' : { java.nio.file.Path path ->
def fileNameAsString = path.fileName.toString()
if (fileNameAsString == 'IterableLikeContainsInAnyOrderAssertions.kt') {
return new Tuple3(
'import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains\nimport ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour',
'<E, T : Any> IterableLikeContains.CheckerStepLogic<E, T, InAnyOrderSearchBehaviour>',
'entryPointStepLogic.container.getImpl'
)
} else if (fileNameAsString == 'IterableLikeContainsAssertions.kt') {
return new Tuple3(
'',
'<E, T : Any, S : IterableLikeContains.SearchBehaviour> IterableLikeContains.EntryPointStepLogic<E, T, S>',
'container.getImpl'
)
} else {
throw new IllegalStateException("define a configuration for this new file $fileNameAsString")
}
}
]
def generateLogic = createGenerateLogicTask(project, "impls", '', map)
compileKotlinCommon.dependsOn(generateLogic)
sourceSets {

View File

@@ -0,0 +1,31 @@
//---------------------------------------------------
// Generated content, modify:
// logic/generateLogic.gradle
// if necessary - enjoy the day 🙂
//---------------------------------------------------
@file:JvmMultifileClass
@file:JvmName("ImplsKt")
package ch.tutteli.atrium.logic.creating.iterable.contains.creators
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour
import ch.tutteli.atrium.logic.creating.iterable.contains.creators.impl.DefaultIterableLikeContainsAssertions
import ch.tutteli.atrium.logic.creating.iterable.contains.creators.impl.DefaultIterableLikeContainsInAnyOrderAssertions
@PublishedApi
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
@UseExperimental(ExperimentalNewExpectTypes::class)
internal inline val <E, T : Any, S : IterableLikeContains.SearchBehaviour> IterableLikeContains.EntryPointStepLogic<E, T, S>._iterableLikeContainsImpl
get() = container.getImpl(IterableLikeContainsAssertions::class) { DefaultIterableLikeContainsAssertions() }
@PublishedApi
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
@UseExperimental(ExperimentalNewExpectTypes::class)
internal inline val <E, T : Any> IterableLikeContains.CheckerStepLogic<E, T, InAnyOrderSearchBehaviour>._iterableLikeContainsInAnyOrderImpl
get() = entryPointStepLogic.container.getImpl(IterableLikeContainsInAnyOrderAssertions::class) { DefaultIterableLikeContainsInAnyOrderAssertions() }

View File

@@ -0,0 +1,32 @@
//---------------------------------------------------
// Generated content, modify:
// logic/generateLogic.gradle
// if necessary - enjoy the day 🙂
//---------------------------------------------------
@file:Suppress("DEPRECATION" /* TODO remove annotation with 1.0.0 */)
package ch.tutteli.atrium.logic.creating.iterable.contains.creators
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InAnyOrderOnlySearchBehaviour
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InOrderOnlyGroupedSearchBehaviour
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InOrderOnlySearchBehaviour
fun <E, T : IterableLike> IterableLikeContains.EntryPointStepLogic<E, T, InAnyOrderOnlySearchBehaviour>.valuesInAnyOrderOnly(expected: List<E>): Assertion = _iterableLikeContainsImpl.valuesInAnyOrderOnly(this, expected)
fun <E : Any, T : IterableLike> IterableLikeContains.EntryPointStepLogic<out E?, T, InAnyOrderOnlySearchBehaviour>.entriesInAnyOrderOnly(assertionCreators: List<(Expect<E>.() -> Unit)?>): Assertion = _iterableLikeContainsImpl.entriesInAnyOrderOnly(this, assertionCreators)
fun <E, T : IterableLike> IterableLikeContains.EntryPointStepLogic<E, T, InOrderOnlySearchBehaviour>.valuesInOrderOnly(expected: List<E>): Assertion = _iterableLikeContainsImpl.valuesInOrderOnly(this, expected)
fun <E : Any, T : IterableLike> IterableLikeContains.EntryPointStepLogic<out E?, T, InOrderOnlySearchBehaviour>.entriesInOrderOnly(assertionCreators: List<(Expect<E>.() -> Unit)?>): Assertion = _iterableLikeContainsImpl.entriesInOrderOnly(this, assertionCreators)
fun <E, T : IterableLike> IterableLikeContains.EntryPointStepLogic<E, T, InOrderOnlyGroupedSearchBehaviour>.valuesInOrderOnlyGrouped(groups: List<List<E>>): Assertion = _iterableLikeContainsImpl.valuesInOrderOnlyGrouped(this, groups)
fun <E : Any, T : IterableLike> IterableLikeContains.EntryPointStepLogic<out E?, T, InOrderOnlyGroupedSearchBehaviour>.entriesInOrderOnlyGrouped(groups: List<List<(Expect<E>.() -> Unit)?>>): Assertion = _iterableLikeContainsImpl.entriesInOrderOnlyGrouped(this, groups)

View File

@@ -0,0 +1,20 @@
//---------------------------------------------------
// Generated content, modify:
// logic/generateLogic.gradle
// if necessary - enjoy the day 🙂
//---------------------------------------------------
@file:Suppress("DEPRECATION" /* TODO remove annotation with 1.0.0 */)
package ch.tutteli.atrium.logic.creating.iterable.contains.creators
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour
fun <E, T : IterableLike> IterableLikeContains.CheckerStepLogic<E, T, InAnyOrderSearchBehaviour>.values(expected: List<E>): Assertion = _iterableLikeContainsInAnyOrderImpl.values(this, expected)
fun <E : Any, T : IterableLike> IterableLikeContains.CheckerStepLogic<out E?, T, InAnyOrderSearchBehaviour>.entries(assertionCreators: List<(Expect<E>.() -> Unit)?>): Assertion = _iterableLikeContainsInAnyOrderImpl.entries(this, assertionCreators)

View File

@@ -10,18 +10,16 @@ import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.creating.AssertionContainer
import ch.tutteli.atrium.domain.creating.changers.ExtractedFeaturePostStep
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.NoOpSearchBehaviour
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.NotSearchBehaviour
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.NotCheckerStep
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.impl.NotCheckerStepImpl
//TODO add with 0.14.0
// fun <T : Any, E> iterableLikeContainsBuilder(
// container: AssertionContainer<T>,
// converter: (T) -> Iterable<E>
// ): IterableLikeContains.Builder<T, E, NoOpSearchBehaviour>
//
// fun <T : Any, E> iterableLikeContainsNotBuilder(
// container: AssertionContainer<T>,
// converter: (T) -> Iterable<E>
// ): IterableLikeContains.Builder<T, E, NotSearchBehaviour>
fun <T : Any, E> AssertionContainer<T>.containsBuilder(converter: (T) -> Iterable<E>): IterableLikeContains.EntryPointStep<E, T, NoOpSearchBehaviour> = _iterableLikeImpl.containsBuilder(this, converter)
fun <T : Any, E> AssertionContainer<T>.containsNotBuilder(converter: (T) -> Iterable<E>): NotCheckerStep<E, T, NotSearchBehaviour> = _iterableLikeImpl.containsNotBuilder(this, converter)
fun <T : Any, E : Any> AssertionContainer<T>.all(converter: (T) -> Iterable<E?>, assertionCreatorOrNull: (Expect<E>.() -> Unit)?): Assertion =
_iterableLikeImpl.all(this, converter, assertionCreatorOrNull)

View File

@@ -4,6 +4,11 @@ import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.creating.AssertionContainer
import ch.tutteli.atrium.domain.creating.changers.ExtractedFeaturePostStep
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.NoOpSearchBehaviour
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.NotSearchBehaviour
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.NotCheckerStep
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.impl.NotCheckerStepImpl
/**
* Collection of assertion functions and builders which are applicable to subjects which can be transformed to an
@@ -11,16 +16,15 @@ import ch.tutteli.atrium.domain.creating.changers.ExtractedFeaturePostStep
*/
interface IterableLikeAssertions {
//TODO add with 0.14.0
// fun <T : Any, E> iterableLikeContainsBuilder(
// container: AssertionContainer<T>,
// converter: (T) -> Iterable<E>
// ): IterableLikeContains.Builder<T, E, NoOpSearchBehaviour>
//
// fun <T : Any, E> iterableLikeContainsNotBuilder(
// container: AssertionContainer<T>,
// converter: (T) -> Iterable<E>
// ): IterableLikeContains.Builder<T, E, NotSearchBehaviour>
fun <T : Any, E> containsBuilder(
container: AssertionContainer<T>,
converter: (T) -> Iterable<E>
): IterableLikeContains.EntryPointStep<E, T, NoOpSearchBehaviour>
fun <T : Any, E> containsNotBuilder(
container: AssertionContainer<T>,
converter: (T) -> Iterable<E>
): NotCheckerStep<E, T, NotSearchBehaviour>
fun <T : Any, E : Any> all(
container: AssertionContainer<T>,

View File

@@ -1,7 +1,7 @@
package ch.tutteli.atrium.logic.creating.charsequence.contains.steps.impl
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
import ch.tutteli.atrium.logic.creating.basic.contains.checkers.NotChecker
import ch.tutteli.atrium.logic.creating.charsequence.contains.checkers.NotChecker
import ch.tutteli.atrium.logic.creating.charsequence.contains.CharSequenceContains
import ch.tutteli.atrium.logic.creating.charsequence.contains.steps.NotCheckerStep
import ch.tutteli.atrium.logic.creating.charsequence.contains.checkers.impl.DefaultNotChecker

View File

@@ -0,0 +1,105 @@
package ch.tutteli.atrium.logic.creating.iterable.contains
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.basic.contains.Contains
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains.*
import ch.tutteli.atrium.logic.creating.iterable.contains.creators.IterableLikeContainsAssertions
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.impl.EntryPointStepImpl
import ch.tutteli.atrium.reporting.translating.Translatable
/**
* Defines the contract for sophisticated [Iterable] contains assertion builders.
*
* The building process is typically started by the creation of a [EntryPointStep],
* goes on by specifying a desired [SearchBehaviour],
* defines which [Checker]s should be applied and
* is finalized by one of the [IterableLikeContainsAssertions] which usually use a [Creator].
*/
interface IterableLikeContains {
/**
* The entry point of the contract.
*
* Use `_logic` to retrieve the [EntryPointStepLogic] counterpart in case you want to extend the building process.
*/
interface EntryPointStep<E, T : IterableLike, out S : SearchBehaviour> : Contains.EntryPointStep<T, S>
/**
* The entry point of the contract on the logic level, containing the [container] -- i.e. the subject of the assertion
* for which the sophisticated `contain` assertion should be created -- as well as the chosen [searchBehaviour].
*
* The [searchBehaviour] might me modified in which case it is recommended that a new [EntryPointStep] is created (retain
* immutability).
*/
interface EntryPointStepLogic<E, T : IterableLike, out S : SearchBehaviour> : Contains.EntryPointStepLogic<T, S> {
/**
* The converter which shall be used to turn the subject of the assertion into an [Iterable] of type [E].
*/
val converter: (T) -> Iterable<E>
fun <S2: SearchBehaviour> withSearchBehaviour(searchBehaviour: S2) : EntryPointStep<E, T, S2> =
EntryPointStepImpl(container, converter, searchBehaviour)
}
/**
* Sole purpose of this interface is to hide [EntryPointStepLogic] from newcomers which
* usually do not have to deal with this type and to keep the API clean.
*
* Moreover, this keeps the API clean and does not pollute it with things like `times`, `containsBuilder` etc.
*
* See https://github.com/robstoll/atrium-roadmap/wiki/Requirements#personas for more information about the personas.
*/
interface EntryPointStepInternal<E, T : IterableLike, out S : SearchBehaviour> :
EntryPointStep<E, T, S>,
EntryPointStepLogic<E, T, S>
/**
* The step of choosing/defining [Checker]s.
*/
interface CheckerStep<E, T : IterableLike, out S : SearchBehaviour>
: Contains.CheckerStep<T, S, Checker, EntryPointStep<E, T, S>>
/**
* The step of choosing/defining [Checker]s on the logic level.
*/
interface CheckerStepLogic<E, T : IterableLike, out S : SearchBehaviour>
: Contains.CheckerStepLogic<T, S, Checker, EntryPointStepLogic<E, T, S>>
/**
* Sole purpose of this interface is to hide [CheckerStepLogic] from newcomers which
* usually don't have to deal with this type and to keep the API clean.
*
* Moreover, this keeps the API clean and does not pollute it with things like `times`, `containsBuilder` etc.
*
* See https://github.com/robstoll/atrium-roadmap/wiki/Requirements#personas for more information about the personas.
*/
interface CheckerStepInternal<E, T : IterableLike, out S : SearchBehaviour> :
CheckerStep<E, T, S>,
CheckerStepLogic<E, T, S>
/**
* Represents a search behaviour but leaves it up to the [Creator] how this behaviour is implemented -- yet, it
* provides a method to decorate a description (a [Translatable]) in order that it reflects the search behaviour.
*/
interface SearchBehaviour : Contains.SearchBehaviour
/**
* Represents the final step of a sophisticated `contains` assertion builder which creates the [AssertionGroup]
* as such.
*
* @param T The type of the subject of the assertion.
* @param SC The type of the search criteria.
*/
interface Creator<T : IterableLike, in SC> : Contains.Creator<T, SC>
/**
* Represents a check for the search result such as:
* the object is contained exactly once in the input of the search.
*
* It provides the method [createAssertion] which creates an [Assertion] representing this check.
*/
interface Checker : Contains.Checker
}

View File

@@ -0,0 +1,10 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.checkers
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
/**
* Represents a check that an expected search criterion is contained at least [times] in the search input.
*/
interface AtLeastChecker :
ch.tutteli.atrium.logic.creating.basic.contains.checkers.AtLeastChecker,
IterableLikeContains.Checker

View File

@@ -0,0 +1,10 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.checkers
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
/**
* Represents a check that an expected search criterion is contained at most [times] in the search input.
*/
interface AtMostChecker :
ch.tutteli.atrium.logic.creating.basic.contains.checkers.AtMostChecker,
IterableLikeContains.Checker

View File

@@ -0,0 +1,10 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.checkers
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
/**
* Represents a check that an expected search criterion is contained exactly [times] in the search input.
*/
interface ExactlyChecker :
ch.tutteli.atrium.logic.creating.basic.contains.checkers.ExactlyChecker,
IterableLikeContains.Checker

View File

@@ -0,0 +1,10 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.checkers
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
/**
* Represents a check that an expected search criterion is not contained in the search input.
*/
interface NotChecker :
ch.tutteli.atrium.logic.creating.basic.contains.checkers.NotChecker,
IterableLikeContains.Checker

View File

@@ -0,0 +1,25 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.checkers.impl
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.logic.creating.basic.contains.checkers.impl.ContainsChecker
import ch.tutteli.atrium.logic.creating.iterable.contains.checkers.AtLeastChecker
import ch.tutteli.atrium.translations.DescriptionIterableAssertion
/**
* Represents a check that an expected entry is contained at least [times] in the [Iterable].
*
* @param times The number which the check uses to compare against the actual number of times an expected object is
* found in the [Iterable].
* @param nameContainsNotFun The function which should be used instead of `atLeastCall` when [times] equals to zero.
* @param atLeastCall The function which was used and should not be used if [times] equals to zero.
* @throws IllegalArgumentException In case [times] is smaller than 1.
*/
class DefaultAtLeastChecker(
times: Int,
override val nameContainsNotFun: String,
override val atLeastCall: (Int) -> String
) : AtLeastChecker, ContainsChecker(times, nameContainsNotFun, atLeastCall) {
override fun createAssertion(foundNumberOfTimes: Int): Assertion =
createDescriptiveAssertion(DescriptionIterableAssertion.AT_LEAST) { foundNumberOfTimes >= times }
}

View File

@@ -0,0 +1,26 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.checkers.impl
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.logic.creating.basic.contains.checkers.impl.ContainsChecker
import ch.tutteli.atrium.logic.creating.iterable.contains.checkers.AtMostChecker
import ch.tutteli.atrium.translations.DescriptionIterableAssertion
/**
* Represents a check that an expected entry is contained at most [times] in the [Iterable].
*
* @param times The number which the check uses to compare against the actual number of times an expected entry is
* found in the [Iterable].
* @param nameContainsNotFun The function which should be used instead of `atMostCall` when [times] equals to zero.
* @param atMostCall The function which was used and should not be used if [times] equals to zero.
*
* @throws IllegalArgumentException In case [times] is smaller than 1.
*/
class DefaultAtMostChecker(
times: Int,
override val nameContainsNotFun: String,
override val atMostCall: (Int) -> String
) : AtMostChecker, ContainsChecker(times, nameContainsNotFun, atMostCall) {
override fun createAssertion(foundNumberOfTimes: Int): Assertion =
createDescriptiveAssertion(DescriptionIterableAssertion.AT_MOST) { foundNumberOfTimes <= times }
}

View File

@@ -0,0 +1,26 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.checkers.impl
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.logic.creating.basic.contains.checkers.impl.ContainsChecker
import ch.tutteli.atrium.logic.creating.iterable.contains.checkers.ExactlyChecker
import ch.tutteli.atrium.translations.DescriptionIterableAssertion
/**
* Represents a check that an expected entry is contained exactly [times] in the [Iterable].
*
* @param times The number which the check uses to compare against the actual number of times an expected entry is
* found in the [Iterable].
* @param nameContainsNotFun The function which should be used instead of `exactlyCall` when [times] equals to zero.
* @param exactlyCall The function call which was used and should not be used if [times] equals to zero.
*
* @throws IllegalArgumentException In case [times] is smaller than 1.
*/
class DefaultExactlyChecker(
times: Int,
override val nameContainsNotFun: String,
override val exactlyCall: (Int) -> String
) : ExactlyChecker, ContainsChecker(times, nameContainsNotFun, exactlyCall) {
override fun createAssertion(foundNumberOfTimes: Int): Assertion =
createDescriptiveAssertion(DescriptionIterableAssertion.EXACTLY) { foundNumberOfTimes == times }
}

View File

@@ -0,0 +1,15 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.checkers.impl
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.assertions.builders.assertionBuilder
import ch.tutteli.atrium.logic.creating.iterable.contains.checkers.NotChecker
import ch.tutteli.atrium.translations.DescriptionBasic
/**
* Represents a check that an expected entry is not contained in the [Iterable].
*/
class DefaultNotChecker : NotChecker {
override fun createAssertion(foundNumberOfTimes: Int): Assertion =
assertionBuilder.createDescriptive(DescriptionBasic.IS, 0) { foundNumberOfTimes == 0 }
}

View File

@@ -0,0 +1,50 @@
@file:Suppress("DEPRECATION" /* TODO remove annotation with 1.0.0 */)
package ch.tutteli.atrium.logic.creating.iterable.contains.creators
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InAnyOrderOnlySearchBehaviour
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InOrderOnlyGroupedSearchBehaviour
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InOrderOnlySearchBehaviour
/**
* Defines the minimum set of `contains` assertion functions for [Iterable],
* which an implementation of the domain of Atrium has to provide.
*/
interface IterableLikeContainsAssertions {
fun <E, T : IterableLike> valuesInAnyOrderOnly(
entryPointStepLogic: IterableLikeContains.EntryPointStepLogic<E, T, InAnyOrderOnlySearchBehaviour>,
expected: List<E>
): Assertion
fun <E : Any, T : IterableLike> entriesInAnyOrderOnly(
entryPointStepLogic: IterableLikeContains.EntryPointStepLogic<out E?, T, InAnyOrderOnlySearchBehaviour>,
assertionCreators: List<(Expect<E>.() -> Unit)?>
): Assertion
fun <E, T : IterableLike> valuesInOrderOnly(
entryPointStepLogic: IterableLikeContains.EntryPointStepLogic<E, T, InOrderOnlySearchBehaviour>,
expected: List<E>
): Assertion
fun <E : Any, T : IterableLike> entriesInOrderOnly(
entryPointStepLogic: IterableLikeContains.EntryPointStepLogic<out E?, T, InOrderOnlySearchBehaviour>,
assertionCreators: List<(Expect<E>.() -> Unit)?>
): Assertion
fun <E, T : IterableLike> valuesInOrderOnlyGrouped(
entryPointStepLogic: IterableLikeContains.EntryPointStepLogic<E, T, InOrderOnlyGroupedSearchBehaviour>,
groups: List<List<E>>
): Assertion
fun <E : Any, T : IterableLike> entriesInOrderOnlyGrouped(
entryPointStepLogic: IterableLikeContains.EntryPointStepLogic<out E?, T, InOrderOnlyGroupedSearchBehaviour>,
groups: List<List<(Expect<E>.() -> Unit)?>>
): Assertion
}

View File

@@ -0,0 +1,26 @@
@file:Suppress("DEPRECATION" /* TODO remove annotation with 1.0.0 */)
package ch.tutteli.atrium.logic.creating.iterable.contains.creators
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour
/**
* Defines the minimum set of `contains` assertion functions for [Iterable],
* which an implementation of the domain of Atrium has to provide.
*/
interface IterableLikeContainsInAnyOrderAssertions {
fun <E, T : IterableLike> values(
checkerStepLogic: IterableLikeContains.CheckerStepLogic<E, T, InAnyOrderSearchBehaviour>,
expected: List<E>
): Assertion
fun <E : Any, T : IterableLike> entries(
checkerStepLogic: IterableLikeContains.CheckerStepLogic<out E?, T, InAnyOrderSearchBehaviour>,
assertionCreators: List<(Expect<E>.() -> Unit)?>
): Assertion
}

View File

@@ -0,0 +1,64 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.creators.impl
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.creators.IterableLikeContainsAssertions
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InAnyOrderOnlySearchBehaviour
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InOrderOnlyGroupedSearchBehaviour
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InOrderOnlySearchBehaviour
class DefaultIterableLikeContainsAssertions : IterableLikeContainsAssertions {
override fun <E, T : IterableLike> valuesInAnyOrderOnly(
entryPointStepLogic: IterableLikeContains.EntryPointStepLogic<E, T, InAnyOrderOnlySearchBehaviour>,
expected: List<E>
): Assertion =
createAssertionGroupWithoutChecker(entryPointStepLogic, expected, ::InAnyOrderOnlyValuesAssertionCreator)
override fun <E : Any, T : IterableLike> entriesInAnyOrderOnly(
entryPointStepLogic: IterableLikeContains.EntryPointStepLogic<out E?, T, InAnyOrderOnlySearchBehaviour>,
assertionCreators: List<(Expect<E>.() -> Unit)?>
): Assertion = createAssertionGroupWithoutChecker(
entryPointStepLogic, assertionCreators, ::InAnyOrderOnlyEntriesAssertionCreator
)
override fun <E, T : IterableLike> valuesInOrderOnly(
entryPointStepLogic: IterableLikeContains.EntryPointStepLogic<E, T, InOrderOnlySearchBehaviour>,
expected: List<E>
): Assertion =
createAssertionGroupWithoutChecker(entryPointStepLogic, expected, ::InOrderOnlyValuesAssertionCreator)
override fun <E : Any, T : IterableLike> entriesInOrderOnly(
entryPointStepLogic: IterableLikeContains.EntryPointStepLogic<out E?, T, InOrderOnlySearchBehaviour>,
assertionCreators: List<(Expect<E>.() -> Unit)?>
): Assertion = createAssertionGroupWithoutChecker(
entryPointStepLogic, assertionCreators, ::InOrderOnlyEntriesAssertionCreator
)
override fun <E, T : IterableLike> valuesInOrderOnlyGrouped(
entryPointStepLogic: IterableLikeContains.EntryPointStepLogic<E, T, InOrderOnlyGroupedSearchBehaviour>,
groups: List<List<E>>
): Assertion = createAssertionGroupWithoutChecker(
entryPointStepLogic, groups, ::InOrderOnlyGroupedValuesAssertionCreator
)
override fun <E : Any, T : IterableLike> entriesInOrderOnlyGrouped(
entryPointStepLogic: IterableLikeContains.EntryPointStepLogic<out E?, T, InOrderOnlyGroupedSearchBehaviour>,
groups: List<List<(Expect<E>.() -> Unit)?>>
): Assertion = createAssertionGroupWithoutChecker(
entryPointStepLogic, groups, ::InOrderOnlyGroupedEntriesAssertionCreator
)
private fun <E, T : IterableLike, SC, S : IterableLikeContains.SearchBehaviour> createAssertionGroupWithoutChecker(
entryPointStepLogic: IterableLikeContains.EntryPointStepLogic<E, T, S>,
expected: List<SC>,
factory: ((T) -> Iterable<E>, S) -> IterableLikeContains.Creator<T, SC>
): AssertionGroup {
val creator = factory(entryPointStepLogic.converter, entryPointStepLogic.searchBehaviour)
return creator.createAssertionGroup(entryPointStepLogic.container, expected)
}
}

View File

@@ -0,0 +1,30 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.creators.impl
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.creators.IterableLikeContainsInAnyOrderAssertions
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour
class DefaultIterableLikeContainsInAnyOrderAssertions : IterableLikeContainsInAnyOrderAssertions {
override fun <E, T : IterableLike> values(
checkerStepLogic: IterableLikeContains.CheckerStepLogic<E, T, InAnyOrderSearchBehaviour>,
expected: List<E>
): Assertion = createAssertionGroup(checkerStepLogic, expected, ::InAnyOrderValuesAssertionCreator)
override fun <E : Any, T : IterableLike> entries(
checkerStepLogic: IterableLikeContains.CheckerStepLogic<out E?, T, InAnyOrderSearchBehaviour>,
assertionCreators: List<(Expect<E>.() -> Unit)?>
): Assertion = createAssertionGroup(checkerStepLogic, assertionCreators, ::InAnyOrderEntriesAssertionCreator)
private fun <E, T : IterableLike, SC, S : IterableLikeContains.SearchBehaviour> createAssertionGroup(
checkerStepLogic: IterableLikeContains.CheckerStepLogic<E, T, S>,
expected: List<SC>,
factory: ((T) -> Iterable<E>, S, List<IterableLikeContains.Checker>) -> IterableLikeContains.Creator<T, SC>
): AssertionGroup {
val creator = factory(checkerStepLogic.entryPointStepLogic.converter, checkerStepLogic.entryPointStepLogic.searchBehaviour, checkerStepLogic.checkers)
return creator.createAssertionGroup(checkerStepLogic.entryPointStepLogic.container, expected)
}
}

View File

@@ -0,0 +1,130 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.creators.impl
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.assertions.DefaultListAssertionGroupType
import ch.tutteli.atrium.assertions.DefaultSummaryAssertionGroupType
import ch.tutteli.atrium.assertions.builders.assertionBuilder
import ch.tutteli.atrium.core.None
import ch.tutteli.atrium.core.Some
import ch.tutteli.atrium.core.getOrElse
import ch.tutteli.atrium.creating.CollectingExpect
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.creating.AssertionContainer
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.basic.contains.creators.impl.ContainsAssertionCreator
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.NotSearchBehaviour
import ch.tutteli.atrium.logic.impl.allCreatedAssertionsHold
import ch.tutteli.atrium.logic.impl.createExplanatoryAssertionGroup
import ch.tutteli.atrium.logic.impl.createHasElementAssertion
import ch.tutteli.atrium.reporting.translating.Translatable
import ch.tutteli.atrium.translations.DescriptionIterableAssertion
import ch.tutteli.atrium.translations.DescriptionIterableAssertion.AN_ENTRY_WHICH
/**
* Represents a creator of a sophisticated `contains` assertions for [Iterable] where an expected entry can appear
* in any order and is identified by holding a group of assertions, created by an assertion creator lambda.
*
* @param T The type of the subject of the assertion for which the `contains` assertion is be build.
*
* @property searchBehaviour The search behaviour -- in this case representing `in any order` which is used to
* decorate the description (a [Translatable]) which is used for the [AssertionGroup].
*
* @constructor Represents a creator of a sophisticated `contains` assertions for [Iterable] where expected entries
* can appear in any order and are identified by holding a group of assertions, created by an assertion
* creator lambda.
* @param searchBehaviour The search behaviour -- in this case representing `in any order` which is used to
* decorate the description (a [Translatable]) which is used for the [AssertionGroup].
* @param checkers The checkers which create assertions based on the search result.
*/
class InAnyOrderEntriesAssertionCreator<E : Any, T : IterableLike>(
private val converter: (T) -> Iterable<E?>,
searchBehaviour: InAnyOrderSearchBehaviour,
checkers: List<IterableLikeContains.Checker>
) : ContainsAssertionCreator<T, List<E?>, (Expect<E>.() -> Unit)?, IterableLikeContains.Checker>(searchBehaviour, checkers),
IterableLikeContains.Creator<T, (Expect<E>.() -> Unit)?> {
override val descriptionContains: Translatable = DescriptionIterableAssertion.CONTAINS
override fun makeSubjectMultipleTimesConsumable(container: AssertionContainer<T>): AssertionContainer<List<E?>> =
turnSubjectToList(container, converter)
override fun searchAndCreateAssertion(
multiConsumableContainer: AssertionContainer<List<E?>>,
searchCriterion: (Expect<E>.() -> Unit)?,
featureFactory: (Int, Translatable) -> AssertionGroup
): AssertionGroup {
val iterator = multiConsumableContainer.maybeSubject.getOrElse { emptyList() }.iterator()
val hasElementAssertion = createHasElementAssertion(iterator)
val (explanatoryGroup, count) =
createExplanatoryAssertionsAndMatchingCount(iterator, searchCriterion)
val featureAssertion = featureFactory(count, DescriptionIterableAssertion.NUMBER_OF_OCCURRENCES)
val assertions = mutableListOf<Assertion>(explanatoryGroup, featureAssertion)
val groupType = if (searchBehaviour is NotSearchBehaviour) {
assertions.add(hasElementAssertion)
addEmptyAssertionCreatorLambdaIfNecessary(assertions, searchCriterion, count)
DefaultSummaryAssertionGroupType
} else {
DefaultListAssertionGroupType
}
return assertionBuilder.customType(groupType)
.withDescriptionAndEmptyRepresentation(AN_ENTRY_WHICH)
.withAssertions(assertions)
.build()
}
private fun createExplanatoryAssertionsAndMatchingCount(
itr: Iterator<E?>,
assertionCreatorOrNull: (Expect<E>.() -> Unit)?
): Pair<AssertionGroup, Int> {
val (firstNonNullOrNull, sequence) = if (itr.hasNext() && assertionCreatorOrNull != null) {
// we search the first non-null element in order that feature assertions
// which are based on the subject can be showed properly in the explanation
getFirstNonNullAndSequence(itr, sequenceOf())
} else {
null to itr.asSequence()
}
val group =
createExplanatoryAssertionGroup(assertionCreatorOrNull) { firstNonNullOrNull?.let { Some(it) } ?: None }
val count = sequence.count { allCreatedAssertionsHold(it, assertionCreatorOrNull) }
return group to count
}
private tailrec fun getFirstNonNullAndSequence(itr: Iterator<E?>, sequence: Sequence<E?>): Pair<E?, Sequence<E?>> {
return if (itr.hasNext()) {
val first = itr.next()
if (first != null) {
first to sequence + sequenceOf(first) + itr.asSequence()
} else {
getFirstNonNullAndSequence(itr, sequence + sequenceOf(first))
}
} else {
null to sequence
}
}
private fun addEmptyAssertionCreatorLambdaIfNecessary(
assertions: MutableList<Assertion>,
searchCriterion: (Expect<E>.() -> Unit)?,
count: Int
) {
if (searchCriterion != null && count == 0) {
val collectingExpect = CollectingExpect<E>(None)
// not using addAssertionsCreatedBy on purpose so that we don't append a failing assertion
collectingExpect.searchCriterion()
val collectedAssertions = collectingExpect.getAssertions()
if (collectedAssertions.isEmpty()) {
assertions.addAll(
CollectingExpect<E>(None)
.addAssertionsCreatedBy(searchCriterion)
.getAssertions()
)
}
}
}
}

View File

@@ -0,0 +1,130 @@
//TODO remove with 1.0.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.logic.creating.iterable.contains.creators.impl
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.assertions.builders.assertionBuilder
import ch.tutteli.atrium.assertions.builders.invisibleGroup
import ch.tutteli.atrium.creating.AssertionContainer
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InAnyOrderOnlySearchBehaviour
import ch.tutteli.atrium.logic.impl.assertions.LazyThreadUnsafeAssertionGroup
import ch.tutteli.atrium.reporting.Text
import ch.tutteli.atrium.reporting.translating.Translatable
import ch.tutteli.atrium.reporting.translating.Untranslatable
import ch.tutteli.atrium.translations.DescriptionAnyAssertion.TO_BE
import ch.tutteli.atrium.translations.DescriptionIterableAssertion
import ch.tutteli.atrium.translations.DescriptionIterableAssertion.*
/**
* Represents the base class for `in any order only` assertion creators and provides a corresponding template to fulfill
* its responsibility.
*
* @param E The type of the elements of the [Iterable] the [converter] is going to create.
* @param T The type of the subject of the assertion for which the `contains` assertion is be build.
* @param SC The type of the search criteria.
*
* @property searchBehaviour The search behaviour -- in this case representing `in any order only` which is used to
* decorate the description (a [Translatable]) which is used for the [AssertionGroup].
*
* @constructor Represents the base class for `in any order only` assertion creators and provides a corresponding
* template to fulfill its responsibility.
* @param searchBehaviour The search behaviour -- in this case representing `in any order only` which is used to
* decorate the description (a [Translatable]) which is used for the [AssertionGroup].
*/
abstract class InAnyOrderOnlyAssertionCreator<E, T : IterableLike, in SC>(
private val converter: (T) -> Iterable<E>,
private val searchBehaviour: InAnyOrderOnlySearchBehaviour
) : IterableLikeContains.Creator<T, SC> {
final override fun createAssertionGroup(
container: AssertionContainer<T>,
searchCriteria: List<SC>
): AssertionGroup {
return LazyThreadUnsafeAssertionGroup {
val list = container.maybeSubject.fold({ mutableListOf<E?>() }) { converter(it).toMutableList() }
val actualSize = list.size
val assertions = mutableListOf<Assertion>()
val mismatches = createAssertionsForAllSearchCriteria(searchCriteria, list, assertions)
val featureAssertions = createSizeFeatureAssertion(searchCriteria, actualSize)
if (mismatches == 0 && list.isNotEmpty()) {
featureAssertions.add(LazyThreadUnsafeAssertionGroup {
createExplanatoryGroupForMismatchesEtc(list, WARNING_ADDITIONAL_ENTRIES)
})
}
assertions.add(
assertionBuilder.feature
.withDescriptionAndRepresentation(Untranslatable("size"), Text(actualSize.toString()))
.withAssertions(featureAssertions)
.build()
)
val description = searchBehaviour.decorateDescription(CONTAINS)
val summary = assertionBuilder.summary
.withDescription(description)
.withAssertions(assertions)
.build()
if (mismatches != 0 && list.isNotEmpty()) {
val warningDescription = when (list.size) {
mismatches -> WARNING_MISMATCHES
else -> WARNING_MISMATCHES_ADDITIONAL_ENTRIES
}
assertionBuilder.invisibleGroup
.withAssertions(
summary,
createExplanatoryGroupForMismatchesEtc(list, warningDescription)
)
.build()
} else {
summary
}
}
}
private fun createAssertionsForAllSearchCriteria(
allSearchCriteria: List<SC>,
list: MutableList<E?>,
assertions: MutableList<Assertion>
): Int {
var mismatches = 0
allSearchCriteria.forEach {
val (found, assertion) = createAssertionForSearchCriterionAndRemoveMatchFromList(it, list)
if (!found) ++mismatches
assertions.add(assertion)
}
return mismatches
}
protected abstract fun createAssertionForSearchCriterionAndRemoveMatchFromList(
searchCriterion: SC,
list: MutableList<E?>
): Pair<Boolean, Assertion>
private fun createSizeFeatureAssertion(allSearchCriteria: List<SC>, actualSize: Int): MutableList<Assertion> =
mutableListOf(
assertionBuilder.descriptive
.withTest { actualSize == allSearchCriteria.size }
.withDescriptionAndRepresentation(TO_BE, Text(allSearchCriteria.size.toString()))
.build()
)
private fun createExplanatoryGroupForMismatchesEtc(
list: MutableList<E?>,
warning: DescriptionIterableAssertion
): AssertionGroup {
val assertions = list.map { assertionBuilder.explanatory.withExplanation(it).build() }
val additionalEntries = assertionBuilder.list
.withDescriptionAndEmptyRepresentation(warning)
.withAssertions(assertions)
.build()
return assertionBuilder.explanatoryGroup
.withWarningType
.withAssertion(additionalEntries)
.build()
}
}

View File

@@ -0,0 +1,51 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.creators.impl
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InAnyOrderOnlySearchBehaviour
import ch.tutteli.atrium.logic.impl.allCreatedAssertionsHold
import ch.tutteli.atrium.logic.impl.createEntryAssertion
import ch.tutteli.atrium.logic.impl.createExplanatoryAssertionGroup
import ch.tutteli.atrium.reporting.translating.Translatable
/**
* Represents a creator of a sophisticated `contains` assertions for [Iterable] where exactly the expected entries have
* to appear in the [Iterable] but in any order -- an entry is identified by holding a group of assertions
* created by an assertion creator lambda.
*
* @param E The type of the elements of the [Iterable] the [converter] is going to create.
* @param T The type of the subject of the assertion for which the `contains` assertion is be build.
*
* @constructor Represents a creator of a sophisticated `contains` assertions for [Iterable] where exactly the expected
* entries have to appear in the [Iterable] but in any order -- an entry is identified by holding a group
* of assertions created by an assertion creator lambda.
* @param searchBehaviour The search behaviour -- in this case representing `in any order only` which is used to
* decorate the description (a [Translatable]) which is used for the [AssertionGroup].
*/
class InAnyOrderOnlyEntriesAssertionCreator<E : Any, T : IterableLike>(
converter: (T) -> Iterable<E?>,
searchBehaviour: InAnyOrderOnlySearchBehaviour
) : InAnyOrderOnlyAssertionCreator<E?, T, (Expect<E>.() -> Unit)?>(converter, searchBehaviour) {
override fun createAssertionForSearchCriterionAndRemoveMatchFromList(
searchCriterion: (Expect<E>.() -> Unit)?,
list: MutableList<E?>
): Pair<Boolean, Assertion> {
val explanatoryAssertions = createExplanatoryAssertionGroup(searchCriterion, list)
val found = removeMatch(list, searchCriterion)
return found to createEntryAssertion(explanatoryAssertions, found)
}
private fun removeMatch(list: MutableList<E?>, assertionCreator: (Expect<E>.() -> Unit)?): Boolean {
val itr = list.iterator()
while (itr.hasNext()) {
if (allCreatedAssertionsHold(itr.next(), assertionCreator)) {
itr.remove()
return true
}
}
return false
}
}

View File

@@ -0,0 +1,35 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.creators.impl
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.assertions.builders.assertionBuilder
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InAnyOrderOnlySearchBehaviour
import ch.tutteli.atrium.reporting.translating.Translatable
import ch.tutteli.atrium.translations.DescriptionIterableAssertion.AN_ENTRY_WHICH_IS
/**
* Represents a creator of a sophisticated `contains` assertions for [Iterable] where exactly the expected entries have
* to appear in the [Iterable] but in any order -- an entry is identified by an expected object (equality comparison).
*
* @param T The type of the subject of the assertion for which the `contains` assertion is be build.
*
* @constructor Represents a creator of a sophisticated `contains` assertions for [Iterable] where exactly the expected
* entries have to appear in the [Iterable] but in any order -- an entry is identified by an expected
* object (equality comparison).
* @param searchBehaviour The search behaviour -- in this case representing `in any order only` which is used to
* decorate the description (a [Translatable]) which is used for the [AssertionGroup].
*/
class InAnyOrderOnlyValuesAssertionCreator<E, T : IterableLike>(
converter: (T) -> Iterable<E>,
searchBehaviour: InAnyOrderOnlySearchBehaviour
) : InAnyOrderOnlyAssertionCreator<E, T, E>(converter, searchBehaviour) {
override fun createAssertionForSearchCriterionAndRemoveMatchFromList(
searchCriterion: E,
list: MutableList<E?>
): Pair<Boolean, Assertion> {
val found: Boolean = list.remove(searchCriterion)
return found to assertionBuilder.createDescriptive(AN_ENTRY_WHICH_IS, searchCriterion) { found }
}
}

View File

@@ -0,0 +1,68 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.creators.impl
import ch.tutteli.atrium.assertions.*
import ch.tutteli.atrium.core.getOrElse
import ch.tutteli.atrium.creating.AssertionContainer
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.basic.contains.creators.impl.ContainsObjectsAssertionCreator
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.NotSearchBehaviour
import ch.tutteli.atrium.logic.impl.createHasElementAssertion
import ch.tutteli.atrium.reporting.translating.Translatable
import ch.tutteli.atrium.translations.DescriptionIterableAssertion
/**
* Represents a creator of a sophisticated `contains` assertions for [Iterable] where an expected entry can appear
* in any order and is identified by expected objects (equality comparison).
*
* @param T The type of the subject of the assertion for which the `contains` assertion is be build.
* @param SC The type of the elements of the iterable, used as search criteria.
*
* @constructor Represents a creator of a sophisticated `contains` assertions for [Iterable] where expected entries
* can appear in any order and are identified by expected objects (equality comparison).
* @param searchBehaviour The search behaviour -- in this case representing `in any order` which is used to
* decorate the description (a [Translatable]) which is used for the [AssertionGroup].
* @param checkers The checkers which create assertions based on the search result.
*/
class InAnyOrderValuesAssertionCreator<SC, T : IterableLike>(
private val converter: (T) -> Iterable<SC>,
searchBehaviour: InAnyOrderSearchBehaviour,
checkers: List<IterableLikeContains.Checker>
) : ContainsObjectsAssertionCreator<T, List<SC>, SC, InAnyOrderSearchBehaviour, IterableLikeContains.Checker>(
searchBehaviour,
checkers
), IterableLikeContains.Creator<T, SC> {
override val descriptionContains: Translatable = DescriptionIterableAssertion.CONTAINS
override val descriptionNumberOfOccurrences: Translatable = DescriptionIterableAssertion.NUMBER_OF_OCCURRENCES
override val groupDescription: Translatable = DescriptionIterableAssertion.AN_ENTRY_WHICH_IS
override fun getAssertionGroupType(): AssertionGroupType {
return if (searchBehaviour is NotSearchBehaviour) {
DefaultSummaryAssertionGroupType
} else {
DefaultListAssertionGroupType
}
}
override fun makeSubjectMultipleTimesConsumable(container: AssertionContainer<T>): AssertionContainer<List<SC>> =
turnSubjectToList(container, converter)
override fun search(multiConsumableContainer: AssertionContainer<List<SC>>, searchCriterion: SC): Int =
multiConsumableContainer.maybeSubject.fold({ -1 }) { subject -> subject.filter { it == searchCriterion }.size }
override fun decorateAssertion(
container: AssertionContainer<List<SC>>,
featureAssertion: Assertion
): List<Assertion> {
return if (searchBehaviour is NotSearchBehaviour) {
listOf(
featureAssertion,
createHasElementAssertion(container.maybeSubject.getOrElse { emptyList() }.iterator())
)
} else {
listOf(featureAssertion)
}
}
}

View File

@@ -0,0 +1,41 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.creators.impl
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InOrderOnlySearchBehaviour
import ch.tutteli.atrium.reporting.translating.Translatable
import ch.tutteli.atrium.translations.DescriptionIterableAssertion
/**
* Represents the base class for `in order only` assertion creators and provides a corresponding template to fulfill
* its responsibility.
*
* @param T The type of the subject of the assertion for which the `contains` assertion is be build.
* @param SC The type of the search criteria.
*
* @property searchBehaviour The search behaviour -- in this case representing `in order only` which is used to
* decorate the description (a [Translatable]) which is used for the [AssertionGroup].
*
* @constructor Represents the base class for `in any order only` assertion creators and provides a corresponding
* template to fulfill its responsibility.
* @param searchBehaviour The search behaviour -- in this case representing `in order only` which is used to
* decorate the description (a [Translatable]) which is used for the [AssertionGroup].
*/
abstract class InOrderOnlyAssertionCreator<E, T : IterableLike, SC>(
converter: (T) -> Iterable<E>,
searchBehaviour: InOrderOnlySearchBehaviour
) : InOrderOnlyBaseAssertionCreator<E, T, SC>(converter, searchBehaviour),
//TODO use protected visibility once https://youtrack.jetbrains.com/issue/KT-24328 is implemented
InOrderOnlyMatcher<E, SC> {
override fun Expect<List<E>>.createAssertionsAndReturnIndex(searchCriteria: List<SC>): Int {
var index = 0
searchCriteria.forEachIndexed { currentIndex, searchCriterion ->
createSingleEntryAssertion(currentIndex, searchCriterion, DescriptionIterableAssertion.ENTRY_WITH_INDEX)
index = currentIndex
}
++index
return index
}
}

View File

@@ -0,0 +1,91 @@
//TODO remove with 1.0.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.logic.creating.iterable.contains.creators.impl
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.assertions.builders.assertionBuilder
import ch.tutteli.atrium.core.Some
import ch.tutteli.atrium.core.getOrElse
import ch.tutteli.atrium.creating.AssertionContainer
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.creating.collectors.assertionCollector
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic._logic
import ch.tutteli.atrium.logic._logicAppend
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.impl.assertions.LazyThreadUnsafeAssertionGroup
import ch.tutteli.atrium.logic.size
import ch.tutteli.atrium.logic.toBe
import ch.tutteli.atrium.reporting.translating.TranslatableWithArgs
import ch.tutteli.atrium.translations.DescriptionIterableAssertion
import ch.tutteli.kbox.ifWithinBound
import ch.tutteli.kbox.mapRemainingWithCounter
abstract class InOrderOnlyBaseAssertionCreator<E, T : IterableLike, SC>(
private val converter: (T) -> Iterable<E>,
private val searchBehaviour: IterableLikeContains.SearchBehaviour
) : IterableLikeContains.Creator<T, SC> {
final override fun createAssertionGroup(
container: AssertionContainer<T>,
searchCriteria: List<SC>
): AssertionGroup {
return LazyThreadUnsafeAssertionGroup {
val subject = turnSubjectToList(container, converter).maybeSubject.getOrElse { emptyList() }
val assertion = assertionCollector.collect(Some(subject)) {
val index = createAssertionsAndReturnIndex(searchCriteria)
val remainingList = subject.ifWithinBound(index,
{ subject.subList(index, subject.size) },
{ emptyList() }
)
addAssertion(createSizeFeatureAssertionForInOrderOnly(index, subject, remainingList.iterator()))
}
val description = searchBehaviour.decorateDescription(DescriptionIterableAssertion.CONTAINS)
assertionBuilder.summary
.withDescription(description)
.withAssertion(assertion)
.build()
}
}
private fun <E> createSizeFeatureAssertionForInOrderOnly(
expectedSize: Int,
iterableAsList: List<E?>,
itr: Iterator<E?>
): Assertion {
return assertionCollector.collect(Some(iterableAsList)) {
_logic.size().addToInitial {
_logicAppend { toBe(expectedSize) }
if (iterableAsList.size > expectedSize) {
addAssertion(LazyThreadUnsafeAssertionGroup {
val additionalEntries = itr.mapRemainingWithCounter { counter, it ->
val description = TranslatableWithArgs(
DescriptionIterableAssertion.ENTRY_WITH_INDEX,
expectedSize + counter
)
assertionBuilder.descriptive
.holding
.withDescriptionAndRepresentation(description, it)
.build()
}
assertionBuilder.explanatoryGroup
.withWarningType
.withAssertion(
assertionBuilder.list
.withDescriptionAndEmptyRepresentation(DescriptionIterableAssertion.WARNING_ADDITIONAL_ENTRIES)
.withAssertions(additionalEntries)
.build()
)
.build()
})
}
}
}
}
protected abstract fun Expect<List<E>>.createAssertionsAndReturnIndex(searchCriteria: List<SC>): Int
}

View File

@@ -0,0 +1,26 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.creators.impl
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InOrderOnlySearchBehaviour
import ch.tutteli.atrium.reporting.translating.Translatable
/**
* Represents a creator of a sophisticated `contains` assertions for [Iterable] where exactly the expected entries
* have to appear in the specified order and where an entry is identified by holding a group of assertions,
* created by an assertion creator lambda.
*
* @param T The type of the subject of the assertion for which the `contains` assertion is be build.
*
* @constructor Represents a creator of a sophisticated `contains` assertions for [Iterable] where exactly the
* expected entries have to appear in the specified order and where an entry is identified by holding a
* group of assertions, created by an assertion creator lambda.
* @param searchBehaviour The search behaviour -- in this case representing `in any order only` which is used to
* decorate the description (a [Translatable]) which is used for the [AssertionGroup].
*/
class InOrderOnlyEntriesAssertionCreator<E : Any, T : IterableLike>(
converter: (T) -> Iterable<E?>,
searchBehaviour: InOrderOnlySearchBehaviour
) : InOrderOnlyAssertionCreator<E?, T, (Expect<E>.() -> Unit)?>(converter, searchBehaviour),
InOrderOnlyMatcher<E?, (Expect<E>.() -> Unit)?> by InOrderOnlyEntriesMatcher()

View File

@@ -0,0 +1,23 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.creators.impl
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.core.Option
import ch.tutteli.atrium.core.getOrElse
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.logic.impl.allCreatedAssertionsHold
import ch.tutteli.atrium.logic.impl.createEntryAssertion
import ch.tutteli.atrium.logic.impl.createExplanatoryAssertionGroup
class InOrderOnlyEntriesMatcher<E : Any> : InOrderOnlyMatcher<E?, (Expect<E>.() -> Unit)?> {
override fun matches(actual: E?, searchCriterion: (Expect<E>.() -> Unit)?): Boolean =
allCreatedAssertionsHold(actual, searchCriterion)
override fun entryAssertionCreator(
maybeSubject: Option<List<E?>>,
searchCriterion: (Expect<E>.() -> Unit)?
): (() -> Boolean) -> Assertion {
val explanatoryGroup = createExplanatoryAssertionGroup(searchCriterion, maybeSubject.getOrElse { emptyList() })
return { found -> createEntryAssertion(explanatoryGroup, found()) }
}
}

View File

@@ -0,0 +1,65 @@
//TODO remove file with 1.0.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.logic.creating.iterable.contains.creators.impl
import ch.tutteli.atrium.core.Option
import ch.tutteli.atrium.core.getOrElse
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic._logic
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InOrderOnlyGroupedSearchBehaviour
import ch.tutteli.atrium.logic.extractFeature
import ch.tutteli.atrium.reporting.translating.TranslatableWithArgs
import ch.tutteli.atrium.translations.DescriptionIterableAssertion
abstract class InOrderOnlyGroupedAssertionCreator<E, T : IterableLike, SC>(
converter: (T) -> Iterable<E>,
searchBehaviour: InOrderOnlyGroupedSearchBehaviour
) : InOrderOnlyBaseAssertionCreator<E, T, List<SC>>(converter, searchBehaviour),
//TODO use protected visibility once https://youtrack.jetbrains.com/issue/KT-24328 is implemented
InOrderOnlyMatcher<E, SC> {
final override fun Expect<List<E>>.createAssertionsAndReturnIndex(
searchCriteria: List<List<SC>>
): Int {
var index = 0
searchCriteria.forEach { group ->
val currentIndex = index
val untilIndex = index + group.size
if (group.size == 1) {
createSingleEntryAssertion(currentIndex, group[0], DescriptionIterableAssertion.INDEX)
} else {
addSublistAssertion(currentIndex, untilIndex, group, maybeSubject.getOrElse { emptyList() })
}
index = untilIndex
}
return index
}
private fun Expect<List<E>>.addSublistAssertion(
currentIndex: Int,
untilIndex: Int,
groupOfSearchCriteria: List<SC>,
subject: List<E>
) {
_logic.extractFeature
.withDescription(
TranslatableWithArgs(DescriptionIterableAssertion.INDEX_FROM_TO, currentIndex, untilIndex - 1)
)
.withRepresentationForFailure(DescriptionIterableAssertion.SIZE_EXCEEDED)
.withFeatureExtraction {
Option.someIf(currentIndex <= it.size) {
val safeUntilIndex = if (untilIndex < subject.size) untilIndex else subject.size
subject.subList(currentIndex, safeUntilIndex)
}
}
.withoutOptions()
.build()
.addToInitial {
addSublistAssertion(groupOfSearchCriteria)
}
}
protected abstract fun Expect<List<E>>.addSublistAssertion(groupOfSearchCriteria: List<SC>)
}

View File

@@ -0,0 +1,25 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.creators.impl
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic._logic
import ch.tutteli.atrium.logic._logicAppend
import ch.tutteli.atrium.logic.containsBuilder
import ch.tutteli.atrium.logic.creating.iterable.contains.creators.entriesInAnyOrderOnly
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InOrderOnlyGroupedSearchBehaviour
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.inAnyOrder
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.butOnly
import ch.tutteli.kbox.identity
class InOrderOnlyGroupedEntriesAssertionCreator<E : Any, T : IterableLike>(
converter: (T) -> Iterable<E?>,
searchBehaviour: InOrderOnlyGroupedSearchBehaviour
) : InOrderOnlyGroupedAssertionCreator<E?, T, (Expect<E>.() -> Unit)?>(converter, searchBehaviour),
InOrderOnlyMatcher<E?, (Expect<E>.() -> Unit)?> by InOrderOnlyEntriesMatcher() {
override fun Expect<List<E?>>.addSublistAssertion(groupOfSearchCriteria: List<(Expect<E>.() -> Unit)?>) {
_logic.containsBuilder(::identity)._logic.inAnyOrder._logic.butOnly._logicAppend {
entriesInAnyOrderOnly(groupOfSearchCriteria)
}
}
}

View File

@@ -0,0 +1,25 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.creators.impl
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic._logic
import ch.tutteli.atrium.logic._logicAppend
import ch.tutteli.atrium.logic.containsBuilder
import ch.tutteli.atrium.logic.creating.iterable.contains.creators.valuesInAnyOrderOnly
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InOrderOnlyGroupedSearchBehaviour
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.inAnyOrder
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.butOnly
import ch.tutteli.kbox.identity
class InOrderOnlyGroupedValuesAssertionCreator<E, T : IterableLike>(
converter: (T) -> Iterable<E>,
searchBehaviour: InOrderOnlyGroupedSearchBehaviour
) : InOrderOnlyGroupedAssertionCreator<E, T, E>(converter, searchBehaviour),
InOrderOnlyMatcher<E, E> by InOrderOnlyValueMatcher() {
override fun Expect<List<E>>.addSublistAssertion(groupOfSearchCriteria: List<E>) {
_logic.containsBuilder(::identity)._logic.inAnyOrder._logic.butOnly._logicAppend {
valuesInAnyOrderOnly(groupOfSearchCriteria)
}
}
}

View File

@@ -0,0 +1,56 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.creators.impl
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.assertions.builders.assertionBuilder
import ch.tutteli.atrium.core.Option
import ch.tutteli.atrium.core.getOrElse
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.reporting.translating.TranslatableWithArgs
import ch.tutteli.atrium.translations.DescriptionIterableAssertion
import ch.tutteli.kbox.ifWithinBound
interface InOrderOnlyMatcher<E, SC> {
fun matches(actual: E, searchCriterion: SC): Boolean
fun entryAssertionCreator(maybeSubject: Option<List<E>>, searchCriterion: SC): (() -> Boolean) -> Assertion
fun Expect<List<E>>.createSingleEntryAssertion(
currentIndex: Int,
searchCriterion: SC,
translatableIndex: DescriptionIterableAssertion
) {
val template = createEntryAssertionTemplate(
this.maybeSubject,
currentIndex,
searchCriterion,
translatableIndex,
::matches
)
addAssertion(template(entryAssertionCreator(this.maybeSubject, searchCriterion)))
}
private fun <E, SC> createEntryAssertionTemplate(
maybeSubject: Option<List<E>>,
index: Int,
searchCriterion: SC,
entryWithIndex: DescriptionIterableAssertion,
matches: (E, SC) -> Boolean
): ((() -> Boolean) -> Assertion) -> AssertionGroup {
return { createEntryFeatureAssertion ->
val list = maybeSubject.getOrElse { emptyList() }
val (found, entryRepresentation) = list.ifWithinBound(index, {
val entry = list[index]
matches(entry, searchCriterion) to entry
}, {
false to DescriptionIterableAssertion.SIZE_EXCEEDED
})
val description = TranslatableWithArgs(entryWithIndex, index)
assertionBuilder.feature
.withDescriptionAndRepresentation(description, entryRepresentation)
.withAssertion(createEntryFeatureAssertion { found })
.build()
}
}
}

View File

@@ -0,0 +1,18 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.creators.impl
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.assertions.builders.assertionBuilder
import ch.tutteli.atrium.core.Option
import ch.tutteli.atrium.translations.DescriptionAnyAssertion.TO_BE
class InOrderOnlyValueMatcher<E> : InOrderOnlyMatcher<E, E> {
override fun matches(actual: E, searchCriterion: E): Boolean = actual == searchCriterion
override fun entryAssertionCreator(
maybeSubject: Option<List<E>>,
searchCriterion: E
): (() -> Boolean) -> Assertion = { found ->
assertionBuilder.createDescriptive(TO_BE, searchCriterion, found)
}
}

View File

@@ -0,0 +1,26 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.creators.impl
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.creating.SubjectProvider
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InOrderOnlySearchBehaviour
import ch.tutteli.atrium.reporting.translating.Translatable
/**
* Represents a creator of a sophisticated `contains` assertions for [Iterable] where exactly the expected entries
* have to appear in the specified order and where an entry is identified by an expected object (equality comparison).
*
* @param T The type of the [AssertionPlant.subject][SubjectProvider.subject] for which the `contains` assertion is be build.
*
* @constructor Represents a creator of a sophisticated `contains` assertions for [Iterable] where exactly the
* expected entries have to appear in the specified order and where an entry is identified by an
* expected object (equality comparison).
* @param searchBehaviour The search behaviour -- in this case representing `in any order only` which is used to
* decorate the description (a [Translatable]) which is used for the [AssertionGroup].
*/
class InOrderOnlyValuesAssertionCreator<E, T : IterableLike>(
converter: (T) -> Iterable<E>,
searchBehaviour: InOrderOnlySearchBehaviour
) : InOrderOnlyAssertionCreator<E, T, E>(converter, searchBehaviour),
//TODO use protected visibility once https://youtrack.jetbrains.com/issue/KT-24328 is implemented
InOrderOnlyMatcher<E, E> by InOrderOnlyValueMatcher()

View File

@@ -0,0 +1,29 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.creators.impl
import ch.tutteli.atrium.creating.AssertionContainer
import ch.tutteli.atrium.logic.changeSubject
import ch.tutteli.atrium.logic.toAssertionContainer
fun <E, T> turnSubjectToList(
container: AssertionContainer<T>,
converter: (T) -> Iterable<E>
): AssertionContainer<List<E>> =
container.maybeSubject.fold(
{
@Suppress(
// if the subject is not present, then we do not have to make it multiple times consumable and
// can safely cast the subject to List<E>
"UNCHECKED_CAST"
)
container as AssertionContainer<List<E>>
},
{ subject ->
val convertedSubject = converter(subject)
container.changeSubject.unreported {
when (convertedSubject) {
is List<E> -> convertedSubject
else -> convertedSubject.toList()
}
}.toAssertionContainer()
}
)

View File

@@ -0,0 +1,9 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
/**
* Represents the search behaviour that expected entries might appear in any order within the [Iterable] but that
* the resulting assertion should not hold if there are less or more entries than expected.
*/
interface InAnyOrderOnlySearchBehaviour : IterableLikeContains.SearchBehaviour

View File

@@ -0,0 +1,8 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
/**
* Represents the search behaviour that expected entries might appear in any order within the [Iterable].
*/
interface InAnyOrderSearchBehaviour : IterableLikeContains.SearchBehaviour

View File

@@ -0,0 +1,10 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
/**
* Represents the search behaviour that expected entries have to appear in the given order in terms of groups within the
* [Iterable] whereas the entries can be in any order within the group and that the resulting assertion should not hold
* if there are less or more entries than expected.
*/
interface InOrderOnlyGroupedSearchBehaviour : IterableLikeContains.SearchBehaviour

View File

@@ -0,0 +1,7 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours
/**
* Represents a filler step to emphasise that the next step defines the order within a group of a
* [InOrderOnlyGroupedSearchBehaviour].
*/
interface InOrderOnlyGroupedWithinSearchBehaviour : InOrderOnlyGroupedSearchBehaviour

View File

@@ -0,0 +1,9 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
/**
* Represents the search behaviour that expected entries have to appear in the given order within the [Iterable] and
* that the resulting assertion should not hold if there are less or more entries than expected.
*/
interface InOrderOnlySearchBehaviour : IterableLikeContains.SearchBehaviour

View File

@@ -0,0 +1,8 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
/**
* Represents the search behaviour that expected entries have to appear in the given order within the [Iterable].
*/
interface InOrderSearchBehaviour : IterableLikeContains.SearchBehaviour

View File

@@ -0,0 +1,18 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.reporting.translating.Translatable
/**
* Represents the default search behaviour or rather does not define a search behaviour at all.
*
* It furthermore implements a no operation for [decorateDescription], meaning it passes back the description which
* is passed in (identity function).
*/
interface NoOpSearchBehaviour : IterableLikeContains.SearchBehaviour {
/**
* Returns the given [description].
* @return The given [description].
*/
override fun decorateDescription(description: Translatable) = description
}

View File

@@ -0,0 +1,6 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours
/**
* Represents the search behaviour that expected entries might appear in any order within the [Iterable].
*/
interface NotSearchBehaviour : InAnyOrderSearchBehaviour

View File

@@ -0,0 +1,43 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours
import ch.tutteli.atrium.core.polyfills.loadSingleService
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
/**
* The access point to an implementation of [SearchBehaviourFactory].
*
* It loads the implementation lazily via [loadSingleService].
*/
val searchBehaviourFactory by lazy { loadSingleService(SearchBehaviourFactory::class) }
/**
* Defines the minimum set of [IterableLikeContains.SearchBehaviour]s an implementation of the domain of Atrium
* has to provide.
*/
interface SearchBehaviourFactory {
fun <E, T : Iterable<E>> inAnyOrder(
builder: IterableLikeContains.EntryPointStep<E, T, NoOpSearchBehaviour>
): IterableLikeContains.EntryPointStep<E, T, InAnyOrderSearchBehaviour>
fun <E, T : Iterable<E>> inAnyOrderOnly(
builder: IterableLikeContains.EntryPointStep<E, T, InAnyOrderSearchBehaviour>
): IterableLikeContains.EntryPointStep<E, T, InAnyOrderOnlySearchBehaviour>
fun <E, T : Iterable<E>> inOrder(
builder: IterableLikeContains.EntryPointStep<E, T, NoOpSearchBehaviour>
): IterableLikeContains.EntryPointStep<E, T, InOrderSearchBehaviour>
fun <E, T : Iterable<E>> inOrderOnly(
builder: IterableLikeContains.EntryPointStep<E, T, InOrderSearchBehaviour>
): IterableLikeContains.EntryPointStep<E, T, InOrderOnlySearchBehaviour>
fun <E, T : Iterable<E>> inOrderOnlyGrouped(
builder: IterableLikeContains.EntryPointStep<E, T, InOrderOnlySearchBehaviour>
): IterableLikeContains.EntryPointStep<E, T, InOrderOnlyGroupedSearchBehaviour>
fun <E, T : Iterable<E>> inOrderOnlyGroupedWithin(
builder: IterableLikeContains.EntryPointStep<E, T, InOrderOnlyGroupedSearchBehaviour>
): IterableLikeContains.EntryPointStep<E, T, InOrderOnlyGroupedWithinSearchBehaviour>
}

View File

@@ -0,0 +1,11 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.impl
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InAnyOrderOnlySearchBehaviour
import ch.tutteli.atrium.reporting.translating.Translatable
import ch.tutteli.atrium.reporting.translating.TranslatableWithArgs
import ch.tutteli.atrium.translations.DescriptionIterableAssertion
class InAnyOrderOnlySearchBehaviourImpl : InAnyOrderOnlySearchBehaviour {
override fun decorateDescription(description: Translatable): Translatable =
TranslatableWithArgs(DescriptionIterableAssertion.IN_ANY_ORDER_ONLY, description)
}

View File

@@ -0,0 +1,11 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.impl
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour
import ch.tutteli.atrium.reporting.translating.Translatable
import ch.tutteli.atrium.reporting.translating.TranslatableWithArgs
import ch.tutteli.atrium.translations.DescriptionIterableAssertion
class InAnyOrderSearchBehaviourImpl : InAnyOrderSearchBehaviour {
override fun decorateDescription(description: Translatable): Translatable =
TranslatableWithArgs(DescriptionIterableAssertion.IN_ANY_ORDER, description)
}

View File

@@ -0,0 +1,11 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.impl
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InOrderOnlyGroupedSearchBehaviour
import ch.tutteli.atrium.reporting.translating.Translatable
import ch.tutteli.atrium.reporting.translating.TranslatableWithArgs
import ch.tutteli.atrium.translations.DescriptionIterableAssertion
class InOrderOnlyGroupedSearchBehaviourImpl : InOrderOnlyGroupedSearchBehaviour {
override fun decorateDescription(description: Translatable): Translatable =
TranslatableWithArgs(DescriptionIterableAssertion.IN_ORDER_ONLY_GROUPED, description)
}

View File

@@ -0,0 +1,11 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.impl
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InOrderOnlyGroupedWithinSearchBehaviour
import ch.tutteli.atrium.reporting.translating.Translatable
import ch.tutteli.atrium.reporting.translating.TranslatableWithArgs
import ch.tutteli.atrium.translations.DescriptionIterableAssertion
class InOrderOnlyGroupedWithinSearchBehaviourImpl : InOrderOnlyGroupedWithinSearchBehaviour {
override fun decorateDescription(description: Translatable): Translatable =
TranslatableWithArgs(DescriptionIterableAssertion.IN_ORDER_ONLY_GROUPED, description)
}

View File

@@ -0,0 +1,11 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.impl
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InOrderOnlySearchBehaviour
import ch.tutteli.atrium.reporting.translating.Translatable
import ch.tutteli.atrium.reporting.translating.TranslatableWithArgs
import ch.tutteli.atrium.translations.DescriptionIterableAssertion
class InOrderOnlySearchBehaviourImpl : InOrderOnlySearchBehaviour {
override fun decorateDescription(description: Translatable): Translatable =
TranslatableWithArgs(DescriptionIterableAssertion.IN_ORDER_ONLY, description)
}

View File

@@ -0,0 +1,11 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.impl
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.InOrderSearchBehaviour
import ch.tutteli.atrium.reporting.translating.Translatable
import ch.tutteli.atrium.reporting.translating.TranslatableWithArgs
import ch.tutteli.atrium.translations.DescriptionIterableAssertion
class InOrderSearchBehaviourImpl : InOrderSearchBehaviour {
override fun decorateDescription(description: Translatable): Translatable =
TranslatableWithArgs(DescriptionIterableAssertion.IN_ORDER, description)
}

View File

@@ -0,0 +1,5 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.impl
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.NoOpSearchBehaviour
class NoOpSearchBehaviourImpl : NoOpSearchBehaviour

View File

@@ -0,0 +1,11 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.impl
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.NotSearchBehaviour
import ch.tutteli.atrium.reporting.translating.Translatable
import ch.tutteli.atrium.translations.DescriptionIterableAssertion
class NotSearchBehaviourImpl : NotSearchBehaviour {
override fun decorateDescription(description: Translatable): Translatable =
DescriptionIterableAssertion.CONTAINS_NOT
}

View File

@@ -0,0 +1,14 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.steps
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
/**
* Represents the extension point for another step after a `contains at least`-check within a sophisticated
* `contains` assertion building process for [CharSequence].
*
* @param T The input type of the search.
* @param S The search behaviour which should be applied for the input of the search.
*/
interface AtLeastCheckerStep<E, T : IterableLike, out S : IterableLikeContains.SearchBehaviour>
: WithTimesCheckerStep<E, T, S>

View File

@@ -0,0 +1,14 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.steps
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
/**
* Represents the extension point for another step after a `contains at least once but at most`-check within
* a sophisticated `contains` assertion building process for [Iterable].
*
* @param T The input type of the search.
* @param S The search behaviour which should be applied for the input of the search.
*/
interface AtMostCheckerStep<E, T : IterableLike, out S : IterableLikeContains.SearchBehaviour>
: WithTimesCheckerStep<E, T, S>

View File

@@ -0,0 +1,14 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.steps
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
/**
* Represents the extension point for another step after a `contains at least but at most`-check within
* a sophisticated `contains` assertion building process for [Iterable].
*
* @param T The input type of the search.
* @param S The search behaviour which should be applied for the input of the search.
*/
interface ButAtMostCheckerStep<E, T : IterableLike, out S : IterableLikeContains.SearchBehaviour>
: WithTimesCheckerStep<E, T, S>

View File

@@ -0,0 +1,14 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.steps
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
/**
* Represents the extension point for another step after a `contains exactly`-check within
* a sophisticated `contains` assertion building process for [Iterable].
*
* @param T The input type of the search.
* @param S The search behaviour which should be applied for the input of the search.
*/
interface ExactlyCheckerStep<E, T : IterableLike, out S : IterableLikeContains.SearchBehaviour>
: WithTimesCheckerStep<E, T, S>

View File

@@ -0,0 +1,24 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.steps
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.core.polyfills.fullName
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
/**
* Represents a "no [IterableLikeContains.Checker]" option, meaning no checker shall be applied to a search result.
*
* The checking as such is then usually carried out by the [IterableLikeContains.Creator].
*/
class NoOpCheckerStep<E, T : IterableLike, out S : IterableLikeContains.SearchBehaviour>(
override val entryPointStepLogic: IterableLikeContains.EntryPointStepLogic<E, T, S>
) : IterableLikeContains.CheckerStepInternal<E, T, S> {
override val checkers: List<IterableLikeContains.Checker> = listOf(NotIntendedForUseChecker)
private object NotIntendedForUseChecker : IterableLikeContains.Checker {
override fun createAssertion(foundNumberOfTimes: Int): Assertion = throw UnsupportedOperationException(
"You have chosen to use ${NoOpCheckerStep::class.fullName} but are still using its checkers which is not allowed."
)
}
}

View File

@@ -0,0 +1,14 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.steps
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
/**
* Represents the extension point for another step after a `contains not at all`-check within
* a sophisticated `contains` assertion building process for [Iterable].
*
* @param T The input type of the search.
* @param S The search behaviour which should be applied for the input of the search.
*/
interface NotCheckerStep<E, T : IterableLike, out S : IterableLikeContains.SearchBehaviour>
: IterableLikeContains.CheckerStep<E, T, S>

View File

@@ -0,0 +1,14 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.steps
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
/**
* Represents the extension point for another step after a `contains not or at most`-check within
* a sophisticated `contains` assertion building process for [Iterable].
*
* @param T The input type of the search.
* @param S The search behaviour which should be applied for the input of the search.
*/
interface NotOrAtMostCheckerStep<E, T : IterableLike, out S : IterableLikeContains.SearchBehaviour>
: IterableLikeContains.CheckerStep<E, T, S>

View File

@@ -0,0 +1,32 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.steps
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
/**
* A [IterableLikeContains.CheckerStep] which is used to choose
* a [IterableLikeContains.Checker] which is based on a number of `times`.
*/
interface WithTimesCheckerStep<E, T : IterableLike, out S : IterableLikeContains.SearchBehaviour>
: IterableLikeContains.CheckerStep<E, T, S>
/**
* A [IterableLikeContains.CheckerStepLogic] which is used to choose
* a [IterableLikeContains.Checker] which is based on a number of [times].
*/
interface WithTimesCheckerStepLogic<E, T : IterableLike, out S : IterableLikeContains.SearchBehaviour>
: IterableLikeContains.CheckerStepLogic<E, T, S> {
val times: Int
}
/**
* Sole purpose of this interface is to hide [IterableLikeContains.CheckerStepLogic] from newcomers which
* usually don't have to deal with this type and to keep the API clean.
*
* Moreover, this keeps the API clean and does not pollute it with things like `times`, `containsBuilder` etc.
*
* See https://github.com/robstoll/atrium-roadmap/wiki/Requirements#personas for more information about the personas.
*/
interface WithTimesCheckerStepInternal<E, T : IterableLike, out S : IterableLikeContains.SearchBehaviour> :
WithTimesCheckerStep<E, T, S>, WithTimesCheckerStepLogic<E, T, S>,
IterableLikeContains.CheckerStepInternal<E, T, S>

View File

@@ -0,0 +1,33 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.steps.impl
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.basic.contains.checkers.validateAtMost
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.AtMostCheckerStep
internal class AtMostCheckerStepImpl<E, T : IterableLike, out S : IterableLikeContains.SearchBehaviour>(
times: Int,
nameContainsNotFun: String,
atMostCall: (Int) -> String,
atLeastCall: (Int) -> String,
exactlyCall: (Int) -> String,
override val entryPointStepLogic: IterableLikeContains.EntryPointStepLogic<E, T, S>
) : AtMostCheckerStep<E, T, S>, IterableLikeContains.CheckerStepInternal<E, T, S> {
init {
validateAtMost(
times,
atMostCall,
atLeastCall,
exactlyCall
)
}
@Suppress( /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2*/ "DEPRECATION")
@UseExperimental(ExperimentalNewExpectTypes::class)
override val checkers: List<IterableLikeContains.Checker> = listOf<IterableLikeContains.Checker>(
atLeastChecker(entryPointStepLogic.container, 1, nameContainsNotFun, atMostCall),
atMostChecker(entryPointStepLogic.container, times, nameContainsNotFun, atMostCall)
)
}

View File

@@ -0,0 +1,36 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.steps.impl
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.basic.contains.checkers.validateButAtMost
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.ButAtMostCheckerStep
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.WithTimesCheckerStepLogic
internal class ButAtMostCheckerStepImpl<E, T : IterableLike, out S : IterableLikeContains.SearchBehaviour>(
times: Int,
atLeastBuilder: WithTimesCheckerStepLogic<E, T, S>,
nameContainsNotFun: String,
atLeastButAtMostCall: (Int, Int) -> String,
atLeastCall: (Int) -> String,
butAtMostCall: (Int) -> String,
exactlyCall: (Int) -> String,
atMostCall: (Int) -> String,
override val entryPointStepLogic: IterableLikeContains.EntryPointStepLogic<E, T, S>
) : ButAtMostCheckerStep<E, T, S>, IterableLikeContains.CheckerStepInternal<E, T, S> {
init {
validateButAtMost(
atLeastBuilder.times,
times,
atLeastButAtMostCall,
atLeastCall,
butAtMostCall,
exactlyCall
)
}
override val checkers: List<IterableLikeContains.Checker> = listOf(
*atLeastBuilder.checkers.toTypedArray(),
atMostChecker(entryPointStepLogic.container, times, nameContainsNotFun, atMostCall)
)
}

View File

@@ -0,0 +1,12 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.steps.impl
import ch.tutteli.atrium.creating.AssertionContainer
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.basic.contains.steps.impl.EntryPointStepImpl
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
class EntryPointStepImpl<E, T : IterableLike, out S : IterableLikeContains.SearchBehaviour>(
container: AssertionContainer<T>,
override val converter: (T) -> Iterable<E>,
searchBehaviour: S
) : EntryPointStepImpl<T, S>(container, searchBehaviour), IterableLikeContains.EntryPointStepInternal<E, T, S>

View File

@@ -0,0 +1,17 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.steps.impl
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.AtLeastCheckerStep
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.ButAtMostCheckerStep
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.ExactlyCheckerStep
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.WithTimesCheckerStepInternal
internal class GenericTimesCheckerStep<E, T : IterableLike, out S : IterableLikeContains.SearchBehaviour>(
override val times: Int,
override val entryPointStepLogic: IterableLikeContains.EntryPointStepLogic<E, T, S>,
override val checkers: List<IterableLikeContains.Checker>
) : WithTimesCheckerStepInternal<E, T, S>,
AtLeastCheckerStep<E, T, S>,
ButAtMostCheckerStep<E, T, S>,
ExactlyCheckerStep<E, T, S>

View File

@@ -0,0 +1,19 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.steps.impl
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.checkers.NotChecker
import ch.tutteli.atrium.logic.creating.iterable.contains.checkers.impl.DefaultNotChecker
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.NotCheckerStep
internal class NotCheckerStepImpl<E, T : IterableLike, out S : IterableLikeContains.SearchBehaviour>(
override val entryPointStepLogic: IterableLikeContains.EntryPointStepLogic<E, T, S>
) : NotCheckerStep<E, T, S>, IterableLikeContains.CheckerStepInternal<E, T, S> {
@Suppress( /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2*/ "DEPRECATION")
@UseExperimental(ExperimentalNewExpectTypes::class)
override val checkers = listOf(
entryPointStepLogic.container.getImpl<NotChecker>(NotChecker::class) { DefaultNotChecker() }
)
}

View File

@@ -0,0 +1,17 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.steps.impl
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.NotOrAtMostCheckerStep
internal class NotOrAtMostCheckerStepImpl<E, T : IterableLike, out S : IterableLikeContains.SearchBehaviour>(
times: Int,
nameContainsNotFun: String,
notOrAtMostCall: (Int) -> String,
override val entryPointStepLogic: IterableLikeContains.EntryPointStepLogic<E, T, S>
) : NotOrAtMostCheckerStep<E, T, S>, IterableLikeContains.CheckerStepInternal<E, T, S> {
override val checkers = listOf(
atMostChecker(entryPointStepLogic.container, times, nameContainsNotFun, notOrAtMostCall)
)
}

View File

@@ -0,0 +1,31 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.steps.impl
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
import ch.tutteli.atrium.creating.AssertionContainer
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.checkers.AtLeastChecker
import ch.tutteli.atrium.logic.creating.iterable.contains.checkers.AtMostChecker
import ch.tutteli.atrium.logic.creating.iterable.contains.checkers.impl.DefaultAtLeastChecker
import ch.tutteli.atrium.logic.creating.iterable.contains.checkers.impl.DefaultAtMostChecker
@Suppress( /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2*/ "DEPRECATION")
@UseExperimental(ExperimentalNewExpectTypes::class)
fun <T : IterableLike> atLeastChecker(
container: AssertionContainer<T>,
times: Int,
nameContainsNotFun: String,
atLeastCall: (Int) -> String
): AtLeastChecker = container.getImpl(AtLeastChecker::class) {
DefaultAtLeastChecker(times, nameContainsNotFun, atLeastCall)
}
@Suppress( /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2*/ "DEPRECATION")
@UseExperimental(ExperimentalNewExpectTypes::class)
fun <T : IterableLike> atMostChecker(
container: AssertionContainer<T>,
times: Int,
nameContainsNotFun: String,
atMostCall: (Int) -> String
): AtMostChecker = container.getImpl(AtMostChecker::class) {
DefaultAtMostChecker(times, nameContainsNotFun, atMostCall)
}

View File

@@ -0,0 +1,105 @@
package ch.tutteli.atrium.logic.creating.iterable.contains.steps
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
import ch.tutteli.atrium.domain.creating.typeutils.IterableLike
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains.*
import ch.tutteli.atrium.logic.creating.iterable.contains.checkers.ExactlyChecker
import ch.tutteli.atrium.logic.creating.iterable.contains.checkers.impl.DefaultExactlyChecker
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.*
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.impl.*
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.impl.*
fun <E, T : IterableLike, S : SearchBehaviour> EntryPointStepLogic<E, T, S>.atLeastCheckerStep(
times: Int,
nameContainsNotFun: String,
atLeastCall: (Int) -> String
): AtLeastCheckerStep<E, T, S> = GenericTimesCheckerStep(
times,
this,
listOf(atLeastChecker(container, times, nameContainsNotFun, atLeastCall))
)
fun <E, T : IterableLike, S : SearchBehaviour> WithTimesCheckerStepLogic<E, T, S>.butAtMostCheckerStep(
times: Int,
nameContainsNotFun: String,
atLeastButAtMostCall: (Int, Int) -> String,
atLeastCall: (Int) -> String,
butAtMostCall: (Int) -> String,
exactlyCall: (Int) -> String,
atMostCall: (Int) -> String
): ButAtMostCheckerStep<E, T, S> = ButAtMostCheckerStepImpl(
times,
this,
nameContainsNotFun,
atLeastButAtMostCall,
atLeastCall,
butAtMostCall,
exactlyCall,
atMostCall,
entryPointStepLogic
)
fun <E, T : IterableLike, S : SearchBehaviour> EntryPointStepLogic<E, T, S>.atMostCheckerStep(
times: Int,
nameContainsNotFun: String,
atMostCall: (Int) -> String,
atLeastCall: (Int) -> String,
exactlyCall: (Int) -> String
): AtMostCheckerStep<E, T, S> = AtMostCheckerStepImpl(
times,
nameContainsNotFun,
atMostCall,
atLeastCall,
exactlyCall,
this
)
@Suppress(
// unchecked ok as the SearchBehaviour is only relevant during compile time (defines extension point)
"UNCHECKED_CAST",
// OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2
"DEPRECATION"
)
@UseExperimental(ExperimentalNewExpectTypes::class)
fun <E, T : IterableLike, S : SearchBehaviour> EntryPointStepLogic<E, T, S>.exactlyCheckerStep(
times: Int,
nameContainsNotFun: String,
exactlyCall: (Int) -> String
): ExactlyCheckerStep<E, T, S> = GenericTimesCheckerStep(
times,
this,
listOf(container.getImpl(ExactlyChecker::class) { DefaultExactlyChecker(times, nameContainsNotFun, exactlyCall) })
)
fun <E, T : IterableLike, S : SearchBehaviour> EntryPointStepLogic<E, T, S>.notOrAtMostCheckerStep(
times: Int,
nameContainsNotFun: String,
notOrAtMostCall: (Int) -> String
): NotOrAtMostCheckerStep<E, T, S> = NotOrAtMostCheckerStepImpl(
times,
nameContainsNotFun,
notOrAtMostCall,
this
)
fun <E, T : IterableLike, S : SearchBehaviour> EntryPointStepLogic<E, T, S>.notCheckerStep(): NotCheckerStep<E, T, S> =
NotCheckerStepImpl(this)
val <E, T : IterableLike> EntryPointStepLogic<E, T, NoOpSearchBehaviour>.inAnyOrder: EntryPointStep<E, T, InAnyOrderSearchBehaviour>
get() = withSearchBehaviour(InAnyOrderSearchBehaviourImpl())
val <E, T : IterableLike> EntryPointStepLogic<E, T, InAnyOrderSearchBehaviour>.butOnly: EntryPointStep<E, T, InAnyOrderOnlySearchBehaviour>
get() = withSearchBehaviour(InAnyOrderOnlySearchBehaviourImpl())
val <E, T : IterableLike> EntryPointStepLogic<E, T, NoOpSearchBehaviour>.inOrder: EntryPointStep<E, T, InOrderSearchBehaviour>
get() = withSearchBehaviour(InOrderSearchBehaviourImpl())
val <E, T : IterableLike> EntryPointStepLogic<E, T, InOrderSearchBehaviour>.andOnly: EntryPointStep<E, T, InOrderOnlySearchBehaviour>
get() = withSearchBehaviour(InOrderOnlySearchBehaviourImpl())
val <E, T : IterableLike> EntryPointStepLogic<E, T, InOrderOnlySearchBehaviour>.grouped: EntryPointStep<E, T, InOrderOnlyGroupedSearchBehaviour>
get() = withSearchBehaviour(InOrderOnlyGroupedSearchBehaviourImpl())
val <E, T : IterableLike> EntryPointStepLogic<E, T, InOrderOnlyGroupedSearchBehaviour>.within: EntryPointStep<E, T, InOrderOnlyGroupedWithinSearchBehaviour>
get() = withSearchBehaviour(InOrderOnlyGroupedWithinSearchBehaviourImpl())

View File

@@ -4,6 +4,7 @@ import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.assertions.builders.assertionBuilder
import ch.tutteli.atrium.assertions.builders.fixedClaimGroup
import ch.tutteli.atrium.assertions.builders.invisibleGroup
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
import ch.tutteli.atrium.core.Option
import ch.tutteli.atrium.core.falseProvider
import ch.tutteli.atrium.core.getOrElse
@@ -11,6 +12,14 @@ import ch.tutteli.atrium.creating.AssertionContainer
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.creating.changers.ExtractedFeaturePostStep
import ch.tutteli.atrium.logic.*
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.impl.NoOpSearchBehaviourImpl
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.impl.NotSearchBehaviourImpl
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.NotCheckerStep
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.impl.EntryPointStepImpl
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.notCheckerStep
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.NoOpSearchBehaviour
import ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours.NotSearchBehaviour
import ch.tutteli.atrium.logic.impl.assertions.LazyThreadUnsafeAssertionGroup
import ch.tutteli.atrium.reporting.translating.TranslatableWithArgs
import ch.tutteli.atrium.translations.DescriptionBasic
@@ -19,6 +28,17 @@ import ch.tutteli.atrium.translations.DescriptionIterableAssertion.NEXT_ELEMENT
import ch.tutteli.kbox.mapWithIndex
class DefaultIterableLikeAssertions : IterableLikeAssertions {
override fun <T : Any, E> containsBuilder(
container: AssertionContainer<T>,
converter: (T) -> Iterable<E>
): IterableLikeContains.EntryPointStep<E, T, NoOpSearchBehaviour> =
EntryPointStepImpl(container, converter, NoOpSearchBehaviourImpl())
override fun <T : Any, E> containsNotBuilder(
container: AssertionContainer<T>,
converter: (T) -> Iterable<E>
): NotCheckerStep<E, T, NotSearchBehaviour> =
EntryPointStepImpl(container, converter, NotSearchBehaviourImpl())._logic.notCheckerStep()
override fun <T : Any, E : Any> all(
container: AssertionContainer<T>,

View File

@@ -2,6 +2,7 @@ package ch.tutteli.atrium.logic.impl
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.assertions.builders.assertionBuilder
import ch.tutteli.atrium.assertions.builders.fixedClaimGroup
import ch.tutteli.atrium.core.None
import ch.tutteli.atrium.core.Option
import ch.tutteli.atrium.core.Some
@@ -58,3 +59,12 @@ internal inline fun <E : Any> createExplanatoryAssertionGroup(
}
.build()
}
internal fun createEntryAssertion(explanatoryGroup: AssertionGroup, found: Boolean): AssertionGroup {
return assertionBuilder.fixedClaimGroup
.withListType
.withClaim(found)
.withDescriptionAndEmptyRepresentation(DescriptionIterableAssertion.AN_ENTRY_WHICH)
.withAssertion(explanatoryGroup)
.build()
}

View File

@@ -29,9 +29,14 @@ inline val <T : CharSequence, S : CharSequenceContains.SearchBehaviour>
WithTimesCheckerStep<T, S>._logic: WithTimesCheckerStepLogic<T, S>
get() = when (this) {
is WithTimesCheckerStepInternal<T, S> -> this
else -> throw UnsupportedOperationException("Unsupported WithTimesCheckerStep: $this -- please open an issue that a hook shall be implemented: $BUG_REPORT_URL?template=feature_request&title=Hook%20for%20WithTimesCheckerStep._logic")
else -> throw UnsupportedOperationException("Unsupported WithTimesCheckerStep: $this -- please open an issue that a hook shall be implemented: $BUG_REPORT_URL?template=feature_request&title=Hook%20for%20CharSequenceContains%20WithTimesCheckerStep._logic")
}
/**
* Appends the [Assertion] the given [factory] creates based on this [CharSequenceContains.CheckerStep].
*
* Use [_logic] for more sophisticated scenarios.
*/
inline fun <T : CharSequence, S : CharSequenceContains.SearchBehaviour>
CharSequenceContains.CheckerStep<T, S>._logicAppend(factory: CharSequenceContains.CheckerStepLogic<T, S>.() -> Assertion): Expect<T> {
val l = _logic

View File

@@ -0,0 +1,73 @@
@file:Suppress("ObjectPropertyName", "FunctionName")
package ch.tutteli.atrium.logic
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.WithTimesCheckerStep
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.WithTimesCheckerStepInternal
import ch.tutteli.atrium.logic.creating.iterable.contains.steps.WithTimesCheckerStepLogic
//import ch.tutteli.atrium.logic.creating.iterable.contains.steps.WithTimesCheckerStep
//import ch.tutteli.atrium.logic.creating.iterable.contains.steps.WithTimesCheckerStepInternal
//import ch.tutteli.atrium.logic.creating.iterable.contains.steps.WithTimesCheckerStepLogic
import ch.tutteli.atrium.reporting.BUG_REPORT_URL
/**
* Appends the [Assertion] the given [factory] creates based on this [IterableLikeContains.EntryPointStep].
*
* Use [_logic] for more sophisticated scenarios.
*/
inline fun <E, T : Any, S : IterableLikeContains.SearchBehaviour>
IterableLikeContains.EntryPointStep<E, T, S>._logicAppend(factory: IterableLikeContains.EntryPointStepLogic<E, T, S>.() -> Assertion): Expect<T> {
val l = _logic
return l.container.toExpect().addAssertion(l.factory())
}
/**
* Entry point to the logic level of Atrium -- which is one level deeper than the API --
* within the building process of a sophisticated `contains` assertion for [Iterable].
*/
inline val <E, T : Any, S : IterableLikeContains.SearchBehaviour>
IterableLikeContains.EntryPointStep<E, T, S>._logic: IterableLikeContains.EntryPointStepLogic<E, T, S>
get() = when (this) {
is IterableLikeContains.EntryPointStepInternal<E, T, S> -> this
else -> throw UnsupportedOperationException("Unsupported IterableLikeContains.Builder: $this -- please open an issue that a hook shall be implemented: $BUG_REPORT_URL?template=feature_request&title=Hook%20for%20IterableLikeContains.EntryPointStep._logic")
}
/**
* Entry point to the logic level of Atrium -- which is one level deeper than the API --
* within the building process of a sophisticated `contains` assertion for [Iterable].
*
* Use [_logicAppend] in case you want to create and append an [Assertion] to the initial [Expect].
*/
inline val <E, T : Any, S : IterableLikeContains.SearchBehaviour>
WithTimesCheckerStep<E, T, S>._logic: WithTimesCheckerStepLogic<E, T, S>
get() = when (this) {
is WithTimesCheckerStepInternal<E, T, S> -> this
else -> throw UnsupportedOperationException("Unsupported WithTimesCheckerStep: $this -- please open an issue that a hook shall be implemented: $BUG_REPORT_URL?template=feature_request&title=Hook%20for%20IterableLikeContains%20WithTimesCheckerStep._logic")
}
/**
* Appends the [Assertion] the given [factory] creates based on this [IterableLikeContains.CheckerStep].
*
* Use [_logic] for more sophisticated scenarios.
*/
inline fun <E, T : Any, S : IterableLikeContains.SearchBehaviour>
IterableLikeContains.CheckerStep<E, T, S>._logicAppend(factory: IterableLikeContains.CheckerStepLogic<E, T, S>.() -> Assertion): Expect<T> {
val l = _logic
return l.entryPointStepLogic.container.toExpect().addAssertion(l.factory())
}
/**
* Entry point to the logic level of Atrium -- which is one level deeper than the API --
* within the building process of a sophisticated `contains` assertion for [Iterable].
*
* Use [_logicAppend] in case you want to create and append an [Assertion] to the initial [Expect].
*/
inline val <E, T : Any, S : IterableLikeContains.SearchBehaviour>
IterableLikeContains.CheckerStep<E, T, S>._logic: IterableLikeContains.CheckerStepLogic<E, T, S>
get() = when (this) {
is IterableLikeContains.CheckerStepInternal<E, T, S> -> this
else -> throw UnsupportedOperationException("Unsupported IterableLikeContains.CheckerStep: $this -- please open an issue that a hook shall be implemented: $BUG_REPORT_URL?template=feature_request&title=Hook%20for%20IterableLikeContains.CheckerStep._logic")
}

View File

@@ -5,12 +5,19 @@ module ch.tutteli.atrium.logic {
exports ch.tutteli.atrium.logic;
exports ch.tutteli.atrium.logic.creating.basic.contains;
exports ch.tutteli.atrium.logic.creating.charsequence.contains;
exports ch.tutteli.atrium.logic.creating.charsequence.contains.checkers;
exports ch.tutteli.atrium.logic.creating.charsequence.contains.creators;
exports ch.tutteli.atrium.logic.creating.charsequence.contains.searchbehaviours;
exports ch.tutteli.atrium.logic.creating.charsequence.contains.steps;
exports ch.tutteli.atrium.logic.creating.iterable.contains;
exports ch.tutteli.atrium.logic.creating.iterable.contains.checkers;
exports ch.tutteli.atrium.logic.creating.iterable.contains.creators;
exports ch.tutteli.atrium.logic.creating.iterable.contains.searchbehaviours;
exports ch.tutteli.atrium.logic.creating.iterable.contains.steps;
exports ch.tutteli.atrium.logic.impl to ch.tutteli.atrium.logic.kotlin_1_3;
exports ch.tutteli.atrium.logic.impl.creating.changers to ch.tutteli.atrium.logic.kotlin_1_3;
}

View File

@@ -4,10 +4,10 @@ import java.nio.file.Paths
import java.util.regex.Pattern
import java.util.stream.Collectors
static def getInterfaces(String path) {
static List<Path> getInterfaces(String path) {
Files.walk(Paths.get(path), 1).withCloseable { stream ->
return stream
.filter { file -> file.getFileName().toString().endsWith("Assertions.kt") }
.filter { file -> file.fileName.toString().endsWith("Assertions.kt") }
.sorted(new Comparator<Path>() {
@Override
int compare(Path a, Path b) {
@@ -22,39 +22,46 @@ def createGenerateLogicTask(
Project project,
String implsFileName,
String suffix = '',
Map<String, Tuple5<String, String, String, String, String>> additionalPackages = [:]
Map<String, Closure<Tuple3<String, String, String>>> additionalPackages = [:]
) {
def generateLogic = task('generateLogic', description: 'generates ext. methods for AssertionContainer based on interfaces') {}
(
['': new Tuple5<String, String, String, String, String>(
'AssertionContainer', 'ch.tutteli.atrium.creating.AssertionContainer', 'container: (AssertionContainer<.+?>)', '<T> AssertionContainer<T>', 'getImpl'
)] + additionalPackages
).forEach { relativePackagePath, tuple ->
def task = createGenerateLogicTaskForPackage(project, implsFileName, relativePackagePath, suffix, tuple.first, tuple.second, tuple.third, tuple.fourth, tuple.fifth)
Map<String, Closure<Tuple3<String, String, String>>> all = (['': { Path p ->
new Tuple3(
'import ch.tutteli.atrium.creating.AssertionContainer',
'<T> AssertionContainer<T>',
'getImpl'
)
}] + additionalPackages)
all.forEach { relativePackagePath, f ->
def task = createGenerateLogicTaskForPackage(project, implsFileName, relativePackagePath, suffix, f)
generateLogic.dependsOn(task)
}
return generateLogic
}
static String getType(Path input) {
def fileName = input.getFileName().toString()
return fileName.substring(0, fileName.length() - "Assertions.kt".length())
}
def createGenerateLogicTaskForPackage(
Project project,
String implsFileName,
String relativePackagePath,
String suffix,
String extensionTypeWithoutTP,
String importType,
String paramSignature,
String extensionTypeSignature,
String getImpl
Closure<Tuple3<String, String, String>> f
) {
String generatedFolder = project.generatedFolder
return task("generateLogic_${relativePackagePath.replaceAll('/', '_')}", description: "generates ext. methods for $extensionTypeWithoutTP based on interfaces") {
return task("generateLogic_${relativePackagePath.replaceAll('/', '_')}", description: "generates ext. methods for pacakge $relativePackagePath") {
def packagePath = 'ch/tutteli/atrium/logic' + relativePackagePath + (suffix != '' ? "/" + suffix : '')
def fullPackage = packagePath.replaceAll('/', '.')
def path = "$project.projectDir/src/main/kotlin/$packagePath/"
def interfaces = getInterfaces(path)
Map<Path, Tuple3<String, String, String>> interfacesWithTuple =
interfaces.collectEntries { [it, f(it)] }
def generatedPath = "$project.projectDir/$generatedFolder/$packagePath"
inputs.files(interfaces)
outputs.dir(generatedPath)
@@ -65,10 +72,6 @@ def createGenerateLogicTaskForPackage(
//TODO delete all files in folder first
def getType = { Path input ->
def fileName = input.getFileName().toString()
fileName.substring(0, fileName.length() - "Assertions.kt".length())
}
def header = """\
//---------------------------------------------------
// Generated content, modify:
@@ -89,18 +92,23 @@ def createGenerateLogicTaskForPackage(
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import $importType
""".stripIndent().replace("\n", ln)
interfaces.forEach {
def type = getType(it)
w << "import ${fullPackage}.impl.Default${type}Assertions$ln"
interfacesWithTuple.collect { _, tuple -> tuple.first }.unique().forEach {
w << "$it".replace("\n", ln)
}
interfacesWithTuple.forEach { interfacePath, tuple ->
def type = getType(interfacePath)
w << "${ln}import ${fullPackage}.impl.Default${type}Assertions"
}
w << "$ln"
w << "$ln$ln"
interfaces.forEach {
def type = getType(it)
interfacesWithTuple.forEach { interfacePath, tuple ->
def type = getType(interfacePath)
def (String importStatements,
String extensionTypeSignature,
String getImpl) = tuple
w << """\
@PublishedApi
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
@@ -115,10 +123,10 @@ def createGenerateLogicTaskForPackage(
def identifier = /[a-zA-Z0-9]+/
def newLine = /(?:\r\n?|\n)/
def newLineAndIndent = /$newLine\s*/
def typeIdentifier = / *fun (<.+?> )?($identifier)\((?:$newLineAndIndent)?$paramSignature/
def parameter = /,(?: |$newLineAndIndent)($identifier): ([^:]+?)/
def returnType = /(?:$newLineAndIndent)?\)(:.+)/
def typeIdentifier = / *fun (<.+?> )?($identifier)\((?:$newLineAndIndent)?$identifier: ($identifier(?:\.$identifier)*<.+>)/
def patterns = (6..0).collect {
def steps = (0..<it * 2).findAll { it % 2 == 0 }
new Tuple3<Pattern, String, String>(
@@ -128,11 +136,12 @@ def createGenerateLogicTaskForPackage(
)
}
interfaces.forEach { input ->
def type = getType(input)
interfacesWithTuple.forEach { interfacePath, tuple ->
def type = getType(interfacePath)
def uncapitalized = type.uncapitalize()
def output = new File("$generatedPath/${uncapitalized}.kt")
def content = input.text
def content = interfacePath.text
def interfaceName = "${type}Assertions"
def implValName = "_${uncapitalized}Impl"

View File

@@ -26,6 +26,7 @@ interface GroupWithNullableEntries<out T : Any?> : Group<T>
* Adds the given [firstGroup], the [secondGroup] and the [otherGroups] into a new [List] and returns it.
* @return a [List] containing [firstGroup], [secondGroup] and [otherGroups].
*/
//TODO copy and move to atrium-logic
fun <T> groupsToList(firstGroup: Group<T>, secondGroup: Group<T>, otherGroups: Array<out Group<T>>): List<List<T>> {
val groups = ArrayList<List<T>>(otherGroups.size + 2)
requireNotEmptyAndAdd(groups, firstGroup)

View File

@@ -1,8 +1,5 @@
package ch.tutteli.atrium.domain.robstoll.lib.creating.iterable.contains.creators
import ch.tutteli.atrium.api.fluent.en_GB.contains
import ch.tutteli.atrium.api.fluent.en_GB.inAnyOrder
import ch.tutteli.atrium.api.fluent.en_GB.only
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.builders.ExpectImpl
import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InOrderOnlyGroupedSearchBehaviour
@@ -13,7 +10,11 @@ class InOrderOnlyGroupedEntriesAssertionCreator<E : Any, in T : Iterable<E?>>(
InOrderOnlyMatcher<E?, (Expect<E>.() -> Unit)?> by InOrderOnlyEntriesMatcher() {
override fun Expect<List<E?>>.createSublistAssertion(groupOfSearchCriteria: List<(Expect<E>.() -> Unit)?>) {
val inAnyOrderOnly = contains.inAnyOrder.only
val inAnyOrderOnly = ExpectImpl.iterable.contains.searchBehaviours.inAnyOrderOnly(
ExpectImpl.iterable.contains.searchBehaviours.inAnyOrder(
ExpectImpl.iterable.containsBuilder(this)
)
)
addAssertion(ExpectImpl.iterable.contains.entriesInAnyOrderOnly(inAnyOrderOnly, groupOfSearchCriteria))
}
}

View File

@@ -1,10 +1,7 @@
package ch.tutteli.atrium.domain.robstoll.lib.creating.iterable.contains.creators
import ch.tutteli.atrium.api.fluent.en_GB.contains
import ch.tutteli.atrium.api.fluent.en_GB.inAnyOrder
import ch.tutteli.atrium.api.fluent.en_GB.only
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.domain.builders.ExpectImpl
import ch.tutteli.atrium.domain.builders.ExpectImpl.iterable
import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InOrderOnlyGroupedSearchBehaviour
class InOrderOnlyGroupedValuesAssertionCreator<E, in T : Iterable<E>>(
@@ -13,7 +10,11 @@ class InOrderOnlyGroupedValuesAssertionCreator<E, in T : Iterable<E>>(
InOrderOnlyMatcher<E, E> by InOrderOnlyValueMatcher() {
override fun Expect<List<E>>.createSublistAssertion(groupOfSearchCriteria: List<E>) {
val inAnyOrderOnly = contains.inAnyOrder.only
addAssertion(ExpectImpl.iterable.contains.valuesInAnyOrderOnly(inAnyOrderOnly, groupOfSearchCriteria))
val inAnyOrderOnly = iterable.contains.searchBehaviours.inAnyOrderOnly(
iterable.contains.searchBehaviours.inAnyOrder(
iterable.containsBuilder(this)
)
)
addAssertion(iterable.contains.valuesInAnyOrderOnly(inAnyOrderOnly, groupOfSearchCriteria))
}
}