Skip to content

Commit

Permalink
Add collection filtering assertions analagous to instanceOf
Browse files Browse the repository at this point in the history
  • Loading branch information
jzbrooks committed Sep 29, 2024
1 parent 6820783 commit 669f726
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

### Added
- Added `containsInstanceOf` and `doesNotContainInstanceOf` for `Iterable`

## [0.27.0] 2023-09-13

### Changed
Expand Down
30 changes: 30 additions & 0 deletions assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package assertk.assertions

import assertk.Assert
import assertk.all
import assertk.assertThat
import assertk.collection
import assertk.assertions.support.appendName
import assertk.assertions.support.expected
import assertk.assertions.support.show
import assertk.fail

/**
* Asserts the iterable contains the expected element, using `in`.
Expand Down Expand Up @@ -121,6 +123,34 @@ internal fun MutableList<*>.removeFirst(value: Any?) {
if (index > -1) removeAt(index)
}

/**
* Asserts the collection contains at least one instance of a given type.
*
* ```
* assertThat(listOf<Any>("one", "two", 1)).containsInstanceOf<String>().each {
* it.hasLength(3)
* }
* ```
*/
inline fun <reified T> Assert<Iterable<*>>.containsInstanceOf(): Assert<List<T>> {
return transform("contains subtype of ${T::class}") { actual ->
actual.filterIsInstance<T>().also {
if (it.isEmpty()) expected("to contain at least one instance of ${T::class} but was $actual")
}
}
}

/**
* Asserts the collection does not contain an instance of a given type.
*
* ```
* assertThat(listOf<Any>("one", "two", 1)).doesNotContainInstanceOf<Double>()
* ```
*/
inline fun <reified T> Assert<Iterable<*>>.doesNotContainInstanceOf() = given { actual ->
if (actual.filterIsInstance<T>().isNotEmpty()) expected("to contain no instances of ${T::class} but was $actual")
}

/**
* Asserts on each item in the iterable. The given lambda will be run for each item.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package test.assertk.assertions

import assertk.all
import assertk.assertFailure
import assertk.assertThat
import assertk.assertions.any
import assertk.assertions.atLeast
Expand All @@ -9,9 +10,11 @@ import assertk.assertions.contains
import assertk.assertions.containsAll
import assertk.assertions.containsExactly
import assertk.assertions.containsExactlyInAnyOrder
import assertk.assertions.containsInstanceOf
import assertk.assertions.containsNone
import assertk.assertions.containsOnly
import assertk.assertions.doesNotContain
import assertk.assertions.doesNotContainInstanceOf
import assertk.assertions.each
import assertk.assertions.exactly
import assertk.assertions.extracting
Expand Down Expand Up @@ -208,6 +211,32 @@ class IterableTest {
}
//endregion

//region containsInstanceOf
@Test fun containsInstanceOf_element_present_passes() {
assertThat(iterableOf(1, "two")).containsInstanceOf<String>().single().isEqualTo("two")
}

@Test fun containsInstanceOf_element_missing_fails() {
val error = assertFailsWith<AssertionError> {
assertThat(iterableOf(1, "two")).containsInstanceOf<Double>()
}
assertEquals("expected to contain at least one instance of class kotlin.Double but was [1, two]", error.message)
}
//endregion

//region doesNotContainInstanceOf
@Test fun doesNotContainInstanceOf_element_present_fails() {
val error = assertFailsWith<AssertionError>() {
assertThat(iterableOf(1, "two")).doesNotContainInstanceOf<String>()
}
assertEquals("expected to contain no instances of class kotlin.String but was [1, two]", error.message)
}

@Test fun doesNotContainInstanceOf_element_missing_passes() {
assertThat(iterableOf(1, "two")).doesNotContainInstanceOf<Double>()
}
//endregion

//region each
@Test fun each_empty_list_passes() {
assertThat(emptyIterable<Int>()).each { it.isEqualTo(1) }
Expand Down

0 comments on commit 669f726

Please sign in to comment.