From 0deb0f831cfa8c2075271339d451f22091a50f99 Mon Sep 17 00:00:00 2001 From: Justin Brooks Date: Sun, 29 Sep 2024 14:57:34 -0400 Subject: [PATCH 1/7] Add collection filtering assertions analagous to instanceOf --- CHANGELOG.md | 4 +++ .../kotlin/assertk/assertions/iterable.kt | 30 +++++++++++++++++++ .../test/assertk/assertions/IterableTest.kt | 29 ++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a47343b9..2af98624 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - signature of `isIn` and `isNotIn` has been changed to ensure at least two items are supplied. - added assertions `isIn(Iterable)` and `isNotIn(Iterable)` +### Added +- Added `doesNotExist` assertions to `Path` +- Added `containsInstanceOf` and `doesNotContainInstanceOf` for `Iterable` + ## [0.28.1] 2024-04-17 ### Added diff --git a/assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt b/assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt index 65861d3d..63760c37 100644 --- a/assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt +++ b/assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt @@ -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`. @@ -131,6 +133,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("one", "two", 1)).containsInstanceOf().each { + * it.hasLength(3) + * } + * ``` + */ +inline fun Assert>.containsInstanceOf(): Assert> { + return transform("contains subtype of ${T::class}") { actual -> + actual.filterIsInstance().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("one", "two", 1)).doesNotContainInstanceOf() + * ``` + */ +inline fun Assert>.doesNotContainInstanceOf() = given { actual -> + if (actual.filterIsInstance().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. * diff --git a/assertk/src/commonTest/kotlin/test/assertk/assertions/IterableTest.kt b/assertk/src/commonTest/kotlin/test/assertk/assertions/IterableTest.kt index 79ed523b..63038b4a 100644 --- a/assertk/src/commonTest/kotlin/test/assertk/assertions/IterableTest.kt +++ b/assertk/src/commonTest/kotlin/test/assertk/assertions/IterableTest.kt @@ -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 @@ -9,9 +10,11 @@ import assertk.assertions.contains import assertk.assertions.containsAtLeast 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 @@ -229,6 +232,32 @@ class IterableTest { } //endregion + //region containsInstanceOf + @Test fun containsInstanceOf_element_present_passes() { + assertThat(iterableOf(1, "two")).containsInstanceOf().single().isEqualTo("two") + } + + @Test fun containsInstanceOf_element_missing_fails() { + val error = assertFailsWith { + assertThat(iterableOf(1, "two")).containsInstanceOf() + } + 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() { + assertThat(iterableOf(1, "two")).doesNotContainInstanceOf() + } + 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() + } + //endregion + //region each @Test fun each_empty_list_passes() { From 3afef391993298e7431985f48be66d13b4deaae4 Mon Sep 17 00:00:00 2001 From: Justin Brooks Date: Mon, 30 Sep 2024 08:36:08 -0400 Subject: [PATCH 2/7] Use none --- assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt b/assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt index 63760c37..a58688f7 100644 --- a/assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt +++ b/assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt @@ -158,7 +158,7 @@ inline fun Assert>.containsInstanceOf(): Assert> * ``` */ inline fun Assert>.doesNotContainInstanceOf() = given { actual -> - if (actual.filterIsInstance().isNotEmpty()) expected("to contain no instances of ${T::class} but was $actual") + if (actual.none { it is T }) expected("to contain no instances of ${T::class} but was $actual") } /** From 9e0cb3a0431fec3890c69c45a8a5915bbaf3ab65 Mon Sep 17 00:00:00 2001 From: Justin Brooks Date: Mon, 30 Sep 2024 08:36:40 -0400 Subject: [PATCH 3/7] Update error message for consistency --- assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt b/assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt index a58688f7..d43229ff 100644 --- a/assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt +++ b/assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt @@ -158,7 +158,7 @@ inline fun Assert>.containsInstanceOf(): Assert> * ``` */ inline fun Assert>.doesNotContainInstanceOf() = given { actual -> - if (actual.none { it is T }) expected("to contain no instances of ${T::class} but was $actual") + if (actual.none { it is T }) expected("to not contain instances of ${T::class} but was $actual") } /** From e3f15e9d86bb9493b644b92d776f43893f792ddd Mon Sep 17 00:00:00 2001 From: Justin Brooks Date: Mon, 30 Sep 2024 10:20:23 -0400 Subject: [PATCH 4/7] Flip logic --- assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt b/assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt index d43229ff..dbaaf9e3 100644 --- a/assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt +++ b/assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt @@ -158,7 +158,7 @@ inline fun Assert>.containsInstanceOf(): Assert> * ``` */ inline fun Assert>.doesNotContainInstanceOf() = given { actual -> - if (actual.none { it is T }) expected("to not contain instances of ${T::class} but was $actual") + if (actual.any { it is T }) expected("to not contain instances of ${T::class} but was $actual") } /** From 0f43f7e7b4298ec4e41fb168c5862949193a3ce1 Mon Sep 17 00:00:00 2001 From: Justin Brooks Date: Mon, 30 Sep 2024 10:22:06 -0400 Subject: [PATCH 5/7] Update assertion message --- .../commonTest/kotlin/test/assertk/assertions/IterableTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assertk/src/commonTest/kotlin/test/assertk/assertions/IterableTest.kt b/assertk/src/commonTest/kotlin/test/assertk/assertions/IterableTest.kt index 63038b4a..4028c81d 100644 --- a/assertk/src/commonTest/kotlin/test/assertk/assertions/IterableTest.kt +++ b/assertk/src/commonTest/kotlin/test/assertk/assertions/IterableTest.kt @@ -250,7 +250,7 @@ class IterableTest { val error = assertFailsWith() { assertThat(iterableOf(1, "two")).doesNotContainInstanceOf() } - assertEquals("expected to contain no instances of class kotlin.String but was [1, two]", error.message) + assertEquals("expected to not contain instances of class kotlin.String but was [1, two]", error.message) } @Test fun doesNotContainInstanceOf_element_missing_passes() { From 167e5f7dc7633e823008e828a4fcd406e2010989 Mon Sep 17 00:00:00 2001 From: Justin Brooks Date: Mon, 30 Sep 2024 10:22:40 -0400 Subject: [PATCH 6/7] Add array filtering --- .../kotlin/assertk/assertions/array.kt | 28 +++++++++++++++++++ .../test/assertk/assertions/ArrayTest.kt | 26 +++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/assertk/src/commonMain/kotlin/assertk/assertions/array.kt b/assertk/src/commonMain/kotlin/assertk/assertions/array.kt index db67357b..0960b68c 100644 --- a/assertk/src/commonMain/kotlin/assertk/assertions/array.kt +++ b/assertk/src/commonMain/kotlin/assertk/assertions/array.kt @@ -178,6 +178,34 @@ fun Assert>.containsExactly(vararg elements: Any?) = given { actual -> expectedListDiff(elements.asList(), actual.asList()) } +/** + * Asserts the collection contains at least one instance of a given type. + * + * ``` + * assertThat(arrayOf("one", "two", 1)).containsInstanceOf().each { + * it.hasLength(3) + * } + * ``` + */ +inline fun Assert>.containsInstanceOf(): Assert> { + return transform("contains subtype of ${T::class}") { actual -> + actual.filterIsInstance().also { + if (it.isEmpty()) expected("to contain at least one instance of ${T::class} but was ${actual.asList()}") + } + } +} + +/** + * Asserts the collection does not contain an instance of a given type. + * + * ``` + * assertThat(arrayOf("one", "two", 1)).doesNotContainInstanceOf() + * ``` + */ +inline fun Assert>.doesNotContainInstanceOf() = given { actual -> + if (actual.any { it is T }) expected("to not contain instances of ${T::class} but was ${actual.asList()}") +} + /** * Asserts on each item in the array. The given lambda will be run for each item. * diff --git a/assertk/src/commonTest/kotlin/test/assertk/assertions/ArrayTest.kt b/assertk/src/commonTest/kotlin/test/assertk/assertions/ArrayTest.kt index 23b096e4..348a9b99 100644 --- a/assertk/src/commonTest/kotlin/test/assertk/assertions/ArrayTest.kt +++ b/assertk/src/commonTest/kotlin/test/assertk/assertions/ArrayTest.kt @@ -322,6 +322,32 @@ class ArrayTest { } //endregion + //region containsInstanceOf + @Test fun containsInstanceOf_element_present_passes() { + assertThat(arrayOf(1, "two")).containsInstanceOf().single().isEqualTo("two") + } + + @Test fun containsInstanceOf_element_missing_fails() { + val error = assertFailsWith { + assertThat(arrayOf(1, "two")).containsInstanceOf() + } + 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() { + assertThat(arrayOf(1, "two")).doesNotContainInstanceOf() + } + assertEquals("expected to not contain instances of class kotlin.String but was [1, two]", error.message) + } + + @Test fun doesNotContainInstanceOf_element_missing_passes() { + assertThat(arrayOf(1, "two")).doesNotContainInstanceOf() + } + //endregion + //region each @Test fun each_empty_list_passes() { From d2e7108a46337720bfac778772480e67f82317ff Mon Sep 17 00:00:00 2001 From: Justin Brooks Date: Sat, 14 Dec 2024 10:44:41 -0500 Subject: [PATCH 7/7] Update function names --- CHANGELOG.md | 2 +- .../commonMain/kotlin/assertk/assertions/array.kt | 10 +++++----- .../kotlin/assertk/assertions/iterable.kt | 10 ++++------ .../kotlin/test/assertk/assertions/ArrayTest.kt | 8 ++++---- .../kotlin/test/assertk/assertions/IterableTest.kt | 13 ++++++------- 5 files changed, 20 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2af98624..a4f2b2e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - Added `doesNotExist` assertions to `Path` -- Added `containsInstanceOf` and `doesNotContainInstanceOf` for `Iterable` +- Added `havingInstancesOf` and `notHavingInstancesOf` for `Iterable` and `Array` ## [0.28.1] 2024-04-17 diff --git a/assertk/src/commonMain/kotlin/assertk/assertions/array.kt b/assertk/src/commonMain/kotlin/assertk/assertions/array.kt index 0960b68c..74f430d4 100644 --- a/assertk/src/commonMain/kotlin/assertk/assertions/array.kt +++ b/assertk/src/commonMain/kotlin/assertk/assertions/array.kt @@ -182,13 +182,13 @@ fun Assert>.containsExactly(vararg elements: Any?) = given { actual -> * Asserts the collection contains at least one instance of a given type. * * ``` - * assertThat(arrayOf("one", "two", 1)).containsInstanceOf().each { + * assertThat(arrayOf("one", "two", 1)).havingInstanceOf().each { * it.hasLength(3) * } * ``` */ -inline fun Assert>.containsInstanceOf(): Assert> { - return transform("contains subtype of ${T::class}") { actual -> +inline fun Assert>.havingInstancesOf(): Assert> { + return transform("contains instances of ${T::class}") { actual -> actual.filterIsInstance().also { if (it.isEmpty()) expected("to contain at least one instance of ${T::class} but was ${actual.asList()}") } @@ -199,10 +199,10 @@ inline fun Assert>.containsInstanceOf(): Assert> { * Asserts the collection does not contain an instance of a given type. * * ``` - * assertThat(arrayOf("one", "two", 1)).doesNotContainInstanceOf() + * assertThat(arrayOf("one", "two", 1)).havingInstancesOf() * ``` */ -inline fun Assert>.doesNotContainInstanceOf() = given { actual -> +inline fun Assert>.notHavingInstancesOf() = given { actual -> if (actual.any { it is T }) expected("to not contain instances of ${T::class} but was ${actual.asList()}") } diff --git a/assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt b/assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt index dbaaf9e3..ba5d43a0 100644 --- a/assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt +++ b/assertk/src/commonMain/kotlin/assertk/assertions/iterable.kt @@ -2,12 +2,10 @@ 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`. @@ -137,13 +135,13 @@ internal fun MutableList<*>.removeFirst(value: Any?) { * Asserts the collection contains at least one instance of a given type. * * ``` - * assertThat(listOf("one", "two", 1)).containsInstanceOf().each { + * assertThat(listOf("one", "two", 1)).havingInstanceOf().each { * it.hasLength(3) * } * ``` */ -inline fun Assert>.containsInstanceOf(): Assert> { - return transform("contains subtype of ${T::class}") { actual -> +inline fun Assert>.havingInstancesOf(): Assert> { + return transform("contains instance of ${T::class}") { actual -> actual.filterIsInstance().also { if (it.isEmpty()) expected("to contain at least one instance of ${T::class} but was $actual") } @@ -157,7 +155,7 @@ inline fun Assert>.containsInstanceOf(): Assert> * assertThat(listOf("one", "two", 1)).doesNotContainInstanceOf() * ``` */ -inline fun Assert>.doesNotContainInstanceOf() = given { actual -> +inline fun Assert>.notHavingInstancesOf() = given { actual -> if (actual.any { it is T }) expected("to not contain instances of ${T::class} but was $actual") } diff --git a/assertk/src/commonTest/kotlin/test/assertk/assertions/ArrayTest.kt b/assertk/src/commonTest/kotlin/test/assertk/assertions/ArrayTest.kt index 348a9b99..4581a1b0 100644 --- a/assertk/src/commonTest/kotlin/test/assertk/assertions/ArrayTest.kt +++ b/assertk/src/commonTest/kotlin/test/assertk/assertions/ArrayTest.kt @@ -324,12 +324,12 @@ class ArrayTest { //region containsInstanceOf @Test fun containsInstanceOf_element_present_passes() { - assertThat(arrayOf(1, "two")).containsInstanceOf().single().isEqualTo("two") + assertThat(arrayOf(1, "two")).havingInstancesOf().single().isEqualTo("two") } @Test fun containsInstanceOf_element_missing_fails() { val error = assertFailsWith { - assertThat(arrayOf(1, "two")).containsInstanceOf() + assertThat(arrayOf(1, "two")).havingInstancesOf() } assertEquals("expected to contain at least one instance of class kotlin.Double but was [1, two]", error.message) } @@ -338,13 +338,13 @@ class ArrayTest { //region doesNotContainInstanceOf @Test fun doesNotContainInstanceOf_element_present_fails() { val error = assertFailsWith() { - assertThat(arrayOf(1, "two")).doesNotContainInstanceOf() + assertThat(arrayOf(1, "two")).notHavingInstancesOf() } assertEquals("expected to not contain instances of class kotlin.String but was [1, two]", error.message) } @Test fun doesNotContainInstanceOf_element_missing_passes() { - assertThat(arrayOf(1, "two")).doesNotContainInstanceOf() + assertThat(arrayOf(1, "two")).notHavingInstancesOf() } //endregion diff --git a/assertk/src/commonTest/kotlin/test/assertk/assertions/IterableTest.kt b/assertk/src/commonTest/kotlin/test/assertk/assertions/IterableTest.kt index 4028c81d..ca6d00ea 100644 --- a/assertk/src/commonTest/kotlin/test/assertk/assertions/IterableTest.kt +++ b/assertk/src/commonTest/kotlin/test/assertk/assertions/IterableTest.kt @@ -1,7 +1,6 @@ package test.assertk.assertions import assertk.all -import assertk.assertFailure import assertk.assertThat import assertk.assertions.any import assertk.assertions.atLeast @@ -10,11 +9,11 @@ import assertk.assertions.contains import assertk.assertions.containsAtLeast import assertk.assertions.containsExactly import assertk.assertions.containsExactlyInAnyOrder -import assertk.assertions.containsInstanceOf +import assertk.assertions.havingInstancesOf import assertk.assertions.containsNone import assertk.assertions.containsOnly import assertk.assertions.doesNotContain -import assertk.assertions.doesNotContainInstanceOf +import assertk.assertions.notHavingInstancesOf import assertk.assertions.each import assertk.assertions.exactly import assertk.assertions.extracting @@ -234,12 +233,12 @@ class IterableTest { //region containsInstanceOf @Test fun containsInstanceOf_element_present_passes() { - assertThat(iterableOf(1, "two")).containsInstanceOf().single().isEqualTo("two") + assertThat(iterableOf(1, "two")).havingInstancesOf().single().isEqualTo("two") } @Test fun containsInstanceOf_element_missing_fails() { val error = assertFailsWith { - assertThat(iterableOf(1, "two")).containsInstanceOf() + assertThat(iterableOf(1, "two")).havingInstancesOf() } assertEquals("expected to contain at least one instance of class kotlin.Double but was [1, two]", error.message) } @@ -248,13 +247,13 @@ class IterableTest { //region doesNotContainInstanceOf @Test fun doesNotContainInstanceOf_element_present_fails() { val error = assertFailsWith() { - assertThat(iterableOf(1, "two")).doesNotContainInstanceOf() + assertThat(iterableOf(1, "two")).notHavingInstancesOf() } assertEquals("expected to not contain instances of class kotlin.String but was [1, two]", error.message) } @Test fun doesNotContainInstanceOf_element_missing_passes() { - assertThat(iterableOf(1, "two")).doesNotContainInstanceOf() + assertThat(iterableOf(1, "two")).notHavingInstancesOf() } //endregion