Skip to content

Commit

Permalink
introduce InAnyOrderOnlyReportingOptions
Browse files Browse the repository at this point in the history
On one hand for contains.inAnyOrder but on the other also for
contains.inOrder.only.grouped.inAnyOrder. There both should be
configurable, the grouped reporting as well as the in-group reporting
options

moreover:
- deprecate InOrderOnlyReportingOptions.numberOfElementsInSummary,
  instead provide showOnlyFailingIfMoreExpectedElementsThan
- only run js test tasks in CI (as they currently re-run even if they
  are successful)
  • Loading branch information
robstoll committed Apr 9, 2022
1 parent 71dd208 commit 1fe6aa7
Show file tree
Hide file tree
Showing 66 changed files with 2,757 additions and 464 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1167,7 +1167,7 @@ then only failing expectations are shown.
<summary>💬 Show only failing expectations/elements earlier than 10 elements?</summary>
You can use the `report` option to specify when Atrium shall start to show only failing expectations.
Following an example changing the limit to 3 elements by using `showOnlyFailingIfMoreElementsThan` :
Following an example changing the limit to 3 elements by using `showOnlyFailingIfMoreExpectedElementsThan` :
<ex-collection-reportOptions-1>
Expand All @@ -1176,7 +1176,7 @@ expect(listOf(1, 2, 2, 4)).toContainExactly(
{ toBeLessThan(3) },
{ toBeLessThan(2) },
{ toBeGreaterThan(1) },
report = { showOnlyFailingIfMoreElementsThan(3) }
report = { showOnlyFailingIfMoreExpectedElementsThan(2) }
)
```
↑ <sub>[Example](https://github.com/robstoll/atrium/tree/main/misc/tools/readme-examples/src/main/kotlin/readme/examples/MostExamplesSpec.kt#L154)</sub> ↓ <sub>[Output](#ex-collection-reportOptions-1)</sub>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import ch.tutteli.atrium.logic.creating.iterable.contains.creators.entriesInAnyO
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.atrium.logic.creating.iterablelike.contains.reporting.InAnyOrderOnlyReportingOptions
import ch.tutteli.atrium.logic.creating.iterablelike.contains.reporting.InOrderOnlyReportingOptions
import ch.tutteli.atrium.logic.creating.typeutils.IterableLikeToIterableTransformer
import ch.tutteli.atrium.logic.utils.toVarArg
import ch.tutteli.kbox.glue
Expand All @@ -26,7 +28,7 @@ import ch.tutteli.kbox.glue
*
* @since 0.14.0 -- API existed for [Iterable] but not for [IterableLike].
*/
fun <E, T: IterableLike> EntryPointStep<E, T, InAnyOrderOnlySearchBehaviour>.value(expected: E): Expect<T> =
fun <E, T : IterableLike> EntryPointStep<E, T, InAnyOrderOnlySearchBehaviour>.value(expected: E): Expect<T> =
values(expected)

/**
Expand All @@ -36,15 +38,19 @@ fun <E, T: IterableLike> EntryPointStep<E, T, InAnyOrderOnlySearchBehaviour>.val
*
* @param expected The value which is expected to be contained within the subject (an [IterableLike]).
* @param otherExpected Additional values which are expected to be contained within [IterableLike].
* @param report The lambda configuring the [InAnyOrderOnlyReportingOptions] -- it is optional where
* the default [InAnyOrderOnlyReportingOptions] apply if not specified.
* since 0.18.0
*
* @return an [Expect] for the subject of `this` expectation.
*
* @since 0.14.0 -- API existed for [Iterable] but not for [IterableLike].
*/
fun <E, T: IterableLike> EntryPointStep<E, T, InAnyOrderOnlySearchBehaviour>.values(
fun <E, T : IterableLike> EntryPointStep<E, T, InAnyOrderOnlySearchBehaviour>.values(
expected: E,
vararg otherExpected: E
): Expect<T> = _logicAppend { valuesInAnyOrderOnly(expected glue otherExpected) }
vararg otherExpected: E,
report: InAnyOrderOnlyReportingOptions.() -> Unit = {}
): Expect<T> = _logicAppend { valuesInAnyOrderOnly(expected glue otherExpected, report) }

/**
* Finishes the specification of the sophisticated `contains` assertion where the subject (an [IterableLike])
Expand All @@ -61,7 +67,7 @@ fun <E, T: IterableLike> EntryPointStep<E, T, InAnyOrderOnlySearchBehaviour>.val
*
* @since 0.14.0 -- API existed for [Iterable] but not for [IterableLike].
*/
fun <E : Any, T: IterableLike> EntryPointStep<out E?, T, InAnyOrderOnlySearchBehaviour>.entry(
fun <E : Any, T : IterableLike> EntryPointStep<out E?, T, InAnyOrderOnlySearchBehaviour>.entry(
assertionCreatorOrNull: (Expect<E>.() -> Unit)?
): Expect<T> = entries(assertionCreatorOrNull)

Expand All @@ -85,15 +91,19 @@ fun <E : Any, T: IterableLike> EntryPointStep<out E?, T, InAnyOrderOnlySearchBeh
* or not. In case it is defined as `null`, then an entry is identified if it is `null` as well.
* @param otherAssertionCreatorsOrNulls Additional identification lambdas which each identify (separately) an entry
* which we are looking for (see [assertionCreatorOrNull] for more information).
* @param report The lambda configuring the [InAnyOrderOnlyReportingOptions] -- it is optional where
* the default [InAnyOrderOnlyReportingOptions] apply if not specified.
* since 0.18.0
*
* @return an [Expect] for the subject of `this` expectation.
*
* @since 0.14.0 -- API existed for [Iterable] but not for [IterableLike].
*/
fun <E : Any, T: IterableLike> EntryPointStep<out E?, T, InAnyOrderOnlySearchBehaviour>.entries(
fun <E : Any, T : IterableLike> EntryPointStep<out E?, T, InAnyOrderOnlySearchBehaviour>.entries(
assertionCreatorOrNull: (Expect<E>.() -> Unit)?,
vararg otherAssertionCreatorsOrNulls: (Expect<E>.() -> Unit)?
): Expect<T> = _logicAppend { entriesInAnyOrderOnly(assertionCreatorOrNull glue otherAssertionCreatorsOrNulls) }
vararg otherAssertionCreatorsOrNulls: (Expect<E>.() -> Unit)?,
report: InAnyOrderOnlyReportingOptions.() -> Unit = {}
): Expect<T> = _logicAppend { entriesInAnyOrderOnly(assertionCreatorOrNull glue otherAssertionCreatorsOrNulls, report) }

/**
* Finishes the specification of the sophisticated `contains` assertion where the subject (an [IterableLike])
Expand All @@ -106,6 +116,9 @@ fun <E : Any, T: IterableLike> EntryPointStep<out E?, T, InAnyOrderOnlySearchBeh
* This function expects [IterableLike] (which is a typealias for [Any]) to avoid cluttering the API.
*
* @param expectedIterableLike The [IterableLike] whose elements are expected to be contained within this [IterableLike]
* @param report The lambda configuring the [InAnyOrderOnlyReportingOptions] -- it is optional where
* the default [InAnyOrderOnlyReportingOptions] apply if not specified.
* since 0.18.0
*
* @return an [Expect] for the subject of `this` expectation.
* @throws IllegalArgumentException in case [expectedIterableLike] is not
Expand All @@ -114,6 +127,7 @@ fun <E : Any, T: IterableLike> EntryPointStep<out E?, T, InAnyOrderOnlySearchBeh
*
* @since 0.14.0 -- API existed for [Iterable] since 0.13.0 but not for [IterableLike].
*/
inline fun <reified E, T: IterableLike> EntryPointStep<E, T, InAnyOrderOnlySearchBehaviour>.elementsOf(
expectedIterableLike: IterableLike
): Expect<T> = _logic.toVarArg<E>(expectedIterableLike).let { (first, rest) -> values(first, *rest) }
inline fun <reified E, T : IterableLike> EntryPointStep<E, T, InAnyOrderOnlySearchBehaviour>.elementsOf(
expectedIterableLike: IterableLike,
noinline report: InAnyOrderOnlyReportingOptions.() -> Unit = {}
): Expect<T> = _logic.toVarArg<E>(expectedIterableLike).let { (first, rest) -> values(first, *rest, report = report) }
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ fun <E, T : IterableLike> EntryPointStep<E, T, InOrderOnlySearchBehaviour>.value
* @param otherExpected Additional values which are expected to be contained within [IterableLike].
* @param report The lambda configuring the [InOrderOnlyReportingOptions] -- it is optional where
* the default [InOrderOnlyReportingOptions] apply if not specified.
* since 0.17.0
*
* @return an [Expect] for the subject of `this` expectation.
*
Expand Down Expand Up @@ -81,6 +82,7 @@ fun <E : Any, T : IterableLike> EntryPointStep<out E?, T, InOrderOnlySearchBehav
* which we are looking for (see [assertionCreatorOrNull] for more information).
* @param report The lambda configuring the [InOrderOnlyReportingOptions] -- it is optional where
* the default [InOrderOnlyReportingOptions] apply if not specified.
* since 0.17.0
*
* @return an [Expect] for the subject of `this` expectation.
*
Expand All @@ -105,6 +107,7 @@ fun <E : Any, T : IterableLike> EntryPointStep<out E?, T, InOrderOnlySearchBehav
* @param expectedIterableLike The [IterableLike] whose elements are expected to be contained within this [IterableLike].
* @param report The lambda configuring the [InOrderOnlyReportingOptions] -- it is optional where
* the default [InOrderOnlyReportingOptions] apply if not specified.
since 0.17.0
*
* @return an [Expect] for the subject of `this` expectation.
* @throws IllegalArgumentException in case [expectedIterableLike] is not an
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains.E
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 ch.tutteli.atrium.logic.creating.iterablelike.contains.reporting.InAnyOrderOnlyReportingOptions
import ch.tutteli.atrium.logic.creating.iterablelike.contains.reporting.InOrderOnlyReportingOptions
import kotlin.jvm.JvmName

Expand All @@ -24,6 +25,10 @@ import kotlin.jvm.JvmName
* [IterableLike] whereas the groups have to appear in the given order.
* @param report The lambda configuring the [InOrderOnlyReportingOptions] -- it is optional where
* the default [InOrderOnlyReportingOptions] apply if not specified.
* since 0.17.0
* @param reportInGroup The lambda configuring the [InAnyOrderOnlyReportingOptions] -- it is optional where
* the default [InOrderOnlyReportingOptions] apply if not specified.
* since 0.18.0
*
* @return an [Expect] for the subject of `this` expectation.
*
Expand All @@ -33,9 +38,10 @@ fun <E, T : IterableLike> EntryPointStep<E, T, InOrderOnlyGroupedWithinSearchBeh
firstGroup: Group<E>,
secondGroup: Group<E>,
vararg otherExpectedGroups: Group<E>,
report: InOrderOnlyReportingOptions.() -> Unit = {}
report: InOrderOnlyReportingOptions.() -> Unit = {},
reportInGroup: InAnyOrderOnlyReportingOptions.() -> Unit = {}
): Expect<T> = _logicAppend {
valuesInOrderOnlyGrouped(groupsToList(firstGroup, secondGroup, otherExpectedGroups), report)
valuesInOrderOnlyGrouped(groupsToList(firstGroup, secondGroup, otherExpectedGroups), report, reportInGroup)
}

/**
Expand All @@ -54,6 +60,10 @@ fun <E, T : IterableLike> EntryPointStep<E, T, InOrderOnlyGroupedWithinSearchBeh
* [IterableLike] whereas the groups have to appear in the given order.
* @param report The lambda configuring the [InOrderOnlyReportingOptions] -- it is optional where
* the default [InOrderOnlyReportingOptions] apply if not specified.
* since 0.17.0
* @param reportInGroup The lambda configuring the [InAnyOrderOnlyReportingOptions] -- it is optional where
* the default [InOrderOnlyReportingOptions] apply if not specified.
* since 0.18.0
*
* @return an [Expect] for the subject of `this` expectation.
*
Expand All @@ -64,7 +74,8 @@ fun <E : Any, T : IterableLike> EntryPointStep<out E?, T, InOrderOnlyGroupedWith
firstGroup: Group<(Expect<E>.() -> Unit)?>,
secondGroup: Group<(Expect<E>.() -> Unit)?>,
vararg otherExpectedGroups: Group<(Expect<E>.() -> Unit)?>,
report: InOrderOnlyReportingOptions.() -> Unit = {}
report: InOrderOnlyReportingOptions.() -> Unit = {},
reportInGroup: InAnyOrderOnlyReportingOptions.() -> Unit = {}
): Expect<T> = _logicAppend {
entriesInOrderOnlyGrouped(groupsToList(firstGroup, secondGroup, otherExpectedGroups), report)
entriesInOrderOnlyGrouped(groupsToList(firstGroup, secondGroup, otherExpectedGroups), report, reportInGroup)
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ fun <K, V, T : MapLike> EntryPointStep<K, V, T, InOrderOnlySearchBehaviour>.entr
* Finishes the specification of the sophisticated `contains` assertion where the subject (a [MapLike])
* needs to contain only the given [keyValuePair] as well as the [otherPairs] in the specified order.
*
* @param report The lambda configuring the [InOrderOnlyReportingOptions] -- it is optional where
* the default [InOrderOnlyReportingOptions] apply if not specified.
* since 0.18.0
*
* @return an [Expect] for the subject of `this` expectation.
*
* @since 0.15.0
Expand All @@ -41,7 +45,7 @@ fun <K, V, T : MapLike> EntryPointStep<K, V, T, InOrderOnlySearchBehaviour>.entr
keyValuePair: Pair<K, V>,
vararg otherPairs: Pair<K, V>,
report: InOrderOnlyReportingOptions.() -> Unit = {}
): Expect<T> = _logicAppend { keyValuePairsInOrderOnly(keyValuePair glue otherPairs,report) }
): Expect<T> = _logicAppend { keyValuePairsInOrderOnly(keyValuePair glue otherPairs, report) }


/**
Expand Down Expand Up @@ -69,6 +73,10 @@ inline fun <K, reified V : Any, T : MapLike> EntryPointStep<K, out V?, T, InOrde
* [KeyValue.valueAssertionCreatorOrNull] creates or needs to be `null` in case
* [KeyValue.valueAssertionCreatorOrNull] is defined as `null`.
*
* @param report The lambda configuring the [InOrderOnlyReportingOptions] -- it is optional where
* the default [InOrderOnlyReportingOptions] apply if not specified.
* since 0.18.0
*
* @return an [Expect] for the subject of `this` expectation.
*
* @since 0.15.0
Expand Down Expand Up @@ -104,10 +112,15 @@ internal fun <K, V : Any, T : MapLike> EntryPointStep<K, out V?, T, InOrderOnlyS
* a [Map], [Sequence] or one of the [Array] types
* or the given [expectedMapLike] does not have elements (is empty).
*
* @param report The lambda configuring the [InOrderOnlyReportingOptions] -- it is optional where
* the default [InOrderOnlyReportingOptions] apply if not specified.
* since 0.18.0
*
* @since 0.15.0
*/
fun <K, V, T : MapLike> EntryPointStep<K, V, T, InOrderOnlySearchBehaviour>.entriesOf(
expectedMapLike: MapLike,
report: InOrderOnlyReportingOptions.() -> Unit = {}
): Expect<T> = _logic.toVarArgPairs<K, V>(expectedMapLike).let { (first, rest) -> entries(first, *rest, report = report) }
): Expect<T> =
_logic.toVarArgPairs<K, V>(expectedMapLike).let { (first, rest) -> entries(first, *rest, report = report) }

Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ class IterableToContainInAnyOrderAtLeast1EntriesExpectationsSpec : Spek({
else expect.toContain.inAnyOrder.atLeast(1).entries(a, *aX)
}


@Suppress("unused", "UNUSED_VALUE")
private fun ambiguityTest() {
var list: Expect<List<Number>> = notImplemented()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,4 @@ class IterableToContainInAnyOrderExactlyValuesExpectationsSpec :
subList = subList.toContain.inAnyOrder.exactly(2).values(1, 2.2)
star = star.toContain.inAnyOrder.exactly(2).values(1, 1.2, "asdf")
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package ch.tutteli.atrium.api.fluent.en_GB

import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.logic.creating.iterablelike.contains.reporting.InAnyOrderOnlyReportingOptions
import ch.tutteli.atrium.specs.integration.IterableToContainSpecBase.Companion.emptyInAnyOrderOnlyReportOptions
import ch.tutteli.atrium.specs.notImplemented
import ch.tutteli.atrium.specs.withNullableSuffix
import org.spekframework.spek2.Spek
Expand All @@ -15,29 +17,37 @@ class IterableToContainInAnyOrderOnlyElementsOfExpectationsSpec : Spek({
(functionDescription to C::toContainElementsOfNullable).withNullableSuffix()
)

object BuilderIterableLikeToIterableSpec : ch.tutteli.atrium.specs.integration.IterableLikeToIterableSpec<List<Int>>(
functionDescription,
listOf(1, 2),
{ input -> toContain.inAnyOrder.only.elementsOf(input) }
)
object BuilderIterableLikeToIterableSpec :
ch.tutteli.atrium.specs.integration.IterableLikeToIterableSpec<List<Int>>(
functionDescription,
listOf(1, 2),
{ input -> toContain.inAnyOrder.only.elementsOf(input) }
)

companion object : IterableToContainSpecBase() {
val functionDescription = "$toContain.$inAnyOrder.$only.$elementsOf"

private fun toContainElementsOf(
expect: Expect<Iterable<Double>>,
a: Double,
aX: Array<out Double>
): Expect<Iterable<Double>> = expect.toContain.inAnyOrder.only.elementsOf(listOf(a, *aX))
aX: Array<out Double>,
report: InAnyOrderOnlyReportingOptions.() -> Unit
): Expect<Iterable<Double>> =
if (report == emptyInAnyOrderOnlyReportOptions) {
expect.toContain.inAnyOrder.only.elementsOf(listOf(a, *aX))
} else expect.toContain.inAnyOrder.only.elementsOf(listOf(a, *aX), report = report)

private fun toContainElementsOfNullable(
expect: Expect<Iterable<Double?>>,
a: Double?,
aX: Array<out Double?>
): Expect<Iterable<Double?>> = expect.toContain.inAnyOrder.only.elementsOf(sequenceOf(a, *aX))
aX: Array<out Double?>,
report: InAnyOrderOnlyReportingOptions.() -> Unit
): Expect<Iterable<Double?>> =
if (report == emptyInAnyOrderOnlyReportOptions) {
expect.toContain.inAnyOrder.only.elementsOf(listOf(a, *aX))
} else expect.toContain.inAnyOrder.only.elementsOf(listOf(a, *aX), report = report)
}


@Suppress("unused", "UNUSED_VALUE")
private fun ambiguityTest() {
var list: Expect<List<Number>> = notImplemented()
Expand All @@ -49,5 +59,16 @@ class IterableToContainInAnyOrderOnlyElementsOfExpectationsSpec : Spek({
nList = nList.toContain.inAnyOrder.only.elementsOf(listOf<Int>())
subList = subList.toContain.inAnyOrder.only.elementsOf(listOf<Int>())
star = star.toContain.inAnyOrder.only.elementsOf(listOf<Int>())

list = list.toContain.inAnyOrder.only.elementsOf(listOf<Int>(), report = {})
nList = nList.toContain.inAnyOrder.only.elementsOf(listOf<Int>(), report = {})
subList = subList.toContain.inAnyOrder.only.elementsOf(listOf<Int>(), report = {})
star = star.toContain.inAnyOrder.only.elementsOf(listOf<Int>(), report = {})

nList = nList.toContain.inAnyOrder.only.elementsOf(listOf<Int?>())
star = star.toContain.inAnyOrder.only.elementsOf(listOf<Int?>())

list = list.toContain.inAnyOrder.only.elementsOf(listOf<Int?>(), report = {})
star = star.toContain.inAnyOrder.only.elementsOf(listOf<Int?>(), report = {})
}
}
Loading

0 comments on commit 1fe6aa7

Please sign in to comment.