Skip to content

Commit 45ec062

Browse files
committed
Add collection filtering assertions analagous to instanceOf
1 parent c67ae5a commit 45ec062

File tree

3 files changed

+63
-1
lines changed

3 files changed

+63
-1
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
99
### Changed
1010
- renamed `prop` to `having` as part of effort to unify API naming, old name is deprecated.
1111
- renamed `suspendCall` to `having` as part of effort to unify API naming, old name is deprecated.
12-
- added `doesNotExist` assertions to `Path`.
12+
13+
### Added
14+
- Added `doesNotExist` assertions to `Path`
15+
- Added `containsInstanceOf` and `doesNotContainInstanceOf` for `Iterable`
1316

1417
## [0.28.1] 2024-04-17
1518

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

Lines changed: 30 additions & 0 deletions
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`.
@@ -131,6 +133,34 @@ internal fun MutableList<*>.removeFirst(value: Any?) {
131133
if (index > -1) removeAt(index)
132134
}
133135

136+
/**
137+
* Asserts the collection contains at least one instance of a given type.
138+
*
139+
* ```
140+
* assertThat(listOf<Any>("one", "two", 1)).containsInstanceOf<String>().each {
141+
* it.hasLength(3)
142+
* }
143+
* ```
144+
*/
145+
inline fun <reified T> Assert<Iterable<*>>.containsInstanceOf(): Assert<List<T>> {
146+
return transform("contains subtype of ${T::class}") { actual ->
147+
actual.filterIsInstance<T>().also {
148+
if (it.isEmpty()) expected("to contain at least one instance of ${T::class} but was $actual")
149+
}
150+
}
151+
}
152+
153+
/**
154+
* Asserts the collection does not contain an instance of a given type.
155+
*
156+
* ```
157+
* assertThat(listOf<Any>("one", "two", 1)).doesNotContainInstanceOf<Double>()
158+
* ```
159+
*/
160+
inline fun <reified T> Assert<Iterable<*>>.doesNotContainInstanceOf() = given { actual ->
161+
if (actual.filterIsInstance<T>().isNotEmpty()) expected("to contain no instances of ${T::class} but was $actual")
162+
}
163+
134164
/**
135165
* Asserts on each item in the iterable. The given lambda will be run for each item.
136166
*

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

Lines changed: 29 additions & 0 deletions
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.containsAtLeast
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
@@ -229,6 +232,32 @@ class IterableTest {
229232
}
230233
//endregion
231234

235+
//region containsInstanceOf
236+
@Test fun containsInstanceOf_element_present_passes() {
237+
assertThat(iterableOf(1, "two")).containsInstanceOf<String>().single().isEqualTo("two")
238+
}
239+
240+
@Test fun containsInstanceOf_element_missing_fails() {
241+
val error = assertFailsWith<AssertionError> {
242+
assertThat(iterableOf(1, "two")).containsInstanceOf<Double>()
243+
}
244+
assertEquals("expected to contain at least one instance of class kotlin.Double but was [1, two]", error.message)
245+
}
246+
//endregion
247+
248+
//region doesNotContainInstanceOf
249+
@Test fun doesNotContainInstanceOf_element_present_fails() {
250+
val error = assertFailsWith<AssertionError>() {
251+
assertThat(iterableOf(1, "two")).doesNotContainInstanceOf<String>()
252+
}
253+
assertEquals("expected to contain no instances of class kotlin.String but was [1, two]", error.message)
254+
}
255+
256+
@Test fun doesNotContainInstanceOf_element_missing_passes() {
257+
assertThat(iterableOf(1, "two")).doesNotContainInstanceOf<Double>()
258+
}
259+
//endregion
260+
232261
//region each
233262
@Test
234263
fun each_empty_list_passes() {

0 commit comments

Comments
 (0)