Skip to content

Commit 669f726

Browse files
committed
Add collection filtering assertions analagous to instanceOf
1 parent 6820783 commit 669f726

File tree

3 files changed

+62
-0
lines changed

3 files changed

+62
-0
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
66

77
## [Unreleased]
88

9+
### Added
10+
- Added `containsInstanceOf` and `doesNotContainInstanceOf` for `Iterable`
11+
912
## [0.27.0] 2023-09-13
1013

1114
### Changed

assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt

+30
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ package assertk.assertions
22

33
import assertk.Assert
44
import assertk.all
5+
import assertk.assertThat
56
import assertk.collection
67
import assertk.assertions.support.appendName
78
import assertk.assertions.support.expected
89
import assertk.assertions.support.show
10+
import assertk.fail
911

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

126+
/**
127+
* Asserts the collection contains at least one instance of a given type.
128+
*
129+
* ```
130+
* assertThat(listOf<Any>("one", "two", 1)).containsInstanceOf<String>().each {
131+
* it.hasLength(3)
132+
* }
133+
* ```
134+
*/
135+
inline fun <reified T> Assert<Iterable<*>>.containsInstanceOf(): Assert<List<T>> {
136+
return transform("contains subtype of ${T::class}") { actual ->
137+
actual.filterIsInstance<T>().also {
138+
if (it.isEmpty()) expected("to contain at least one instance of ${T::class} but was $actual")
139+
}
140+
}
141+
}
142+
143+
/**
144+
* Asserts the collection does not contain an instance of a given type.
145+
*
146+
* ```
147+
* assertThat(listOf<Any>("one", "two", 1)).doesNotContainInstanceOf<Double>()
148+
* ```
149+
*/
150+
inline fun <reified T> Assert<Iterable<*>>.doesNotContainInstanceOf() = given { actual ->
151+
if (actual.filterIsInstance<T>().isNotEmpty()) expected("to contain no instances of ${T::class} but was $actual")
152+
}
153+
124154
/**
125155
* Asserts on each item in the iterable. The given lambda will be run for each item.
126156
*

assertk/src/commonTest/kotlin/test/assertk/assertions/IterableTest.kt

+29
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package test.assertk.assertions
22

33
import assertk.all
4+
import assertk.assertFailure
45
import assertk.assertThat
56
import assertk.assertions.any
67
import assertk.assertions.atLeast
@@ -9,9 +10,11 @@ import assertk.assertions.contains
910
import assertk.assertions.containsAll
1011
import assertk.assertions.containsExactly
1112
import assertk.assertions.containsExactlyInAnyOrder
13+
import assertk.assertions.containsInstanceOf
1214
import assertk.assertions.containsNone
1315
import assertk.assertions.containsOnly
1416
import assertk.assertions.doesNotContain
17+
import assertk.assertions.doesNotContainInstanceOf
1518
import assertk.assertions.each
1619
import assertk.assertions.exactly
1720
import assertk.assertions.extracting
@@ -208,6 +211,32 @@ class IterableTest {
208211
}
209212
//endregion
210213

214+
//region containsInstanceOf
215+
@Test fun containsInstanceOf_element_present_passes() {
216+
assertThat(iterableOf(1, "two")).containsInstanceOf<String>().single().isEqualTo("two")
217+
}
218+
219+
@Test fun containsInstanceOf_element_missing_fails() {
220+
val error = assertFailsWith<AssertionError> {
221+
assertThat(iterableOf(1, "two")).containsInstanceOf<Double>()
222+
}
223+
assertEquals("expected to contain at least one instance of class kotlin.Double but was [1, two]", error.message)
224+
}
225+
//endregion
226+
227+
//region doesNotContainInstanceOf
228+
@Test fun doesNotContainInstanceOf_element_present_fails() {
229+
val error = assertFailsWith<AssertionError>() {
230+
assertThat(iterableOf(1, "two")).doesNotContainInstanceOf<String>()
231+
}
232+
assertEquals("expected to contain no instances of class kotlin.String but was [1, two]", error.message)
233+
}
234+
235+
@Test fun doesNotContainInstanceOf_element_missing_passes() {
236+
assertThat(iterableOf(1, "two")).doesNotContainInstanceOf<Double>()
237+
}
238+
//endregion
239+
211240
//region each
212241
@Test fun each_empty_list_passes() {
213242
assertThat(emptyIterable<Int>()).each { it.isEqualTo(1) }

0 commit comments

Comments
 (0)