diff --git a/strikt-core/src/main/kotlin/strikt/assertions/Iterable.kt b/strikt-core/src/main/kotlin/strikt/assertions/Iterable.kt index 0363daf5..664d53d0 100644 --- a/strikt-core/src/main/kotlin/strikt/assertions/Iterable.kt +++ b/strikt-core/src/main/kotlin/strikt/assertions/Iterable.kt @@ -1,6 +1,5 @@ package strikt.assertions -import strikt.api.Assertion import strikt.api.Assertion.Builder import strikt.internal.iterable.ElementWithOrderingConstraints import strikt.internal.iterable.OrderingConstraint @@ -654,20 +653,27 @@ fun , E> Builder.containsWithOrderingConstraints( allSections.flatMap { it.elementsWithConstraints.map { it.element } } ) { var elementsConsumed = 0 - fun consumeElementsAndAssertSection(section: SectionAssertionSpec): Assertion.Builder> { + fun consumeElementsAndAssertSection(section: SectionAssertionSpec): Builder> { val sectionElementCount: Int val assertion = when (val endDefinedBy = section.endDefinedBy) { - SectionAssertionSpec.EndDefinition.DeclaredElementCount -> { - // Define the section by the number of elements declared with `expect` - sectionElementCount = section.elementsWithConstraints.size - get("section %s") { drop(elementsConsumed).take(sectionElementCount) } - .assert("has %s elements", sectionElementCount) { - if (it.size == sectionElementCount) { - pass() - } else { - fail(it.size, "only %s elements left in list") + SectionAssertionSpec.EndDefinition.Undefined -> { + if (section === allSections.last()) { + // Define the section by taking everything + val remainingElements = subject.drop(elementsConsumed) + sectionElementCount = remainingElements.size + get("section %s") { remainingElements } + } else { + // Define the section by the number of elements declared with `expect` + sectionElementCount = section.elementsWithConstraints.size + get("section %s") { drop(elementsConsumed).take(sectionElementCount) } + .assert("has %s elements", sectionElementCount) { + if (it.size == sectionElementCount) { + pass() + } else { + fail(it.size, "only %s elements left in list") + } } - } + } } is SectionAssertionSpec.EndDefinition.DeclaredElement -> { // Define the section by taking everything until the end element diff --git a/strikt-core/src/main/kotlin/strikt/internal/iterable/AssertionOrderingConstraints.kt b/strikt-core/src/main/kotlin/strikt/internal/iterable/AssertionOrderingConstraints.kt index 1db4dbb0..fd323568 100644 --- a/strikt-core/src/main/kotlin/strikt/internal/iterable/AssertionOrderingConstraints.kt +++ b/strikt-core/src/main/kotlin/strikt/internal/iterable/AssertionOrderingConstraints.kt @@ -29,6 +29,7 @@ internal class OrderingConstraintsAssertScopeImpl: OrderingConstraintsAssertS override fun expectNoFurtherElements() { expectsNoFurtherElements = true + currentBuildingSection.expectsNoOtherElements = true } override fun startNewSection() = endSectionIfInProgress() @@ -91,11 +92,11 @@ internal data class ElementWithOrderingConstraints(val element: E, val constr internal class SectionAssertionSpec { val elementsWithConstraints = mutableListOf>() - var endDefinedBy: EndDefinition = EndDefinition.DeclaredElementCount + var endDefinedBy: EndDefinition = EndDefinition.Undefined var expectsNoOtherElements = false sealed class EndDefinition { - data object DeclaredElementCount : EndDefinition() + data object Undefined : EndDefinition() data class DeclaredElement(val element: E) : EndDefinition() } } diff --git a/strikt-core/src/test/kotlin/strikt/assertions/IterableOrderingConstraintsAssertions.kt b/strikt-core/src/test/kotlin/strikt/assertions/IterableOrderingConstraintsAssertions.kt index 7b8ee2f6..b0d79b8b 100644 --- a/strikt-core/src/test/kotlin/strikt/assertions/IterableOrderingConstraintsAssertions.kt +++ b/strikt-core/src/test/kotlin/strikt/assertions/IterableOrderingConstraintsAssertions.kt @@ -276,6 +276,14 @@ class IterableOrderingConstraintsAssertions { } } + @Test + fun passesWithElementBeforeExpectedElement() { + expectThat(listOf("a", "b")) + .containsWithOrderingConstraints { + expect("b") + } + } + @Test fun failsWithDuplicateElement() { assertThrows {