diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 91f76ffb0..eeb4f1511 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -96,7 +96,16 @@ Please write a comment such as `I am working on this` in the issue, this way we can assign the task to you (so that others know there is already someone working on the issue) and it gives us the chance to have a look at the description again and revise if necessary. +*Architecture* + +The following diagram illustrates the current architecture of Atrium and what it meant to add a shortcut for `Throwable.cause`. Many times, especially in [good first issues](https://github.com/robstoll/atrium/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) we refer to this names and they are also reflected in the directory structure of the project. + +![Component diagram](https://raw.githubusercontent.com/robstoll/atrium/gh-pages/components.png?sanitize=true6) + + +*Git* + Dealing with Git for the first time? Here are some recommendations for how to set up Git when working on an issue: - create a new branch for the issue using `git checkout -b ` (preferrably, the branch name should be descriptive of the issue or the change being made, e.g `#108-path-exists`.) Working diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 571dedf98..90050329f 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,4 +1,4 @@ ----- +______________________________________ I confirm that I have read the [Contributor Agreements v1.0](https://github.com/robstoll/atrium/blob/master/.github/Contributor%20Agreements%20v1.0.txt), agree to be bound on them and confirm that my contribution is compliant. diff --git a/.github/workflows/java-windows.yml b/.github/workflows/java-windows.yml index 4071cbd02..eeb4911ad 100644 --- a/.github/workflows/java-windows.yml +++ b/.github/workflows/java-windows.yml @@ -18,9 +18,14 @@ jobs: java-version: ${{ matrix.java_version }} - name: Build buildNonDeprecatedJvm run: ./gradlew buildNonDeprecatedJvm + env: + CI: true - name: build sample atrium+spek project run: samples\jvm\spek\gradlew -p samples\jvm\spek build - name: Build sample atrium+junit5 project run: samples\jvm\junit5\gradlew -p samples\jvm\junit5 build + + - name: Build sample atrium+mpp kotlin project + run: samples\multiplatform\gradlew -p samples\multiplatform build diff --git a/.github/workflows/validate-gradle-wrapper.yml b/.github/workflows/validate-gradle-wrapper.yml new file mode 100644 index 000000000..cbf839cf4 --- /dev/null +++ b/.github/workflows/validate-gradle-wrapper.yml @@ -0,0 +1,10 @@ +name: "Validate Gradle Wrapper" +on: [push, pull_request] + +jobs: + validation: + name: "Validation" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: gradle/wrapper-validation-action@v1 diff --git a/.travis.yml b/.travis.yml index 2ee46bd82..de7c23f23 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,6 +32,7 @@ jobs: script: - samples/jvm/spek/gradlew -p ./samples/jvm/spek build - samples/jvm/junit5/gradlew -p ./samples/jvm/junit5 build + - samples/multiplatform/gradlew -p ./samples/multiplatform/ build before_cache: - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock diff --git a/LICENSE.txt b/LICENSE.txt index fd1d5d16b..74a0faa17 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Atrium © Copyright Robert Stoll 2017, 2019 +Atrium © Copyright Robert Stoll 2017, 2020 EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016 diff --git a/README.md b/README.md index 26ebe9edd..45d513af0 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,21 @@ + + [![Download](https://api.bintray.com/packages/robstoll/tutteli-jars/atrium/images/download.svg)](https://bintray.com/robstoll/tutteli-jars/atrium/_latestVersion "Download from Bintray") [![EUPL](https://img.shields.io/badge/%E2%9A%96-EUPL%201.2-%230b45a6)](https://joinup.ec.europa.eu/collection/eupl/eupl-text-11-12 "License") [![atrium @ kotlinlang.slack.com](https://img.shields.io/static/v1?label=kotlinlang&message=atrium&color=blue&logo=slack)](https://kotlinlang.slack.com/messages/C887ZKGCQ "See invitation link under section FAQ") [![Build Status Travis](https://travis-ci.org/robstoll/atrium.svg?branch=master)](https://travis-ci.org/robstoll/atrium/branches) [![Build Status GitHub Actions](https://github.com/robstoll/atrium/workflows/Windows/badge.svg)](https://github.com/robstoll/atrium/actions/) -[![Coverage](https://codecov.io/gh/robstoll/atrium/branch/master/graph/badge.svg)](https://codecov.io/github/robstoll/atrium/branch/master) +[![Coverage](https://codecov.io/gh/robstoll/atrium/branch/master/graph/badge.svg)](https://codecov.io/github/robstoll/atrium/branch/master) [![Newcomers Welcome](https://img.shields.io/badge/%F0%9F%91%8B-Newcomers%20Welcome-blueviolet)](https://github.com/robstoll/atrium/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22 "Ask in slack for help") + + + # Atrium Atrium is an open-source multiplatform assertion library for Kotlin with support for JVM, JS and Android. It is designed to support multiple [APIs](#api-styles), different error reporting styles and [Internationalization](#internationalization-1) (i18n). @@ -20,10 +30,10 @@ Atrium currently provides two [API Styles](#api-styles): pure fluent and infix where both of them have their design focus on usability in conjunction with code completion functionality provided by your IDE. See [Examples](#examples) below to get a feel for how you could benefit from Atrium. ----- +--- ❗ You are taking a *sneak peek* at the next version. Please have a look at the README of the git tag in case you are looking for the documentation of the corresponding version. -For instance, the [README of v0.9.0](https://github.com/robstoll/atrium/tree/v0.9.0/README.md). +For instance, the [README of v0.10.0](https://github.com/robstoll/atrium/tree/v0.10.0/README.md). ---- @@ -63,7 +73,6 @@ For instance, the [README of v0.9.0](https://github.com/robstoll/atrium/tree/v0. - [KDoc - Code Documentation](#kdoc---code-documentation) - [Known Limitations](#known-limitations) - [FAQ](#faq) -- [Kotlin Bugs](#kotlin-bugs) - [Roadmap](#roadmap) - [Contributors and contribute](#contributors-and-contribute) - [Sponsors](#sponsors) @@ -79,7 +88,7 @@ but can also be retrieved directly from [bintray](https://bintray.com/robstoll/t *gradle*: ``` buildscript { - ext { atrium_version='0.9.0' } + ext { atrium_version='0.10.0' } } repositories { mavenCentral() @@ -103,6 +112,7 @@ You can enable them as follows: dependencies { testImplementation "ch.tutteli.atrium:atrium-api-fluent-en_GB-jdk8:$atrium_version" testImplementation "ch.tutteli.atrium:atrium-api-fluent-en_GB-kotlin_1_3:$atrium_version" + testRuntimeOnly "ch.tutteli.atrium:atrium-domain-robstoll-kotlin_1_3:$atrium_version" } ``` @@ -110,7 +120,7 @@ dependencies { click to see how the setup for the infix API looks like -The new infix API which is based on `Expect` and no longer on `Assert` is not yet available in v0.9.0. +The new infix API which is based on `Expect` and no longer on `Assert` is not yet available in v0.10.0. [Your help](https://github.com/robstoll/atrium/issues?utf8=%E2%9C%93&q=is%3Aopen+label%3A%22good+first+issue%22++new+infix) in bringing the new infix API forward is appreciated. @@ -147,7 +157,7 @@ That is all, you are all set. Jump to [Examples](#examples) which shows how to u ``` buildscript { - ext { atrium_version='0.9.0' } + ext { atrium_version='0.10.0' } } repositories { mavenCentral() @@ -193,6 +203,7 @@ You can enable them as follows: ``` dependencies { testImplementation "ch.tutteli.atrium:atrium-api-fluent-en_GB-kotlin_1_3-js:$atrium_version" + testRuntimeOnly "ch.tutteli.atrium:atrium-domain-robstoll-kotlin_1_3-js:$atrium_version" } ``` @@ -200,7 +211,7 @@ dependencies { click to see how the setup for the infix API looks like -The new infix API which is based on `Expect` and no longer on `Assert` is not yet available in v0.9.0. +The new infix API which is based on `Expect` and no longer on `Assert` is not yet available in v0.10.0. [Your help](https://github.com/robstoll/atrium/issues?utf8=%E2%9C%93&q=is%3Aopen+label%3A%22good+first+issue%22++new+infix) in bringing the new infix API forward is appreciated. @@ -506,7 +517,7 @@ expected that subject: Person(firstName=Robert, lastName=Stoll, isStudent=false) We are sorry that the syntax is not yet the nicest one. We admit that one has to get used to it first and that is a pity. -Yet, it is due to many [Kotlin Bugs](#kotlin-bugs) standing in the way -- +Yet, it is due to many [Kotlin Bugs](https://github.com/robstoll/atrium/wiki/Kotlin-Bugs-and-missing-features) standing in the way -- we hope we can provide a better API once Kotlin 1.4 is out (the new type inference respectively). `feature` has several overloads, we are looking at the one expecting a lambda in which you have to provide a `MetaFeature`. @@ -581,7 +592,7 @@ if the property as such is renamed (e.g., as part of an IDE refactoring). As you can see, you would need to keep the property name and the name of the assertion function in sync to be meaningful (otherwise one gets quickly confused or has to remember two names for the same thing). -Writing assertion functions for methods is a different story though, especially due to [overload bugs in Kotlin](#kotlin-bugs). +Writing assertion functions for methods is a different story though, especially due to [overload bugs in Kotlin](https://github.com/robstoll/atrium/wiki/Kotlin-Bugs-and-missing-features). Also, code completion is not yet as good as it should be when it comes to methods. Last but not least, in case it is not always safe to call a method (e.g. `List.get` => IndexOutOfBound) then it makes sense to wrap it into an assertion function and use `ExpectImpl.feature.extractor` instead. @@ -712,7 +723,7 @@ Also this version of `feature` provides to kind of overloads, one without and on ### Ambiguity Problems Unfortunately there are several Kotlin bugs when it comes to overloading, especially in conjunction with `KFunction` -(see [Kotlin Bugs](#kotlin-bugs) and upvote in case you run into one). +(see [Kotlin Bugs](https://github.com/robstoll/atrium/wiki/Kotlin-Bugs-and-missing-features) and upvote in case you run into one). However, Atrium provides alternative functions next to `f` within the `MetaFeature`-provider-lambda to disambiguate the situation. Use `p` for properties and `f0` to `f5` for methods. Likely you need to specify the type parameters manually as Kotlin is not able to infer them correctly. @@ -1460,7 +1471,7 @@ expected that subject: "calling myFun with ..." <1234789> The example should be self explanatory. One detail to note though is the usage of `subExpect`. -It is a helper function which circumvents certain [Kotlin type inference bugs](#kotlin-bugs) (upvote them please). +It is a helper function which circumvents certain [Kotlin type inference bugs](https://github.com/robstoll/atrium/wiki/Kotlin-Bugs-and-missing-features) (upvote them please). Writing the same as `mapOf.() -> Unit>( 1 to { ... } )` would not work as the type for a lambda involved in a `Pair` is not (yet) inferred correctly by Kotlin. @@ -2425,49 +2436,6 @@ Deprecated APIs: See [Ambiguity Problems](#ambiguity-problems) and [Property does not exist](#property-does-not-exist). -# Kotlin Bugs -The following issues hinder Atrium to progress in certain areas or they are the reason that we cannot use Atrium as intended in all cases. -Please upvote them (especially if you encounter them yourself): -- [Symbol is declared in unnamed module](https://youtrack.jetbrains.com/issue/KT-35343) -- [Gradle runtimeOnly bug](https://youtrack.jetbrains.com/issue/KT-21685) (reason that you see functions from package cc.en_GB when using cc.infix.en_GB) -- [navigate to source or show KDoc for overloaded extension function](https://youtrack.jetbrains.com/issue/KT-24836) -- [Lower bounds](https://youtrack.jetbrains.com/issue/KT-209), i.a. that functions intended for nullable subject do not show up on non-nullable subjects. -- [CTRL+P shows extension functions of unrelated type](https://youtrack.jetbrains.com/issue/KT-29133) -- [Expose @OnlyInputTypes to restrict e.g. toBe](https://youtrack.jetbrains.com/issue/KT-13198) -- [Type inference KFunction overload bug 1](https://youtrack.jetbrains.com/issue/KT-17340) -- [Type inference KFunction overload bug 2](https://youtrack.jetbrains.com/issue/KT-19884) -- [Type inference KProperty/KFunction ambiguity bug](https://youtrack.jetbrains.com/issue/KT-17341) -- [Type inference fails to infer T of KFunction0 for most types](https://youtrack.jetbrains.com/issue/KT-29515) -- [Type inference type parameter bug](https://youtrack.jetbrains.com/issue/KT-12963) -- [Type inference return type bug](https://youtrack.jetbrains.com/issue/KT-24918) -- [Type inference out type parameter bug](https://youtrack.jetbrains.com/issue/KT-18401) -- [Type inference explicit type and overloads](https://youtrack.jetbrains.com/issue/KT-23791) -- [Type inference Pair with receiver type](https://youtrack.jetbrains.com/issue/KT-29129) -- [Type inference unable to infer primitive type](https://youtrack.jetbrains.com/issue/KT-33290) -- [Overload resolution null bug](https://youtrack.jetbrains.com/issue/KT-6591) (reason why you need to specify what type `null` is in the infix API when using `assert(listOf(...)) contains null`) -- [Extension resolution null as receiver bug](https://youtrack.jetbrains.com/issue/KT-30496) (reason why you need to define that `null to null` is a Pair in the infix API) -- [Overload resolution nullable bug](https://youtrack.jetbrains.com/issue/KT-23768) -- [Overload resolution primitive type bug](https://youtrack.jetbrains.com/issue/KT-24230) -- [Overload resolution function type bug](https://youtrack.jetbrains.com/issue/KT-23883) -- [Overload resolution generic upper bound bug](https://youtrack.jetbrains.com/issue/KT-30235) -- [Overload ambiguity between val and fun](https://youtrack.jetbrains.com/issue/KT-32958) -- [false positive: remove explicit type arguments](https://youtrack.jetbrains.com/issue/KT-32869) -- [Wrong JS generated in case of name clash](https://youtrack.jetbrains.com/issue/KT-33294) -- [forbid function types as substitute of reified types ](https://youtrack.jetbrains.com/issue/KT-27846) -- [forbid parameterised types as substitute of reified types](https://youtrack.jetbrains.com/issue/KT-27826) -- [ReplaceWith does not add type parameter](https://youtrack.jetbrains.com/issue/KT-33685) -- [Wrong warning about predetermined type parameter](https://youtrack.jetbrains.com/issue/KT-34257) - -And some features which would be handy -- [hide function with deprecation level error in code completion](https://youtrack.jetbrains.com/issue/KT-25263) -- [Method reference without `this`](https://youtrack.jetbrains.com/issue/KT-22920) -- [Infix function call with type parameters](https://youtrack.jetbrains.com/issue/KT-21593) -- [Extensibility for infix API](https://youtrack.jetbrains.com/issue/KT-27659) -- [Summarising overloads in code completion](https://youtrack.jetbrains.com/issue/KT-25079) -- [vararg for lambdas](https://youtrack.jetbrains.com/issue/KT-24287) -- [delegate with inline modifier](https://youtrack.jetbrains.com/issue/KT-23241) - - # Roadmap The roadmap is maintained at [atrium-roadmap](https://github.com/robstoll/atrium-roadmap). diff --git a/apis/cc-en_GB/atrium-api-cc-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/en_GB/anyAssertions.kt b/apis/cc-en_GB/atrium-api-cc-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/en_GB/anyAssertions.kt index b022fdf6c..32ac01e50 100644 --- a/apis/cc-en_GB/atrium-api-cc-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/en_GB/anyAssertions.kt +++ b/apis/cc-en_GB/atrium-api-cc-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/en_GB/anyAssertions.kt @@ -164,14 +164,5 @@ val AssertionPlant.and: AssertionPlant get() = this * * @return This plant to support a fluent API. */ -@Deprecated( - "Switch from Assert to Expect; will be removed with 1.0.0", - ReplaceWith( - "this.asExpect().and(assertionCreator).asAssert()", - "ch.tutteli.atrium.domain.builders.migration.asExpect", - "ch.tutteli.atrium.domain.builders.migration.asAssert", - "ch.tutteli.atrium.api.fluent.en_GB.and" - ) -) infix fun AssertionPlant.and(assertionCreator: Assert.() -> Unit) = addAssertionsCreatedBy(assertionCreator) diff --git a/apis/cc-en_GB/atrium-api-cc-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/en_GB/arrayAssertions.kt b/apis/cc-en_GB/atrium-api-cc-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/en_GB/arrayAssertions.kt index 1e80672c4..3520f501b 100644 --- a/apis/cc-en_GB/atrium-api-cc-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/en_GB/arrayAssertions.kt +++ b/apis/cc-en_GB/atrium-api-cc-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/cc/en_GB/arrayAssertions.kt @@ -17,10 +17,10 @@ import kotlin.jvm.JvmName @Deprecated( "Switch from Assert to Expect; will be removed with 1.0.0", ReplaceWith( - "this.asExpect().asIterable().asAssert()", + "this.asExpect().asList().asAssert()", "ch.tutteli.atrium.domain.builders.migration.asExpect", "ch.tutteli.atrium.domain.builders.migration.asAssert", - "ch.tutteli.atrium.api.fluent.en_GB.asIterable" + "ch.tutteli.atrium.api.fluent.en_GB.asList" ) ) fun Assert>.asIterable(): Assert> = @@ -38,10 +38,10 @@ fun Assert>.asIterable(): Assert> = @Deprecated( "Switch from Assert to Expect; will be removed with 1.0.0", ReplaceWith( - "this.asExpect().asIterable().asAssert(assertionCreator)", + "this.asExpect().asList().asAssert(assertionCreator)", "ch.tutteli.atrium.domain.builders.migration.asExpect", "ch.tutteli.atrium.domain.builders.migration.asAssert", - "ch.tutteli.atrium.api.fluent.en_GB.asIterable" + "ch.tutteli.atrium.api.fluent.en_GB.asList" ) ) fun Assert>.asIterable(assertionCreator: Assert>.() -> Unit): Assert> = @@ -59,10 +59,10 @@ fun Assert>.asIterable(assertionCreator: Assert>.() @Deprecated( "Switch from Assert to Expect; will be removed with 1.0.0", ReplaceWith( - "this.asExpect().asIterable().asAssert()", + "this.asExpect().asList().asAssert()", "ch.tutteli.atrium.domain.builders.migration.asExpect", "ch.tutteli.atrium.domain.builders.migration.asAssert", - "ch.tutteli.atrium.api.fluent.en_GB.asIterable" + "ch.tutteli.atrium.api.fluent.en_GB.asList" ) ) @JvmName("byteArrAsIterable") @@ -81,10 +81,10 @@ fun Assert.asIterable(): Assert> = @Deprecated( "Switch from Assert to Expect; will be removed with 1.0.0", ReplaceWith( - "this.asExpect().asIterable().asAssert(assertionCreator)", + "this.asExpect().asList().asAssert(assertionCreator)", "ch.tutteli.atrium.domain.builders.migration.asExpect", "ch.tutteli.atrium.domain.builders.migration.asAssert", - "ch.tutteli.atrium.api.fluent.en_GB.asIterable" + "ch.tutteli.atrium.api.fluent.en_GB.asList" ) ) @JvmName("byteArrAsIterable") @@ -103,10 +103,10 @@ fun Assert.asIterable(assertionCreator: Assert>.() -> @Deprecated( "Switch from Assert to Expect; will be removed with 1.0.0", ReplaceWith( - "this.asExpect().asIterable().asAssert()", + "this.asExpect().asList().asAssert()", "ch.tutteli.atrium.domain.builders.migration.asExpect", "ch.tutteli.atrium.domain.builders.migration.asAssert", - "ch.tutteli.atrium.api.fluent.en_GB.asIterable" + "ch.tutteli.atrium.api.fluent.en_GB.asList" ) ) @JvmName("charArrAsIterable") @@ -125,10 +125,10 @@ fun Assert.asIterable(): Assert> = @Deprecated( "Switch from Assert to Expect; will be removed with 1.0.0", ReplaceWith( - "this.asExpect().asIterable().asAssert(assertionCreator)", + "this.asExpect().asList().asAssert(assertionCreator)", "ch.tutteli.atrium.domain.builders.migration.asExpect", "ch.tutteli.atrium.domain.builders.migration.asAssert", - "ch.tutteli.atrium.api.fluent.en_GB.asIterable" + "ch.tutteli.atrium.api.fluent.en_GB.asList" ) ) @JvmName("charArrAsIterable") @@ -147,10 +147,10 @@ fun Assert.asIterable(assertionCreator: Assert>.() -> @Deprecated( "Switch from Assert to Expect; will be removed with 1.0.0", ReplaceWith( - "this.asExpect().asIterable().asAssert()", + "this.asExpect().asList().asAssert()", "ch.tutteli.atrium.domain.builders.migration.asExpect", "ch.tutteli.atrium.domain.builders.migration.asAssert", - "ch.tutteli.atrium.api.fluent.en_GB.asIterable" + "ch.tutteli.atrium.api.fluent.en_GB.asList" ) ) @JvmName("shortArrAsIterable") @@ -169,10 +169,10 @@ fun Assert.asIterable(): Assert> = @Deprecated( "Switch from Assert to Expect; will be removed with 1.0.0", ReplaceWith( - "this.asExpect().asIterable().asAssert(assertionCreator)", + "this.asExpect().asList().asAssert(assertionCreator)", "ch.tutteli.atrium.domain.builders.migration.asExpect", "ch.tutteli.atrium.domain.builders.migration.asAssert", - "ch.tutteli.atrium.api.fluent.en_GB.asIterable" + "ch.tutteli.atrium.api.fluent.en_GB.asList" ) ) @JvmName("shortArrAsIterable") @@ -191,10 +191,10 @@ fun Assert.asIterable(assertionCreator: Assert>.() - @Deprecated( "Switch from Assert to Expect; will be removed with 1.0.0", ReplaceWith( - "this.asExpect().asIterable().asAssert()", + "this.asExpect().asList().asAssert()", "ch.tutteli.atrium.domain.builders.migration.asExpect", "ch.tutteli.atrium.domain.builders.migration.asAssert", - "ch.tutteli.atrium.api.fluent.en_GB.asIterable" + "ch.tutteli.atrium.api.fluent.en_GB.asList" ) ) @JvmName("intArrAsIterable") @@ -212,10 +212,10 @@ fun Assert.asIterable(): Assert> = ExpectImpl.changeSubj @Deprecated( "Switch from Assert to Expect; will be removed with 1.0.0", ReplaceWith( - "this.asExpect().asIterable().asAssert(assertionCreator)", + "this.asExpect().asList().asAssert(assertionCreator)", "ch.tutteli.atrium.domain.builders.migration.asExpect", "ch.tutteli.atrium.domain.builders.migration.asAssert", - "ch.tutteli.atrium.api.fluent.en_GB.asIterable" + "ch.tutteli.atrium.api.fluent.en_GB.asList" ) ) @JvmName("intArrAsIterable") @@ -234,10 +234,10 @@ fun Assert.asIterable(assertionCreator: Assert>.() -> Un @Deprecated( "Switch from Assert to Expect; will be removed with 1.0.0", ReplaceWith( - "this.asExpect().asIterable().asAssert()", + "this.asExpect().asList().asAssert()", "ch.tutteli.atrium.domain.builders.migration.asExpect", "ch.tutteli.atrium.domain.builders.migration.asAssert", - "ch.tutteli.atrium.api.fluent.en_GB.asIterable" + "ch.tutteli.atrium.api.fluent.en_GB.asList" ) ) @JvmName("longArrAsIterable") @@ -256,10 +256,10 @@ fun Assert.asIterable(): Assert> = @Deprecated( "Switch from Assert to Expect; will be removed with 1.0.0", ReplaceWith( - "this.asExpect().asIterable().asAssert(assertionCreator)", + "this.asExpect().asList().asAssert(assertionCreator)", "ch.tutteli.atrium.domain.builders.migration.asExpect", "ch.tutteli.atrium.domain.builders.migration.asAssert", - "ch.tutteli.atrium.api.fluent.en_GB.asIterable" + "ch.tutteli.atrium.api.fluent.en_GB.asList" ) ) @JvmName("longArrAsIterable") @@ -278,10 +278,10 @@ fun Assert.asIterable(assertionCreator: Assert>.() -> @Deprecated( "Switch from Assert to Expect; will be removed with 1.0.0", ReplaceWith( - "this.asExpect().asIterable().asAssert()", + "this.asExpect().asList().asAssert()", "ch.tutteli.atrium.domain.builders.migration.asExpect", "ch.tutteli.atrium.domain.builders.migration.asAssert", - "ch.tutteli.atrium.api.fluent.en_GB.asIterable" + "ch.tutteli.atrium.api.fluent.en_GB.asList" ) ) @JvmName("floatArrAsIterable") @@ -300,10 +300,10 @@ fun Assert.asIterable(): Assert> = @Deprecated( "Switch from Assert to Expect; will be removed with 1.0.0", ReplaceWith( - "this.asExpect().asIterable().asAssert(assertionCreator)", + "this.asExpect().asList().asAssert(assertionCreator)", "ch.tutteli.atrium.domain.builders.migration.asExpect", "ch.tutteli.atrium.domain.builders.migration.asAssert", - "ch.tutteli.atrium.api.fluent.en_GB.asIterable" + "ch.tutteli.atrium.api.fluent.en_GB.asList" ) ) @JvmName("floatArrAsIterable") @@ -322,10 +322,10 @@ fun Assert.asIterable(assertionCreator: Assert>.() - @Deprecated( "Switch from Assert to Expect; will be removed with 1.0.0", ReplaceWith( - "this.asExpect().asIterable().asAssert()", + "this.asExpect().asList().asAssert()", "ch.tutteli.atrium.domain.builders.migration.asExpect", "ch.tutteli.atrium.domain.builders.migration.asAssert", - "ch.tutteli.atrium.api.fluent.en_GB.asIterable" + "ch.tutteli.atrium.api.fluent.en_GB.asList" ) ) @JvmName("doubleArrAsIterable") @@ -344,10 +344,10 @@ fun Assert.asIterable(): Assert> = @Deprecated( "Switch from Assert to Expect; will be removed with 1.0.0", ReplaceWith( - "this.asExpect().asIterable().asAssert(assertionCreator)", + "this.asExpect().asList().asAssert(assertionCreator)", "ch.tutteli.atrium.domain.builders.migration.asExpect", "ch.tutteli.atrium.domain.builders.migration.asAssert", - "ch.tutteli.atrium.api.fluent.en_GB.asIterable" + "ch.tutteli.atrium.api.fluent.en_GB.asList" ) ) @JvmName("doubleArrAsIterable") @@ -366,10 +366,10 @@ fun Assert.asIterable(assertionCreator: Assert>.() @Deprecated( "Switch from Assert to Expect; will be removed with 1.0.0", ReplaceWith( - "this.asExpect().asIterable().asAssert()", + "this.asExpect().asList().asAssert()", "ch.tutteli.atrium.domain.builders.migration.asExpect", "ch.tutteli.atrium.domain.builders.migration.asAssert", - "ch.tutteli.atrium.api.fluent.en_GB.asIterable" + "ch.tutteli.atrium.api.fluent.en_GB.asList" ) ) @JvmName("boolArrAsIterable") @@ -388,10 +388,10 @@ fun Assert.asIterable(): Assert> = @Deprecated( "Switch from Assert to Expect; will be removed with 1.0.0", ReplaceWith( - "this.asExpect().asIterable().asAssert(assertionCreator)", + "this.asExpect().asList().asAssert(assertionCreator)", "ch.tutteli.atrium.domain.builders.migration.asExpect", "ch.tutteli.atrium.domain.builders.migration.asAssert", - "ch.tutteli.atrium.api.fluent.en_GB.asIterable" + "ch.tutteli.atrium.api.fluent.en_GB.asList" ) ) @JvmName("boolArrAsIterable") diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-android/build.gradle b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-android/build.gradle index 7997dbfbe..fc012fbfc 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-android/build.gradle +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-android/build.gradle @@ -5,6 +5,7 @@ dependencies { api prefixedProject('domain-builders-android') testImplementation prefixedProject('verbs-internal-android') + testImplementation prefixedProject('api-infix-en_GB-android') } srcAndResourcesFromJvmProject(project) diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/build.gradle b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/build.gradle index 6912f5606..ddeca8877 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/build.gradle +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/build.gradle @@ -13,6 +13,7 @@ dependencies { api prefixedProject('domain-builders-jvm') testImplementation prefixedProject('verbs-internal-jvm') + testImplementation prefixedProject('api-infix-en_GB-jvm') } //TODO should not be necessary https://youtrack.jetbrains.com/issue/KT-28124 diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/AnyAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/AnyAssertionsSpec.kt index 7f99a86a3..cb4b15dab 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/AnyAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/AnyAssertionsSpec.kt @@ -6,6 +6,7 @@ import ch.tutteli.atrium.creating.Assert import ch.tutteli.atrium.creating.AssertionPlantNullable import kotlin.reflect.KFunction2 +//TODO remove with 1.0.0, no need to migrate to Spek 2 class AnyAssertionsSpec : ch.tutteli.atrium.spec.integration.AnyAssertionsSpec( AssertionVerbFactory, AnyAssertionsSpecFunFactory(), diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/ArrayAsIterableAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/ArrayAsIterableAssertionsSpec.kt index 1534eb02f..43a55beaf 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/ArrayAsIterableAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/ArrayAsIterableAssertionsSpec.kt @@ -4,6 +4,7 @@ package ch.tutteli.atrium.api.cc.infix.en_GB import ch.tutteli.atrium.creating.Assert import ch.tutteli.atrium.verbs.internal.AssertionVerbFactory +//TODO remove with 1.0.0, no need to migrate to Spek 2 class ArrayAsIterableAssertionsSpec : ch.tutteli.atrium.spec.integration.ArrayAsIterableAssertionsSpec( AssertionVerbFactory, "asIterable", diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/BigDecimalAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/BigDecimalAssertionsSpec.kt index 1b6f4ba2f..71857e441 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/BigDecimalAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/BigDecimalAssertionsSpec.kt @@ -6,6 +6,7 @@ import ch.tutteli.atrium.creating.Assert import java.math.BigDecimal import kotlin.reflect.KFunction2 +//TODO remove with 1.0.0, no need to migrate to Spek 2 class BigDecimalAssertionsSpec : ch.tutteli.atrium.spec.integration.BigDecimalAssertionsSpec( AssertionVerbFactory, toBePair(), diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/BooleanAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/BooleanAssertionsSpec.kt index fd941b10d..83f4b0812 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/BooleanAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/BooleanAssertionsSpec.kt @@ -5,6 +5,7 @@ import ch.tutteli.atrium.verbs.internal.AssertionVerbFactory import ch.tutteli.atrium.creating.Assert import kotlin.reflect.KFunction2 +//TODO remove with 1.0.0, no need to migrate to Spek 2 class BooleanAssertionsSpec : ch.tutteli.atrium.spec.integration.BooleanAssertionsSpec( AssertionVerbFactory, toBeName() to Companion::toBeTrue, diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceAssertionsSpec.kt index 078b211d1..07c0d081c 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceAssertionsSpec.kt @@ -7,6 +7,7 @@ import ch.tutteli.atrium.creating.Assert import ch.tutteli.atrium.reporting.translating.Translatable import ch.tutteli.atrium.verbs.internal.AssertionVerbFactory +//TODO remove with 1.0.0, no need to migrate to Spek 2 class CharSequenceAssertionsSpec : ch.tutteli.atrium.spec.integration.CharSequenceAssertionsSpec( AssertionVerbFactory, getContainsDefaultTranslationOfPair(), diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsAtLeastAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsAtLeastAssertionsSpec.kt index ffb603708..8826501e4 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsAtLeastAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsAtLeastAssertionsSpec.kt @@ -6,6 +6,7 @@ import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.case import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.contain import ch.tutteli.atrium.creating.Assert +//TODO remove with 1.0.0, no need to migrate to Spek 2 class CharSequenceContainsAtLeastAssertionsSpec : ch.tutteli.atrium.spec.integration.CharSequenceContainsAtLeastAssertionsSpec( AssertionVerbFactory, getAtLeastTriple(), diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsAtMostAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsAtMostAssertionsSpec.kt index ac77043f5..dd1a60e43 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsAtMostAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsAtMostAssertionsSpec.kt @@ -6,6 +6,7 @@ import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.case import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.contain import ch.tutteli.atrium.creating.Assert +//TODO remove with 1.0.0, no need to migrate to Spek 2 class CharSequenceContainsAtMostAssertionsSpec : ch.tutteli.atrium.spec.integration.CharSequenceContainsAtMostAssertionsSpec( AssertionVerbFactory, getAtMostTriple(), diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsContainsNotAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsContainsNotAssertionsSpec.kt index ba49143d9..fc70e3130 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsContainsNotAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsContainsNotAssertionsSpec.kt @@ -5,6 +5,7 @@ import ch.tutteli.atrium.verbs.internal.AssertionVerbFactory import ch.tutteli.atrium.creating.Assert import kotlin.reflect.KFunction2 +//TODO remove with 1.0.0, no need to migrate to Spek 2 class CharSequenceContainsContainsNotAssertionsSpec : ch.tutteli.atrium.spec.integration.CharSequenceContainsContainsNotAssertionsSpec( AssertionVerbFactory, getContainsPair(), diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsExactlyAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsExactlyAssertionsSpec.kt index d8d3980d9..805e10e03 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsExactlyAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsExactlyAssertionsSpec.kt @@ -6,6 +6,7 @@ import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.case import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.contain import ch.tutteli.atrium.creating.Assert +//TODO remove with 1.0.0, no need to migrate to Spek 2 class CharSequenceContainsExactlyAssertionsSpec : ch.tutteli.atrium.spec.integration.CharSequenceContainsExactlyAssertionsSpec( AssertionVerbFactory, getExactlyTriple(), diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsNotAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsNotAssertionsSpec.kt index c925b24ec..6fceb4ff4 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsNotAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsNotAssertionsSpec.kt @@ -6,6 +6,7 @@ import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.case import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.contain import ch.tutteli.atrium.creating.Assert +//TODO remove with 1.0.0, no need to migrate to Spek 2 class CharSequenceContainsNotAssertionsSpec : ch.tutteli.atrium.spec.integration.CharSequenceContainsNotAssertionsSpec( AssertionVerbFactory, getContainsNotTriple(), diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsNotOrAtMostAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsNotOrAtMostAssertionsSpec.kt index b08fd2514..ee01944e0 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsNotOrAtMostAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsNotOrAtMostAssertionsSpec.kt @@ -6,6 +6,7 @@ import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.case import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.contain import ch.tutteli.atrium.creating.Assert +//TODO remove with 1.0.0, no need to migrate to Spek 2 class CharSequenceContainsNotOrAtMostAssertionsSpec : ch.tutteli.atrium.spec.integration.CharSequenceContainsNotOrAtMostAssertionsSpec( AssertionVerbFactory, getNotOrAtMostTriple(), diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsRegexAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsRegexAssertionsSpec.kt index 31de2d036..bb0e73b0c 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsRegexAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsRegexAssertionsSpec.kt @@ -6,6 +6,7 @@ import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.case import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.contain import ch.tutteli.atrium.creating.Assert +//TODO remove with 1.0.0, no need to migrate to Spek 2 class CharSequenceContainsRegexAssertionsSpec : ch.tutteli.atrium.spec.integration.CharSequenceContainsRegexAssertionsSpec( AssertionVerbFactory, getNameContainsRegex(), diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsSpecBase.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsSpecBase.kt index dbcf98e71..8dcb75f8e 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsSpecBase.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CharSequenceContainsSpecBase.kt @@ -9,6 +9,7 @@ import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceConta import ch.tutteli.atrium.domain.creating.charsequence.contains.searchbehaviours.NoOpSearchBehaviour import kotlin.reflect.KFunction2 +//TODO remove with 1.0.0, no need to migrate to Spek 2 abstract class CharSequenceContainsSpecBase { private val containsNotFun: KFunction2, Any, Assert> = Assert::containsNot protected val toContain = "${Assert::to.name} ${contain::class.simpleName}" diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CollectionAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CollectionAssertionsSpec.kt index 42b56250f..5dd41321e 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CollectionAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CollectionAssertionsSpec.kt @@ -5,6 +5,7 @@ import ch.tutteli.atrium.verbs.internal.AssertionVerbFactory import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.Empty import ch.tutteli.atrium.creating.Assert +//TODO remove with 1.0.0, no need to migrate to Spek 2 class CollectionAssertionsSpec : ch.tutteli.atrium.spec.integration.CollectionAssertionsSpec( AssertionVerbFactory, Assert>::hasSize.name to Companion::hasSize, diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CollectionFeatureAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CollectionFeatureAssertionsSpec.kt index 2d3d9c887..c7c8d6ac3 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CollectionFeatureAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/CollectionFeatureAssertionsSpec.kt @@ -6,6 +6,7 @@ import ch.tutteli.atrium.verbs.internal.AssertionVerbFactory import kotlin.reflect.KProperty1 import kotlin.reflect.KFunction2 +//TODO remove with 1.0.0, no need to migrate to Spek 2 class CollectionFeatureAssertionsSpec : ch.tutteli.atrium.spec.integration.CollectionFeatureAssertionsSpec( AssertionVerbFactory, sizeVal.name to sizeVal, diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/ComparableAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/ComparableAssertionsSpec.kt index e933b627d..966c786f4 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/ComparableAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/ComparableAssertionsSpec.kt @@ -4,6 +4,7 @@ package ch.tutteli.atrium.api.cc.infix.en_GB import ch.tutteli.atrium.verbs.internal.AssertionVerbFactory import ch.tutteli.atrium.creating.Assert +//TODO remove with 1.0.0, no need to migrate to Spek 2 class ComparableAssertionsSpec : ch.tutteli.atrium.spec.integration.ComparableAssertionsSpec( AssertionVerbFactory, Assert::isLessThan.name to Companion::isLessThan, diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/FeatureAssertionsBoundedReferenceSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/FeatureAssertionsBoundedReferenceSpec.kt index ec182dde1..d2cfff8e5 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/FeatureAssertionsBoundedReferenceSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/FeatureAssertionsBoundedReferenceSpec.kt @@ -7,6 +7,7 @@ import ch.tutteli.atrium.spec.integration.TestData internal typealias F = Assert.() -> Unit +//TODO remove with 1.0.0, no need to migrate to Spek 2 class FeatureAssertionsBoundedReferenceSpec : ch.tutteli.atrium.spec.integration.FeatureAssertionsSpec( AssertionVerbFactory, propertyImmediate, diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/FeatureAssertionsBoundedReferenceWhenCollectingPlantSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/FeatureAssertionsBoundedReferenceWhenCollectingPlantSpec.kt index e83cb4d34..cac355b0b 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/FeatureAssertionsBoundedReferenceWhenCollectingPlantSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/FeatureAssertionsBoundedReferenceWhenCollectingPlantSpec.kt @@ -5,6 +5,7 @@ import ch.tutteli.atrium.creating.CollectingAssertionPlant import ch.tutteli.atrium.spec.integration.TestData import ch.tutteli.atrium.verbs.internal.AssertionVerbFactory +//TODO remove with 1.0.0, no need to migrate to Spek 2 class FeatureAssertionsBoundedReferenceWhenCollectingPlantSpec : ch.tutteli.atrium.spec.integration.FeatureAssertionsBoundedReferenceWhenCollectingPlantSpec( AssertionVerbFactory, propertyImmediate, diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/FeatureAssertionsClassReferenceSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/FeatureAssertionsClassReferenceSpec.kt index bf4080297..b377dbcb1 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/FeatureAssertionsClassReferenceSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/FeatureAssertionsClassReferenceSpec.kt @@ -5,6 +5,7 @@ import ch.tutteli.atrium.domain.builders.utils.subAssert import ch.tutteli.atrium.spec.integration.TestData import ch.tutteli.atrium.verbs.internal.AssertionVerbFactory +//TODO remove with 1.0.0, no need to migrate to Spek 2 class FeatureAssertionsClassReferenceSpec : ch.tutteli.atrium.spec.integration.FeatureAssertionsSpec( AssertionVerbFactory, propertyImmediate, diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableAllAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableAllAssertionsSpec.kt index 727c95cdd..6105c8d99 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableAllAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableAllAssertionsSpec.kt @@ -7,6 +7,7 @@ import org.jetbrains.spek.api.Spek import org.jetbrains.spek.api.include import kotlin.reflect.KFunction2 +//TODO remove with 1.0.0, no need to migrate to Spek 2 class IterableAllAssertionsSpec: Spek({ include(PredicateSpec) }) { diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableAnyAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableAnyAssertionsSpec.kt index 77f27ce0c..79d76e87a 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableAnyAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableAnyAssertionsSpec.kt @@ -10,6 +10,7 @@ import org.jetbrains.spek.api.Spek import org.jetbrains.spek.api.include import kotlin.reflect.KFunction2 +//TODO remove with 1.0.0, no need to migrate to Spek 2 class IterableAnyAssertionsSpec : Spek({ include(PredicateSpec) include(BuilderSpec) diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderAtLeast1EntriesAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderAtLeast1EntriesAssertionsSpec.kt index c32253cfa..94f7ad996 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderAtLeast1EntriesAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderAtLeast1EntriesAssertionsSpec.kt @@ -9,6 +9,7 @@ import org.jetbrains.spek.api.Spek import org.jetbrains.spek.api.include import kotlin.reflect.KFunction2 +//TODO remove with 1.0.0, no need to migrate to Spek 2 class IterableContainsInAnyOrderAtLeast1EntriesAssertionsSpec : Spek({ include(BuilderSpec) include(ShortcutSpec) diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec.kt index 715b089f7..870d88b0e 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec.kt @@ -9,6 +9,7 @@ import org.jetbrains.spek.api.Spek import org.jetbrains.spek.api.include import kotlin.reflect.KFunction2 +//TODO remove with 1.0.0, no need to migrate to Spek 2 class IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec : Spek({ include(BuilderSpec) include(ShortcutSpec) diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderAtLeastValuesAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderAtLeastValuesAssertionsSpec.kt index 61f99119c..ec09203d7 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderAtLeastValuesAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderAtLeastValuesAssertionsSpec.kt @@ -6,6 +6,7 @@ import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.contain import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.order import ch.tutteli.atrium.creating.Assert +//TODO remove with 1.0.0, no need to migrate to Spek 2 class IterableContainsInAnyOrderAtLeastValuesAssertionsSpec : ch.tutteli.atrium.spec.integration.IterableContainsInAnyOrderAtLeastValuesAssertionSpec( AssertionVerbFactory, getAtLeastTriple(), diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderAtMostValuesAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderAtMostValuesAssertionsSpec.kt index 9aa4eeccd..7005a5c6e 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderAtMostValuesAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderAtMostValuesAssertionsSpec.kt @@ -6,6 +6,7 @@ import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.contain import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.order import ch.tutteli.atrium.creating.Assert +//TODO remove with 1.0.0, no need to migrate to Spek 2 class IterableContainsInAnyOrderAtMostValuesAssertionsSpec : ch.tutteli.atrium.spec.integration.IterableContainsInAnyOrderAtMostValuesAssertionSpec( AssertionVerbFactory, getAtMostTriple(), diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderExactlyValuesAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderExactlyValuesAssertionsSpec.kt index 52c072596..1ec3531a6 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderExactlyValuesAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderExactlyValuesAssertionsSpec.kt @@ -6,6 +6,7 @@ import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.contain import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.order import ch.tutteli.atrium.creating.Assert +//TODO remove with 1.0.0, no need to migrate to Spek 2 class IterableContainsInAnyOrderExactlyValuesAssertionsSpec : ch.tutteli.atrium.spec.integration.IterableContainsInAnyOrderExactlyValuesAssertionsSpec( AssertionVerbFactory, getExactlyTriple(), diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderNotOrAtMostValuesAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderNotOrAtMostValuesAssertionsSpec.kt index 0be3539b0..92ebdf998 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderNotOrAtMostValuesAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderNotOrAtMostValuesAssertionsSpec.kt @@ -6,6 +6,7 @@ import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.contain import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.order import ch.tutteli.atrium.creating.Assert +//TODO remove with 1.0.0, no need to migrate to Spek 2 class IterableContainsInAnyOrderNotOrAtMostValuesAssertionsSpec : ch.tutteli.atrium.spec.integration.IterableContainsInAnyOrderNotOrAtMostValuesAssertionsSpec( AssertionVerbFactory, getNotOrAtMostTriple(), diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderOnlyEntriesAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderOnlyEntriesAssertionsSpec.kt index 0cc827383..0e8dc9f1f 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderOnlyEntriesAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderOnlyEntriesAssertionsSpec.kt @@ -7,6 +7,7 @@ import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.only import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.order import ch.tutteli.atrium.creating.Assert +//TODO remove with 1.0.0, no need to migrate to Spek 2 class IterableContainsInAnyOrderOnlyEntriesAssertionsSpec : ch.tutteli.atrium.spec.integration.IterableContainsInAnyOrderOnlyEntriesAssertionsSpec( AssertionVerbFactory, getContainsPair(), diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderOnlyValuesAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderOnlyValuesAssertionsSpec.kt index 830206ccc..8513624d0 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderOnlyValuesAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInAnyOrderOnlyValuesAssertionsSpec.kt @@ -7,6 +7,7 @@ import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.only import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.order import ch.tutteli.atrium.creating.Assert +//TODO remove with 1.0.0, no need to migrate to Spek 2 class IterableContainsInAnyOrderOnlyValuesAssertionsSpec : ch.tutteli.atrium.spec.integration.IterableContainsInAnyOrderOnlyValuesAssertionsSpec( AssertionVerbFactory, getContainsPair(), diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInOrderOnlyEntriesAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInOrderOnlyEntriesAssertionsSpec.kt index f0d72079f..c118e0ddd 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInOrderOnlyEntriesAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInOrderOnlyEntriesAssertionsSpec.kt @@ -10,6 +10,7 @@ import org.jetbrains.spek.api.Spek import org.jetbrains.spek.api.include import kotlin.reflect.KFunction2 +//TODO remove with 1.0.0, no need to migrate to Spek 2 class IterableContainsInOrderOnlyEntriesAssertionsSpec : Spek({ include(BuilderSpec) diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInOrderOnlyGroupedEntriesAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInOrderOnlyGroupedEntriesAssertionsSpec.kt index fb8c8159e..49eacecf0 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInOrderOnlyGroupedEntriesAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInOrderOnlyGroupedEntriesAssertionsSpec.kt @@ -6,6 +6,7 @@ import ch.tutteli.atrium.creating.Assert import ch.tutteli.atrium.domain.builders.utils.Group import ch.tutteli.atrium.verbs.internal.AssertionVerbFactory +//TODO remove with 1.0.0, no need to migrate to Spek 2 class IterableContainsInOrderOnlyGroupedEntriesAssertionsSpec : ch.tutteli.atrium.spec.integration.IterableContainsInOrderOnlyGroupedEntriesAssertionsSpec( AssertionVerbFactory, getContainsPair(), diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInOrderOnlyGroupedValuesAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInOrderOnlyGroupedValuesAssertionsSpec.kt index 496e162b2..b3ccba247 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInOrderOnlyGroupedValuesAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInOrderOnlyGroupedValuesAssertionsSpec.kt @@ -6,6 +6,7 @@ import ch.tutteli.atrium.creating.Assert import ch.tutteli.atrium.domain.builders.utils.Group import ch.tutteli.atrium.verbs.internal.AssertionVerbFactory +//TODO remove with 1.0.0, no need to migrate to Spek 2 class IterableContainsInOrderOnlyGroupedValuesAssertionsSpec : ch.tutteli.atrium.spec.integration.IterableContainsInOrderOnlyGroupedValuesAssertionsSpec( AssertionVerbFactory, getContainsPair(), diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInOrderOnlyValuesAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInOrderOnlyValuesAssertionsSpec.kt index ad894571b..b98d5ecad 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInOrderOnlyValuesAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsInOrderOnlyValuesAssertionsSpec.kt @@ -10,6 +10,7 @@ import org.jetbrains.spek.api.Spek import org.jetbrains.spek.api.include import kotlin.reflect.KFunction2 +//TODO remove with 1.0.0, no need to migrate to Spek 2 class IterableContainsInOrderOnlyValuesAssertionsSpec : Spek({ include(BuilderSpec) diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsNotEntriesAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsNotEntriesAssertionsSpec.kt index 3cb4fd1f5..4029386f5 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsNotEntriesAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsNotEntriesAssertionsSpec.kt @@ -5,6 +5,7 @@ import ch.tutteli.atrium.verbs.internal.AssertionVerbFactory import ch.tutteli.atrium.api.cc.infix.en_GB.keywords.contain import ch.tutteli.atrium.creating.Assert +//TODO remove with 1.0.0, no need to migrate to Spek 2 class IterableContainsNotEntriesAssertionsSpec : ch.tutteli.atrium.spec.integration.IterableContainsNotEntriesAssertionsSpec( AssertionVerbFactory, getContainsNotPair(), diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsNotValuesAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsNotValuesAssertionsSpec.kt index 2afdfecb7..520e36f6a 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsNotValuesAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsNotValuesAssertionsSpec.kt @@ -8,6 +8,7 @@ import org.jetbrains.spek.api.Spek import org.jetbrains.spek.api.include import kotlin.reflect.KFunction2 +//TODO remove with 1.0.0, no need to migrate to Spek 2 class IterableContainsNotValuesAssertionsSpec : Spek({ include(BuilderSpec) diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsSpecBase.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsSpecBase.kt index 3e1727919..4f72e6d82 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsSpecBase.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableContainsSpecBase.kt @@ -15,6 +15,7 @@ import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.* import ch.tutteli.atrium.verbs.internal.assert import kotlin.reflect.KFunction2 +//TODO remove with 1.0.0, no need to migrate to Spek 2 abstract class IterableContainsSpecBase { protected val Values = Values::class.simpleName private val Entries = Entries::class.simpleName diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableNoneAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableNoneAssertionsSpec.kt index bcecee904..4026db58e 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableNoneAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/IterableNoneAssertionsSpec.kt @@ -8,6 +8,7 @@ import org.jetbrains.spek.api.Spek import org.jetbrains.spek.api.include import kotlin.reflect.KFunction2 +//TODO remove with 1.0.0, no need to migrate to Spek 2 class IterableNoneAssertionsSpec : Spek({ include(PredicateSpec) diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/ListFeatureAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/ListFeatureAssertionsSpec.kt index fff8fe06b..f596156e5 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/ListFeatureAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/ListFeatureAssertionsSpec.kt @@ -12,6 +12,7 @@ import org.jetbrains.spek.api.Spek import org.jetbrains.spek.api.include import kotlin.reflect.KFunction2 +//TODO remove with 1.0.0, no need to migrate to Spek 2 class ListFeatureAssertionsSpec : Spek({ include(AtriumFeatureAssertionsSpec) diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapAsEntriesAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapAsEntriesAssertionsSpec.kt index 3184d4a98..8c343152c 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapAsEntriesAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapAsEntriesAssertionsSpec.kt @@ -4,6 +4,7 @@ package ch.tutteli.atrium.api.cc.infix.en_GB import ch.tutteli.atrium.creating.Assert import ch.tutteli.atrium.verbs.internal.AssertionVerbFactory +//TODO remove with 1.0.0, no need to migrate to Spek 2 class MapAsEntriesAssertionsSpec : ch.tutteli.atrium.spec.integration.MapAsEntriesAssertionsSpec( AssertionVerbFactory, "asEntries", diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapAssertionsSpec.kt index 5c9a0aca2..a398b227a 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapAssertionsSpec.kt @@ -8,6 +8,7 @@ import ch.tutteli.atrium.verbs.internal.AssertionVerbFactory import ch.tutteli.atrium.verbs.internal.assert import kotlin.reflect.KFunction2 +//TODO remove with 1.0.0, no need to migrate to Spek 2 class MapAssertionsSpec : ch.tutteli.atrium.spec.integration.MapAssertionsSpec( AssertionVerbFactory, containsFun.name to Companion::contains, diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapEntryAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapEntryAssertionsSpec.kt index 5f9a83a6c..9f10fbb06 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapEntryAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapEntryAssertionsSpec.kt @@ -4,6 +4,7 @@ package ch.tutteli.atrium.api.cc.infix.en_GB import ch.tutteli.atrium.creating.Assert import ch.tutteli.atrium.verbs.internal.AssertionVerbFactory +//TODO remove with 1.0.0, no need to migrate to Spek 2 class MapEntryAssertionsSpec : ch.tutteli.atrium.spec.integration.MapEntryAssertionsSpec( AssertionVerbFactory, isKeyValueFun.name to Companion::isKeyValue diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapEntryFeatureAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapEntryFeatureAssertionsSpec.kt index 97bca9024..2c753ee99 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapEntryFeatureAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapEntryFeatureAssertionsSpec.kt @@ -7,6 +7,7 @@ import ch.tutteli.atrium.verbs.internal.AssertionVerbFactory import kotlin.reflect.KFunction2 import kotlin.reflect.KProperty1 +//TODO remove with 1.0.0, no need to migrate to Spek 2 class MapEntryFeatureAssertionsSpec : ch.tutteli.atrium.spec.integration.MapEntryFeatureAssertionsSpec( AssertionVerbFactory, keyVal.name to keyVal, diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapFeatureAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapFeatureAssertionsSpec.kt index 3b5476710..50570d239 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapFeatureAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/MapFeatureAssertionsSpec.kt @@ -15,6 +15,7 @@ import kotlin.reflect.KProperty1 import ch.tutteli.atrium.verbs.internal.assert import java.lang.IllegalArgumentException +//TODO remove with 1.0.0, no need to migrate to Spek 2 class MapFeatureAssertionsSpec : Spek({ include(AtriumMapFeatureAssertionsSpec) diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/PairFeatureAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/PairFeatureAssertionsSpec.kt index 31ef93cbb..77c316d84 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/PairFeatureAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/PairFeatureAssertionsSpec.kt @@ -7,6 +7,7 @@ import ch.tutteli.atrium.verbs.internal.AssertionVerbFactory import kotlin.reflect.KFunction2 import kotlin.reflect.KProperty1 +//TODO remove with 1.0.0, no need to migrate to Spek 2 class PairFeatureAssertionsSpec : ch.tutteli.atrium.spec.integration.PairFeatureAssertionsSpec( AssertionVerbFactory, firstVal.name to firstVal, diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/ThrowableAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/ThrowableAssertionsSpec.kt index c147004b0..cc726db40 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/ThrowableAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/ThrowableAssertionsSpec.kt @@ -5,6 +5,7 @@ import ch.tutteli.atrium.verbs.internal.AssertionVerbFactory import ch.tutteli.atrium.creating.Assert import ch.tutteli.atrium.domain.creating.throwable.thrown.ThrowableThrown +//TODO remove with 1.0.0, no need to migrate to Spek 2 class ThrowableAssertionsSpec : ch.tutteli.atrium.spec.integration.ThrowableAssertionsSpec( AssertionVerbFactory, getToThrowTriple(), diff --git a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/TypeTransformationAssertionsSpec.kt b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/TypeTransformationAssertionsSpec.kt index a85ac0631..0ebb8eab3 100644 --- a/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/TypeTransformationAssertionsSpec.kt +++ b/apis/cc-infix-en_GB/atrium-api-cc-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/cc/infix/en_GB/TypeTransformationAssertionsSpec.kt @@ -8,6 +8,7 @@ import kotlin.reflect.KFunction import kotlin.reflect.KFunction2 +//TODO remove with 1.0.0, no need to migrate to Spek 2 class TypeTransformationAssertionsSpec : ch.tutteli.atrium.spec.integration.TypeTransformationAssertionsSpec( AssertionVerbFactory, getNotToBeNullPair(), diff --git a/apis/differences.md b/apis/differences.md index 1663e47f6..bd20f9781 100644 --- a/apis/differences.md +++ b/apis/differences.md @@ -14,19 +14,18 @@ These modules bundle: Following a list of the available bundle-modules. The links point to the KDoc of their included API where you find an overview of all available assertion functions of the API. -- [atrium-cc-de_CH-robstoll](https://robstoll.github.io/atrium/latest#/doc/ch.tutteli.atrium.api.cc.de_-c-h/index.html) -- [atrium-cc-en_GB-robstoll](https://robstoll.github.io/atrium/latest#/doc/ch.tutteli.atrium.api.cc.en_-g-b/index.html) -- [atrium-cc-infix-en_GB-robstoll](https://robstoll.github.io/atrium/latest#/doc/ch.tutteli.atrium.api.cc.infix.en_-g-b/index.html) +- [atrium-fluent-en_GB](https://robstoll.github.io/atrium/latest#/doc/ch.tutteli.atrium.api.fluent.en_-g-b/index.html) +- [atrium-infix-en_GB](https://robstoll.github.io/atrium/latest#/doc/ch.tutteli.atrium.api.infix.en_-g-b/index.html) ---- -Following an excerpt of a build.gradle file which uses two APIs (see +Following an excerpt of a build.gradle file which uses twit APIs (see [README#Installation](https://github.com/robstoll/atrium/tree/master/README.md#installation) for the rest): ``` dependencies { - testCompile "ch.tutteli:atrium-cc-en_GB-robstoll:$atrium_version" - testCompile "ch.tutteli:atrium-api-cc-infix-en_GB-jvm:$atrium_version" + testCompile "ch.tutteli:atrium-fluent-en_GB:$atrium_version" + testCompile "ch.tutteli:atrium-api-infix-en_GB:$atrium_version" } ``` @@ -34,25 +33,24 @@ The first dependency points to a bundle-module, the second one just adds the inf :warning: if you want to use the same API in different languages, then you have to make sure that you exclude all translation modules but one (I suggest you keep the one which is your primary language). -If you forget to do it, then the compiler will complain that you have the same enums multiple times on your classpath. +If you forget to dit it, then the compiler will complain that you have the same enums multiple times on your classpath. # Different API styles -Atrium provides different APIs where the API differ in its style and the language in which it is written. -This site focuses on the different styles of APIs and compares their en_GB versions. -We do not show every single difference but merely where the APIs differ in naming. -For instance, the assertion function `Assert.toBe`: +Atrium currently provides two API styles: fluent and infix. +We dit not show every single difference but merely where the APIs differ in naming. +For instance, the assertion function `Expect.toBe`: -*atrium-api-cc-en_GB* +*atrium-api-fluent-en_GB* ```kotlin -assert(x).toBe(2) +expect(x).toBe(2) ``` -*atrium-api-cc-infix-en_GB* +*atrium-api-infix-en_GB* ```kotlin -assert(x) toBe 2 +expect(x) toBe 2 ``` -is too similar, we will not list it here (ok, we did now but I guess you get the point). +is toit similar, we will not list it here (ok, we did now but I guess you get the point). ## Table of Content - [Empty CharSequence / Collection](#empty-charsequence--collection) @@ -69,42 +67,47 @@ is too similar, we will not list it here (ok, we did now but I guess you get the ## Empty CharSequence / Collection -*atrium-api-cc-en_GB* +*atrium-api-fluent-en_GB* ```kotlin -assert(x).isEmpty() -assert(x).isNotEmpty() +expect(x).isEmpty() +expect(x).isNotEmpty() ``` -*atrium-api-cc-infix-en_GB* +*atrium-api-infix-en_GB* ```kotlin -assert(x) toBe Empty -assert(x) notToBe Empty +expect(x) toBe empty +expect(x) notToBe empty ``` ## `and` property -*atrium-api-cc-en_GB* +*atrium-api-fluent-en_GB* ```kotlin -assert(x).isGreaterThan(1).and.isLessThan(10) -assert(x) { /*...*/ } and { /*...*/ } +expect(x).isGreaterThan(1).and.isLessThan(10) +expect(x) { /*...*/ } and { /*...*/ } ``` -*atrium-api-cc-infix-en_GB* +*atrium-api-infix-en_GB* ```kotlin -// does only support the group syntax -assert(x) { /*...*/ } and { /*...*/ } +expect(x) isGreaterThan 1 and o isLessThan 10 +expect(x) { /*...*/ } and { /*...*/ } ``` +Note that `o` is a filler object which is only there so that we can turn extension methods without parameters into +a method with one parameter and thus make it available as infix method. + ## CharSequence contains -*atrium-api-cc-en_GB* +*atrium-api-fluent-en_GB* ```kotlin -assert(x).contains("hello", "world") -assert(x).contains.atLeast(1).butAtMost(2).value("hello") -assert(x).contains.exactly(1).values("hello", "robert") -assert(x).contains.atMost(2).regex("h(e|a)llo") -assert(x).contains.ignoringCase.notOrAtMost(1).regex("h(e|a)llo", "[Rr]obert") +expect(x).contains("hello", "world") +expect(x).contains.atLeast(1).butAtMost(2).value("hello") +expect(x).contains.exactly(1).values("hello", "robert") +expect(x).contains.atMost(2).regex("h(e|a)llo") +expect(x).contains.atMost(2).regex(Regex("h(e|a)llo")) +expect(x).contains.ignoringCase.regex("h(e|a)llo", "[Rr]obert") +expect(x).contains.ignoringCase.notOrAtMost(1).elementsOf(anIterable) ``` Notice that the final steps `value`, `values` and `regex` @@ -113,39 +116,41 @@ are applicable to all shown examples (e.g. `exactly(1).values("hello", "robert")` could have been finished with `exactly(1).regex("h(e|a)llo")` as well). -*atrium-api-cc-infix-en_GB* +*atrium-api-infix-en_GB* ```kotlin -assert(x) contains Values("hello", "world") -assert(x) to contain atLeast 1 butAtMost 2 value "hello" -assert(x) to contain exactly 1 the Values("hello", "robert") -assert(x) to contain atMost 2 regex "h(e|a)llo" -assert(x) to contain ignoring case notOrAtMost 1 the RegexPatterns("h(e|a)llo", "[Rr]obert") +expect(x) contains values("hello", "world") +expect(x) contains o atLeast 1 butAtMost 2 value "hello" +expect(x) contains o exactly 1 the values("hello", "robert") +expect(x) contains o atMost 2 regex "h(e|a)llo" +expect(x) contains o atMost 2 matchFor Regex("h(e|a)llo") +expect(x) contains o ignoring case notOrAtMost 1 the regexPatterns("h(e|a)llo", "[Rr]obert") +expect(x) contains o ignoring case notOrAtMost 1 elementsOf anIterable ``` Notice that the final steps -`value`, `Values(...)`, `regex` and `RegexPatterns(..)` +`value`, `values(...)`, `regex` and `regexPatterns(..)` in the sophisticated assertion building process are applicable to all shown examples -(e.g. `exactly(1).values("hello", "robert")` could have been finished with `exactly(1).regex("h(e|a)llo")` as well). +(e.g. `exactly 1 values("hello", "robert")` could have been finished with `exactly 1 regex "h(e|a)llo"` as well). ## Iterable contains ### Iterable contains in any order -*atrium-api-cc-en_GB* +*atrium-api-fluent-en_GB* ```kotlin -assert(x).contains(1.2) -assert(x).contains(1.2, 5.7) -assert(x).contains { isLessThan(2) } -assert(x).contains({ isLessThan(2) }, { isGreaterThan 5 }) +expect(x).contains(1.2) +expect(x).contains(1.2, 5.7) +expect(x).contains { isLessThan(2) } +expect(x).contains({ isLessThan(2) }, { isGreaterThan(5) }) -assert(x).contains.inAnyOrder.atLeast(1).butAtMost(2).value(3.2) -assert(x).contains.inAnyOrder.exactly(1).values("hello", "robert") -assert(x).contains.inAnyOrder.atMost(2).entry { isLessOrEquals(2) } -assert(x).contains.inAnyOrder.notOrAtMost(2).entries({ notToBe(3) }, { isGreaterOrEquals(2) }) -assert(x).contains.inAnyOrder.only.value("hello") -assert(x).contains.inAnyOrder.only.values(personA, personB) -assert(x).contains.inAnyOrder.only.entry { isLessThan(2) } -assert(x).contains.inAnyOrder.only.entries({ toBe(3) }, { isLessThan(2) }) +expect(x).contains.inAnyOrder.atLeast(1).butAtMost(2).value(3.2) +expect(x).contains.inAnyOrder.exactly(1).values("hello", "robert") +expect(x).contains.inAnyOrder.atMost(2).entry { isLessOrEquals(2) } +expect(x).contains.inAnyOrder.notOrAtMost(2).entries({ notToBe(3) }, { isGreaterOrEquals(2) }) +expect(x).contains.inAnyOrder.only.value("hello") +expect(x).contains.inAnyOrder.only.values(personA, personB) +expect(x).contains.inAnyOrder.only.entry { isLessThan(2) } +expect(x).contains.inAnyOrder.only.entries({ toBe(3) }, { isLessThan(2) }) ``` Notice that the final steps `value`, `values`, `entry` and `entries` @@ -153,198 +158,203 @@ in the sophisticated assertion building process are applicable to all shown examples (e.g. `butAtMost(2).value(3.2)` could have been finished with `entries(...)` as well) -*atrium-api-cc-infix-en_GB* +*atrium-api-infix-en_GB* ```kotlin -assert(x) contains 1.2 -assert(x) contains Values(1.2, 5.7) // or Objects as alternative -assert(x) contains { o isLessThan 2 } -assert(x) contains Entries({ o isLessThan 2 }, { o isGreaterThan 5 }) +expect(x) contains 1.2 +expect(x) contains values(1.2, 5.7) // or Objects as alternative +expect(x) contains { it isLessThan 2 } +expect(x) contains entries({ it isLessThan 2 }, { it isGreaterThan 5 }) -assert(x) to contain inAny order atLeast 1 butAtMost 2 value 3.2 -assert(x) to contain inAny order exactly 1 the Values("hello", "robert") -assert(x) to contain inAny order atMost 2 entry { o isLessOrEquals 2 } -assert(x) to contain inAny order notOrAtMost 2 the Entries({ o notToBe 3 }, { o isGreaterOrEquals 2 }) -assert(x) to contain inAny order but only value "hello") -assert(x) to contain inAny order but only the Values(personA, personB) -assert(x) to contain inAny order but only entry { o isLessThan 2 } -assert(x) to contain inAny order but only the Entries({ o toBe 3 }, { o isLessThan 2 }) +expect(x) contains o inAny order atLeast 1 butAtMost 2 value 3.2 +expect(x) contains o inAny order exactly 1 the values("hello", "robert") +expect(x) contains o inAny order atMost 2 entry { it isLessOrEquals 2 } +expect(x) contains o inAny order notOrAtMost 2 the entries({ it notToBe 3 }, { it isGreaterOrEquals 2 }) +expect(x) contains o inAny order but only value "hello" +expect(x) contains o inAny order but only the values(personA, personB) +expect(x) contains o inAny order but only entry { it isLessThan 2 } +expect(x) contains o inAny order but only the entries({ it toBe 3 }, { it isLessThan 2 }) ``` -Notice that the final steps -`value`, `Values(...)`, `entry` and `Entries(...)` +Note that `o` is a filler object which is only there so that we can turn extension methods without parameters into +a method with one parameter and thus make it available as infix method. + +The final steps `value`, `values(...)`, `entry` and `entries(...)` in the sophisticated assertion building process, are applicable to all shown examples -(e.g. `butAtMost 2 value 3.2` could have been finished with `Entries(...)` as well) +(e.g. `butAtMost 2 value 3.2` could have been finished with `entries(...)` as well) ### Iterable contains in order -*atrium-api-cc-en_GB* +*atrium-api-fluent-en_GB* ```kotlin -assert(x).containsExactly(1.2) -assert(x).containsExactly(1.2, 5.7) -assert(x).containsExactly({ isLessThan(2) }) -assert(x).containsExactly({ isLessThan(2) }, { isGreaterThan 5 }) +expect(x).containsExactly(1.2) +expect(x).containsExactly(1.2, 5.7) +expect(x).containsExactly({ isLessThan(2) }) +expect(x).containsExactly({ isLessThan(2) }, { isGreaterThan 5 }) -assert(x).contains.inOrder.only.value("hello") -assert(x).contains.inOrder.only.values("hello", "world") -assert(x).contains.inOrder.only.entry { isLessThan(2) } -assert(x).contains.inOrder.only.entries({ toBe(3) }, { isLessThan(2) }) -assert(x).contains.inOrder.only.grouped.within.inAnyOrder( - Value(1), - Values(1, 2), - Values(3, 4) +expect(x).contains.inOrder.only.value("hello") +expect(x).contains.inOrder.only.values("hello", "world") +expect(x).contains.inOrder.only.entry { isLessThan(2) } +expect(x).contains.inOrder.only.entries({ toBe(3) }, { isLessThan(2) }) +expect(x).contains.inOrder.only.grouped.within.inAnyOrder( + value(1), + values(1, 2), + values(3, 4) ) -assert(x).contains.inOrder.only.grouped.within.inAnyOrder( - Entry({ toBe(1) }), - Entries({ isLessThan(2) },{ isGreaterThan(2) }), - Entries({ toBe(3) }, { toBe(4) }) +expect(x).contains.inOrder.only.grouped.within.inAnyOrder( + entry { toBe(1) }, + entries({ isLessThan(2) },{ isGreaterThan(2) }), + entries({ toBe(3) }, { toBe(4) }) ) ``` -*atrium-api-cc-infix-en_GB* +*atrium-api-infix-en_GB* ```kotlin -assert(x) containsExactly 1.2 -assert(x) containsExactly Values(1.2, 5.7) // or Objects as alternative -assert(x) containsExactly { o isLessThan 2 } -assert(x) containsExactly Entries({ o isLessThan 2 }, { o isGreaterThan 5 }) +expect(x) containsExactly 1.2 +expect(x) containsExactly values(1.2, 5.7) // or Objects as alternative +expect(x) containsExactly { it isLessThan 2 } +expect(x) containsExactly entries({ it isLessThan 2 }, { it isGreaterThan 5 }) -assert(x) contains inGiven order and only value "hello" -assert(x) contains inGiven order and only the Values("hello", "world") -assert(x) contains inGiven order and only entry { o isLessThan 2 } -assert(x) contains inGiven order and only the Entries({ o toBe 3 }, { o isLessThan 2 }) -assert(x) contains inGiven order and only grouped entries within group inAny Order( - Value(1), - Values(1, 2), - Values(3, 4) +expect(x) contains o inGiven order and only value "hello" +expect(x) contains o inGiven order and only the values("hello", "world") +expect(x) contains o inGiven order and only entry { it isLessThan 2 } +expect(x) contains o inGiven order and only the entries({ it toBe 3 }, { it isLessThan 2 }) +expect(x) contains o inGiven order and only grouped entries within group inAny Order( + value(1), + values(1, 2), + values(3, 4) ) -assert(x) contains inGiven order and only grouped entries within group inAny Order( - Entry({ o toBe(1) }), - Entries({ o isLessThan(2) },{ o isGreaterThan(2) }), - Entries({ o toBe(3) }, { o toBe(4) }) +expect(x) contains o inGiven order and only grouped entries within group inAny Order( + entry { it toBe 1 }, + entries({ it isLessThan 2 },{ it isGreaterThan 2 }), + entries({ it toBe 3 }, { it toBe 4 }) ) ``` +Note that `o` is a filler object which is only there so that we can turn extension methods without parameters into +a method with one parameter and thus make it available as infix method. + ## Iterable contains not -*atrium-api-cc-en_GB* +*atrium-api-fluent-en_GB* ```kotlin -assert(x).containsNot(1.2) -assert(x).containsNot(1.2, 5.7) +expect(x).containsNot(1.2) +expect(x).containsNot(1.2, 5.7) -assert(x).containsNot.value(null) -assert(x).containsNot.values(null, 1) -assert(x).containsNot.entry { isLessThan(2) } -assert(x).containsNot.entries(null, { isLessThan(2) }, { isGreaterThan 5 }) +expect(x).containsNot.value(null) +expect(x).containsNot.values(null, 1) +expect(x).containsNot.entry { isLessThan(2) } +expect(x).containsNot.entries(null, { isLessThan(2) }, { isGreaterThan 5 }) ``` -*atrium-api-cc-infix-en_GB* +*atrium-api-infix-en_GB* ```kotlin -assert(x) containsNot 1.2 -assert(x) containsNot Values(1.2, 5.7) +expect(x) containsNot 1.2 +expect(x) containsNot values(1.2, 5.7) -assert(x) notTo contain value null -assert(x) notTo contain the Values(null, 1) -assert(x) notTo contain entry { o isLessThan 2 } -assert(x) notTo contain the Entries(null, { o isLessThan 2 }, { o isGreaterThan 5 }) +expect(x) containsNot o value null +expect(x) containsNot o the values(null, 1) +expect(x) containsNot o entry { it isLessThan 2 } +expect(x) containsNot o the entries(null, { it isLessThan 2 }, { it isGreaterThan 5 }) ``` # Iterable predicate-like assertions For more sophisticated assertions such as "there should be two matches", use the sophisticated assertion builder `contains.inAnyOrder` -> see [Iterable contains in any order](#iterable-contains-in-any-order) for more information -*atrium-api-cc-en_GB* +*atrium-api-fluent-en_GB* ```kotlin -assert(x).any { startsWith("hello") } -assert(x).none { endsWith(".") } -assert(x).all { isNumericallyEqualTo(12.2) } +expect(x).any { startsWith("hello") } +expect(x).none { endsWith(".") } +expect(x).all { isNumericallyEqualTo(12.2) } -assert(x).any(null) -assert(x).none(null) -assert(x).all(null) +expect(x).any(null) +expect(x).none(null) +expect(x).all(null) ``` -*atrium-api-cc-infix-en_GB* +*atrium-api-infix-en_GB* ```kotlin -assert(x) any { o startsWith "hello" } -assert(x) none { o endsWith "." } -assert(x) all { o isNumericallyEqualTo 12.2 } +expect(x) any { it startsWith "hello" } +expect(x) none { it endsWith "." } +expect(x) all { it isNumericallyEqualTo 12.2 } -assert(x) any null -assert(x) none null -assert(x) all null +expect(x) any null +expect(x) none null +expect(x) all null ``` # List get -*atrium-api-cc-en_GB* +*atrium-api-fluent-en_GB* ```kotlin -assert(x).get(0).isLessThan(1) -assert(x).get(0) { isGreaterThan(1) } +expect(x).get(0).isLessThan(1) +expect(x).get(0) { isGreaterThan(1) } //in case of a nullable element type -assert(x).get(0).toBe(null) +expect(x).get(0).toBe(null) ``` -*atrium-api-cc-infix-en_GB* +*atrium-api-infix-en_GB* ```kotlin -assert(x) get 0 isLessThan 1 -assert(x) get Index(0) assertIt { o isGreaterThan 1 } +expect(x) get 0 isLessThan 1 +expect(x) get index(0) { it isGreaterThan 1 } //in case of a nullable element type -assert(x) get 0 toBe null +expect(x) get 0 toBe null ``` # Map getExisting -*atrium-api-cc-en_GB* +*atrium-api-fluent-en_GB* ```kotlin -assert(x).getExisting("a").isLessThan(1) -assert(x).getExisting("a") { isGreaterThan(1) } +expect(x).getExisting("a").isLessThan(1) +expect(x).getExisting("a") { isGreaterThan(1) } //in case of a nullable value type -assert(x).getExisting("a").notToBeNull { isGreaterThan(1) } +expect(x).getExisting("a").notToBeNull { isGreaterThan(1) } ``` -*atrium-api-cc-infix-en_GB* +*atrium-api-infix-en_GB* ```kotlin -assert(x) getExisting "a" isLessThan 1 -assert(x) getExisting Key("a") assertIt { o isGreaterThan 1 } +expect(x) getExisting "a" isLessThan 1 +expect(x) getExisting key("a") { it isGreaterThan 1 } //in case of a nullable value type -assert(x) getExisting Key("a") notToBeNull { o isGreaterThan 1 } +expect(x) getExisting "a" notToBeNull { it isGreaterThan 1 } ``` # Map contains -*atrium-api-cc-en_GB* +*atrium-api-fluent-en_GB* ```kotlin -assert(x).contains("a" to 1) -assert(x).contains("a" to 1, "b" to 2) -assert(x).contains(KeyValue("a") { isGreaterThan(3).and.isLessThan(10) }) -assert(x).contains(KeyValue("a") { toBe(2) }, KeyValue("b") { isLessThan(3) }) +expect(x).contains("a" to 1) +expect(x).contains("a" to 1, "b" to 2) +expect(x).contains(KeyValue("a") { isGreaterThan(3).and.isLessThan(10) }) +expect(x).contains(KeyValue("a") { toBe(2) }, KeyValue("b") { isLessThan(3) }) //in case of a nullable value type -assert(x).contains("a" to null) -assert(x).contains("a" to null, "b" to 2) -assert(x).contains(KeyValue("a", null)) -assert(x).contains( +expect(x).contains("a" to null) +expect(x).contains("a" to null, "b" to 2) +expect(x).contains(KeyValue("a", null)) +expect(x).contains( KeyValue("a", null) KeyValue("b") { isLessThan(2) } ) ``` -*atrium-api-cc-infix-en_GB* +*atrium-api-infix-en_GB* ```kotlin -assert(x) contains ("a" to 1) -assert(x) contains Pairs("a" to 1, "b" to 2) -assert(x) contains KeyValue("a") { - o isGreaterThan 3 - o isLessThan 10 +expect(x) contains ("a" to 1) +expect(x) contains pairs("a" to 1, "b" to 2) +expect(x) contains keyValue("a") { + it isGreaterThan 3 + it isLessThan 10 } -assert(x) contains All(KeyValue("a") { o toBe 2 }, KeyValue("b") { o isLessThan 3 }) +expect(x) contains all(keyValue("a") { it toBe 2 }, keyValue("b") { it isLessThan 3 }) //in case of a nullable value type -assert(x) contains ("a" to null) -assert(x) contains Pairs("a" to null, "b" to 2) -assert(x) contains KeyValue("a", null) -assert(x) contains All( - KeyValue("a", null), - KeyValue("b") { o isLessThan 2 } +expect(x) contains ("a" to null) +expect(x) contains pairs("a" to null, "b" to 2) +expect(x) contains keyValue("a", null) +expect(x) contains all( + keyValue("a", null), + keyValue("b") { it isLessThan 2 } ) ``` diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/anyAssertions.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/anyAssertions.kt index 02bf6492c..5436baa1f 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/anyAssertions.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/anyAssertions.kt @@ -8,7 +8,7 @@ import ch.tutteli.atrium.reporting.Reporter /** * Expects that the subject of the assertion is (equal to) [expected]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun Expect.toBe(expected: T) = addAssertion(ExpectImpl.any.toBe(this, expected)) @@ -16,7 +16,7 @@ fun Expect.toBe(expected: T) = addAssertion(ExpectImpl.any.toBe(this, exp /** * Expects that the subject of the assertion is not (equal to) [expected]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun Expect.notToBe(expected: T) = addAssertion(ExpectImpl.any.notToBe(this, expected)) @@ -24,7 +24,7 @@ fun Expect.notToBe(expected: T) = addAssertion(ExpectImpl.any.notToBe(thi /** * Expects that the subject of the assertion is the same instance as [expected]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun Expect.isSameAs(expected: T) = addAssertion(ExpectImpl.any.isSame(this, expected)) @@ -32,7 +32,7 @@ fun Expect.isSameAs(expected: T) = addAssertion(ExpectImpl.any.isSame(thi /** * Expects that the subject of the assertion is not the same instance as [expected]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun Expect.isNotSameAs(expected: T) = addAssertion(ExpectImpl.any.isNotSame(this, expected)) @@ -47,7 +47,7 @@ fun Expect.isNotSameAs(expected: T) = addAssertion(ExpectImpl.any.isNotSa * else notToBeNull(assertionCreatorOrNull) * ``` * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ inline fun Expect.toBeNullIfNullGivenElse( @@ -59,7 +59,7 @@ inline fun Expect.toBeNullIfNullGivenElse( * * It delegates to [isA] with [T] as type. * - * @return An assertion container with the non-nullable type [T] (was `T?` before). + * @return An [Expect] with the non-nullable type [T] (was `T?` before). * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ @Suppress(/* less magic */ "RemoveExplicitTypeArguments") @@ -71,7 +71,7 @@ inline fun Expect.notToBeNull(): Expect = isA() * * It delegates to [isA] with [T] as type. * - * @return An assertion container with the non-nullable type [T] (was `T?` before) + * @return An [Expect] with the non-nullable type [T] (was `T?` before) * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ @Suppress(/* less magic */ "RemoveExplicitTypeArguments") @@ -94,7 +94,7 @@ inline fun Expect.notToBeNull(noinline assertionCreator: E * the element type is actually `String`. Or in other words * `assert(listOf(1, 2)).isA>{}` holds, even though `List` is clearly not a `List`. * - * @return An assertion container with the new type [TSub]. + * @return An [Expect] with the new type [TSub]. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ inline fun Expect<*>.isA(): Expect = @@ -138,7 +138,7 @@ inline fun Expect<*>.isA(): Expect = * the element type is actually `String`. Or in other words * `assert(listOf(1, 2)).isA>{}` holds, even though `List` is clearly not a `List`. * - * @return An assertion container with the new type [TSub]. + * @return An [Expect] with the new type [TSub]. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ inline fun Expect<*>.isA(noinline assertionCreator: Expect.() -> Unit): Expect = @@ -152,7 +152,7 @@ inline fun Expect<*>.isA(noinline assertionCreator: Expect< * asserts that 1 is greater than 0. If the first assertion fails, then usually (depending on the configured * [AssertionChecker]) the second assertion is not evaluated. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. */ inline val Expect.and: Expect get() = this @@ -164,6 +164,6 @@ inline val Expect.and: Expect get() = this * second one is evaluated as a whole. Meaning, even though 1 is not even, it still evaluates that 1 is greater than 1. * Hence the reporting might (depending on the configured [Reporter]) contain both failing sub-assertions. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. */ infix fun Expect.and(assertionCreator: Expect.() -> Unit) = addAssertionsCreatedBy(assertionCreator) diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/arrayAssertions.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/arrayAssertions.kt index 4c9dd8a89..c0d54fc3c 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/arrayAssertions.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/arrayAssertions.kt @@ -11,6 +11,8 @@ import kotlin.jvm.JvmName * Use `feature(Array::asList)` if you want to show the transformation in reporting. * * @return The newly created [Expect] for the transformed subject. + * + * @since 0.9.0 */ fun Expect>.asList(): Expect> = ExpectImpl.changeSubject(this).unreported { it.asList() } @@ -23,6 +25,8 @@ fun Expect>.asList(): Expect> = * Use `feature(Array::asList, assertionCreator)` if you want to show the transformation in reporting. * * @return The newly created [Expect] for the transformed subject. + * + * @since 0.9.0 */ fun Expect>.asList(assertionCreator: Expect>.() -> Unit): Expect> = apply { asList().addAssertionsCreatedBy(assertionCreator) } @@ -35,6 +39,8 @@ fun Expect>.asList(assertionCreator: Expect>.() -> Unit): E * Use `feature(Array::asList, assertionCreator)` if you want to show the transformation in reporting. * * @return The newly created [Expect] for the transformed subject. + * + * @since 0.9.0 */ @JvmName("asListEOut") fun Expect>.asList(assertionCreator: Expect>.() -> Unit): Expect> = @@ -47,6 +53,8 @@ fun Expect>.asList(assertionCreator: Expect>.() -> Unit * Use `feature(ByteArray::asList)` if you want to show the transformation in reporting. * * @return The newly created [Expect] for the transformed subject. + * + * @since 0.9.0 */ @JvmName("byteArrAsList") fun Expect.asList(): Expect> = @@ -60,6 +68,8 @@ fun Expect.asList(): Expect> = * Use `feature(ByteArray::asList, assertionCreator)` if you want to show the transformation in reporting. * * @return The newly created [Expect] for the transformed subject. + * + * @since 0.9.0 */ @JvmName("byteArrAsList") fun Expect.asList(assertionCreator: Expect>.() -> Unit): Expect = @@ -73,6 +83,8 @@ fun Expect.asList(assertionCreator: Expect>.() -> Unit): E * Use `feature(CharArray::asList)` if you want to show the transformation in reporting. * * @return The newly created [Expect] for the transformed subject. + * + * @since 0.9.0 */ @JvmName("charArrAsList") fun Expect.asList(): Expect> = @@ -86,6 +98,8 @@ fun Expect.asList(): Expect> = * Use `feature(CharArray::asList, assertionCreator)` if you want to show the transformation in reporting. * * @return The newly created [Expect] for the transformed subject. + * + * @since 0.9.0 */ @JvmName("charArrAsList") fun Expect.asList(assertionCreator: Expect>.() -> Unit): Expect = @@ -99,6 +113,8 @@ fun Expect.asList(assertionCreator: Expect>.() -> Unit): E * Use `feature(ShortArray::asList)` if you want to show the transformation in reporting. * * @return The newly created [Expect] for the transformed subject. + * + * @since 0.9.0 */ @JvmName("shortArrAsList") fun Expect.asList(): Expect> = @@ -112,6 +128,8 @@ fun Expect.asList(): Expect> = * Use `feature(ShortArray::asList, assertionCreator)` if you want to show the transformation in reporting. * * @return The newly created [Expect] for the transformed subject. + * + * @since 0.9.0 */ @JvmName("shortArrAsList") fun Expect.asList(assertionCreator: Expect>.() -> Unit): Expect = @@ -125,6 +143,8 @@ fun Expect.asList(assertionCreator: Expect>.() -> Unit): * Use `feature(IntArray::asList)` if you want to show the transformation in reporting. * * @return The newly created [Expect] for the transformed subject. + * + * @since 0.9.0 */ @JvmName("intArrAsList") fun Expect.asList(): Expect> = ExpectImpl.changeSubject(this).unreported { it.asList() } @@ -137,6 +157,8 @@ fun Expect.asList(): Expect> = ExpectImpl.changeSubject(this * Use `feature(IntArray::asList, assertionCreator)` if you want to show the transformation in reporting. * * @return The newly created [Expect] for the transformed subject. + * + * @since 0.9.0 */ @JvmName("intArrAsList") fun Expect.asList(assertionCreator: Expect>.() -> Unit): Expect = @@ -150,6 +172,8 @@ fun Expect.asList(assertionCreator: Expect>.() -> Unit): Exp * Use `feature(LongArray::asList)` if you want to show the transformation in reporting. * * @return The newly created [Expect] for the transformed subject. + * + * @since 0.9.0 */ @JvmName("longArrAsList") fun Expect.asList(): Expect> = @@ -163,6 +187,8 @@ fun Expect.asList(): Expect> = * Use `feature(LongArray::asList, assertionCreator)` if you want to show the transformation in reporting. * * @return The newly created [Expect] for the transformed subject. + * + * @since 0.9.0 */ @JvmName("longArrAsList") fun Expect.asList(assertionCreator: Expect>.() -> Unit): Expect = @@ -176,6 +202,8 @@ fun Expect.asList(assertionCreator: Expect>.() -> Unit): E * Use `feature(FloatArray::asList)` if you want to show the transformation in reporting. * * @return The newly created [Expect] for the transformed subject. + * + * @since 0.9.0 */ @JvmName("floatArrAsList") fun Expect.asList(): Expect> = @@ -189,6 +217,8 @@ fun Expect.asList(): Expect> = * Use `feature(FloatArray::asList, assertionCreator)` if you want to show the transformation in reporting. * * @return The newly created [Expect] for the transformed subject. + * + * @since 0.9.0 */ @JvmName("floatArrAsList") fun Expect.asList(assertionCreator: Expect>.() -> Unit): Expect = @@ -202,6 +232,8 @@ fun Expect.asList(assertionCreator: Expect>.() -> Unit): * Use `feature(DoubleArray::asList)` if you want to show the transformation in reporting. * * @return The newly created [Expect] for the transformed subject. + * + * @since 0.9.0 */ @JvmName("doubleArrAsList") fun Expect.asList(): Expect> = @@ -215,6 +247,8 @@ fun Expect.asList(): Expect> = * Use `feature(DoubleArray::asList, assertionCreator)` if you want to show the transformation in reporting. * * @return The newly created [Expect] for the transformed subject. + * + * @since 0.9.0 */ @JvmName("doubleArrAsList") fun Expect.asList(assertionCreator: Expect>.() -> Unit): Expect = @@ -228,6 +262,8 @@ fun Expect.asList(assertionCreator: Expect>.() -> Unit * Use `feature(BooleanArray::asList)` if you want to show the transformation in reporting. * * @return The newly created [Expect] for the transformed subject. + * + * @since 0.9.0 */ @JvmName("boolArrAsList") fun Expect.asList(): Expect> = @@ -241,6 +277,8 @@ fun Expect.asList(): Expect> = * Use `feature(BooleanArray::asList, assertionCreator)` if you want to show the transformation in reporting. * * @return The newly created [Expect] for the transformed subject. + * + * @since 0.9.0 */ @JvmName("boolArrAsList") fun Expect.asList(assertionCreator: Expect>.() -> Unit): Expect = diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/charSequenceAssertions.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/charSequenceAssertions.kt index 85ce8f0a3..7f623cddb 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/charSequenceAssertions.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/charSequenceAssertions.kt @@ -35,19 +35,19 @@ val Expect.containsNot: NotCheckerOption Expect.contains(expected: Any, vararg otherExpected: A * Notice that a runtime check applies which assures that only [CharSequence], [Number] and [Char] are passed (this * function expects `Any` for your convenience, so that you can mix [String] and [Int] for instance). * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun Expect.containsNot(expected: Any, vararg otherExpected: Any) = @@ -76,9 +76,9 @@ fun Expect.containsNot(expected: Any, vararg otherExpected * * It is a shortcut for `contains.atLeast(1).regex(pattern, *otherPatterns)`. * - * By non disjoint is meant that `'aa'` in `'aaaa'` is found three times and not only two times. - * Also notice, that it does not search for unique matches. Meaning, if the input of the search is `'ab'` and [pattern] - * is defined as `'a(b)?'` and one of the [otherPatterns] is defined as `'a(b)?'` as well, then both match, even though + * By non disjoint is meant that `"aa"` in `"aaaa"` is found three times and not only two times. + * Also notice, that it does not search for unique matches. Meaning, if the input of the search is `"ab"` and [pattern] + * is defined as `"a(b)?"` and one of the [otherPatterns] is defined as `"a(b)?"` as well, then both match, even though * they match the same sequence in the input of the search. Use an option such as [atLeast], [atMost] and [exactly] to * control the number of occurrences you expect. * @@ -90,7 +90,7 @@ fun Expect.containsNot(expected: Any, vararg otherExpected * @param pattern The pattern which is expected to have a match against the input of the search. * @param otherPatterns Additional patterns which are expected to have a match against the input of the search. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun Expect.containsRegex(pattern: String, vararg otherPatterns: String): Expect = @@ -102,9 +102,9 @@ fun Expect.containsRegex(pattern: String, vararg otherPatt * * It is a shortcut for `contains.atLeast(1).regex(pattern, *otherPatterns)`. * - * By non disjoint is meant that `'aa'` in `'aaaa'` is found three times and not only two times. - * Also notice, that it does not search for unique matches. Meaning, if the input of the search is `'ab'` and [pattern] - * is defined as `'a(b)?'` and one of the [otherPatterns] is defined as `'a(b)?'` as well, then both match, even though + * By non disjoint is meant that `"aa"` in `"aaaa"` is found three times and not only two times. + * Also notice, that it does not search for unique matches. Meaning, if the input of the search is `"ab"` and [pattern] + * is defined as `"a(b)?"` and one of the [otherPatterns] is defined as `"a(b)?"` as well, then both match, even though * they match the same sequence in the input of the search. Use an option such as [atLeast], [atMost] and [exactly] to * control the number of occurrences you expect. * @@ -116,7 +116,7 @@ fun Expect.containsRegex(pattern: String, vararg otherPatt * @param pattern The pattern which is expected to have a match against the input of the search. * @param otherPatterns Additional patterns which are expected to have a match against the input of the search. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -127,7 +127,7 @@ fun Expect.containsRegex(pattern: Regex, vararg otherPatte /** * Expects that the subject of the assertion (a [CharSequence]) starts with [expected]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun Expect.startsWith(expected: CharSequence) = @@ -136,7 +136,7 @@ fun Expect.startsWith(expected: CharSequence) = /** * Expects that the subject of the assertion (a [CharSequence]) starts with [expected]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -146,7 +146,7 @@ fun Expect.startsWith(expected: Char) = startsWith(expecte /** * Expects that the subject of the assertion (a [CharSequence]) does not start with [expected]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun Expect.startsNotWith(expected: CharSequence) = @@ -155,7 +155,7 @@ fun Expect.startsNotWith(expected: CharSequence) = /** * Expects that the subject of the assertion (a [CharSequence]) does not start with [expected]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -166,7 +166,7 @@ fun Expect.startsNotWith(expected: Char) = startsNotWith(e /** * Expects that the subject of the assertion (a [CharSequence]) ends with [expected]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun Expect.endsWith(expected: CharSequence) = @@ -175,7 +175,7 @@ fun Expect.endsWith(expected: CharSequence) = /** * Expects that the subject of the assertion (a [CharSequence]) ends with [expected]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -185,7 +185,7 @@ fun Expect.endsWith(expected: Char) = endsWith(expected.to /** * Expects that the subject of the assertion (a [CharSequence]) does not end with [expected]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun Expect.endsNotWith(expected: CharSequence) = @@ -194,7 +194,7 @@ fun Expect.endsNotWith(expected: CharSequence) = /** * Expects that the subject of the assertion (a [CharSequence]) does not end with [expected]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -205,7 +205,7 @@ fun Expect.endsNotWith(expected: Char) = endsNotWith(expec /** * Expects that the subject of the assertion (a [CharSequence]) [CharSequence].[kotlin.text.isEmpty]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun Expect.isEmpty() = addAssertion(ExpectImpl.charSequence.isEmpty(this)) @@ -213,7 +213,7 @@ fun Expect.isEmpty() = addAssertion(ExpectImpl.charSequenc /** * Expects that the subject of the assertion (a [CharSequence]) [CharSequence].[kotlin.text.isNotEmpty]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun Expect.isNotEmpty() = addAssertion(ExpectImpl.charSequence.isNotEmpty(this)) @@ -221,7 +221,7 @@ fun Expect.isNotEmpty() = addAssertion(ExpectImpl.charSequ /** * Expects that the subject of the assertion (a [CharSequence]) [CharSequence].[kotlin.text.isNotBlank]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun Expect.isNotBlank() = addAssertion(ExpectImpl.charSequence.isNotBlank(this)) @@ -229,7 +229,9 @@ fun Expect.isNotBlank() = addAssertion(ExpectImpl.charSequ /** * Expects that the subject of the assertion (a [CharSequence]) matches the given [expected] [Regex]. * - * @return This assertion container to support a fluent API. + * In contrast to [containsRegex] it does not look for a partial match but for an entire match. + * + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -240,7 +242,9 @@ fun Expect.matches(expected: Regex) = /** * Expects that the subject of the assertion (a [CharSequence]) mismatches the given [expected] [Regex]. * - * @return This assertion container to support a fluent API. + * In contrast to `containsNot.regex` it does not look for a partial match but for an entire match. + * + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/charSequenceContainsCreators.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/charSequenceContainsCreators.kt index 639b35b56..5b4e0364e 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/charSequenceContainsCreators.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/charSequenceContainsCreators.kt @@ -3,7 +3,9 @@ package ch.tutteli.atrium.api.fluent.en_GB import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.domain.builders.ExpectImpl import ch.tutteli.atrium.domain.builders.creating.basic.contains.addAssertion +import ch.tutteli.atrium.domain.builders.utils.toVarArg import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains +import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains.* import ch.tutteli.atrium.domain.creating.charsequence.contains.searchbehaviours.IgnoringCaseSearchBehaviour import ch.tutteli.atrium.domain.creating.charsequence.contains.searchbehaviours.NoOpSearchBehaviour import ch.tutteli.kbox.glue @@ -18,15 +20,15 @@ import kotlin.jvm.JvmName * Notice that a runtime check applies which assures that only [CharSequence], [Number] and [Char] are passed (this * function expects `Any` for your convenience, so that you can mix [String] and [Int] for instance). * - * By non disjoint is meant that 'aa' in 'aaaa' is found three times and not only two times. + * By non disjoint is meant that "aa" in "aaaa" is found three times and not only two times. * * @param expected The value which is expected to be contained within the input of the search. * - * @return The [Expect] for which the assertion was built to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * @throws IllegalArgumentException in case [expected] is not a [CharSequence], [Number] or [Char]. */ -fun CharSequenceContains.CheckerOption.value(expected: Any): Expect = +fun CheckerOption.value(expected: Any): Expect = values(expected) /** @@ -36,26 +38,26 @@ fun CharSequenceContains.CheckerOption CharSequenceContains.CheckerOption.values( +fun CheckerOption.values( expected: Any, vararg otherExpected: Any ): Expect = addAssertion(ExpectImpl.charSequence.contains.values(this, expected glue otherExpected)) @@ -70,16 +72,16 @@ fun CharSequenceContains.CheckerOption CharSequenceContains.CheckerOption.value( +fun CheckerOption.value( expected: Any ): Expect = values(expected) @@ -90,27 +92,27 @@ fun CharSequenceContains.CheckerOption CharSequenceContains.CheckerOption.values( +fun CheckerOption.values( expected: Any, vararg otherExpected: Any ): Expect = addAssertion(ExpectImpl.charSequence.contains.valuesIgnoringCase(this, expected glue otherExpected)) @@ -120,20 +122,20 @@ fun CharSequenceContains.CheckerOption CharSequenceContains.Builder.value(expected: Any): Expect = +fun Builder.value(expected: Any): Expect = atLeast(1).value(expected) /** @@ -146,20 +148,20 @@ fun CharSequenceContains.Builder CharSequenceContains.Builder.values( +fun Builder.values( expected: Any, vararg otherExpected: Any ): Expect = atLeast(1).values(expected, *otherExpected) @@ -168,9 +170,9 @@ fun CharSequenceContains.Builder CharSequenceContains.Builder CharSequenceContains.CheckerOption.regex( +fun CheckerOption.regex( pattern: String, vararg otherPatterns: String ): Expect = addAssertion(ExpectImpl.charSequence.contains.regex(this, pattern glue otherPatterns)) /** - * Finishes the specification of the sophisticated `contains` assertion where the given regular expression [pattern] + * Finishes the specification of the sophisticated `contains` assertion where the given [Regex] [pattern] * as well as the [otherPatterns] are expected to have a match, using a non disjoint search. * - * By non disjoint is meant that `'aa'` in `'aaaa'` is found three times and not only two times. - * Also notice, that it does not search for unique matches. Meaning, if the input of the search is `'ab'` and [pattern] - * is defined as `'a(b)?'` and one of the [otherPatterns] is defined as `'a(b)?'` as well, then both match, even though + * By non disjoint is meant that `"aa"` in `"aaaa"` is found three times and not only two times. + * Also notice, that it does not search for unique matches. Meaning, if the input of the search is `"ab"` and [pattern] + * is defined as `"a(b)?"` and one of the [otherPatterns] is defined as `"a(b)?"` as well, then both match, even though * they match the same sequence in the input of the search. Use an option such as [atLeast], [atMost] and [exactly] to * control the number of occurrences you expect. * @@ -208,12 +210,13 @@ fun CharSequenceContains.CheckerOption CharSequenceContains.CheckerOption.regex( +//TODO rename to `matchFor` with 1.0.0 +fun CheckerOption.regex( pattern: Regex, vararg otherPatterns: Regex ): Expect = addAssertion(ExpectImpl.charSequence.contains.regex(this, pattern glue otherPatterns)) @@ -222,25 +225,25 @@ fun CharSequenceContains.CheckerOption CharSequenceContains.CheckerOption.regex( +fun CheckerOption.regex( pattern: String, vararg otherPatterns: String ): Expect = addAssertion(ExpectImpl.charSequence.contains.regexIgnoringCase(this, pattern glue otherPatterns)) @@ -252,24 +255,24 @@ fun CharSequenceContains.CheckerOption CharSequenceContains.Builder.regex( +fun Builder.regex( pattern: String, vararg otherPatterns: String ): Expect = atLeast(1).regex(pattern, *otherPatterns) @@ -284,21 +287,22 @@ fun CharSequenceContains.Builder CharSequenceContains.CheckerOption.elementsOf( +fun CheckerOption.elementsOf( expectedIterable: Iterable ): Expect { - require(expectedIterable.iterator().hasNext()) { "Iterable without elements are not allowed." } - return values(expectedIterable.first(), *expectedIterable.drop(1).toTypedArray()) + val (first, rest) = toVarArg(expectedIterable) + return values(first, *rest) } /** @@ -311,20 +315,29 @@ fun CharSequenceContains.CheckerOption CharSequenceContains.CheckerOption.elementsOf( +fun CheckerOption.elementsOf( expectedIterable: Iterable ): Expect { - require(expectedIterable.iterator().hasNext()) { "Iterable without elements are not allowed." } - return values(expectedIterable.first(), *expectedIterable.drop(1).toTypedArray()) + val (first, rest) = toVarArg(expectedIterable) + return values(first, *rest) +} + +@JvmName("elementsOfIgnoringCase") +fun CharSequenceContains.Builder.elementsOf( + expectedIterable: Iterable +): Expect { + val (first, rest) = toVarArg(expectedIterable) + return values(first, *rest) } diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/collectionAssertions.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/collectionAssertions.kt index 3fc129558..77bb3107c 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/collectionAssertions.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/collectionAssertions.kt @@ -6,7 +6,7 @@ import ch.tutteli.atrium.domain.builders.ExpectImpl /** * Expects that the subject of the assertion (a [Collection]) is an empty [Collection]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.isEmpty() = addAssertion(ExpectImpl.collection.isEmpty(this)) @@ -14,7 +14,7 @@ fun > Expect.isEmpty() = addAssertion(ExpectImpl.collection /** * Expects that the subject of the assertion (a [Collection]) is not an empty [Collection]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.isNotEmpty() = addAssertion(ExpectImpl.collection.isNotEmpty(this)) @@ -22,9 +22,9 @@ fun > Expect.isNotEmpty() = addAssertion(ExpectImpl.collect /** * Expects that the subject of the assertion (a [Collection]) has the given [expected] size. * - * Shortcut for `expected.toBe(expectedSize)`. + * Shortcut for `size.toBe(expected)`. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.hasSize(expected: Int) = size { toBe(expected) } @@ -33,16 +33,17 @@ fun > Expect.hasSize(expected: Int) = size { toBe(expected) * Creates an [Expect] for the property [Collection.size] of the subject of the assertion, * so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. */ val > Expect.size: Expect get() = ExpectImpl.collection.size(this).getExpectOfFeature() /** * Expects that the property [Collection.size] of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.size(assertionCreator: Expect.() -> Unit): Expect = diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/comparableAssertions.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/comparableAssertions.kt index c96f93aad..7f1151866 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/comparableAssertions.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/comparableAssertions.kt @@ -7,7 +7,7 @@ import ch.tutteli.atrium.domain.builders.ExpectImpl * Expects that the subject of the assertion is less than [expected]. * The comparison is carried out with [Comparable.compareTo]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.isLessThan(expected: T) = @@ -17,7 +17,7 @@ fun > Expect.isLessThan(expected: T) = * Expects that the subject of the assertion is less than or equal [expected]. * The comparison is carried out with [Comparable.compareTo]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.isLessThanOrEqual(expected: T) = @@ -27,7 +27,7 @@ fun > Expect.isLessThanOrEqual(expected: T) = * Expects that the subject of the assertion is greater than [expected]. * The comparison is carried out with [Comparable.compareTo]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.isGreaterThan(expected: T) = @@ -37,7 +37,7 @@ fun > Expect.isGreaterThan(expected: T) = * Expects that the subject of the assertion is greater than or equal [expected]. * The comparison is carried out with [Comparable.compareTo]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.isGreaterThanOrEqual(expected: T) = diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/expectExtensions.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/expectExtensions.kt index fcbcef7dd..a7349f600 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/expectExtensions.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/expectExtensions.kt @@ -1,5 +1,6 @@ package ch.tutteli.atrium.api.fluent.en_GB +import ch.tutteli.atrium.core.None import ch.tutteli.atrium.core.coreFactory import ch.tutteli.atrium.creating.* import ch.tutteli.atrium.domain.builders.creating.changers.FeatureExtractorBuilder @@ -9,55 +10,109 @@ import ch.tutteli.atrium.domain.builders.reporting.ExpectOptions import ch.tutteli.atrium.reporting.RawString import ch.tutteli.atrium.reporting.reporter +@Suppress("DEPRECATION" /* RequiresOptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */) @Experimental @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.FUNCTION) annotation class ExperimentalWithOptions /** - * Uses the given [textRepresentation] as representation of the subject instead of the current representation - * (which defaults to the subject itself). + * Wraps the given [textRepresentation] into a [RawString] and uses it as representation of the subject + * instead of the representation that has been defined so far (which defaults to the subject itself). + * + * In case [Expect.maybeSubject] is not defined i.e. [None], then the previous representation is used. + * + * @return An [Expect] for the current subject of the assertion. */ @ExperimentalWithOptions -fun RootExpect.withOptions(textRepresentation: String): Expect = - withOptions(ExpectOptions(representation = RawString.create(textRepresentation))) +fun RootExpect.withRepresentation(textRepresentation: String): Expect = + withOptions { withRepresentation(textRepresentation) } + +/** + * Uses the given [representationProvider] to retrieve a representation which can be based on the current + * subject where it is used as new representation of the subject + * instead of the representation that has been defined so far (which defaults to the subject itself). + * + * Notice, if you want to use text (e.g. a [String]) as representation, + * then wrap it into a [RawString] via [RawString.create] and pass the [RawString] instead. + * If your text does not include the current subject, then we recommend to use the other overload which expects + * a `String` and does the wrapping for you. + * + * In case [Expect.maybeSubject] is not defined i.e. [None], then the previous representation is used. + * + * @return An [Expect] for the current subject of the assertion. + */ +@ExperimentalWithOptions +fun RootExpect.withRepresentation(representationProvider: (T) -> Any): Expect = + withOptions { withRepresentation(representationProvider) } /** * Uses the given [configuration]-lambda to create an [ExpectOptions] which in turn is used * to override (parts) of the existing configuration. + * + * @return An [Expect] for the current subject of the assertion. */ @ExperimentalWithOptions -fun RootExpect.withOptions(configuration: ExpectBuilder.OptionsChooser.() -> Unit): Expect = +fun RootExpect.withOptions(configuration: ExpectBuilder.OptionsChooser.() -> Unit): Expect = withOptions(ExpectBuilder.OptionsChooser.createAndBuild(configuration)) //TODO #280 get rid of AssertionChecker, that's one root of a bug (which is more a nice to have but still) roadmap#11 //in the same go we should get rid of ReportingAssertionContainer.AssertionCheckerDecorator, rename it respectively. /** * Uses the given [options] to override (parts) of the existing configuration. + * + * @return An [Expect] for the current subject of the assertion. */ @ExperimentalWithOptions +@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */) @UseExperimental(ExperimentalExpectConfig::class) -fun RootExpect.withOptions(options: ExpectOptions): Expect = coreFactory.newReportingAssertionContainer( +fun RootExpect.withOptions(options: ExpectOptions): Expect = coreFactory.newReportingAssertionContainer( ReportingAssertionContainer.AssertionCheckerDecorator.create( options.assertionVerb ?: this.config.description, this.maybeSubject, - options.representation ?: this.config.representation, + options.representationInsteadOfSubject?.let { provider -> + this.maybeSubject.fold({ null }) { provider(it) } + } ?: this.config.representation, //TODO #280 reporter should be configurable as well coreFactory.newThrowingAssertionChecker(options.reporter ?: reporter) ) ) /** - * Uses the given [textRepresentation] as representation of the subject instead of the current representation - * (which defaults to the subject itself). + * Wraps the given [textRepresentation] into a [RawString] and uses it as representation of the subject + * instead of the representation that has been defined so far (which defaults to the subject itself). + * + * In case [Expect.maybeSubject] is not defined i.e. [None], then the previous representation is used. + * + * @return An [Expect] for the current subject of the assertion. */ @ExperimentalWithOptions -fun FeatureExpect.withOptions(textRepresentation: String): Expect = - withOptions { withTextRepresentation(textRepresentation) } +fun FeatureExpect.withRepresentation(textRepresentation: String): Expect = + withOptions { withRepresentation(textRepresentation) } + +/** + * Uses the given [representationProvider] to retrieve a representation which can be based on the current + * subject where it is used as new representation of the subject + * instead of the representation that has been defined so far (which defaults to the subject itself). + * + * Notice, if you want to use text (e.g. a [String]) as representation, + * then wrap it into a [RawString] via [RawString.create] and pass the [RawString] instead. + * If your text does not include the current subject, then we recommend to use the other overload which expects + * a `String` and does the wrapping for you. + * + * In case [Expect.maybeSubject] is not defined i.e. [None], then the previous representation is used. + * + * @return An [Expect] for the current subject of the assertion. + */ +@ExperimentalWithOptions +fun FeatureExpect.withRepresentation(representationProvider: (R) -> Any): Expect = + withOptions { withRepresentation(representationProvider) } /** * Uses the given [configuration]-lambda to create an [ExpectOptions] which in turn is used * to override (parts) of the existing configuration. + * + * @return An [Expect] for the current subject of the assertion. */ @ExperimentalWithOptions fun FeatureExpect.withOptions(configuration: FeatureExtractorBuilder.OptionsChooser.() -> Unit): Expect = @@ -65,8 +120,11 @@ fun FeatureExpect.withOptions(configuration: FeatureExtractorBuilde /** * Uses the given [options] to override (parts) of the existing configuration. + * + * @return An [Expect] for the current subject of the assertion. */ @ExperimentalWithOptions +@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */) @UseExperimental(ExperimentalExpectConfig::class) fun FeatureExpect.withOptions(options: FeatureOptions): Expect = coreFactory.newFeatureExpect( @@ -74,10 +132,9 @@ fun FeatureExpect.withOptions(options: FeatureOptions): Expect options.representationInsteadOfFeature?.invoke(subject) ?: config.representation } - ) + options.representationInsteadOfFeature?.let { provider -> + this.maybeSubject.fold({ null }) { provider(it) } + } ?: this.config.representation ), getAssertions() ) diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/featureAssertions.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/featureAssertions.kt index d18e87aa7..f26049fa8 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/featureAssertions.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/featureAssertions.kt @@ -13,7 +13,7 @@ import kotlin.reflect.* * creates a new [Expect] for it and * returns it so that subsequent calls are based on the feature. * - * @return An [Expect] for the given [property]. + * @return The newly created [Expect] for the given [property]. * * @since 0.9.0 */ @@ -26,7 +26,7 @@ fun Expect.feature(property: KProperty1): FeatureExpect * applies an assertion group based on the given [assertionCreator] for the feature and * returns the initial [Expect] with the current subject. * - * @return The current [Expect]. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] in case the created [AssertionGroup] does not hold. * * @since 0.9.0 @@ -42,7 +42,8 @@ fun Expect.feature( * creates a new [Expect] for it and * returns it so that subsequent calls are based on the feature. * - * @return An [Expect] for the return value of calling [f] on the current subject of the assertion. + * @return The newly created [Expect] for the return value of calling the method [f] + * on the current subject of the assertion. * * @since 0.9.0 */ @@ -55,7 +56,7 @@ fun Expect.feature(f: KFunction1): FeatureExpect = * applies an assertion group based on the given [assertionCreator] for the feature and * returns the initial [Expect] with the current subject. * - * @return The current [Expect]. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] in case the created [AssertionGroup] does not hold. * * @since 0.9.0 @@ -72,7 +73,8 @@ fun Expect.feature( * creates a new [Expect] for it and * returns it so that subsequent calls are based on the feature. * - * @return An [Expect] for the return value of calling [f] on the current subject of the assertion. + * @return The newly created [Expect] for the return value of calling the method [f] + * on the current subject of the assertion. * * @since 0.9.0 */ @@ -88,7 +90,7 @@ fun Expect.feature( * applies an assertion group based on the given [assertionCreator] for the feature and * returns the initial [Expect] with the current subject. * - * @return The current [Expect]. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] in case the created [AssertionGroup] does not hold. * * @since 0.9.0 @@ -106,7 +108,8 @@ fun Expect.feature( * creates a new [Expect] for it and * returns it so that subsequent calls are based on the feature. * - * @return An [Expect] for the return value of calling [f] on the current subject of the assertion. + * @return The newly created [Expect] for the return value of calling the method [f] + * on the current subject of the assertion. * * @since 0.9.0 */ @@ -122,7 +125,7 @@ fun Expect.feature( * applies an assertion group based on the given [assertionCreator] for the feature and * returns the initial [Expect] with the current subject. * - * @return The current [Expect]. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] in case the created [AssertionGroup] does not hold. * * @since 0.9.0 @@ -140,7 +143,8 @@ fun Expect.feature( * creates a new [Expect] for it and * returns it so that subsequent calls are based on the feature. * - * @return An [Expect] for the return value of calling [f] on the current subject of the assertion. + * @return The newly created [Expect] for the return value of calling the method [f] + * on the current subject of the assertion. * * @since 0.9.0 */ @@ -156,7 +160,7 @@ fun Expect.feature( * applies an assertion group based on the given [assertionCreator] for the feature and * returns the initial [Expect] with the current subject. * - * @return The current [Expect]. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] in case the created [AssertionGroup] does not hold. * * @since 0.9.0 @@ -174,7 +178,8 @@ fun Expect.feature( * creates a new [Expect] for it and * returns it so that subsequent calls are based on the feature. * - * @return An [Expect] for the return value of calling [f] on the current subject of the assertion. + * @return The newly created [Expect] for the return value of calling the method [f] + * on the current subject of the assertion. * * @since 0.9.0 */ @@ -190,7 +195,7 @@ fun Expect.feature( * applies an assertion group based on the given [assertionCreator] for the feature and * returns the initial [Expect] with the current subject. * - * @return The current [Expect]. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] in case the created [AssertionGroup] does not hold. * * @since 0.9.0 @@ -208,7 +213,7 @@ fun Expect.feature( * creates a new [Expect] for it and * returns it so that subsequent calls are based on the feature. * - * @return An [Expect] for the return value of calling [f] on the current subject of the assertion. + * @return The newly [Expect] for the return value of calling [f] on the current subject of the assertion. * * @since 0.9.0 */ @@ -224,7 +229,7 @@ fun Expect.feature( * applies an assertion group based on the given [assertionCreator] for the feature and * returns the initial [Expect] with the current subject. * - * @return The current [Expect]. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] in case the created [AssertionGroup] does not hold. * * @since 0.9.0 @@ -245,7 +250,7 @@ fun Expect.feature( * @param provider Extracts the feature where the subject of the assertion is available via * implicit parameter `it`. * - * @return An [Expect] for the extracted feature. + * @return The newly created [Expect] for the extracted feature. * * @since 0.9.0 */ @@ -262,7 +267,7 @@ fun Expect.feature(description: String, provider: T.() -> R): FeatureE * @param provider Extracts the feature where the subject of the assertion is available via * implicit parameter `it`. * - * @return The current [Expect]. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] in case the created [AssertionGroup] does not hold. * * @since 0.9.0 @@ -284,7 +289,7 @@ fun Expect.feature( * implicit parameter `it`. Usually you use [f][MetaFeatureOption.f] to create a [MetaFeature], * e.g. `feature { f(it::size) }` * - * @return An [Expect] for the extracted feature. + * @return The newly created [Expect] for the extracted feature. * * @since 0.9.0 */ @@ -301,7 +306,7 @@ fun Expect.feature(provider: MetaFeatureOption.(T) -> MetaFeature.toBeWithErrorTolerance(expected: Float, tolerance: Float) = @@ -34,7 +34,7 @@ fun Expect.toBeWithErrorTolerance(expected: Float, tolerance: Float) = * * | `subject of the assertion` - [expected] | ≤ [tolerance] * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun Expect.toBeWithErrorTolerance(expected: Double, tolerance: Double) = diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/fun0Assertions.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/fun0Assertions.kt index 800df45d8..c985389c4 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/fun0Assertions.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/fun0Assertions.kt @@ -10,7 +10,7 @@ import ch.tutteli.atrium.domain.builders.ExpectImpl * For instance `toThrow>` would only check if the subject is a `MyException` without checking if * the element type is actually `String`. * - * @return An assertion container with the new type [TExpected]. + * @return An [Expect] with the new type [TExpected]. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ inline fun Expect Any?>.toThrow(): Expect = @@ -46,7 +46,7 @@ inline fun Expect Any?>.toThrow(): Exp * For instance `toThrow>` would only check if the subject is a `MyException` without checking if * the element type is actually `String`. * - * @return An assertion container with the new type [TExpected]. + * @return An [Expect] with the new type [TExpected]. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ inline fun Expect Any?>.toThrow( @@ -58,6 +58,7 @@ inline fun Expect Any?>.toThrow( * Expects that no [Throwable] is thrown at all when calling the subject (a lambda with arity 0, i.e. without arguments) * and changes the subject of the assertion to the return value of type [R]. * + * @return An [Expect] with the new type [R]. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun R> Expect.notToThrow(): Expect = ExpectImpl.fun0.isNotThrowing(this).getExpectOfFeature() @@ -66,6 +67,7 @@ fun R> Expect.notToThrow(): Expect = ExpectImpl.fun0.isNotTh * Expects that no [Throwable] is thrown at all when calling the subject (a lambda with arity 0, i.e. without arguments) * and that the corresponding return value holds all assertions the given [assertionCreator] creates. * + * @return An [Expect] with the new type [R]. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun R> Expect.notToThrow( diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableAssertions.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableAssertions.kt index 1537bc3ce..e1b8a46f6 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableAssertions.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableAssertions.kt @@ -27,45 +27,54 @@ val > Expect.containsNot: NotCheckerOption, T : Iterable> Expect.min(): Expect = + ExpectImpl.iterable.min(this).getExpectOfFeature() + +/** + * Expects that the result of calling `min()` on the subject of the assertion + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * * @since 0.9.0 */ fun , T : Iterable> Expect.min(assertionCreator: Expect.() -> Unit): Expect = ExpectImpl.iterable.min(this).addToInitial(assertionCreator) -/** - * Creates an [Expect] for the property min of the subject of the assertion, - * so that further fluent calls are assertions about it. - * - * @return The newly created [Expect]. - * @since 0.9.0 - */ -fun , T : Iterable> Expect.min(): Expect = ExpectImpl.iterable.min(this).getExpectOfFeature() /** - * Expects that the property max of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * Creates an [Expect] for the result of calling `max()` on the subject of the assertion, + * so that further fluent calls are assertions about it. * - * @return This assertion container to support a fluent API. + * @return The newly created [Expect] for the extracted feature. + * + * @since 0.9.0 + */ +fun , T : Iterable> Expect.max(): Expect = + ExpectImpl.iterable.max(this).getExpectOfFeature() + +/** + * Expects that the result of calling `max()` on the subject of the assertion + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * * @since 0.9.0 */ fun , T : Iterable> Expect.max(assertionCreator: Expect.() -> Unit): Expect = ExpectImpl.iterable.max(this).addToInitial(assertionCreator) -/** - * Creates an [Expect] for the property max of the subject of the assertion, - * so that further fluent calls are assertions about it. - * - * @return The newly created [Expect]. - * @since 0.9.0 - */ -fun , T : Iterable> Expect.max(): Expect = ExpectImpl.iterable.max(this).getExpectOfFeature() - /** * Expects that the subject of the assertion (an [Iterable]) contains the * [expected] value and the [otherExpected] values (if given). @@ -81,7 +90,7 @@ fun , T : Iterable> Expect.max(): Expect = ExpectImpl * instead of: * `contains('a', 'a')` * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.contains(expected: E, vararg otherExpected: E): Expect = @@ -98,7 +107,7 @@ fun > Expect.contains(expected: E, vararg otherExpected: E * for has to hold; or in other words, the function which defines whether an entry is the one we are looking for * or not. In case it is defined as `null`, then an entry is identified if it is `null` as well. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.contains(assertionCreatorOrNull: (Expect.() -> Unit)?): Expect = @@ -118,7 +127,7 @@ fun > Expect.contains(assertionCreatorOrNull: (Expe * @param otherAssertionCreatorsOrNulls Additional identification lambdas which each identify (separately) an entry * which we are looking for (see [assertionCreatorOrNull] for more information). * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.contains( @@ -136,7 +145,7 @@ fun > Expect.contains( * which will cause a binary backward compatibility break (see * [#292](https://github.com/robstoll/atrium/issues/292) for more information) * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.containsExactly(expected: E, vararg otherExpected: E): Expect = @@ -157,7 +166,7 @@ fun > Expect.containsExactly(expected: E, vararg otherExpe * for has to hold; or in other words, the function which defines whether an entry is the one we are looking for * or not. In case it is defined as `null`, then an entry is identified if it is `null` as well. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.containsExactly(assertionCreatorOrNull: (Expect.() -> Unit)?): Expect = @@ -181,7 +190,7 @@ fun > Expect.containsExactly(assertionCreatorOrNull * @param otherAssertionCreatorsOrNulls Additional identification lambdas which each identify (separately) an entry * which we are looking for (see [assertionCreatorOrNull] for more information). * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.containsExactly( @@ -196,7 +205,7 @@ fun > Expect.containsExactly( * * It is a shortcut for `containsNot.values(expected, *otherExpected)` * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.containsNot(expected: E, vararg otherExpected: E) = @@ -209,7 +218,7 @@ fun > Expect.containsNot(expected: E, vararg otherExpected * * It is a shortcut for `contains.inAnyOrder.atLeast(1).entry(assertionCreatorOrNull)` * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.any(assertionCreatorOrNull: (Expect.() -> Unit)?): Expect = @@ -223,7 +232,7 @@ fun > Expect.any(assertionCreatorOrNull: (Expect * * It is a shortcut for `containsNot.entry(assertionCreatorOrNull)` * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.none(assertionCreatorOrNull: (Expect.() -> Unit)?) = @@ -235,7 +244,7 @@ fun > Expect.none(assertionCreatorOrNull: (Expect> Expect.all(assertionCreatorOrNull: (Expect.() -> Unit)?) = @@ -244,7 +253,7 @@ fun > Expect.all(assertionCreatorOrNull: (Expect /** * Expects that the subject of the assertion (an [Iterable]) has at least one element. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -254,7 +263,7 @@ fun > Expect.hasNext() = addAssertion(ExpectImpl.iterable. /** * Expects that the subject of the assertion (an [Iterable]) does not have next element. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableContainsInAnyOrderCreators.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableContainsInAnyOrderCreators.kt index 4411dd470..6190c56b7 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableContainsInAnyOrderCreators.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableContainsInAnyOrderCreators.kt @@ -3,7 +3,8 @@ package ch.tutteli.atrium.api.fluent.en_GB import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.domain.builders.ExpectImpl import ch.tutteli.atrium.domain.builders.creating.basic.contains.addAssertion -import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains +import ch.tutteli.atrium.domain.builders.utils.toVarArg +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains.CheckerOption import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour import ch.tutteli.kbox.glue @@ -15,10 +16,10 @@ import ch.tutteli.kbox.glue * * @param expected The value which is expected to be contained within this [Iterable]. * - * @return The [Expect] for which the assertion was built to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ -fun > IterableContains.CheckerOption.value(expected: E): Expect = +fun > CheckerOption.value(expected: E): Expect = values(expected) /** @@ -38,10 +39,10 @@ fun > IterableContains.CheckerOption> IterableContains.CheckerOption.values( +fun > CheckerOption.values( expected: E, vararg otherExpected: E ): Expect = addAssertion(ExpectImpl.iterable.contains.valuesInAnyOrder(this, expected glue otherExpected)) @@ -57,10 +58,10 @@ fun > IterableContains.CheckerOption> IterableContains.CheckerOption.entry( +fun > CheckerOption.entry( assertionCreatorOrNull: (Expect.() -> Unit)? ): Expect = entries(assertionCreatorOrNull) @@ -76,10 +77,10 @@ fun > IterableContains.CheckerOption> IterableContains.CheckerOption.entries( +fun > CheckerOption.entries( assertionCreatorOrNull: (Expect.() -> Unit)?, vararg otherAssertionCreatorsOrNulls: (Expect.() -> Unit)? ): Expect = addAssertion( @@ -98,15 +99,15 @@ fun > IterableContains.CheckerOption> IterableContains.CheckerOption.elementsOf( +inline fun > CheckerOption.elementsOf( expectedIterable: Iterable ): Expect { - require(expectedIterable.iterator().hasNext()) { "Iterable without elements are not allowed." } - return values(expectedIterable.first(), *expectedIterable.drop(1).toTypedArray()) + val (first, rest) = toVarArg(expectedIterable) + return values(first, *rest) } diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableContainsInAnyOrderOnlyCreators.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableContainsInAnyOrderOnlyCreators.kt index dd2e7d7da..12ec88a2c 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableContainsInAnyOrderOnlyCreators.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableContainsInAnyOrderOnlyCreators.kt @@ -3,7 +3,8 @@ package ch.tutteli.atrium.api.fluent.en_GB import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.domain.builders.ExpectImpl import ch.tutteli.atrium.domain.builders.creating.basic.contains.addAssertion -import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains +import ch.tutteli.atrium.domain.builders.utils.toVarArg +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains.Builder import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InAnyOrderOnlySearchBehaviour import ch.tutteli.kbox.glue @@ -19,10 +20,10 @@ import ch.tutteli.kbox.glue * * @param expected The value which is expected to be contained within the [Iterable]. * - * @return The [Expect] for which the assertion was built to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ -fun > IterableContains.Builder.value(expected: E): Expect = +fun > Builder.value(expected: E): Expect = values(expected) /** @@ -38,10 +39,10 @@ fun > IterableContains.Builder> IterableContains.Builder.values( +fun > Builder.values( expected: E, vararg otherExpected: E ): Expect = addAssertion(ExpectImpl.iterable.contains.valuesInAnyOrderOnly(this, expected glue otherExpected)) @@ -61,10 +62,10 @@ fun > IterableContains.Builder> IterableContains.Builder.entry( +fun > Builder.entry( assertionCreatorOrNull: (Expect.() -> Unit)? ): Expect = entries(assertionCreatorOrNull) @@ -93,10 +94,10 @@ fun > IterableContains.Builder> IterableContains.Builder.entries( +fun > Builder.entries( assertionCreatorOrNull: (Expect.() -> Unit)?, vararg otherAssertionCreatorsOrNulls: (Expect.() -> Unit)? ): Expect = addAssertion( @@ -119,15 +120,15 @@ fun > IterableContains.Builder> IterableContains.Builder.elementsOf( +inline fun > Builder.elementsOf( expectedIterable: Iterable ): Expect { - require(expectedIterable.iterator().hasNext()) { "Iterable without elements are not allowed" } - return values(expectedIterable.first(), *expectedIterable.drop(1).toTypedArray()) + val (first, rest) = toVarArg(expectedIterable) + return values(first, *rest) } diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableContainsInOrderOnlyCreators.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableContainsInOrderOnlyCreators.kt index 55d400301..7b7a29117 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableContainsInOrderOnlyCreators.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableContainsInOrderOnlyCreators.kt @@ -3,7 +3,8 @@ package ch.tutteli.atrium.api.fluent.en_GB import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.domain.builders.ExpectImpl import ch.tutteli.atrium.domain.builders.creating.basic.contains.addAssertion -import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains +import ch.tutteli.atrium.domain.builders.utils.toVarArg +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains.Builder import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InOrderOnlySearchBehaviour import ch.tutteli.kbox.glue @@ -19,10 +20,10 @@ import ch.tutteli.kbox.glue * * @param expected The value which is expected to be contained within the [Iterable]. * - * @return The [Expect] for which the assertion was built to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ -fun > IterableContains.Builder.value(expected: E): Expect = +fun > Builder.value(expected: E): Expect = values(expected) /** @@ -37,10 +38,10 @@ fun > IterableContains.Builder> IterableContains.Builder.values( +fun > Builder.values( expected: E, vararg otherExpected: E ): Expect = addAssertion(ExpectImpl.iterable.contains.valuesInOrderOnly(this, expected glue otherExpected)) @@ -60,10 +61,10 @@ fun > IterableContains.Builder> IterableContains.Builder.entry( +fun > Builder.entry( assertionCreatorOrNull: (Expect.() -> Unit)? ): Expect = entries(assertionCreatorOrNull) @@ -83,10 +84,10 @@ fun > IterableContains.Builder> IterableContains.Builder.entries( +fun > Builder.entries( assertionCreatorOrNull: (Expect.() -> Unit)?, vararg otherAssertionCreatorsOrNulls: (Expect.() -> Unit)? ): Expect = addAssertion( @@ -109,15 +110,15 @@ fun > IterableContains.Builder> IterableContains.Builder.elementsOf( +inline fun > Builder.elementsOf( expectedIterable: Iterable ): Expect { - require(expectedIterable.iterator().hasNext()) { "Iterable without elements are not allowed." } - return values(expectedIterable.first(), *expectedIterable.drop(1).toTypedArray()) + val (first, rest) = toVarArg(expectedIterable) + return values(first, *rest) } diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableContainsInOrderOnlyGroupedCreators.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableContainsInOrderOnlyGroupedCreators.kt index 95eb8bf0c..a82240127 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableContainsInOrderOnlyGroupedCreators.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableContainsInOrderOnlyGroupedCreators.kt @@ -5,7 +5,7 @@ import ch.tutteli.atrium.domain.builders.ExpectImpl import ch.tutteli.atrium.domain.builders.creating.basic.contains.addAssertion import ch.tutteli.atrium.domain.builders.utils.Group import ch.tutteli.atrium.domain.builders.utils.groupsToList -import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains.Builder import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InOrderOnlyGroupedWithinSearchBehaviour import kotlin.jvm.JvmName @@ -19,10 +19,10 @@ import kotlin.jvm.JvmName * @param otherExpectedGroups Additional groups of values which are expected to appear after the [secondGroup] within * [Iterable] whereas the groups have to appear in the given order. * - * @return The [Expect] for which the assertion was built to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ -fun > IterableContains.Builder.inAnyOrder( +fun > Builder.inAnyOrder( firstGroup: Group, secondGroup: Group, vararg otherExpectedGroups: Group @@ -48,11 +48,11 @@ fun > IterableContains.Builder> IterableContains.Builder.inAnyOrder( +fun > Builder.inAnyOrder( firstGroup: Group<(Expect.() -> Unit)?>, secondGroup: Group<(Expect.() -> Unit)?>, vararg otherExpectedGroups: Group<(Expect.() -> Unit)?> diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableContainsSearchBehaviours.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableContainsSearchBehaviours.kt index 514be712d..5989f127f 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableContainsSearchBehaviours.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/iterableContainsSearchBehaviours.kt @@ -1,7 +1,7 @@ package ch.tutteli.atrium.api.fluent.en_GB import ch.tutteli.atrium.domain.builders.ExpectImpl -import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains.Builder import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.* import kotlin.jvm.JvmName @@ -11,7 +11,7 @@ import kotlin.jvm.JvmName * * @return The newly created builder. */ -val > IterableContains.Builder.inAnyOrder +val > Builder.inAnyOrder get() = ExpectImpl.iterable.contains.searchBehaviours.inAnyOrder(this) /** @@ -20,7 +20,7 @@ val > IterableContains.Builder.inA * * @return The newly created builder. */ -val > IterableContains.Builder.only +val > Builder.only @JvmName("butOnly") get() = ExpectImpl.iterable.contains.searchBehaviours.inAnyOrderOnly(this) @@ -31,7 +31,7 @@ val > IterableContains.Builder> IterableContains.Builder.inOrder +val > Builder.inOrder get() = ExpectImpl.iterable.contains.searchBehaviours.inOrder(this) /** @@ -40,7 +40,7 @@ val > IterableContains.Builder.inO * * @return The newly created builder. */ -val > IterableContains.Builder.only +val > Builder.only @JvmName("andOnly") get() = ExpectImpl.iterable.contains.searchBehaviours.inOrderOnly(this) @@ -50,7 +50,7 @@ val > IterableContains.Builder. * * @return The newly created builder. */ -val > IterableContains.Builder.grouped +val > Builder.grouped get() = ExpectImpl.iterable.contains.searchBehaviours.inOrderOnlyGrouped(this) /** @@ -58,5 +58,5 @@ val > IterableContains.Builder> IterableContains.Builder.within +val > Builder.within get() = ExpectImpl.iterable.contains.searchBehaviours.inOrderOnlyGroupedWithin(this) diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/listAssertions.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/listAssertions.kt index 8280ea4bf..edfc888a1 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/listAssertions.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/listAssertions.kt @@ -10,13 +10,14 @@ import ch.tutteli.atrium.domain.builders.ExpectImpl * @return The newly created [Expect] for the element at position [index]. * @throws AssertionError Might throw an [AssertionError] if the given [index] is out of bound. */ -fun > Expect.get(index: Int): Expect = ExpectImpl.list.get(this, index).getExpectOfFeature() +fun > Expect.get(index: Int): Expect = + ExpectImpl.list.get(this, index).getExpectOfFeature() /** * Expects that the given [index] is within the bounds of the subject of the assertion (a [List]) and that * the element at that position holds all assertions the given [assertionCreator] creates for it. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the given [index] is out of bound. */ fun > Expect.get(index: Int, assertionCreator: Expect.() -> Unit): Expect = diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/mapAssertions.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/mapAssertions.kt index cc7bb8a57..236c44237 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/mapAssertions.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/mapAssertions.kt @@ -14,7 +14,7 @@ import ch.tutteli.kbox.glue * defined as `'a' to 1` and one of the [otherPairs] is defined as `'a' to 1` as well, then both match, * even though they match the same entry. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.contains( @@ -33,7 +33,7 @@ fun > Expect.contains( * defined as `Key('a') { isGreaterThan(0) }` and one of the [otherKeyValues] is defined as `Key('a') { isLessThan(2) }` * , then both match, even though they match the same entry. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ inline fun > Expect.contains( @@ -46,7 +46,7 @@ inline fun > Expect.contains( /** * Expects that the subject of the assertion (a [Map]) contains the given [key]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.containsKey(key: K) = addAssertion(ExpectImpl.map.containsKey(this, key)) @@ -54,7 +54,7 @@ fun > Expect.containsKey(key: K) = addAssertion(ExpectIm /** * Expects that the subject of the assertion (a [Map]) does not contain the given [key]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.containsNotKey(key: K) = addAssertion(ExpectImpl.map.containsNotKey(this, key)) @@ -63,7 +63,7 @@ fun > Expect.containsNotKey(key: K) = addAssertion(Expec /** * Expects that the subject of the assertion (a [Map]) is an empty [Map]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.isEmpty() = addAssertion(ExpectImpl.map.isEmpty(this)) @@ -71,7 +71,7 @@ fun > Expect.isEmpty() = addAssertion(ExpectImpl.map.isEmpty(th /** * Expects that the subject of the assertion (a [Map]) is not an empty [Map]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.isNotEmpty() = addAssertion(ExpectImpl.map.isNotEmpty(this)) @@ -82,7 +82,7 @@ fun > Expect.isNotEmpty() = addAssertion(ExpectImpl.map.isNotEm * creates an [Expect] for the corresponding value and returns the newly created assertion container, * so that further fluent calls are assertions about it. * - * @return The newly created [Expect] for the feature. + * @return The newly created [Expect] for the extracted feature. * @throws AssertionError Might throw an [AssertionError] if the given [key] does not exist. */ fun > Expect.getExisting(key: K): Expect = @@ -92,7 +92,7 @@ fun > Expect.getExisting(key: K): Expect = * Expects that the subject of the assertion (a [Map]) contains the given [key] and that * the corresponding value holds all assertions the given [assertionCreator] creates for it. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if a created [Assertion]s (by calling [assertionCreator]) * does not hold. */ @@ -103,43 +103,41 @@ fun > Expect.getExisting(key: K, assertionCreator: Ex * Creates an [Expect] for the property [Map.keys] of the subject of the assertion, * so that further fluent calls are assertions about it. * - * @return The newly created [Expect] for the feature. + * @return The newly created [Expect] for the extracted feature. */ val > Expect.keys: Expect> - get() = keys(this).getExpectOfFeature() + get() = ExpectImpl.feature.property(this, Map::keys).getExpectOfFeature() /** * Expects that the property [Map.keys] of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.keys(assertionCreator: Expect>.() -> Unit): Expect = - keys(this).addToInitial(assertionCreator) - -private fun > keys(e: Expect) = ExpectImpl.feature.property(e, Map::keys) + ExpectImpl.feature.property(this, Map::keys).addToInitial(assertionCreator) /** * Creates an [Expect] for the property [Map.values] of the subject of the assertion, * so that further fluent calls are assertions about it. * - * @return The newly created [Expect] for the feature. + * @return The newly created [Expect] for the extracted feature. */ val > Expect.values: Expect> - get() = values().getExpectOfFeature() + get() = ExpectImpl.feature.property(this, Map::values).getExpectOfFeature() /** * Expects that the property [Map.keys] of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.values(assertionCreator: Expect>.() -> Unit): Expect = - values().addToInitial(assertionCreator) - -private fun > Expect.values() = ExpectImpl.feature.property(this, Map::values) + ExpectImpl.feature.property(this, Map::values).addToInitial(assertionCreator) /** * Turns `Expect>` into `Expect>>`. @@ -154,12 +152,12 @@ fun > Expect.asEntries(): Expect> /** * Turns `Expect>` into `Expect>>` and expects that it holds all assertions the given - * [assertionCreator] creates. + * [assertionCreator] creates for it. * * The transformation as such is not reflected in reporting. * Use `feature { f(it::entries) }` if you want to show the transformation in reporting. * - * @return The newly created [Expect] for the transformed subject. + * @return An [Expect] for the current subject of the assertion. */ fun > Expect.asEntries( assertionCreator: Expect>>.() -> Unit diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/mapEntryAssertions.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/mapEntryAssertions.kt index 902723d42..3a344eb6a 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/mapEntryAssertions.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/mapEntryAssertions.kt @@ -11,7 +11,7 @@ import ch.tutteli.atrium.domain.builders.ExpectImpl * block. Yet, the actual behaviour depends on implementation - could also be fail fast for instance or augment * reporting etc. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.isKeyValue(key: K, value: V): Expect = @@ -21,16 +21,17 @@ fun > Expect.isKeyValue(key: K, value: V): Expect> Expect.key: Expect get() = ExpectImpl.map.entry.key(this).getExpectOfFeature() /** * Expects that the property [Map.Entry.key] of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.key(assertionCreator: Expect.() -> Unit): Expect = @@ -40,16 +41,17 @@ fun > Expect.key(assertionCreator: Expect.() -> * Creates an [Expect] for the property [Map.Entry.value] of the subject of the assertion, * so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. */ val > Expect.value: Expect get() = ExpectImpl.map.entry.value(this).getExpectOfFeature() /** * Expects that the property [Map.Entry.value] of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.value(assertionCreator: Expect.() -> Unit): Expect = diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/pairAssertions.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/pairAssertions.kt index 0d4e73da3..e584f7ffa 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/pairAssertions.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/pairAssertions.kt @@ -7,16 +7,17 @@ import ch.tutteli.atrium.domain.builders.ExpectImpl * Creates an [Expect] for the property [Pair.first] of the subject of the assertion, * so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. */ -val > Expect.first: Expect - get() = ExpectImpl.pair.first(this).getExpectOfFeature() +val > Expect.first + get() : Expect = ExpectImpl.pair.first(this).getExpectOfFeature() /** * Expects that the property [Pair.first] of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.first(assertionCreator: Expect.() -> Unit): Expect = @@ -26,16 +27,17 @@ fun > Expect.first(assertionCreator: Expect.() -> Uni * Creates an [Expect] for the property [Pair.second] of the subject of the assertion, * so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. */ -val > Expect.second: Expect - get() = ExpectImpl.pair.second(this).getExpectOfFeature() +val > Expect.second + get() : Expect = ExpectImpl.pair.second(this).getExpectOfFeature() /** * Expects that the property [Pair.second] of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun > Expect.second(assertionCreator: Expect.() -> Unit): Expect = diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/sequenceAssertions.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/sequenceAssertions.kt index 04378221d..6aeb691f2 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/sequenceAssertions.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/sequenceAssertions.kt @@ -21,7 +21,7 @@ fun > Expect.asIterable(): Expect> = * The transformation as such is not reflected in reporting. * Use `feature(Sequence::asIterable, assertionCreator)` if you want to show the transformation in reporting. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. */ fun > Expect.asIterable(assertionCreator: Expect>.() -> Unit): Expect = apply { asIterable().addAssertionsCreatedBy(assertionCreator) } diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/throwableAssertions.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/throwableAssertions.kt index 8bec46bac..b24342608 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/throwableAssertions.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/throwableAssertions.kt @@ -1,12 +1,13 @@ package ch.tutteli.atrium.api.fluent.en_GB import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl /** * Expects that the property [Throwable.message] of the subject of the assertion is not null, * creates an [Expect] for it and returns it. * - * @return The newly created [Expect] for the property [Throwable.message] of the subject of the assertion + * @return The newly created [Expect] for the property [Throwable.message] of the subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ val Expect.message: Expect @@ -14,9 +15,10 @@ val Expect.message: Expect /** * Expects that the property [Throwable.message] of the subject of the assertion is not null and - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun Expect.message(assertionCreator: Expect.() -> Unit): Expect = @@ -33,8 +35,39 @@ fun Expect.message(assertionCreator: Expect.() -> Uni * Notice that a runtime check applies which assures that only [CharSequence], [Number] and [Char] are passed * (this function expects `Any` for your convenience, so that you can mix [String] and [Int] for instance). * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun Expect.messageContains(expected: Any, vararg otherExpected: Any): Expect = message { contains(expected, *otherExpected) } + + +/** + * Expects that the property [Throwable.cause] of the subject *is a* [TExpected] (the same type or a sub-type), + * creates an [Expect] of the [TExpected] type for it and returns it. + * + * @return The newly created [Expect] for the property [Throwable.cause] of the subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.10.0 + */ +inline fun Expect.cause(): Expect = + ExpectImpl.throwable.cause(this, TExpected::class).getExpectOfFeature() + +/** + * + * Expects that the property [Throwable.cause] of the subject *is a* [TExpected] (the same type or a sub-type) and + * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * + * Notice, in contrast to other assertion functions which expect an [assertionCreator], this function returns not + * [Expect] of the initial type, which was some type `T `, but an [Expect] of the specified type [TExpected]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.10.0 + */ +inline fun Expect.cause( + noinline assertionCreator: Expect.() -> Unit +): Expect = + ExpectImpl.throwable.cause(this, TExpected::class).addToFeature(assertionCreator) diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/AnyAssertionsSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/AnyAssertionsSpec.kt index 5ce782d8e..34bb7ccb9 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/AnyAssertionsSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/AnyAssertionsSpec.kt @@ -2,6 +2,7 @@ package ch.tutteli.atrium.api.fluent.en_GB import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.specs.fun1 +import ch.tutteli.atrium.specs.withNullableSuffix import kotlin.reflect.KFunction2 import kotlin.reflect.KProperty1 @@ -12,16 +13,16 @@ class AnyAssertionsSpec : ch.tutteli.atrium.specs.integration.AnyAssertionsSpec( fun1(Expect::toBe), fun1(Expect::notToBe), fun1(Expect::notToBe), - fun1(Expect::notToBe, suffix = " nullable"), - fun1(Expect::notToBe, suffix = " nullable"), + fun1(Expect::notToBe).withNullableSuffix(), + fun1(Expect::notToBe).withNullableSuffix(), fun1(Expect::isSameAs), fun1(Expect::isSameAs), - fun1(Expect::isSameAs, suffix = " nullable"), - fun1(Expect::isSameAs, suffix = " nullable"), + fun1(Expect::isSameAs).withNullableSuffix(), + fun1(Expect::isSameAs).withNullableSuffix(), fun1(Expect::isNotSameAs), fun1(Expect::isNotSameAs), - fun1(Expect::isNotSameAs, suffix = " nullable"), - fun1(Expect::isNotSameAs, suffix = " nullable"), + fun1(Expect::isNotSameAs).withNullableSuffix(), + fun1(Expect::isNotSameAs).withNullableSuffix(), "${Expect::toBe.name}(null)" to Companion::toBeNull, fun1(Expect::toBeNullIfNullGivenElse), @@ -43,7 +44,8 @@ class AnyAssertionsSpec : ch.tutteli.atrium.specs.integration.AnyAssertionsSpec( companion object { private fun toBeNull(expect: Expect) = expect.toBe(null) - private fun isAFeature(expect: Expect): Expect = expect.isA() + @Suppress("RemoveExplicitTypeArguments") + private fun isAFeature(expect: Expect): Expect = expect.isA() private val andImmediate: KProperty1, Expect> = Expect::and fun getAndImmediatePair(): Pair.() -> Expect> = andImmediate.name to Expect::and diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CharSequenceAssertionsSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CharSequenceAssertionsSpec.kt index f2615bb64..9ae85d4af 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CharSequenceAssertionsSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CharSequenceAssertionsSpec.kt @@ -3,8 +3,9 @@ package ch.tutteli.atrium.api.fluent.en_GB import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.specs.fun0 import ch.tutteli.atrium.specs.fun1 +import ch.tutteli.atrium.specs.notImplemented -object CharSequenceAssertionsSpec : ch.tutteli.atrium.specs.integration.CharSequenceAssertionsSpec( +class CharSequenceAssertionsSpec : ch.tutteli.atrium.specs.integration.CharSequenceAssertionsSpec( fun0(Expect::isEmpty), fun0(Expect::isNotEmpty), fun0(Expect::isNotBlank), @@ -18,4 +19,26 @@ object CharSequenceAssertionsSpec : ch.tutteli.atrium.specs.integration.CharSequ fun1(Expect::endsNotWith), fun1(Expect::matches), fun1(Expect::mismatches) -) +) { + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + val a1: Expect = notImplemented() + + a1.isEmpty() + a1.isNotEmpty() + a1.isNotBlank() + + a1.startsWith("expected") + a1.startsNotWith("expected") + a1.endsWith("expected") + a1.endsNotWith("expected") + + a1.startsWith('a') + a1.startsNotWith('a') + a1.endsWith('a') + a1.endsNotWith('a') + + a1.matches(Regex("a")) + a1.mismatches(Regex("a")) + } +} diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CharSequenceContainsAtLeastAssertionsSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CharSequenceContainsAtLeastAssertionsSpec.kt index 8c40b75b1..d2b46b4fb 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CharSequenceContainsAtLeastAssertionsSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CharSequenceContainsAtLeastAssertionsSpec.kt @@ -29,20 +29,27 @@ class CharSequenceContainsAtLeastAssertionsSpec : Spek({ ) {}) include(object : Spek({ - describe("elementsOf") { + describe("atLeast(1).elementsOf") { it("passing an empty iterable throws an IllegalArgumentException") { expect { expect("test").contains.atLeast(1).elementsOf(emptyList()) }.toThrow { messageContains("Iterable without elements are not allowed") } } } - describe("elementsOf ignoring case") { + describe("ignoringCase.atLeast(1).elementsOf") { it("passing an empty iterable throws an IllegalArgumentException") { expect { expect("test").contains.ignoringCase.atLeast(1).elementsOf(emptyList()) }.toThrow { messageContains("Iterable without elements are not allowed") } } } + describe("ignoringCase.elementsOf") { + it("passing an empty iterable throws an IllegalArgumentException") { + expect { + expect("test").contains.ignoringCase.elementsOf(emptyList()) + }.toThrow { messageContains("Iterable without elements are not allowed") } + } + } }) {}) }) { @@ -101,7 +108,13 @@ class CharSequenceContainsAtLeastAssertionsSpec : Spek({ a: Any, aX: Array ): Expect = - expect.contains.ignoringCase.atLeast(atLeast).elementsOf(listOf(a, *aX)) + if (aX.isEmpty()) { + if (atLeast == 1) expect.contains.ignoringCase.elementsOf(listOf(a)) + else expect.contains.ignoringCase.atLeast(atLeast).elementsOf(listOf(a)) + } else { + if (atLeast == 1) expect.contains.ignoringCase.elementsOf(listOf(a, *aX)) + else expect.contains.ignoringCase.atLeast(atLeast).elementsOf(listOf(a, *aX)) + } private val atLeastButAtMostDescr = { what: String, timesAtLeast: String, timesAtMost: String -> "$contains $what $atLeast $timesAtLeast $butAtMost $timesAtMost" @@ -155,7 +168,7 @@ class CharSequenceContainsAtLeastAssertionsSpec : Spek({ aX: Array ) = expect.contains.ignoringCase.atLeast(atLeast).butAtMost(butAtMost).elementsOf(listOf(a, *aX)) - private fun getContainsNotPair() = containsNot to Companion::getErrorMsgContainsNot + private fun getContainsNotPair() = containsNot to ::getErrorMsgContainsNot private fun getErrorMsgContainsNot(times: Int) = "use $containsNot instead of $atLeast($times)" diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CharSequenceContainsContainsNotAssertionsSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CharSequenceContainsContainsNotAssertionsSpec.kt index a6708ee78..01e19abd6 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CharSequenceContainsContainsNotAssertionsSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CharSequenceContainsContainsNotAssertionsSpec.kt @@ -1,28 +1,52 @@ package ch.tutteli.atrium.api.fluent.en_GB import ch.tutteli.atrium.creating.Expect -import kotlin.reflect.KFunction3 +import ch.tutteli.atrium.specs.fun2 +import ch.tutteli.atrium.specs.notImplemented +import org.spekframework.spek2.Spek -class CharSequenceContainsContainsNotAssertionsSpec : - ch.tutteli.atrium.specs.integration.CharSequenceContainsContainsNotAssertionsSpec( +class CharSequenceContainsContainsNotAssertionsSpec : Spek({ + + include(object : ch.tutteli.atrium.specs.integration.CharSequenceContainsContainsNotAssertionsSpec( getContainsPair(), getContainsNotPair(), - "◆ ", "⚬ ", "▶ " - ) { + "◆ ", "⚬ ", "▶ ", + "[Atrium][Builder]" + ) {}) + + include(object : ch.tutteli.atrium.specs.integration.CharSequenceContainsContainsNotAssertionsSpec( + getContainsShortcutPair(), + getContainsNotShortcutPair(), + "◆ ", "⚬ ", "▶ ", + "[Atrium][Shortcut]" + ) {}) +}) { companion object : CharSequenceContainsSpecBase() { - private val containsFun: KFunction3, Any, Array, Expect> = - Expect::contains + private fun getContainsPair() = "$contains.$atLeast(1).values" to Companion::containsValues - fun getContainsPair() = containsFun.name to Companion::containsShortcut + private fun containsValues(expect: Expect, a: Any, aX: Array) = + if (aX.isEmpty()) expect.contains.atLeast(1).value(a) + else expect.contains.atLeast(1).values(a, *aX) - private fun containsShortcut(expect: Expect, a: Any, aX: Array) = expect.contains(a, *aX) + private fun getContainsNotPair() = + "${super.containsNot} o $atLeast 1 value/the Values" to Companion::containsNotValues - private val containsNotFun: KFunction3, Any, Array, Expect> = - Expect::containsNot + private fun containsNotValues(expect: Expect, a: Any, aX: Array) = + if (aX.isEmpty()) expect.containsNot.value(a) + else expect.containsNot.values(a, *aX) - private fun getContainsNotPair() = containsNotFun.name to Companion::containsNotShortcut + private fun getContainsShortcutPair() = + fun2>(Expect::contains) - private fun containsNotShortcut(expect: Expect, a: Any, aX: Array) = - expect.containsNot(a, *aX) + private fun getContainsNotShortcutPair() = + fun2>(Expect::containsNot) + } + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + val a1: Expect = notImplemented() + + a1.contains(1, "a", 'c') + a1.containsNot(1, "a", 'c') } } diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CharSequenceContainsSpecBase.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CharSequenceContainsSpecBase.kt index 0298ff043..a250dce86 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CharSequenceContainsSpecBase.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CharSequenceContainsSpecBase.kt @@ -6,6 +6,7 @@ import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceConta import ch.tutteli.atrium.domain.creating.charsequence.contains.searchbehaviours.NoOpSearchBehaviour import ch.tutteli.atrium.specs.fun2 import ch.tutteli.atrium.specs.name +import ch.tutteli.atrium.specs.notImplemented import kotlin.reflect.KFunction3 import kotlin.reflect.KProperty @@ -28,4 +29,55 @@ abstract class CharSequenceContainsSpecBase { > = CharSequenceContains.CheckerOption<*, NoOpSearchBehaviour>::regex protected val regex = regexKFun.name protected val ignoringCase = CharSequenceContains.Builder<*, NoOpSearchBehaviour>::ignoringCase.name + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + val a1: Expect = notImplemented() + + a1.contains.atLeast(1).value(1) + a1.contains.atMost(2).values("a", 1) + a1.contains.notOrAtMost(2).regex("h|b") + a1.contains.exactly(2).regex("h|b", "b") + a1.contains.atLeast(2).regex(Regex("bla")) + a1.contains.atLeast(2).regex(Regex("bla"), Regex("b")) + a1.contains.atLeast(2).elementsOf(listOf("a", 2)) + + a1.containsNot.value(1) + a1.containsNot.values("a", 1) + a1.containsNot.regex("h|b", "b") + a1.containsNot.regex(Regex("bla")) + a1.containsNot.regex(Regex("bla"), Regex("b")) + a1.containsNot.elementsOf(listOf("a", 2)) + + a1.contains.ignoringCase.atLeast(1).value("a") + a1.contains.ignoringCase.atLeast(1).values("a", 'b') + a1.contains.ignoringCase.atLeast(1).regex("a") + a1.contains.ignoringCase.atLeast(1).regex("a", "bl") + // not supported on purpose as one can specify an ignore case flag for Regex + // and hence these would be a second way to do the same thing + //a1.contains.ignoringCase.atLeast(1).regex(Regex("a")) + //a1.contains.ignoringCase.atLeast(1).regex(Regex("a"), Regex("bl")) + a1.contains.ignoringCase.atLeast(1).elementsOf(listOf(1, 2)) + + a1.containsNot.ignoringCase.value("a") + a1.containsNot.ignoringCase.values("a", 'b') + a1.containsNot.ignoringCase.regex("a") + a1.containsNot.ignoringCase.regex("a", "bl") + // not supported on purpose as one can specify an ignore case flag for Regex + // and hence these would be a second way to do the same thing + //a1.containsNot.ignoringCase.regex(Regex("a")) + //a1.containsNot.ignoringCase.regex(Regex("a"), Regex("bl")) + a1.containsNot.ignoringCase.elementsOf(listOf(1, 2)) + + // skip atLeast + a1.contains.ignoringCase.value("a") + a1.contains.ignoringCase.values("a", 'b') + a1.contains.ignoringCase.regex("a") + a1.contains.ignoringCase.regex("a", "bl") + // not supported on purpose as one can specify an ignore case flag for Regex + // and hence these would be a second way to do the same thing + //a1.contains.ignoringCase.regex(Regex("a")) + //a1.contains.ignoringCase.regex(Regex("a"), Regex("bl")) + a1.contains.ignoringCase.elementsOf(listOf("a", 2)) + } } diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CollectionAssertionsSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CollectionAssertionsSpec.kt index e0523bce2..0e62df1b7 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CollectionAssertionsSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CollectionAssertionsSpec.kt @@ -10,8 +10,8 @@ object CollectionAssertionsSpec : ch.tutteli.atrium.specs.integration.Collection ) { @Suppress("unused", "UNUSED_VALUE") private fun ambiguityTest() { - val a1: Expect> = notImplemented() - val a1b: Expect> = notImplemented() + val a1: Expect> = notImplemented() + val a1b: Expect> = notImplemented() val star: Expect> = notImplemented() diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CollectionFeatureAssertionsSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CollectionFeatureAssertionsSpec.kt index 77150aae4..80bb1df3b 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CollectionFeatureAssertionsSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/CollectionFeatureAssertionsSpec.kt @@ -11,10 +11,10 @@ object CollectionFeatureAssertionsSpec : ch.tutteli.atrium.specs.integration.Col ) { @Suppress("unused", "UNUSED_VALUE") private fun ambiguityTest() { - var a1: Expect> = notImplemented() - var a1b: Expect> = notImplemented() + var a1: Expect> = notImplemented() + var a1b: Expect> = notImplemented() - var star: Expect> = notImplemented() + var star: Expect> = notImplemented() a1.size a1 = a1.size { } diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/FloatingPointWithErrorToleranceAssertionsSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/FloatingPointWithErrorToleranceAssertionsSpec.kt index 281a0ea08..573590536 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/FloatingPointWithErrorToleranceAssertionsSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/FloatingPointWithErrorToleranceAssertionsSpec.kt @@ -1,10 +1,11 @@ package ch.tutteli.atrium.api.fluent.en_GB import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.adjustName import ch.tutteli.atrium.specs.fun2 class FloatingPointWithErrorToleranceAssertionsSpec : ch.tutteli.atrium.specs.integration.FloatingPointWithErrorToleranceAssertionsSpec( - fun2(Expect::toBeWithErrorTolerance, suffix = " for Float"), - fun2(Expect::toBeWithErrorTolerance, suffix = " for Double") + fun2(Expect::toBeWithErrorTolerance).adjustName { "$it for Float" }, + fun2(Expect::toBeWithErrorTolerance).adjustName { "$it for Double" } ) diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/Fun0AssertionsSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/Fun0AssertionsSpec.kt index 504be460c..7843e4d1f 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/Fun0AssertionsSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/Fun0AssertionsSpec.kt @@ -4,19 +4,23 @@ import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.specs.feature0 import ch.tutteli.atrium.specs.feature1 import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.withFeatureSuffix class Fun0AssertionsSpec : ch.tutteli.atrium.specs.integration.Fun0AssertionsSpec( - "toThrow" to Companion::toThrowFeature, + ("toThrow" to Companion::toThrowFeature).withFeatureSuffix(), "toThrow" to Companion::toThrow, feature0<() -> Int, Int>(Expect<() -> Int>::notToThrow), feature1<() -> Int, Expect.() -> Unit, Int>(Expect<() -> Int>::notToThrow), "⚬ ", "» " ) { - companion object { - fun toThrowFeature(expect: Expect Any?>) = expect.toThrow() - fun toThrow(expect: Expect Any?>, assertionCreator: Expect.() -> Unit) = - expect.toThrow { assertionCreator() } + private fun toThrowFeature(expect: Expect Any?>) = + expect.toThrow() + + private fun toThrow( + expect: Expect Any?>, + assertionCreator: Expect.() -> Unit + ) = expect.toThrow { assertionCreator() } } @Suppress("unused", "UNUSED_VALUE", "UNUSED_VARIABLE") @@ -37,3 +41,4 @@ class Fun0AssertionsSpec : ch.tutteli.atrium.specs.integration.Fun0AssertionsSpe val r8: Expect = a2.notToThrow {} } } + diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableAllAssertionsSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableAllAssertionsSpec.kt index 760bb7016..813e6cbf3 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableAllAssertionsSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableAllAssertionsSpec.kt @@ -3,18 +3,19 @@ package ch.tutteli.atrium.api.fluent.en_GB import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.specs.fun1 import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.withNullableSuffix object IterableAllAssertionsSpec : ch.tutteli.atrium.specs.integration.IterableAllAssertionsSpec( fun1(Expect>::all), - fun1(Expect>::all), + fun1(Expect>::all).withNullableSuffix(), "◆ ", "❗❗ ", "⚬ ", "» ", "▶ ", "◾ " ) { @Suppress("unused", "UNUSED_VALUE") private fun ambiguityTest() { - var a1: Expect> = notImplemented() - var a1b: Expect> = notImplemented() + var a1: Expect> = notImplemented() + var a1b: Expect> = notImplemented() - var star: Expect> = notImplemented() + var star: Expect> = notImplemented() a1 = a1.all {} diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableAnyAssertionsSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableAnyAssertionsSpec.kt index 7f6534a7a..160715c85 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableAnyAssertionsSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableAnyAssertionsSpec.kt @@ -4,9 +4,9 @@ import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.domain.builders.ExpectImpl import ch.tutteli.atrium.specs.fun1 import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.withNullableSuffix import org.spekframework.spek2.Spek import kotlin.reflect.KFunction2 -import kotlin.reflect.KFunction3 class IterableAnyAssertionsSpec : Spek({ include(PredicateSpec) @@ -16,75 +16,75 @@ class IterableAnyAssertionsSpec : Spek({ }) { object PredicateSpec : ch.tutteli.atrium.specs.integration.IterableAnyAssertionsSpec( fun1(Expect>::any), - fun1(Expect>::any), + fun1(Expect>::any).withNullableSuffix(), "◆ ", "[Atrium][Predicate] " ) object BuilderSpec : ch.tutteli.atrium.specs.integration.IterableAnyAssertionsSpec( getContainsPair(), - getContainsNullablePair(), + getContainsNullablePair().withNullableSuffix(), "◆ ", "[Atrium][Builder] " ) object ShortcutSpec : ch.tutteli.atrium.specs.integration.IterableAnyAssertionsSpec( getContainsShortcutPair(), - getContainsNullableShortcutPair(), + getContainsNullableShortcutPair().withNullableSuffix(), "◆ ", "[Atrium][Shortcut] " ) object SequenceSpec : ch.tutteli.atrium.specs.integration.IterableAnyAssertionsSpec( getContainsSequencePair(), - getContainsNullableSequencePair(), + getContainsNullableSequencePair().withNullableSuffix(), "◆ ", "[Atrium][Sequence] " ) companion object : IterableContainsSpecBase() { fun getContainsPair() = - "$contains.$inAnyOrder.$atLeast(1).$inAnyOrderEntries" to Companion::containsInAnyOrderEntries + "$contains.$inAnyOrder.$atLeast(1).$inAnyOrderEntries" to Companion::containsInAnyOrderEntry - private fun containsInAnyOrderEntries(expect: Expect>, a: Expect.() -> Unit) = + private fun containsInAnyOrderEntry(expect: Expect>, a: Expect.() -> Unit) = expect.contains.inAnyOrder.atLeast(1).entry(a) fun getContainsNullablePair() = - "$contains.$inAnyOrder.$atLeast(1).$inAnyOrderEntries" to Companion::containsNullableEntries + "$contains.$inAnyOrder.$atLeast(1).$inAnyOrderEntries" to Companion::containsNullableEntry - private fun containsNullableEntries(expect: Expect>, a: (Expect.() -> Unit)?) = + private fun containsNullableEntry(expect: Expect>, a: (Expect.() -> Unit)?) = expect.contains.inAnyOrder.atLeast(1).entry(a) - private val containsShortcutFun: KFunction3>, Expect.() -> Unit, Array.() -> Unit>, Expect>> = + private val containsShortcutFun: KFunction2>, Expect.() -> Unit, Expect>> = Expect>::contains - fun getContainsShortcutPair() = containsShortcutFun.name to Companion::containsInAnyOrderEntriesShortcut + fun getContainsShortcutPair() = containsShortcutFun.name to Companion::containsInAnyOrderEntryShortcut - private fun containsInAnyOrderEntriesShortcut(expect: Expect>, a: Expect.() -> Unit) = + private fun containsInAnyOrderEntryShortcut(expect: Expect>, a: Expect.() -> Unit) = expect.contains(a) private val containsShortcutNullableFun: KFunction2>, (Expect.() -> Unit)?, Expect>> = Expect>::contains fun getContainsNullableShortcutPair() = - containsShortcutNullableFun.name to Companion::containsNullableEntriesShortcut + containsShortcutNullableFun.name to Companion::containsNullableEntryShortcut - private fun containsNullableEntriesShortcut( + private fun containsNullableEntryShortcut( expect: Expect>, a: (Expect.() -> Unit)? ) = expect.contains(a) private fun getContainsSequencePair() = - "asSequence().${Sequence<*>::asIterable.name}().${containsShortcutFun.name}" to Companion::containsInAnyOrderEntriesSequence + "asSequence().${Sequence<*>::asIterable.name}().${containsShortcutFun.name}" to Companion::containsInAnyOrderEntrySequence - private fun containsInAnyOrderEntriesSequence(expect: Expect>, a: Expect.() -> Unit) = + private fun containsInAnyOrderEntrySequence(expect: Expect>, a: Expect.() -> Unit) = ExpectImpl.changeSubject(expect).unreported { it.asSequence() }.asIterable().contains(a) fun getContainsNullableSequencePair() = - "asSequence().${Sequence<*>::asIterable.name}().${containsShortcutNullableFun.name}" to Companion::containsNullableEntriesSequence + "asSequence().${Sequence<*>::asIterable.name}().${containsShortcutNullableFun.name}" to Companion::containsNullableEntrySequence - private fun containsNullableEntriesSequence( + private fun containsNullableEntrySequence( expect: Expect>, a: (Expect.() -> Unit)? ) = ExpectImpl.changeSubject(expect).unreported { it.asSequence() }.asIterable().contains(a) @@ -92,10 +92,10 @@ class IterableAnyAssertionsSpec : Spek({ @Suppress("unused", "UNUSED_VALUE") private fun ambiguityTest() { - var a1: Expect> = notImplemented() - var a1b: Expect> = notImplemented() + var a1: Expect> = notImplemented() + var a1b: Expect> = notImplemented() - var star: Expect> = notImplemented() + var star: Expect> = notImplemented() a1 = a1.any {} a1 = a1.contains {} diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableAssertionsSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableAssertionsSpec.kt index c01de5b2a..b53bea38e 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableAssertionsSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableAssertionsSpec.kt @@ -11,10 +11,9 @@ object IterableAssertionsSpec : ch.tutteli.atrium.specs.integration.IterableAsse @Suppress("unused", "UNUSED_VALUE") private fun ambiguityTest() { - var a1: Expect> = notImplemented() - var a1b: Expect> = notImplemented() - - var star: Expect> = notImplemented() + var a1: Expect> = notImplemented() + var a1b: Expect> = notImplemented() + var star: Expect> = notImplemented() a1 = a1.hasNext() a1 = a1.hasNotNext() diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec.kt index 501480e1c..f0f3b5fd9 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec.kt @@ -59,7 +59,7 @@ class IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec : Spek({ else expect.contains(a, *aX) - private val containsNullableFun: KFunction3>, Double, Array, Expect>> = + private val containsNullableFun: KFunction3>, Double?, Array, Expect>> = Expect>::contains fun getContainsNullableShortcutPair() = containsNullableFun.name to Companion::containsNullableValuesShortcut diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableContainsInOrderOnlyGroupedValuesAssertionsSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableContainsInOrderOnlyGroupedValuesAssertionsSpec.kt index 36d701663..499d250e7 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableContainsInOrderOnlyGroupedValuesAssertionsSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableContainsInOrderOnlyGroupedValuesAssertionsSpec.kt @@ -21,9 +21,7 @@ class IterableContainsInOrderOnlyGroupedValuesAssertionsSpec : a1: Group, a2: Group, aX: Array> - ): Expect> { - return expect.contains.inOrder.only.grouped.within.inAnyOrder(a1, a2, *aX) - } + ): Expect> = expect.contains.inOrder.only.grouped.within.inAnyOrder(a1, a2, *aX) private fun groupFactory(groups: Array): Group = when (groups.size) { @@ -43,9 +41,7 @@ class IterableContainsInOrderOnlyGroupedValuesAssertionsSpec : a1: Group, a2: Group, aX: Array> - ): Expect> { - return expect.contains.inOrder.only.grouped.within.inAnyOrder(a1, a2, *aX) - } + ): Expect> = expect.contains.inOrder.only.grouped.within.inAnyOrder(a1, a2, *aX) private fun nullableGroupFactory(groups: Array): Group = when (groups.size) { diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableContainsSpecBase.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableContainsSpecBase.kt index 2bd64bb35..393cc923b 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableContainsSpecBase.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableContainsSpecBase.kt @@ -43,30 +43,69 @@ abstract class IterableContainsSpecBase { @Suppress("unused") private fun ambiguityTest() { val list: Expect> = notImplemented() - val nullableList: Expect> = notImplemented() + val nullableList: Expect> = notImplemented() val subList: Expect> = notImplemented() + val star: Expect> = notImplemented() list.contains(1) list.contains(1f) - list.contains(1, 2) list.contains(1, 2f) list.contains {} list.contains({}, {}) + list.containsNot(1) + list.containsNot(1f) + list.containsNot(1, 2f) + list.containsNot.entry {} + list.containsNot.entries({}, {}) + subList.contains(1) subList.contains(1f) - subList.contains(1, 2) subList.contains(1, 2f) subList.contains {} subList.contains({}, {}) + subList.containsNot(1) + subList.containsNot(1f) + subList.containsNot(1, 2f) + subList.containsNot.entry {} + subList.containsNot.entries({}, {}) + nullableList.contains(1) nullableList.contains(1f) - nullableList.contains(1, 2) nullableList.contains(1, 2f) nullableList.contains {} + nullableList.contains({}, {}) + nullableList.containsNot(1) + nullableList.containsNot(1f) + nullableList.containsNot(1, 2f) + nullableList.containsNot.entry {} + nullableList.containsNot.entries({}, {}) nullableList.contains(null) nullableList.contains({}, null) - nullableList.contains({}, {}) nullableList.contains(null, {}) + nullableList.contains(null, null) + nullableList.containsNot(null) + nullableList.containsNot.entries({}, null) + nullableList.containsNot.entries(null, {}) + nullableList.containsNot.entries(null, null) + + star.contains(1) + star.contains(1f) + star.contains(1, 2f) + star.contains {} + star.contains({}, {}) + star.containsNot(1) + star.containsNot(1f) + star.containsNot(1, 2f) + star.containsNot.entry {} + star.containsNot.entries({}, {}) + star.contains(null) + star.contains({}, null) + star.contains(null, {}) + star.contains(null, null) + star.containsNot(null) + star.containsNot.entries({}, null) + star.containsNot.entries(null, {}) + star.containsNot.entries(null, null) list.containsExactly(1) list.containsExactly(1, 2f) @@ -85,67 +124,162 @@ abstract class IterableContainsSpecBase { nullableList.containsExactly(null, {}) list.contains.inAnyOrder.atLeast(1).value(1) - list.contains.inAnyOrder.atLeast(1).value(null) + list.contains.inAnyOrder.atLeast(1).values(2, 1) list.contains.inAnyOrder.atLeast(1).entry {} - list.contains.inAnyOrder.atLeast(1).entry(null) + list.contains.inAnyOrder.atLeast(1).entries({}, {}) + list.contains.inAnyOrder.atLeast(1).elementsOf(listOf(1, 2)) subList.contains.inAnyOrder.atLeast(1).value(1) - subList.contains.inAnyOrder.atLeast(1).value(null) + subList.contains.inAnyOrder.atLeast(1).values(2, 1) subList.contains.inAnyOrder.atLeast(1).entry {} - subList.contains.inAnyOrder.atLeast(1).entry(null) + subList.contains.inAnyOrder.atLeast(1).entries({}, {}) + subList.contains.inAnyOrder.atLeast(1).elementsOf(listOf(1, 2)) + nullableList.contains.inAnyOrder.atLeast(1).value(1) + nullableList.contains.inAnyOrder.atLeast(1).values(2, 1) + nullableList.contains.inAnyOrder.atLeast(1).entry {} + nullableList.contains.inAnyOrder.atLeast(1).entries({}, {}) + nullableList.contains.inAnyOrder.atLeast(1).elementsOf(listOf(1, 2)) + nullableList.contains.inAnyOrder.atLeast(1).value(null) + nullableList.contains.inAnyOrder.atLeast(1).values(null, 1) + nullableList.contains.inAnyOrder.atLeast(1).values(2, null) + nullableList.contains.inAnyOrder.atLeast(1).values(null, null) + nullableList.contains.inAnyOrder.atLeast(1).entry(null) + nullableList.contains.inAnyOrder.atLeast(1).entries(null, {}) + nullableList.contains.inAnyOrder.atLeast(1).entries({}, null) + nullableList.contains.inAnyOrder.atLeast(1).entries(null, null) + star.contains.inAnyOrder.atLeast(1).value(1) + star.contains.inAnyOrder.atLeast(1).values(2, 1) + star.contains.inAnyOrder.atLeast(1).entry {} + star.contains.inAnyOrder.atLeast(1).entries({}, {}) + star.contains.inAnyOrder.atLeast(1).elementsOf(listOf(1, 2)) + star.contains.inAnyOrder.atLeast(1).value(null) + star.contains.inAnyOrder.atLeast(1).values(null, 1) + star.contains.inAnyOrder.atLeast(1).values(2, null) + star.contains.inAnyOrder.atLeast(1).values(null, null) + star.contains.inAnyOrder.atLeast(1).entry(null) + star.contains.inAnyOrder.atLeast(1).entries(null, {}) + star.contains.inAnyOrder.atLeast(1).entries({}, null) + star.contains.inAnyOrder.atLeast(1).entries(null, null) list.contains.inAnyOrder.only.value(1) - list.contains.inAnyOrder.only.value(null) + list.contains.inAnyOrder.only.values(2, 1) list.contains.inAnyOrder.only.entry {} - list.contains.inAnyOrder.only.entry(null) + list.contains.inAnyOrder.only.entries({}, {}) + list.contains.inAnyOrder.only.elementsOf(listOf(1, 2)) subList.contains.inAnyOrder.only.value(1) - subList.contains.inAnyOrder.only.value(null) + subList.contains.inAnyOrder.only.values(2, 1) subList.contains.inAnyOrder.only.entry {} - subList.contains.inAnyOrder.only.entry(null) + subList.contains.inAnyOrder.only.entries({}, {}) + subList.contains.inAnyOrder.only.elementsOf(listOf(1, 2)) + nullableList.contains.inAnyOrder.only.value(1) + nullableList.contains.inAnyOrder.only.values(2, 1) + nullableList.contains.inAnyOrder.only.entry {} + nullableList.contains.inAnyOrder.only.entries({}, {}) + nullableList.contains.inAnyOrder.only.elementsOf(listOf(1, 2)) + nullableList.contains.inAnyOrder.only.value(null) + nullableList.contains.inAnyOrder.only.values(null, 1) + nullableList.contains.inAnyOrder.only.values(2, null) + nullableList.contains.inAnyOrder.only.values(null, null) + nullableList.contains.inAnyOrder.only.entry(null) + nullableList.contains.inAnyOrder.only.entries(null, {}) + nullableList.contains.inAnyOrder.only.entries({}, null) + nullableList.contains.inAnyOrder.only.entries(null, null) + star.contains.inAnyOrder.only.value(1) + star.contains.inAnyOrder.only.values(2, 1) + star.contains.inAnyOrder.only.entry {} + star.contains.inAnyOrder.only.entries({}, {}) + star.contains.inAnyOrder.only.elementsOf(listOf(1, 2)) + star.contains.inAnyOrder.only.value(null) + star.contains.inAnyOrder.only.values(null, 1) + star.contains.inAnyOrder.only.values(2, null) + star.contains.inAnyOrder.only.values(null, null) + star.contains.inAnyOrder.only.entry(null) + star.contains.inAnyOrder.only.entries(null, {}) + star.contains.inAnyOrder.only.entries({}, null) + star.contains.inAnyOrder.only.entries(null, null) list.contains.inOrder.only.value(1) - list.contains.inOrder.only.value(null) + list.contains.inOrder.only.values(2, 1) list.contains.inOrder.only.entry {} - list.contains.inOrder.only.entry(null) + list.contains.inOrder.only.entries({}, {}) + list.contains.inOrder.only.elementsOf(listOf(1, 2)) subList.contains.inOrder.only.value(1) - subList.contains.inOrder.only.value(null) + subList.contains.inOrder.only.values(2, 1) subList.contains.inOrder.only.entry {} - subList.contains.inOrder.only.entry(null) - + subList.contains.inOrder.only.entries({}, {}) + subList.contains.inOrder.only.elementsOf(listOf(1, 2)) + nullableList.contains.inOrder.only.value(1) + nullableList.contains.inOrder.only.values(2, 1) + nullableList.contains.inOrder.only.entry {} + nullableList.contains.inOrder.only.entries({}, {}) + nullableList.contains.inOrder.only.elementsOf(listOf(1, 2)) + nullableList.contains.inOrder.only.value(null) + nullableList.contains.inOrder.only.values(null, 1) + nullableList.contains.inOrder.only.values(2, null) + nullableList.contains.inOrder.only.values(null, null) + nullableList.contains.inOrder.only.entry(null) + nullableList.contains.inOrder.only.entries(null, {}) + nullableList.contains.inOrder.only.entries({}, null) + nullableList.contains.inOrder.only.entries(null, null) + star.contains.inOrder.only.value(1) + star.contains.inOrder.only.values(2, 1) + star.contains.inOrder.only.entry {} + star.contains.inOrder.only.entries({}, {}) + star.contains.inOrder.only.elementsOf(listOf(1, 2)) + star.contains.inOrder.only.value(null) + star.contains.inOrder.only.values(null, 1) + star.contains.inOrder.only.values(2, null) + star.contains.inOrder.only.values(null, null) + star.contains.inOrder.only.entry(null) + star.contains.inOrder.only.entries(null, {}) + star.contains.inOrder.only.entries({}, null) + star.contains.inOrder.only.entries(null, null) list.contains.inOrder.only.grouped.within.inAnyOrder( Value(1), - Value(null), Values(1f), - Values(null), - Values(1f, 1), - Values(1, null), - Values(null, null) + Values(1f, 1) ) subList.contains.inOrder.only.grouped.within.inAnyOrder( Value(1), - Value(null), Values(1f), + Values(1f, 1) + ) + nullableList.contains.inOrder.only.grouped.within.inAnyOrder( + Value(null), Values(null), - Values(1f, 1), + Values(null, 2), + Values(1, null), + Values(null, null) + ) + star.contains.inOrder.only.grouped.within.inAnyOrder( + Value(null), + Values(null), + Values(null, 2), Values(1, null), Values(null, null) ) list.contains.inOrder.only.grouped.within.inAnyOrder( Entry {}, - Entry(null), Entries({}), + Entries({}, {}) + ) + subList.contains.inOrder.only.grouped.within.inAnyOrder( + Entry {}, + Entries({}), + Entries({}, {}) + ) + nullableList.contains.inOrder.only.grouped.within.inAnyOrder( + Entry(null), Entries(null), - Entries({}, {}), + Entries(null, {}), Entries({}, null), Entries(null, null) ) - subList.contains.inOrder.only.grouped.within.inAnyOrder( - Entry {}, + star.contains.inOrder.only.grouped.within.inAnyOrder( Entry(null), - Entries({}), Entries(null), - Entries({}, {}), + Entries(null, {}), Entries({}, null), Entries(null, null) ) diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableFeatureAssertionsSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableFeatureAssertionsSpec.kt index d7d75beae..551704c45 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableFeatureAssertionsSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableFeatureAssertionsSpec.kt @@ -6,14 +6,14 @@ import ch.tutteli.atrium.specs.fun1 import ch.tutteli.atrium.specs.notImplemented class IterableFeatureAssertionsSpec : ch.tutteli.atrium.specs.integration.IterableFeatureAssertionsSpec( - feature0, Int>(Expect>::min, "min"), + feature0, Int>(Expect>::min), fun1, Expect.() -> Unit>(Expect>::min), - feature0, Int>(Expect>::max, "max"), + feature0, Int>(Expect>::max), fun1, Expect.() -> Unit>(Expect>::max) ) { @Suppress("unused", "UNUSED_VALUE") private fun ambiguityTest() { - var a1: Expect> = notImplemented() + var a1: Expect> = notImplemented() //nullable not supported by min/max or rather T : Comparable does not exist for T? (one cannot implement an interface for the nullable type) //same for Iterable<*> diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableNoneAssertionsSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableNoneAssertionsSpec.kt index 63d7be6df..ddba85eed 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableNoneAssertionsSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/IterableNoneAssertionsSpec.kt @@ -3,6 +3,7 @@ package ch.tutteli.atrium.api.fluent.en_GB import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.specs.fun1 import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.withNullableSuffix import org.spekframework.spek2.Spek class IterableNoneAssertionsSpec : Spek({ @@ -13,14 +14,14 @@ class IterableNoneAssertionsSpec : Spek({ }) { object PredicateSpec : ch.tutteli.atrium.specs.integration.IterableNoneAssertionsSpec( fun1(Expect>::none), - fun1(Expect>::none), + fun1(Expect>::none).withNullableSuffix(), "◆ ", "✔ ", "✘ ", "⚬ ", "» ", "▶ ", "◾ ", "[Atrium][Predicate] " ) object BuilderSpec : ch.tutteli.atrium.specs.integration.IterableNoneAssertionsSpec( getContainsNotPair(), - getContainsNotNullablePair(), + getContainsNotNullablePair().withNullableSuffix(), "◆ ", "✔ ", "✘ ", "⚬ ", "» ", "▶ ", "◾ ", "[Atrium][Builder] " ) @@ -40,10 +41,10 @@ class IterableNoneAssertionsSpec : Spek({ @Suppress("unused", "UNUSED_VALUE") private fun ambiguityTest() { - var a1: Expect> = notImplemented() - var a1b: Expect> = notImplemented() + var a1: Expect> = notImplemented() + var a1b: Expect> = notImplemented() - var star: Expect> = notImplemented() + var star: Expect> = notImplemented() a1 = a1.none {} a1 = a1.containsNot.entry {} diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/ListFeatureAssertionsSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/ListFeatureAssertionsSpec.kt index 81c46f13a..d8ca71bbc 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/ListFeatureAssertionsSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/ListFeatureAssertionsSpec.kt @@ -1,20 +1,18 @@ package ch.tutteli.atrium.api.fluent.en_GB import ch.tutteli.atrium.creating.Expect -import ch.tutteli.atrium.specs.feature1 -import ch.tutteli.atrium.specs.fun2 -import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.* object ListFeatureAssertionsSpec : ch.tutteli.atrium.specs.integration.ListFeatureAssertionsSpec( feature1, Int, Int>(Expect>::get), fun2, Int, Expect.() -> Unit>(Expect>::get), - feature1, Int, Int?>(Expect>::get), - fun2, Int, Expect.() -> Unit>(Expect>::get) + feature1, Int, Int?>(Expect>::get).withNullableSuffix(), + fun2, Int, Expect.() -> Unit>(Expect>::get).withNullableSuffix() ) { @Suppress("unused", "UNUSED_VALUE") private fun ambiguityTest() { - var a1: Expect> = notImplemented() - var a1b: Expect> = notImplemented() + var a1: Expect> = notImplemented() + var a1b: Expect> = notImplemented() var star: Expect> = notImplemented() diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/MapAssertionsSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/MapAssertionsSpec.kt index 867eda698..7077f4f70 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/MapAssertionsSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/MapAssertionsSpec.kt @@ -2,31 +2,26 @@ package ch.tutteli.atrium.api.fluent.en_GB import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.domain.builders.utils.mapArguments -import ch.tutteli.atrium.specs.fun0 -import ch.tutteli.atrium.specs.fun1 -import ch.tutteli.atrium.specs.fun2 -import ch.tutteli.atrium.specs.notImplemented -import kotlin.reflect.KFunction3 +import ch.tutteli.atrium.specs.* +import ch.tutteli.atrium.specs.integration.mfun2 +import kotlin.jvm.JvmName class MapAssertionsSpec : ch.tutteli.atrium.specs.integration.MapAssertionsSpec( - fun2, Pair, Array>>(Expect>::contains), - fun2, Pair, Array>>(Expect>::contains), - "${containsKeyWithValueAssertionsFun.name} ${KeyValue::class.simpleName}" to Companion::containsKeyValue, - "${containsKeyWithNullableValueAssertionsFun.name} ${KeyValue::class.simpleName}" to Companion::containsNullable, + mfun2(Expect>::contains), + mfun2(Expect>::contains).withNullableSuffix(), + mfun2.() -> Unit>(Companion::contains).adjustName { "$it ${KeyValue::class.simpleName}" }, + mfun2.() -> Unit)?>(Companion::contains).adjustName { "$it ${KeyValue::class.simpleName}" } + .withNullableSuffix(), fun1(Expect>::containsKey), - fun1(Expect>::containsKey), + fun1(Expect>::containsKey).withNullableSuffix(), fun1(Expect>::containsNotKey), - fun1(Expect>::containsNotKey), + fun1(Expect>::containsNotKey).withNullableSuffix(), fun0(Expect>::isEmpty), fun0(Expect>::isNotEmpty) ) { - companion object { - //@formatter:off - private val containsKeyWithValueAssertionsFun : KFunction3>, KeyValue, Array>, Expect>> = Expect>::contains - private val containsKeyWithNullableValueAssertionsFun : KFunction3>, KeyValue, Array>, Expect>> = Expect>::contains - //@formatter:on - fun containsKeyValue( + companion object { + private fun contains( expect: Expect>, keyValue: Pair.() -> Unit>, otherKeyValues: Array.() -> Unit>> @@ -34,13 +29,15 @@ class MapAssertionsSpec : ch.tutteli.atrium.specs.integration.MapAssertionsSpec( expect.contains(first, *others) } - fun containsNullable( + @JvmName("containsNullable") + private fun contains( expect: Expect>, keyValue: Pair.() -> Unit)?>, otherKeyValues: Array.() -> Unit)?>> ) = mapArguments(keyValue, otherKeyValues).to { KeyValue(it.first, it.second) }.let { (first, others) -> expect.contains(first, *others) } + } @Suppress("unused", "UNUSED_VALUE") diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/MapEntryAssertionsSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/MapEntryAssertionsSpec.kt index 70b8f6ea6..fed5f4967 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/MapEntryAssertionsSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/MapEntryAssertionsSpec.kt @@ -3,10 +3,11 @@ package ch.tutteli.atrium.api.fluent.en_GB import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.specs.fun2 import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.withNullableSuffix object MapEntryAssertionsSpec : ch.tutteli.atrium.specs.integration.MapEntryAssertionsSpec( fun2(Expect>::isKeyValue), - fun2(Expect>::isKeyValue) + fun2(Expect>::isKeyValue).withNullableSuffix() ) { @Suppress("unused", "UNUSED_VALUE") private fun ambiguityTest() { diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/MapEntryFeatureAssertionsSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/MapEntryFeatureAssertionsSpec.kt index 0b4fab830..1696afc76 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/MapEntryFeatureAssertionsSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/MapEntryFeatureAssertionsSpec.kt @@ -1,19 +1,17 @@ package ch.tutteli.atrium.api.fluent.en_GB import ch.tutteli.atrium.creating.Expect -import ch.tutteli.atrium.specs.fun1 -import ch.tutteli.atrium.specs.notImplemented -import ch.tutteli.atrium.specs.property +import ch.tutteli.atrium.specs.* class MapEntryFeatureAssertionsSpec : ch.tutteli.atrium.specs.integration.MapEntryFeatureAssertionsSpec( property, String>(Expect>::key), fun1, Expect.() -> Unit>(Expect>::key), property, Int>(Expect>::value), fun1, Expect.() -> Unit>(Expect>::value), - property, String?>(Expect>::key), - fun1, Expect.() -> Unit>(Expect>::key), - property, Int?>(Expect>::value), - fun1, Expect.() -> Unit>(Expect>::value) + property, String?>(Expect>::key).withNullableSuffix(), + fun1, Expect.() -> Unit>(Expect>::key).withNullableSuffix(), + property, Int?>(Expect>::value).withNullableSuffix(), + fun1, Expect.() -> Unit>(Expect>::value).withNullableSuffix() ) { @Suppress("unused", "UNUSED_VALUE") diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/MapFeatureAssertionsSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/MapFeatureAssertionsSpec.kt index 80dddc742..86ede5a7a 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/MapFeatureAssertionsSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/MapFeatureAssertionsSpec.kt @@ -10,8 +10,8 @@ class MapFeatureAssertionsSpec : ch.tutteli.atrium.specs.integration.MapFeatureA fun1, Expect>.() -> Unit>(Expect>::values), feature1, String, Int>(Expect>::getExisting), fun2, String, Expect.() -> Unit>(Expect>::getExisting), - feature1, String?, Int?>(Expect>::getExisting), - fun2, String?, Expect.() -> Unit>(Expect>::getExisting) + feature1, String?, Int?>(Expect>::getExisting).withNullableSuffix(), + fun2, String?, Expect.() -> Unit>(Expect>::getExisting).withNullableSuffix() ) { @Suppress("unused", "UNUSED_VALUE") diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/ThrowableAssertionsSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/ThrowableAssertionsSpec.kt index 7607a7431..d26cab9af 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/ThrowableAssertionsSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/ThrowableAssertionsSpec.kt @@ -1,23 +1,39 @@ package ch.tutteli.atrium.api.fluent.en_GB import ch.tutteli.atrium.creating.Expect -import ch.tutteli.atrium.specs.fun1 -import ch.tutteli.atrium.specs.fun2 -import ch.tutteli.atrium.specs.notImplemented -import ch.tutteli.atrium.specs.property +import ch.tutteli.atrium.specs.* class ThrowableAssertionsSpec : ch.tutteli.atrium.specs.integration.ThrowableAssertionsSpec( property(Expect::message), fun1.() -> Unit>(Expect::message), - fun2(Expect::messageContains) + fun2(Expect::messageContains), + ("cause" to Companion::causeFeature).withFeatureSuffix(), + "cause" to Companion::cause ) { + companion object { + + @Suppress("RemoveExplicitTypeArguments") + private fun causeFeature(expect: Expect): Expect = + expect.cause() + + @Suppress("RemoveExplicitTypeArguments") + private fun cause( + expect: Expect, + assertionCreator: Expect.() -> Unit + ) = expect.cause(assertionCreator) + + } + @Suppress("unused", "UNUSED_VALUE") private fun ambiguityTest() { - var a1: Expect = notImplemented() + var a1: Expect = notImplemented() a1.message a1 = a1.message {} a1 = a1.messageContains("asdf") + + a1.cause() + a1.cause { } } } diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/bigDecimalAssertions.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/bigDecimalAssertions.kt index b32793d84..25a253fc3 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/bigDecimalAssertions.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/bigDecimalAssertions.kt @@ -46,7 +46,7 @@ fun Expect.toBe(expected: T): Nothing = throw PleaseUseRepl /** * Expects that the subject of the assertion (a [BigDecimal]) is `null`. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ @JvmName("toBeNull") @@ -87,7 +87,7 @@ fun Expect.notToBe(expected: T): Nothing = throw PleaseUseRe * - `expect(BigDecimal("10")).isEqualIncludingScale(BigDecimal("10.0"))` does not hold. * - `expect(BigDecimal("10")).isNumericallyEqualTo(BigDecimal("10.0"))` holds. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun Expect.isNumericallyEqualTo(expected: T) = @@ -105,7 +105,7 @@ fun Expect.isNumericallyEqualTo(expected: T) = * - `expect(BigDecimal("10")).isNotEqualIncludingScale(BigDecimal("10.0"))` holds. * - `expect(BigDecimal("10")).isNotNumericallyEqualTo(BigDecimal("10.0"))` does not hold. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun Expect.isNotNumericallyEqualTo(expected: T) = @@ -121,7 +121,7 @@ fun Expect.isNotNumericallyEqualTo(expected: T) = * - `expect(BigDecimal("10")).isEqualIncludingScale(BigDecimal("10.0"))` does not hold. * - `expect(BigDecimal("10")).isNumericallyEqualTo(BigDecimal("10.0"))` holds. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun Expect.isEqualIncludingScale(expected: T) = @@ -136,7 +136,7 @@ fun Expect.isEqualIncludingScale(expected: T) = * - `expect(BigDecimal("10")).isNotEqualIncludingScale(BigDecimal("10.0"))` holds. * - `expect(BigDecimal("10")).isNotNumericallyEqualTo(BigDecimal("10.0"))` does not hold. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun Expect.isNotEqualIncludingScale(expected: T) = diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/floatingPointJvmAssertions.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/floatingPointJvmAssertions.kt index 971b5d5b5..eff41ce25 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/floatingPointJvmAssertions.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/floatingPointJvmAssertions.kt @@ -18,7 +18,7 @@ import java.math.BigDecimal * * | `subject of the assertion` - [expected] | ≤ [tolerance] * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun Expect.toBeWithErrorTolerance(expected: BigDecimal, tolerance: BigDecimal) = diff --git a/apis/fluent-en_GB/atrium-api-fluent-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/Fun0AssertionsJvmSpec.kt b/apis/fluent-en_GB/atrium-api-fluent-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/Fun0AssertionsJvmSpec.kt index 9d8ad3fd6..b3af86b30 100644 --- a/apis/fluent-en_GB/atrium-api-fluent-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/Fun0AssertionsJvmSpec.kt +++ b/apis/fluent-en_GB/atrium-api-fluent-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/Fun0AssertionsJvmSpec.kt @@ -3,9 +3,10 @@ package ch.tutteli.atrium.api.fluent.en_GB import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.specs.feature0 import ch.tutteli.atrium.specs.feature1 +import ch.tutteli.atrium.specs.withFeatureSuffix class Fun0AssertionsJvmSpec : ch.tutteli.atrium.specs.integration.Fun0AssertionsJvmSpec( - "toThrow" to Companion::toThrowFeature, + ("toThrow" to Companion::toThrowFeature).withFeatureSuffix(), "toThrow" to Companion::toThrow, feature0<() -> Int, Int>(Expect<() -> Int>::notToThrow), feature1<() -> Int, Expect.() -> Unit, Int>(Expect<() -> Int>::notToThrow), diff --git a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/chronoLocalDateAssertions.kt b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/chronoLocalDateAssertions.kt index 4c3d92a46..c289a9eee 100644 --- a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/chronoLocalDateAssertions.kt +++ b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/chronoLocalDateAssertions.kt @@ -11,7 +11,7 @@ import java.time.chrono.ChronoLocalDate * Expects that the subject of the assertion (a [ChronoLocalDate]) * is before the [expected] [ChronoLocalDate]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -23,7 +23,7 @@ fun Expect.isBefore(expected: ChronoLocalDate): Expect< * Expects that the subject of the assertion (a [ChronoLocalDate]) * is before or equal the [expected] [ChronoLocalDate]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -36,7 +36,7 @@ fun Expect.isBeforeOrEqual(expected: ChronoLocalDate): * Expects that the subject of the assertion (a [ChronoLocalDate]) * is after the [expected] [ChronoLocalDate]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -48,7 +48,7 @@ fun Expect.isAfter(expected: ChronoLocalDate): Expect Expect.isAfterOrEqual(expected: ChronoLocalDate): E * Expects that the subject of the assertion (a [ChronoLocalDate]) * is equal to the [expected] [ChronoLocalDate]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 diff --git a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/chronoLocalDateTimeAssertions.kt b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/chronoLocalDateTimeAssertions.kt index 0f9be7ca0..b966b8ff9 100644 --- a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/chronoLocalDateTimeAssertions.kt +++ b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/chronoLocalDateTimeAssertions.kt @@ -12,7 +12,7 @@ import java.time.chrono.ChronoLocalDateTime * Expects that the subject of the assertion (a [ChronoLocalDateTime]) * is before the [expected] [ChronoLocalDateTime]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -24,46 +24,50 @@ fun > Expect.isBefore(expected: * Expects that the subject of the assertion (a [ChronoLocalDateTime]) * is before or equal the [expected] [ChronoLocalDateTime]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 */ -fun > Expect.isBeforeOrEqual(expected: ChronoLocalDateTime<*>): Expect = - addAssertion(ExpectImpl.chronoLocalDateTime.isBeforeOrEquals(this, expected)) +fun > Expect.isBeforeOrEqual( + expected: ChronoLocalDateTime<*> +): Expect = addAssertion(ExpectImpl.chronoLocalDateTime.isBeforeOrEquals(this, expected)) /** * Expects that the subject of the assertion (a [ChronoLocalDateTime]) * is after the [expected] [ChronoLocalDateTime]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 */ -fun > Expect.isAfter(expected: ChronoLocalDateTime<*>): Expect = - addAssertion(ExpectImpl.chronoLocalDateTime.isAfter(this, expected)) +fun > Expect.isAfter( + expected: ChronoLocalDateTime<*> +): Expect = addAssertion(ExpectImpl.chronoLocalDateTime.isAfter(this, expected)) /** * Expects that the subject of the assertion (a [ChronoLocalDateTime]) * is after or equal the [expected] [ChronoLocalDateTime]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 */ -fun > Expect.isAfterOrEqual(expected: ChronoLocalDateTime<*>): Expect = - addAssertion(ExpectImpl.chronoLocalDateTime.isAfterOrEquals(this, expected)) +fun > Expect.isAfterOrEqual( + expected: ChronoLocalDateTime<*> +): Expect = addAssertion(ExpectImpl.chronoLocalDateTime.isAfterOrEquals(this, expected)) /** * Expects that the subject of the assertion (a [ChronoLocalDateTime]) * is equal to the [expected] [ChronoLocalDateTime]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 */ -fun > Expect.isEqual(expected: ChronoLocalDateTime<*>): Expect = - addAssertion(ExpectImpl.chronoLocalDateTime.isEqual(this, expected)) +fun > Expect.isEqual( + expected: ChronoLocalDateTime<*> +): Expect = addAssertion(ExpectImpl.chronoLocalDateTime.isEqual(this, expected)) diff --git a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/chronoZonedDateTimeAssertions.kt b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/chronoZonedDateTimeAssertions.kt index bf0ef514f..d234a5b61 100644 --- a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/chronoZonedDateTimeAssertions.kt +++ b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/chronoZonedDateTimeAssertions.kt @@ -12,58 +12,63 @@ import java.time.chrono.ChronoZonedDateTime * Expects that the subject of the assertion (a [ChronoZonedDateTime]) * is before the [expected] [ChronoZonedDateTime]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 */ -fun > Expect.isBefore(expected: ChronoZonedDateTime<*>): Expect = - addAssertion(ExpectImpl.chronoZonedDateTime.isBefore(this, expected)) +fun > Expect.isBefore( + expected: ChronoZonedDateTime<*> +): Expect = addAssertion(ExpectImpl.chronoZonedDateTime.isBefore(this, expected)) /** * Expects that the subject of the assertion (a [ChronoZonedDateTime]) * is before or equals the [expected] [ChronoZonedDateTime]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 */ -fun > Expect.isBeforeOrEqual(expected: ChronoZonedDateTime<*>): Expect = - addAssertion(ExpectImpl.chronoZonedDateTime.isBeforeOrEqual(this, expected)) +fun > Expect.isBeforeOrEqual( + expected: ChronoZonedDateTime<*> +): Expect = addAssertion(ExpectImpl.chronoZonedDateTime.isBeforeOrEqual(this, expected)) /** * Expects that the subject of the assertion (a [ChronoZonedDateTime]) * is after the [expected] [ChronoZonedDateTime]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 */ -fun > Expect.isAfter(expected: ChronoZonedDateTime<*>): Expect = - addAssertion(ExpectImpl.chronoZonedDateTime.isAfter(this, expected)) +fun > Expect.isAfter( + expected: ChronoZonedDateTime<*> +): Expect = addAssertion(ExpectImpl.chronoZonedDateTime.isAfter(this, expected)) /** * Expects that the subject of the assertion (a [ChronoZonedDateTime]) * is after or equal the [expected] [ChronoZonedDateTime]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 */ -fun > Expect.isAfterOrEqual(expected: ChronoZonedDateTime<*>): Expect = - addAssertion(ExpectImpl.chronoZonedDateTime.isAfterOrEqual(this, expected)) +fun > Expect.isAfterOrEqual( + expected: ChronoZonedDateTime<*> +): Expect = addAssertion(ExpectImpl.chronoZonedDateTime.isAfterOrEqual(this, expected)) /** * Expects that the subject of the assertion (a [ChronoZonedDateTime]) * is equal to the [expected] [ChronoZonedDateTime]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 */ -fun > Expect.isEqual(expected: ChronoZonedDateTime<*>): Expect = - addAssertion(ExpectImpl.chronoZonedDateTime.isEqual(this, expected)) +fun > Expect.isEqual( + expected: ChronoZonedDateTime<*> +): Expect = addAssertion(ExpectImpl.chronoZonedDateTime.isEqual(this, expected)) diff --git a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/fileAssertions.kt b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/fileAssertions.kt index fa1d7068f..cc47c6073 100644 --- a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/fileAssertions.kt +++ b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/fileAssertions.kt @@ -27,7 +27,7 @@ fun Expect.asPath(): Expect = * The transformation as such is not reflected in reporting. * Use `feature(File::toPath, assertionCreator)` if you want to show the transformation in reporting. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * * @since 0.9.0 */ diff --git a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/localDateAssertions.kt b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/localDateAssertions.kt index 759e51e04..50286d416 100644 --- a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/localDateAssertions.kt +++ b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/localDateAssertions.kt @@ -15,7 +15,7 @@ import java.time.LocalDate * Creates an [Expect] for the property [LocalDate.year][LocalDate.getYear] of the subject of the assertion, * so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. * * @since 0.9.0 */ @@ -24,9 +24,10 @@ val Expect.year: Expect /** * Expects that the property [LocalDate.year][LocalDate.getYear]of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -38,7 +39,7 @@ fun Expect.year(assertionCreator: Expect.() -> Unit): Ex * Creates an [Expect] for the property [LocalDate.monthValue][LocalDate.getMonthValue] of the subject of the assertion, * so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. * * @since 0.9.0 */ @@ -47,9 +48,10 @@ val Expect.month: Expect /** * Expects that the property [LocalDate.monthValue][LocalDate.getMonthValue] of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -61,7 +63,7 @@ fun Expect.month(assertionCreator: Expect.() -> Unit): E * Creates an [Expect] for the property [LocalDate.getDayOfWeek] of the subject of the assertion, * so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. * * @since 0.9.0 */ @@ -70,9 +72,10 @@ val Expect.dayOfWeek: Expect /** * Expects that the property [LocalDate.getDayOfWeek] of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -85,7 +88,7 @@ fun Expect.dayOfWeek(assertionCreator: Expect.() - * Creates an [Expect] for the property [LocalDate.dayOfMonth][LocalDate.getDayOfMonth] of the subject of the assertion, * so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. * * @since 0.9.0 */ @@ -94,9 +97,10 @@ val Expect.day: Expect /** * Expects that the property [LocalDate.dayOfMonth][LocalDate.getDayOfMonth] of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 diff --git a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/localDateTimeAssertions.kt b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/localDateTimeAssertions.kt index 3822dedee..aa3bc0d3e 100644 --- a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/localDateTimeAssertions.kt +++ b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/localDateTimeAssertions.kt @@ -15,7 +15,7 @@ import java.time.LocalDateTime * Creates an [Expect] for the property [LocalDateTime.year][[LocalDateTime.getYear] of the subject of the assertion, * so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. * * @since 0.9.0 */ @@ -24,9 +24,10 @@ val Expect.year: Expect /** * Expects that the property [LocalDateTime.year][LocalDateTime.getYear] of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -38,7 +39,7 @@ fun Expect.year(assertionCreator: Expect.() -> Unit) * Creates an [Expect] for the property [LocalDateTime.monthValue][LocalDateTime.getMonthValue] * of the subject of the assertion, so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. * * @since 0.9.0 */ @@ -47,9 +48,10 @@ val Expect.month: Expect /** * Expects that the property [LocalDateTime.monthValue][LocalDateTime.getMonthValue]of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -61,7 +63,7 @@ fun Expect.month(assertionCreator: Expect.() -> Unit * Creates an [Expect] for the property [LocalDateTime.dayOfWeek][LocalDateTime.getDayOfWeek] * of the subject of the assertion, so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. * * @since 0.9.0 */ @@ -70,9 +72,10 @@ val Expect.dayOfWeek: Expect /** * Expects that the property [LocalDateTime.dayOfWeek][LocalDateTime.getDayOfWeek]of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -84,7 +87,7 @@ fun Expect.dayOfWeek(assertionCreator: Expect. * Creates an [Expect] for the property [LocalDateTime.dayOfMonth][LocalDateTime.getDayOfMonth] * of the subject of the assertion, so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. * * @since 0.9.0 */ @@ -93,9 +96,10 @@ val Expect.day: Expect /** * Expects that the property [LocalDateTime.dayOfMonth][LocalDateTime.getDayOfMonth] of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 diff --git a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/optionalAssertions.kt b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/optionalAssertions.kt index c9bb54ad5..8b711c4d0 100644 --- a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/optionalAssertions.kt +++ b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/optionalAssertions.kt @@ -13,7 +13,7 @@ import java.util.* * Shortcut for more or less something like `feature(Optional::isEmpty) { toBe(true) }` * depends on the underlying implementation though. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -27,7 +27,7 @@ fun > Expect.isEmpty(): Expect = addAssertion(ExpectImpl.o * Shortcut for more or less something like `feature(Optional::get)` but with error handling; yet it * depends on the underlying implementation though. * - * @return The newly created [Expect] if the given assertion is success + * @return The newly created [Expect] for the inner type [E]. * @throws AssertionError Might throw an [AssertionError] if the given assertion is not a success. * * @since 0.9.0 @@ -38,7 +38,7 @@ fun > Expect.isPresent(): Expect = ExpectImpl.optional. * Expects that the subject of the assertion (an [Optional]) is present and * that it holds all assertions the given [assertionCreator] creates. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the given assertions are not success. * * @since 0.9.0 diff --git a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/pathAssertions.kt b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/pathAssertions.kt index 4a9ad4ba4..d89c7efe1 100644 --- a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/pathAssertions.kt +++ b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/pathAssertions.kt @@ -10,7 +10,7 @@ import java.nio.file.Path /** * Expects that the subject of the assertion (a [Path]) starts with the [expected] [Path]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -21,7 +21,7 @@ fun Expect.startsWith(expected: Path): Expect = /** * Expects that the subject of the assertion (a [Path]) does not start with the [expected] [Path]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -32,7 +32,7 @@ fun Expect.startsNotWith(expected: Path): Expect = /** * Expects that the subject of the assertion (a [Path]) ends with the expected [Path]. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -44,7 +44,7 @@ fun Expect.endsWith(expected: Path): Expect = * Expects that the subject of the assertion (a [Path]) does not end with the expected [Path]; * * @param expected The [Path] provided to the assertion - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -59,7 +59,7 @@ fun Expect.endsNotWith(expected: Path): Expect = * This matcher _resolves_ symbolic links. Therefore, if a symbolic link exists at the location the subject points to, * then the search will continue at that location. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -73,7 +73,7 @@ fun Expect.exists(): Expect = addAssertion(ExpectImpl.path.exis * This matcher _resolves_ symbolic links. Therefore, if a symbolic link exists at the location the subject points to, * then the search will continue at that location. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -85,7 +85,7 @@ fun Expect.existsNot(): Expect = addAssertion(ExpectImpl.path.e * (provided via [niok](https://github.com/robstoll/niok)) of the subject of the assertion, * so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. * * @since 0.9.0 */ @@ -95,9 +95,10 @@ val Expect.fileName: Expect /** * Expects that the property [Path.fileNameAsString][ch.tutteli.niok.fileNameAsString] * (provided via [niok](https://github.com/robstoll/niok)) of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -110,7 +111,7 @@ fun Expect.fileName(assertionCreator: Expect.() -> Unit): * (provided via [niok](https://github.com/robstoll/niok)) of the subject of the assertion, * so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -122,9 +123,9 @@ val Expect.fileNameWithoutExtension: Expect * Expects that the property [Path.fileNameWithoutExtension][ch.tutteli.niok.fileNameWithoutExtension] * (provided via [niok](https://github.com/robstoll/niok)) * of the subject of the assertion holds all assertions the given [assertionCreator] creates for it - * and returns this assertion container. + * and returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -136,7 +137,7 @@ fun Expect.fileNameWithoutExtension(assertionCreator: Expect Expect.parent: Expect get() = ExpectImpl.path.parent(this).getExpectOfFeature() /** - * Expects that this [Path] has a [parent][Path.getParent] and that the parent holds all assertions the - * given [assertionCreator] creates for it and returns this assertion container. + * Expects that this [Path] has a [parent][Path.getParent], that the parent holds all assertions the + * given [assertionCreator] creates for it and returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -156,6 +157,29 @@ val Expect.parent: Expect fun Expect.parent(assertionCreator: Expect.() -> Unit): Expect = ExpectImpl.path.parent(this).addToInitial(assertionCreator) +/** + * Expects that [other] resolves against this [Path] and creates an [Expect] for the resolved [Path] + * so that further fluent calls are assertions about it. + * + * @return The newly created [Expect] for the extracted feature. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.10.0 + */ +fun Expect.resolve(other: String): Expect = + ExpectImpl.path.resolve(this, other).getExpectOfFeature() + +/** + * Expects that [other] resolves against this [Path], that the resolved [Path] holds all assertions the + * given [assertionCreator] creates for it and returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.10.0 + */ +fun Expect.resolve(other: String, assertionCreator: Expect.() -> Unit): Expect = + ExpectImpl.path.resolve(this, other).addToInitial(assertionCreator) /** * Expects that the subject of the assertion (a [Path]) is readable; @@ -170,7 +194,7 @@ fun Expect.parent(assertionCreator: Expect.() -> Unit): Expe * Its result, in particular its extended explanations, may be wrong if such concurrent file system operations * take place. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -186,7 +210,7 @@ fun Expect.isReadable(): Expect = addAssertion(ExpectImpl.path. * Therefore, if a symbolic link exists at the location the subject points to, search will continue * at the location the link points at. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -205,7 +229,7 @@ fun Expect.isWritable(): Expect = addAssertion(ExpectImpl.path. * Its result, in particular its extended explanations, may be wrong if such concurrent file system operations * take place. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -224,7 +248,7 @@ fun Expect.isRegularFile(): Expect = addAssertion(ExpectImpl.pa * Its result, in particular its extended explanations, may be wrong if such concurrent file system operations * take place. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -236,7 +260,7 @@ fun Expect.isDirectory(): Expect = addAssertion(ExpectImpl.path * (provided via [niok](https://github.com/robstoll/niok)) of the subject of the assertion, * so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. * * @since 0.9.0 */ @@ -246,9 +270,10 @@ val Expect.extension: Expect /** * Expects that the property [Path.extension][ch.tutteli.niok.extension] * (provided via [niok](https://github.com/robstoll/niok)) of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 diff --git a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/zonedDateTimeAssertions.kt b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/zonedDateTimeAssertions.kt index 50ce004a6..20740d426 100644 --- a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/zonedDateTimeAssertions.kt +++ b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/zonedDateTimeAssertions.kt @@ -15,7 +15,7 @@ import java.time.ZonedDateTime * Creates an [Expect] for the property [ZonedDateTime.year][ZonedDateTime.getYear] of the subject of the assertion, * so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. * * @since 0.9.0 */ @@ -24,9 +24,10 @@ val Expect.year: Expect /** * Expects that the property [ZonedDateTime.year][ZonedDateTime.getYear] of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -38,7 +39,7 @@ fun Expect.year(assertionCreator: Expect.() -> Unit) * Creates an [Expect] for the property [ZonedDateTime.monthValue][ZonedDateTime.getMonthValue] * of the subject of the assertion, so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. * * @since 0.9.0 */ @@ -47,9 +48,10 @@ val Expect.month: Expect /** * Expects that the property [ZonedDateTime.monthValue][ZonedDateTime.getMonthValue] of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -61,7 +63,7 @@ fun Expect.month(assertionCreator: Expect.() -> Unit * Creates an [Expect] for the property [ZonedDatetime.dayOfWeek][ZonedDateTime.getDayOfWeek] * of the subject of the assertion, so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. * * @since 0.9.0 */ @@ -70,9 +72,10 @@ val Expect.dayOfWeek: Expect /** * Expects that the property [ZonedDatetime.dayOfWeek][ZonedDateTime.getDayOfWeek] of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -84,7 +87,7 @@ fun Expect.dayOfWeek(assertionCreator: Expect. * Creates an [Expect] for the property [ZonedDateTime.dayOfMonth][ZonedDateTime.getDayOfMonth] * of the subject of the assertion, so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. * * @since 0.9.0 */ @@ -93,9 +96,10 @@ val Expect.day: Expect /** * Expects that the property [ZonedDateTime.dayOfMonth][ZonedDateTime.getDayOfMonth] of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 diff --git a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/module/module-info.java b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/module/module-info.java index 906db56a2..709bf449c 100644 --- a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/module/module-info.java +++ b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/module/module-info.java @@ -1,4 +1,5 @@ module ch.tutteli.atrium.api.fluent.en_GB.jdk8 { + requires ch.tutteli.atrium.api.fluent.en_GB; requires ch.tutteli.atrium.domain.builders; requires ch.tutteli.kbox; requires ch.tutteli.niok; diff --git a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/OptionalAssertionsSpec.kt b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/OptionalAssertionsSpec.kt index 9fd4fa990..88777edb8 100644 --- a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/OptionalAssertionsSpec.kt +++ b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/OptionalAssertionsSpec.kt @@ -20,5 +20,13 @@ class OptionalAssertionsSpec : OptionalAssertionsSpec( o1 = o1.isEmpty() o1b = o1b.isEmpty() star = star.isEmpty() + o1.isPresent() + o1b.isPresent() + // following is not supported on purpose as we don't know what type the element is in this case + // star.isPresent() + o1.isPresent {} + o1b.isPresent {} + // following is not supported on purpose as we don't know what type the element is in this case + // star.isPresent {} } } diff --git a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/PathFeatureAssertionsSpec.kt b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/PathFeatureAssertionsSpec.kt index 39b569a06..25d7a07a5 100644 --- a/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/PathFeatureAssertionsSpec.kt +++ b/apis/fluent-en_GB/extensions/jdk8/atrium-api-fluent-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/jdk8/PathFeatureAssertionsSpec.kt @@ -1,14 +1,14 @@ package ch.tutteli.atrium.api.fluent.en_GB.jdk8 import ch.tutteli.atrium.creating.Expect -import ch.tutteli.atrium.specs.fun1 -import ch.tutteli.atrium.specs.notImplemented -import ch.tutteli.atrium.specs.property +import ch.tutteli.atrium.specs.* import java.nio.file.Path class PathFeatureAssertionsSpec : ch.tutteli.atrium.specs.integration.PathFeatureAssertionsSpec( property(Expect::parent), fun1.() -> Unit>(Expect::parent), + feature1(Expect::resolve), + fun2.() -> Unit>(Expect::resolve), property(Expect::fileName), fun1.() -> Unit>(Expect::fileName), property(Expect::fileNameWithoutExtension), @@ -31,5 +31,8 @@ class PathFeatureAssertionsSpec : ch.tutteli.atrium.specs.integration.PathFeatur a1.extension a1 = a1.extension { } + + a1.resolve("test") + a1.resolve("test", {}) } } diff --git a/apis/fluent-en_GB/extensions/kotlin_1_3/atrium-api-fluent-en_GB-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/kotlin_1_3/resultAssertions.kt b/apis/fluent-en_GB/extensions/kotlin_1_3/atrium-api-fluent-en_GB-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/kotlin_1_3/resultAssertions.kt index 85bf2569e..9f591f0aa 100644 --- a/apis/fluent-en_GB/extensions/kotlin_1_3/atrium-api-fluent-en_GB-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/kotlin_1_3/resultAssertions.kt +++ b/apis/fluent-en_GB/extensions/kotlin_1_3/atrium-api-fluent-en_GB-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/kotlin_1_3/resultAssertions.kt @@ -19,7 +19,7 @@ fun > Expect.isSuccess(): Expect = ExpectImpl.result.isSu * Expects that the subject of the assertion (a [Result]) is a Success and * that it holds all assertions the given [assertionCreator] creates. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the given assertions are not success. * * @since 0.9.0 @@ -31,7 +31,7 @@ fun > Expect.isSuccess(assertionCreator: Expect.() -> Uni * Expects that the subject of the assertion (a [Result]) is a Failure and * that it encapsulates an exception of type [TExpected]. * - * @return An assertion container with the new type [TExpected] + * @return An [Expect] with the new type [TExpected] * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 @@ -44,7 +44,7 @@ inline fun Expect>.isFailure(): Ex * it encapsulates an exception of type [TExpected] and that the exception * holds all assertions the given [assertionCreator] creates. * - * @return An assertion container with the new type [TExpected] + * @return An [Expect] with the new type [TExpected] * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. * * @since 0.9.0 diff --git a/apis/fluent-en_GB/extensions/kotlin_1_3/atrium-api-fluent-en_GB-kotlin_1_3-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/kotlin_1_3/ResultFeatureAssertionsSpec.kt b/apis/fluent-en_GB/extensions/kotlin_1_3/atrium-api-fluent-en_GB-kotlin_1_3-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/kotlin_1_3/ResultFeatureAssertionsSpec.kt index 6be2a19ba..bbc9f52f1 100644 --- a/apis/fluent-en_GB/extensions/kotlin_1_3/atrium-api-fluent-en_GB-kotlin_1_3-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/kotlin_1_3/ResultFeatureAssertionsSpec.kt +++ b/apis/fluent-en_GB/extensions/kotlin_1_3/atrium-api-fluent-en_GB-kotlin_1_3-common/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/kotlin_1_3/ResultFeatureAssertionsSpec.kt @@ -1,17 +1,15 @@ package ch.tutteli.atrium.api.fluent.en_GB.kotlin_1_3 import ch.tutteli.atrium.creating.Expect -import ch.tutteli.atrium.specs.feature0 -import ch.tutteli.atrium.specs.fun1 +import ch.tutteli.atrium.specs.* import ch.tutteli.atrium.specs.integration.ResultFeatureAssertionsSpec -import ch.tutteli.atrium.specs.notImplemented class ResultFeatureAssertionsSpec : ResultFeatureAssertionsSpec( feature0, Int>(Expect>::isSuccess), fun1, Expect.() -> Unit>(Expect>::isSuccess), - feature0, Int?>(Expect>::isSuccess), - fun1, Expect.() -> Unit>(Expect>::isSuccess), - "isFailure" to Companion::isFailureFeature, + feature0, Int?>(Expect>::isSuccess).withNullableSuffix(), + fun1, Expect.() -> Unit>(Expect>::isSuccess).withNullableSuffix(), + ("isFailure" to Companion::isFailureFeature).withFeatureSuffix(), "isFailure" to Companion::isFailure ) { companion object { diff --git a/apis/fluent-en_GB/extensions/kotlin_1_3/atrium-api-fluent-en_GB-kotlin_1_3-jvm/src/module/module-info.java b/apis/fluent-en_GB/extensions/kotlin_1_3/atrium-api-fluent-en_GB-kotlin_1_3-jvm/src/module/module-info.java index 82f4eed69..8dd94c0e0 100644 --- a/apis/fluent-en_GB/extensions/kotlin_1_3/atrium-api-fluent-en_GB-kotlin_1_3-jvm/src/module/module-info.java +++ b/apis/fluent-en_GB/extensions/kotlin_1_3/atrium-api-fluent-en_GB-kotlin_1_3-jvm/src/module/module-info.java @@ -1,4 +1,5 @@ module ch.tutteli.atrium.api.fluent.en_GB.kotlin_1_3 { + requires ch.tutteli.atrium.api.fluent.en_GB; requires ch.tutteli.atrium.domain.builders.kotlin_1_3; requires ch.tutteli.kbox; requires kotlin.stdlib; diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/anyAssertions.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/anyAssertions.kt new file mode 100644 index 000000000..8f3bc3d7d --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/anyAssertions.kt @@ -0,0 +1,201 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.checking.AssertionChecker +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.reporting.Reporter + +/** + * Expects that the subject of the assertion is (equal to) [expected]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Expect.toBe(expected: T) = addAssertion(ExpectImpl.any.toBe(this, expected)) + +/** + * Expects that the subject of the assertion is not (equal to) [expected]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Expect.notToBe(expected: T) = addAssertion(ExpectImpl.any.notToBe(this, expected)) + +/** + * Expects that the subject of the assertion is the same instance as [expected]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Expect.isSameAs(expected: T) = addAssertion(ExpectImpl.any.isSame(this, expected)) + +/** + * Expects that the subject of the assertion is not the same instance as [expected]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Expect.isNotSameAs(expected: T) = addAssertion(ExpectImpl.any.isNotSame(this, expected)) + +/** + * Expects that the subject of the assertion is either `null` in case [assertionCreatorOrNull] + * is `null` or is not `null` and holds all assertions [assertionCreatorOrNull] creates. + * + * Depending on the implementation, it is not much more than a shortcut for + * ```kotlin + * if (assertionCreatorOrNull == null) toBe(null) + * else notToBeNull(assertionCreatorOrNull) + * ``` + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +inline infix fun Expect.toBeNullIfNullGivenElse( + noinline assertionCreatorOrNull: (Expect.() -> Unit)? +) = addAssertion(ExpectImpl.any.toBeNullIfNullGivenElse(this, T::class, assertionCreatorOrNull)) + + +/** + * Expects that the subject of the assertion is not null and changes the subject to the non-nullable version. + * + * It delegates to [isA] with [T] as type. + * + * @param o The filler object [o]. + * + * @return An [Expect] with the non-nullable type [T] (was `T?` before). + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +@Suppress(/* less magic */ "RemoveExplicitTypeArguments") +inline infix fun Expect.notToBeNull(@Suppress("UNUSED_PARAMETER") o: o): Expect = isA() + +/** + * Expects that the subject of the assertion is not null and + * that it holds all assertions the given [assertionCreator] creates. + * + * It delegates to [isA] with [T] as type. + * + * @return An [Expect] with the non-nullable type [T] (was `T?` before) + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +@Suppress(/* less magic */ "RemoveExplicitTypeArguments") +inline infix fun Expect.notToBeNull(noinline assertionCreator: Expect.() -> Unit): Expect = + isA(assertionCreator) + +/** + * Expects that the subject of the assertion *is a* [TSub] (the same type or a sub-type) + * and changes the subject to this type. + * + * Notice, that asserting a function type is [flawed](https://youtrack.jetbrains.com/issue/KT-27846). + * The actual types are ignored as function types erase to Function0, + * Function1 etc. on byte code level, which means the assertion holds as long as the subject is a + * function and has the same amount of arguments regardless if the types differ. For instance + * `assert({x: Int -> "hello"}).isA Unit>{}` holds, even though `(Int) -> String` is clearly not + * a `(String) -> Unit`. + * + * More generally speaking, the [flaw](https://youtrack.jetbrains.com/issue/KT-27826) applies to all generic types. + * For instance `isA>` would only check if the subject is a `List` without checking if + * the element type is actually `String`. Or in other words + * `assert(listOf(1, 2)).isA>{}` holds, even though `List` is clearly not a `List`. + * + * @return An [Expect] with the new type [TSub]. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +//TODO make infix and add `o` as parameter as soon as https://youtrack.jetbrains.com/issue/KT-21593 is fixed +inline fun Expect<*>.isA(): Expect = + ExpectImpl.any.isA(this, TSub::class).getExpectOfFeature() + +/** + * Expects that the subject of the assertion *is a* [TSub] (the same type or a sub-type) and + * that it holds all assertions the given [assertionCreator] creates. + * + * Notice, in contrast to other assertion functions which expect an [assertionCreator], this function returns not + * [Expect] of the initial type, which was some type `T `, but an [Expect] of the specified type [TSub]. + * This has the side effect that a subsequent call has only assertion functions available which are suited for [TSub]. + * Since [Expect] is invariant it especially means that an assertion function which was not written in a generic way + * will not be available. Fixing such a function is easy (in most cases), + * you need to transform it into a generic from. Following an example: + * + * ``` + * interface Person + * class Student: Person + * fun Expect.foo() = "dummy" // limited only to Person, not recommended + * fun Expect.bar() = "dummy" // available to Person and all subtypes, the way to go + * fun Expect.baz() = "dummy" // specific only for Student, ok since closed class + * + * val p: Person = Student() + * expect(p) // subject of type Person + * .isA { ... } // subject now refined to Student + * .baz() // available via Student + * .foo() // not available to Student, only to Person, results in compilation error + * .bar() // available via T : Person + * ``` + * + * Notice, that asserting a function type is [flawed](https://youtrack.jetbrains.com/issue/KT-27846). + * The actual types are ignored as function types erase to Function0, + * Function1 etc. on byte code level, which means the assertion holds as long as the subject is a + * function and has the same amount of arguments regardless if the types differ. For instance + * `assert({x: Int -> "hello"}).isA Unit>{}` holds, even though `(Int) -> String` is clearly not + * a `(String) -> Unit`. + * + * More generally speaking, the [flaw](https://youtrack.jetbrains.com/issue/KT-27826) applies to all generic types. + * For instance `isA>` would only check if the subject is a `List` without checking if + * the element type is actually `String`. Or in other words + * `assert(listOf(1, 2)).isA>{}` holds, even though `List` is clearly not a `List`. + * + * @return An [Expect] with the new type [TSub]. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +inline infix fun Expect<*>.isA(noinline assertionCreator: Expect.() -> Unit): Expect = + ExpectImpl.any.isA(this, TSub::class).addToFeature(assertionCreator) + +/** + * Can be used to separate single assertions. + * + * For instance `expect(1).isLessThan(2).and.isGreaterThan(0)` creates + * two assertions (not one assertion with two sub-assertions) - the first asserts that 1 is less than 2 and the second + * asserts that 1 is greater than 0. If the first assertion fails, then usually (depending on the configured + * [AssertionChecker]) the second assertion is not evaluated. + * + * @param o The filler object [o]. + * + * @return An [Expect] for the current subject of the assertion. + * + * @since 0.11.0 + */ +@Suppress("NOTHING_TO_INLINE") +inline infix fun Expect.and(@Suppress("UNUSED_PARAMETER") o: o): Expect = this + +/** + * Can be used to create a group of sub assertions when using the fluent API. + * + * For instance `assert(1).isLessThan(3).and { isEven(); isGreaterThan(1) }` creates + * two assertions where the second one consists of two sub-assertions. In case the first assertion holds, then the + * second one is evaluated as a whole. Meaning, even though 1 is not even, it still evaluates that 1 is greater than 1. + * Hence the reporting might (depending on the configured [Reporter]) contain both failing sub-assertions. + * + * @return An [Expect] for the current subject of the assertion. + */ +infix fun Expect.and(assertionCreator: Expect.() -> Unit): Expect = + addAssertionsCreatedBy(assertionCreator) + +/** + * Inline property referring actually to `this` and allows to write infix assertions within an assertion group block + * + * For instance, instead of: + * ``` + * expect("hello world") { + * this startsWith "hello" + * this ends with "world" + * } + * ``` + * You can write + * ``` + * expect("hello world") { + * o startsWith "hello" + * o ends with "world" + * } + * ``` + * + * @return `this` + */ +inline val Expect.it get() : Expect = this diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/arrayAssertions.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/arrayAssertions.kt new file mode 100644 index 000000000..c7754e484 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/arrayAssertions.kt @@ -0,0 +1,285 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import kotlin.jvm.JvmName + +/** + * Turns `Expect>` into `Expect>`. + * + * The transformation as such is not reflected in reporting. + * Use `feature { f(it::asList) }` if you want to show the transformation in reporting. + * + * @return The newly created [Expect] for the transformed subject. + * + * @since 0.11.0 + */ +infix fun Expect>.asList(@Suppress("UNUSED_PARAMETER") o: o): Expect> = + ExpectImpl.changeSubject(this).unreported { it.asList() } + +/** + * Expects that the subject of the assertion holds all assertions the given [assertionCreator] creates for + * the subject as [List]. + * + * The transformation as such is not reflected in reporting. + * Use `feature of({ f(it::asList) }, assertionCreator)` if you want to show the transformation in reporting. + * + * @return The newly created [Expect] for the transformed subject. + * + * @since 0.11.0 + */ +infix fun Expect>.asList(assertionCreator: Expect>.() -> Unit): Expect> = + apply { asList(o).addAssertionsCreatedBy(assertionCreator) } + +/** + * Expects that the subject of the assertion holds all assertions the given [assertionCreator] creates for + * the subject as [List]. + * + * The transformation as such is not reflected in reporting. + * Use `feature of({ f(it::asList) }, assertionCreator)` if you want to show the transformation in reporting. + * + * @return The newly created [Expect] for the transformed subject. + * + * @since 0.11.0 + */ +@JvmName("asListEOut") +infix fun Expect>.asList(assertionCreator: Expect>.() -> Unit): Expect> = + apply { asList(o).addAssertionsCreatedBy(assertionCreator) } + +/** + * Turns `Expect` into `Expect>`. + * + * The transformation as such is not reflected in reporting. + * Use `feature { f(it::asList) }` if you want to show the transformation in reporting. + * + * @return The newly created [Expect] for the transformed subject. + * + * @since 0.11.0 + */ +@JvmName("byteArrAsList") +infix fun Expect.asList(@Suppress("UNUSED_PARAMETER") o: o): Expect> = + ExpectImpl.changeSubject(this).unreported { it.asList() } + +/** + * Expects that the subject of the assertion holds all assertions the given [assertionCreator] creates for + * the subject as [List]. + * + * The transformation as such is not reflected in reporting. + * Use `feature of({ f(it::asList) }, assertionCreator)` if you want to show the transformation in reporting. + * + * @return The newly created [Expect] for the transformed subject. + * + * @since 0.11.0 + */ +@JvmName("byteArrAsList") +infix fun Expect.asList(assertionCreator: Expect>.() -> Unit): Expect = + apply { asList(o).addAssertionsCreatedBy(assertionCreator) } + + +/** + * Turns `Expect` into `Expect>`. + * + * The transformation as such is not reflected in reporting. + * Use `feature { f(it::asList) }` if you want to show the transformation in reporting. + * + * @return The newly created [Expect] for the transformed subject. + * + * @since 0.11.0 + */ +@JvmName("charArrAsList") +infix fun Expect.asList(@Suppress("UNUSED_PARAMETER") o: o): Expect> = + ExpectImpl.changeSubject(this).unreported { it.asList() } + +/** + * Expects that the subject of the assertion holds all assertions the given [assertionCreator] creates for + * the subject as [List]. + * + * The transformation as such is not reflected in reporting. + * Use `feature of({ f(it::asList) }, assertionCreator)` if you want to show the transformation in reporting. + * + * @return The newly created [Expect] for the transformed subject. + * + * @since 0.11.0 + */ +@JvmName("charArrAsList") +infix fun Expect.asList(assertionCreator: Expect>.() -> Unit): Expect = + apply { asList(o).addAssertionsCreatedBy(assertionCreator) } + + +/** + * Turns `Expect` into `Expect>`. + * + * The transformation as such is not reflected in reporting. + * Use `feature { f(it::asList) }` if you want to show the transformation in reporting. + * + * @return The newly created [Expect] for the transformed subject. + * + * @since 0.11.0 + */ +@JvmName("shortArrAsList") +infix fun Expect.asList(@Suppress("UNUSED_PARAMETER") o: o): Expect> = + ExpectImpl.changeSubject(this).unreported { it.asList() } + +/** + * Expects that the subject of the assertion holds all assertions the given [assertionCreator] creates for + * the subject as [List]. + * + * The transformation as such is not reflected in reporting. + * Use `feature of({ f(it::asList) }, assertionCreator)` if you want to show the transformation in reporting. + * + * @return The newly created [Expect] for the transformed subject. + * + * @since 0.11.0 + */ +@JvmName("shortArrAsList") +infix fun Expect.asList(assertionCreator: Expect>.() -> Unit): Expect = + apply { asList(o).addAssertionsCreatedBy(assertionCreator) } + + +/** + * Turns `Expect` into `Expect>`. + * + * The transformation as such is not reflected in reporting. + * Use `feature { f(it::asList) }` if you want to show the transformation in reporting. + * + * @return The newly created [Expect] for the transformed subject. + * + * @since 0.11.0 + */ +@JvmName("intArrAsList") +infix fun Expect.asList(@Suppress("UNUSED_PARAMETER") o: o): Expect> = ExpectImpl.changeSubject(this).unreported { it.asList() } + +/** + * Expects that the subject of the assertion holds all assertions the given [assertionCreator] creates for + * the subject as [List]. + * + * The transformation as such is not reflected in reporting. + * Use `feature of({ f(it::asList) }, assertionCreator)` if you want to show the transformation in reporting. + * + * @return The newly created [Expect] for the transformed subject. + * + * @since 0.11.0 + */ +@JvmName("intArrAsList") +infix fun Expect.asList(assertionCreator: Expect>.() -> Unit): Expect = + apply { asList(o).addAssertionsCreatedBy(assertionCreator) } + + +/** + * Turns `Expect` into `Expect>`. + * + * The transformation as such is not reflected in reporting. + * Use `feature { f(it::asList) }` if you want to show the transformation in reporting. + * + * @return The newly created [Expect] for the transformed subject. + * + * @since 0.11.0 + */ +@JvmName("longArrAsList") +infix fun Expect.asList(@Suppress("UNUSED_PARAMETER") o: o): Expect> = + ExpectImpl.changeSubject(this).unreported { it.asList() } + +/** + * Expects that the subject of the assertion holds all assertions the given [assertionCreator] creates for + * the subject as [List]. + * + * The transformation as such is not reflected in reporting. + * Use `feature of({ f(it::asList) }, assertionCreator)` if you want to show the transformation in reporting. + * + * @return The newly created [Expect] for the transformed subject. + * + * @since 0.11.0 + */ +@JvmName("longArrAsList") +infix fun Expect.asList(assertionCreator: Expect>.() -> Unit): Expect = + apply { asList(o).addAssertionsCreatedBy(assertionCreator) } + + +/** + * Turns `Expect` into `Expect>`. + * + * The transformation as such is not reflected in reporting. + * Use `feature { f(it::asList) }` if you want to show the transformation in reporting. + * + * @return The newly created [Expect] for the transformed subject. + * + * @since 0.11.0 + */ +@JvmName("floatArrAsList") +infix fun Expect.asList(@Suppress("UNUSED_PARAMETER") o: o): Expect> = + ExpectImpl.changeSubject(this).unreported { it.asList() } + +/** + * Expects that the subject of the assertion holds all assertions the given [assertionCreator] creates for + * the subject as [List]. + * + * The transformation as such is not reflected in reporting. + * Use `feature of({ f(it::asList) }, assertionCreator)` if you want to show the transformation in reporting. + * + * @return The newly created [Expect] for the transformed subject. + * + * @since 0.11.0 + */ +@JvmName("floatArrAsList") +infix fun Expect.asList(assertionCreator: Expect>.() -> Unit): Expect = + apply { asList(o).addAssertionsCreatedBy(assertionCreator) } + + +/** + * Turns `Expect` into `Expect>`. + * + * The transformation as such is not reflected in reporting. + * Use `feature { f(it::asList) }` if you want to show the transformation in reporting. + * + * @return The newly created [Expect] for the transformed subject. + * + * @since 0.11.0 + */ +@JvmName("doubleArrAsList") +infix fun Expect.asList(@Suppress("UNUSED_PARAMETER") o: o): Expect> = + ExpectImpl.changeSubject(this).unreported { it.asList() } + +/** + * Expects that the subject of the assertion holds all assertions the given [assertionCreator] creates for + * the subject as [List]. + * + * The transformation as such is not reflected in reporting. + * Use `feature of({ f(it::asList) }, assertionCreator)` if you want to show the transformation in reporting. + * + * @return The newly created [Expect] for the transformed subject. + * + * @since 0.11.0 + */ +@JvmName("doubleArrAsList") +infix fun Expect.asList(assertionCreator: Expect>.() -> Unit): Expect = + apply { asList(o).addAssertionsCreatedBy(assertionCreator) } + + +/** + * Turns `Expect` into `Expect>`. + * + * The transformation as such is not reflected in reporting. + * Use `feature { f(it::asList) }` if you want to show the transformation in reporting. + * + * @return The newly created [Expect] for the transformed subject. + * + * @since 0.11.0 + */ +@JvmName("boolArrAsList") +infix fun Expect.asList(@Suppress("UNUSED_PARAMETER") o: o): Expect> = + ExpectImpl.changeSubject(this).unreported { it.asList() } + +/** + * Expects that the subject of the assertion holds all assertions the given [assertionCreator] creates for + * the subject as [List]. + * + * The transformation as such is not reflected in reporting. + * Use `feature of({ f(it::asList) }, assertionCreator)` if you want to show the transformation in reporting. + * + * @return The newly created [Expect] for the transformed subject. + * + * @since 0.11.0 + */ +@JvmName("boolArrAsList") +infix fun Expect.asList(assertionCreator: Expect>.() -> Unit): Expect = + apply { asList(o).addAssertionsCreatedBy(assertionCreator) } diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/charSequenceAssertions.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/charSequenceAssertions.kt new file mode 100644 index 000000000..992e46804 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/charSequenceAssertions.kt @@ -0,0 +1,343 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.NotCheckerOption +import ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.impl.NotCheckerOptionImpl +import ch.tutteli.atrium.api.infix.en_GB.creating.All +import ch.tutteli.atrium.api.infix.en_GB.creating.RegexPatterns +import ch.tutteli.atrium.api.infix.en_GB.creating.Values +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains +import ch.tutteli.atrium.domain.creating.charsequence.contains.searchbehaviours.NoOpSearchBehaviour +import ch.tutteli.atrium.domain.creating.charsequence.contains.searchbehaviours.NotSearchBehaviour + + +/** + * Creates a [CharSequenceContains.Builder] based on this [Expect] which allows to define + * a sophisticated `contains` assertion. + * + * @param o The filler object [o]. + * + * @return The newly created builder. + */ +infix fun Expect.contains( + @Suppress("UNUSED_PARAMETER") o: o +): CharSequenceContains.Builder = ExpectImpl.charSequence.containsBuilder(this) + +/** + * Creates a [CharSequenceContains.Builder] based on this [Expect] which allows to define + * more sophisticated `contains not` assertion. + * + * @param o The filler object [o]. + * + * @return The newly created builder. + */ +infix fun Expect.containsNot( + @Suppress("UNUSED_PARAMETER") o: o +): NotCheckerOption = NotCheckerOptionImpl(ExpectImpl.charSequence.containsNotBuilder(this)) + + +/** + * Expects that the subject of the assertion (a [CharSequence]) contains the [expected]'s [toString] representation. + * + * It is a shortcut for `contains o atLeast 1 value expected`. + * + * Notice that a runtime check applies which assures that only [CharSequence], [Number] and [Char] are passed (this + * function expects `Any` for your convenience, so that you can mix [String] and [Int] for instance). + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * @throws IllegalArgumentException in case [expected] is not a + * [CharSequence], [Number] or [Char]. + */ +infix fun Expect.contains(expected: Any): Expect = + this contains o atLeast 1 value expected + +/** + * Expects that the subject of the assertion (a [CharSequence]) contains the [toString] representation of the + * given [values] using a non disjoint search. + * + * It is a shortcut for `contains o atLeast 1 the values(expected, *otherExpected)`. + * + * Notice that a runtime check applies which assures that only [CharSequence], [Number] and [Char] are passed (this + * function expects `Any` for your convenience, so that you can mix [String] and [Int] for instance). + * + * By non disjoint is meant that `"aa"` in `"aaaa"` is found three times and not only two times. + * Also notice, that it does not search for unique matches. Meaning, if the input of the search is `"a"` and + * [Values] is defined as `values("a", "a")`, then both match, + * even though they match the same sequence in the input of the search. + * Use an option such as [atLeast], [atMost] and [exactly] to control the number of occurrences you expect. + * + * Meaning you might want to use: + * `contains o exactly 2 value "a"` + * instead of: + * `contains values("a", "a")` + * + * @param values The values which are expected to be contained within the input of the search + * -- use the function `values(t, ...)` to create a [Values]. + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * @throws IllegalArgumentException in case one of the [values] is not a + * [CharSequence], [Number] or [Char]. + */ +infix fun Expect.contains(values: Values): Expect = + this contains o atLeast 1 the values + +/** + * Expects that the subject of the assertion (a [CharSequence]) does not contain [expected]'s [toString] representation. + * + * It is a shortcut for `contains not value expected`. + * + * Notice that a runtime check applies which assures that only [CharSequence], [Number] and [Char] are passed (this + * function expects `Any` for your convenience, so that you can mix [String] and [Int] for instance). + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Expect.containsNot(expected: Any) = + this containsNot o value expected + +/** + * Expects that the subject of the assertion (a [CharSequence]) does not contain the [toString] representation + * of the given [values]. + * + * It is a shortcut for `contains not the values(expected, *otherExpected)`. + * + * Notice that a runtime check applies which assures that only [CharSequence], [Number] and [Char] are passed (this + * function expects `Any` for your convenience, so that you can mix [String] and [Int] for instance). + * + * @param values The values which should not be found -- use the function `values(t, ...)` to create a [Values]. + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Expect.containsNot(values: Values) = + this containsNot o the values + +/** + * Expects that the subject of the assertion (a [CharSequence]) contains a sequence which matches the given + * regular expression [pattern]. + * + * It is a shortcut for `contains o atLeast 1 regex pattern`. + * + * @param pattern The pattern which is expected to have a match against the input of the search. + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Expect.containsRegex(pattern: String): Expect = + this contains o atLeast 1 regex pattern + +/** + * Expects that the subject of the assertion (a [CharSequence]) contains a sequence which matches the given + * regular expression [pattern]. + * + * It is a shortcut for `contains o atLeast 1 matchFor pattern`. + * + * @param pattern The pattern which is expected to have a match against the input of the search. + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Expect.contains(pattern: Regex): Expect = + this contains o atLeast 1 matchFor pattern + +/** + * Expects that the subject of the assertion (a [CharSequence]) contains a sequence which matches the given + * regular expression [patterns], using a non disjoint search. + * + * It is a shortcut for `contains o atLeast 1 the regexPatterns(pattern, *otherPatterns)`. + * + * By non disjoint is meant that `"aa"` in `"aaaa"` is found three times and not only two times. + * Also notice, that it does not search for unique matches. Meaning, if the input of the search is `"ab"` and + * [RegexPatterns] is defined as `regexPatterns("a(b)?", "a(b)?")` as well, then both match, + * even though they match the same sequence in the input of the search. + * Use an option such as [atLeast], [atMost] and [exactly] to control the number of occurrences you expect. + * + * Meaning you might want to use: + * `contains o exactly 2 regex "a(b)?"` + * instead of: + * `contains o atLeast 1 the regexPatterns("a(b)?", "a(b)?")` + * + * @param patterns The patterns which are expected to have a match against the input of the search -- + * use the function `regexPatterns(t, ...)` to create a [RegexPatterns]. + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Expect.containsRegex(patterns: RegexPatterns): Expect = + this contains o atLeast 1 the patterns + +/** + * Helper function to create a [RegexPatterns] based on the given [pattern] and [otherPatterns] + * -- allows to express `String, vararg String`. + */ +fun regexPatterns(pattern: String, vararg otherPatterns: String): RegexPatterns = + RegexPatterns(pattern, otherPatterns) + +/** + * Expects that the subject of the assertion (a [CharSequence]) contains a sequence which matches the given + * regular expression [patterns], using a non disjoint search. + * + * It is a shortcut for `contains o atLeast 1 regex All(pattern, *otherPatterns)`. + * + * By non disjoint is meant that `"aa"` in `"aaaa"` is found three times and not only two times. + * Also notice, that it does not search for unique matches. Meaning, if the input of the search is `"ab"` and + * [All] is defined as `all(Regex("a(b)?"), Regex("a(b)?"))` as well, then both match, + * even though they match the same sequence in the input of the search. + * Use an option such as [atLeast], [atMost] and [exactly] to control the number of occurrences you expect. + * + * Meaning you might want to use: + * `contains o exactly 2 regex "a(b)?"` + * instead of: + * `contains o atLeast 1 the all(Regex("a(b)?"), Regex("a(b)?"))` + * + * @param patterns The patterns which are expected to have a match against the input of the search -- + * use the function `all(Regex(...), ...)` to create a [All]. + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Expect.contains(patterns: All): Expect = + this contains o atLeast 1 matchFor patterns +/** + * Expects that the subject of the assertion (a [CharSequence]) starts with [expected]. + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Expect.startsWith(expected: CharSequence) = + addAssertion(ExpectImpl.charSequence.startsWith(this, expected)) + +/** + * Expects that the subject of the assertion (a [CharSequence]) starts with [expected]. + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.startsWith(expected: Char) = + it startsWith expected.toString() + +/** + * Expects that the subject of the assertion (a [CharSequence]) does not start with [expected]. + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Expect.startsNotWith(expected: CharSequence) = + addAssertion(ExpectImpl.charSequence.startsNotWith(this, expected)) + +/** + * Expects that the subject of the assertion (a [CharSequence]) does not start with [expected]. + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.startsNotWith(expected: Char) = + it startsNotWith expected.toString() + + +/** + * Expects that the subject of the assertion (a [CharSequence]) ends with [expected]. + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Expect.endsWith(expected: CharSequence) = + addAssertion(ExpectImpl.charSequence.endsWith(this, expected)) + +/** + * Expects that the subject of the assertion (a [CharSequence]) ends with [expected]. + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.endsWith(expected: Char) = + it endsWith expected.toString() + +/** + * Expects that the subject of the assertion (a [CharSequence]) does not end with [expected]. + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Expect.endsNotWith(expected: CharSequence) = + addAssertion(ExpectImpl.charSequence.endsNotWith(this, expected)) + +/** + * Expects that the subject of the assertion (a [CharSequence]) does not end with [expected]. + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.endsNotWith(expected: Char) = + it endsNotWith expected.toString() + + +/** + * Expects that the subject of the assertion (a [CharSequence]) [CharSequence].[kotlin.text.isEmpty]. + * + * @param empty Use the pseudo-keyword `empty`. + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Expect.toBe(@Suppress("UNUSED_PARAMETER") empty: empty) = + addAssertion(ExpectImpl.charSequence.isEmpty(this)) + +/** + * Expects that the subject of the assertion (a [CharSequence]) [CharSequence].[kotlin.text.isNotEmpty]. + * + * @param empty Use the pseudo-keyword `empty`. + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Expect.notToBe(@Suppress("UNUSED_PARAMETER") empty: empty) = + addAssertion(ExpectImpl.charSequence.isNotEmpty(this)) + +/** + * Expects that the subject of the assertion (a [CharSequence]) [CharSequence].[kotlin.text.isNotBlank]. + * + * @param blank Use the pseudo-keyword `blank`. + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Expect.notToBe(@Suppress("UNUSED_PARAMETER") blank: blank) = + addAssertion(ExpectImpl.charSequence.isNotBlank(this)) + +/** + * Expects that the subject of the assertion (a [CharSequence]) matches the given [expected] [Regex]. + * + * In contrast to [containsRegex] it does not look for a partial match but for an entire match. + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.matches(expected: Regex) = + addAssertion(ExpectImpl.charSequence.matches(this, expected)) + +/** + * Expects that the subject of the assertion (a [CharSequence]) mismatches the given [expected] [Regex]. + * + * In contrast to `containsNot.regex` it does not look for a partial match but for an entire match. + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.mismatches(expected: Regex) = + addAssertion(ExpectImpl.charSequence.mismatches(this, expected)) diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/charSequenceContainsCheckers.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/charSequenceContainsCheckers.kt new file mode 100644 index 000000000..be8e9797b --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/charSequenceContainsCheckers.kt @@ -0,0 +1,90 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.* +import ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.impl.* +import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains +import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains.SearchBehaviour + +/** + * Restricts a `contains` assertion by specifying that the number of occurrences of the value which we are looking + * for occurs `at least` number of [times] within the search input. + * + * @param times The number which the check will compare against the actual number of times an expected value is + * found in the input of the search. + * + * @return The newly created builder. + * @throws IllegalArgumentException In case [times] is smaller than zero. + * @throws IllegalArgumentException In case [times] equals to zero; use [containsNot] instead. + */ +infix fun CharSequenceContains.Builder.atLeast( + times: Int +): AtLeastCheckerOption = AtLeastCheckerOptionImpl(times, this) + +/** + * Restricts a `contains at least` assertion by specifying that the number of occurrences of the value which we + * are looking for occurs `at most` number of [times] within the search input. + * + * The resulting restriction will be a `contains at least but at most` assertion. + * + * @param times The number which the check will compare against the actual number of times an expected value is + * found in the input of the search. + * + * @return The newly created builder. + * @throws IllegalArgumentException In case [times] is smaller than zero. + * @throws IllegalArgumentException In case [times] equals to zero; use [containsNot] instead. + * @throws IllegalArgumentException In case [times] of this `at most` restriction equals to the number of the + * `at least` restriction; use the [exactly] restriction instead. + */ +infix fun AtLeastCheckerOption.butAtMost( + times: Int +): ButAtMostCheckerOption = ButAtMostCheckerOptionImpl(times, this, containsBuilder) + +/** + * Restricts a `contains` assertion by specifying that the number of occurrences of the value which we + * are looking for occurs `exactly` number of [times] within the search input. + * + * @param times The number which the check will compare against the actual number of times an expected value is + * found in the input of the search. + * + * @return The newly created builder. + * @throws IllegalArgumentException In case [times] is smaller than zero. + * @throws IllegalArgumentException In case [times] equals to zero; use [containsNot] instead. + */ +infix fun CharSequenceContains.Builder.exactly( + times: Int +): ExactlyCheckerOption = ExactlyCheckerOptionImpl(times, this) + +/** + * Restricts a `contains` assertion by specifying that the number of occurrences of the value which we + * are looking for occurs `at least` once but `at most` number of [times] within the search input. + * + * If you want to use a higher lower bound than one, then use `atLeast(2).butAtMost(3)` instead of `atMost(3)`. + * And in case you want to state that it is either not contained at all or at most a certain number of times, + * then use `notOrAstMost(2)` instead. + * + * @param times The number which the check will compare against the actual number of times an expected value is + * found in the input of the search. + * + * @return The newly created builder. + * @throws IllegalArgumentException In case [times] is smaller than zero. + * @throws IllegalArgumentException In case [times] equals to zero; use [containsNot] instead. + * @throws IllegalArgumentException In case [times] equals to one; use [exactly] instead. + */ +infix fun CharSequenceContains.Builder.atMost( + times: Int +): AtMostCheckerOption = AtMostCheckerOptionImpl(times, this) + +/** + * Restricts a `contains` assertion by specifying that the number of occurrences of the value which we + * are looking for occurs `not at all or at most` number of [times] within the search input. + * + * @param times The number which the check will compare against the actual number of times an expected value is + * found in the input of the search. + * + * @return The newly created builder. + * @throws IllegalArgumentException In case [times] is smaller than zero. + * @throws IllegalArgumentException In case [times] equals to zero; use [containsNot] instead. + */ +infix fun CharSequenceContains.Builder.notOrAtMost( + times: Int +): NotOrAtMostCheckerOption = NotOrAtMostCheckerOptionImpl(times, this) diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/charSequenceContainsCreators.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/charSequenceContainsCreators.kt new file mode 100644 index 000000000..ac3f8565f --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/charSequenceContainsCreators.kt @@ -0,0 +1,391 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.infix.en_GB.creating.All +import ch.tutteli.atrium.api.infix.en_GB.creating.RegexPatterns +import ch.tutteli.atrium.api.infix.en_GB.creating.Values +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.domain.builders.creating.basic.contains.addAssertion +import ch.tutteli.atrium.domain.builders.utils.toVarArg +import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains +import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains.Builder +import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains.CheckerOption +import ch.tutteli.atrium.domain.creating.charsequence.contains.searchbehaviours.IgnoringCaseSearchBehaviour +import ch.tutteli.atrium.domain.creating.charsequence.contains.searchbehaviours.NoOpSearchBehaviour +import kotlin.jvm.JvmName + +/** + * Finishes the specification of the sophisticated `contains` assertion where the [expected] object shall be searched, + * using a non disjoint search. + * + * Delegates to `the values(expected)`. + * + * Notice that a runtime check applies which assures that only [CharSequence], [Number] and [Char] are passed (this + * function expects `Any` for your convenience, so that you can mix [String] and [Int] for instance). + * + * By non disjoint is meant that "aa" in "aaaa" is found three times and not only two times. + * + * @param expected The value which is expected to be contained within the input of the search. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * @throws IllegalArgumentException in case [expected] is not a [CharSequence], [Number] or [Char]. + */ +infix fun CheckerOption.value(expected: Any): Expect = + this the values(expected) + +/** + * Finishes the specification of the sophisticated `contains` assertion where the given [values] + * shall be searched, using a non disjoint search. + * + * Notice that a runtime check applies which assures that only [CharSequence], [Number] and [Char] are passed (this + * function expects `Any` for your convenience, so that you can mix [String] and [Int] for instance). + * + * By non disjoint is meant that `"aa"` in `"aaaa"` is found three times and not only two times. + * Also notice, that it does not search for unique matches. Meaning, if the input of the search is `"a"` and + * [Values] is defined as `values("a", "a")`, then both match, + * even though they match the same sequence in the input of the search. + * Use an option such as [atLeast], [atMost] and [exactly] to control the number of occurrences you expect. + * + * Meaning you might want to use: + * `contains o exactly 2 the value "a"` + * instead of: + * `contains o atLeast 1 the values("a", "a")` + * + * @param values The values which should not be found within the input of the search + * -- use the function `values(t, ...)` to create a [Values]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * @throws IllegalArgumentException in case one of the [values] is not a [CharSequence], [Number] or [Char]. + */ +infix fun CheckerOption.the(values: Values): Expect = + addAssertion(ExpectImpl.charSequence.contains.values(this, values.toList())) + + +/** + * Finishes the specification of the sophisticated `contains` assertion where the [expected] value shall be searched + * (ignoring case), using a non disjoint search. + * + * Delegates to `the values(expected)`. + * + * Notice that a runtime check applies which assures that only [CharSequence], [Number] and [Char] are passed (this + * function expects `Any` for your convenience, so that you can mix [String] and [Int] for instance). + * + * By non disjoint is meant that "aa" in "aaaa" is found three times and not only two times. + * + * @param expected The value which is expected to be contained within the input of the search. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * @throws IllegalArgumentException in case [expected] is not a [CharSequence], [Number] or [Char]. + */ +@JvmName("valueIgnoringCase") +infix fun CheckerOption.value(expected: Any): Expect = + this the values(expected) + +/** + * Finishes the specification of the sophisticated `contains` assertion where the [values] + * shall be searched (ignoring case), using a non disjoint search. + * + * Notice that a runtime check applies which assures that only [CharSequence], [Number] and [Char] are passed (this + * function expects `Any` for your convenience, so that you can mix [String] and [Int] for instance). + * + * By non disjoint is meant that `"aa"` in `"aaaa"` is found three times and not only two times. + * Also notice, that it does not search for unique matches. Meaning, if the input of the search is `"a"` and + * [Values] is defined as `values("a", "a")`, then both match, + * even though they match the same sequence in the input of the search. + * Use an option such as [atLeast], [atMost] and [exactly] to control the number of occurrences you expect. + * + * Meaning you might want to use: + * `contains o ignoring case exactly 2 the value "a"` + * instead of: + * `contains o ignoring case atLeast 1 the values("a", "a")` + * + * @param values The values which are expected to be contained within the input of the search + * -- use the function `values(t, ...)` to create a [Values]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * @throws IllegalArgumentException in case one of the [values] is not a [CharSequence], [Number] or [Char]. + */ +@JvmName("valuesIgnoringCase") +infix fun CheckerOption.the(values: Values): Expect = + addAssertion(ExpectImpl.charSequence.contains.valuesIgnoringCase(this, values.toList())) + +/** + * Finishes the specification of the sophisticated `contains` assertion where the [expected] value shall be searched + * (ignoring case), using a non disjoint search where it needs to be contained at least once. + * + * Delegates to `atLeast 1 value expected`. + * + * Notice that a runtime check applies which assures that only [CharSequence], [Number] and [Char] are passed (this + * function expects `Any` for your convenience, so that you can mix [String] and [Int] for instance). + * + * By non disjoint is meant that "aa" in "aaaa" is found three times and not only two times. + * + * @param expected The value which is expected to be contained within the input of the search. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * @throws IllegalArgumentException in case [expected] is not a [CharSequence], [Number] or [Char]. + */ +infix fun Builder.value(expected: Any): Expect = + this atLeast 1 value expected + +/** + * Finishes the specification of the sophisticated `contains` assertion where the [values] + * shall be searched (ignoring case), using a non disjoint search + * where each need to be contained at least once. + * + * Delegates to `atLeast 1 the value` + * + * By non disjoint is meant that `"aa"` in `"aaaa"` is found three times and not only two times. + * Also notice, that it does not search for unique matches. Meaning, if the input of the search is `"a"` and + * [Values] is defined as `values("a", "a")`, then both match, + * even though they match the same sequence in the input of the search. + * Use an option such as [atLeast], [atMost] and [exactly] to control the number of occurrences you expect. + * + * Meaning you might want to use: + * `contains o ignoring case exactly 2 the value "a"` + * instead of: + * `contains o ignoring case atLeast 1 the values("a", "a")` + * + * @param values The values which are expected to be contained within the input of the search + * -- use the function `values(t, ...)` to create a [Values]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * @throws IllegalArgumentException in case one of the [values] is not a [CharSequence], [Number] or [Char]. + */ +infix fun Builder.the(values: Values): Expect = + this atLeast 1 the values + +/** + * Finishes the specification of the sophisticated `contains` assertion where the given regular expression [pattern] + * is expected to have a match, using a non disjoint search. + * + * Delegates to `the regexPatterns(pattern)`. + * + * @param pattern The pattern which is expected to have a match against the input of the search. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun CheckerOption.regex(pattern: String): Expect = + this the regexPatterns(pattern) + +/** + * Finishes the specification of the sophisticated `contains` assertion where the given [Regex] [pattern] + * is expected to have a match. + * + * Delegates to `matchFor all(pattern)` + * + * @param pattern The pattern which is expected to have a match against the input of the search. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun CheckerOption.matchFor( + pattern: Regex +): Expect = this matchFor all(pattern) + +/** + * Finishes the specification of the sophisticated `contains` assertion where the given regular expression [patterns] + * are expected to have a match, using a non disjoint search. + * + * By non disjoint is meant that `"aa"` in `"aaaa"` is found three times and not only two times. + * Also notice, that it does not search for unique matches. Meaning, if the input of the search is `"ab"` and + * [RegexPatterns] is defined as `regexPatterns("a(b)?", "a(b)?")` as well, then both match, + * even though they match the same sequence in the input of the search. + * Use an option such as [atLeast], [atMost] and [exactly] to control the number of occurrences you expect. + * + * Meaning you might want to use: + * `contains o exactly 2 regex "a(b)?"` + * instead of: + * `contains o atLeast 1 the regexPatterns("a(b)?", "a(b)?")` + * + * @param patterns The patterns which are expected to have a match against the input of the search + * -- use the function `regexPatterns(t, ...)` to create a [RegexPatterns]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun CheckerOption.the(patterns: RegexPatterns): Expect = + addAssertion(ExpectImpl.charSequence.contains.regex(this, patterns.toList())) + +/** + * Finishes the specification of the sophisticated `contains` assertion where the given [Regex] [patterns] + * are expected to have a match, using a non disjoint search. + * + * By non disjoint is meant that `"aa"` in `"aaaa"` is found three times and not only two times. + * Also notice, that it does not search for unique matches. Meaning, if the input of the search is `"ab"` and + * [All] is defined as `all(Regex("a(b)?"), Regex("a(b)?"))` as well, then both match, + * even though they match the same sequence in the input of the search. + * Use an option such as [atLeast], [atMost] and [exactly] to control the number of occurrences you expect. + * + * Meaning you might want to use: + * `contains o exactly 2 regex "a(b)?"` + * instead of: + * `contains o atLeast 1 the all(Regex("a(b)?"), Regex("a(b)?"))` + * + * @param patterns The patterns which are expected to have a match against the input of the search -- + * use the function `all(Regex(...), ...)` to create a [All]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun CheckerOption.matchFor(patterns: All): Expect = + addAssertion(ExpectImpl.charSequence.contains.regex(this, patterns.toList())) + + + +/** + * Finishes the specification of the sophisticated `contains` assertion where the given regular expression [pattern] + * is expected to have a match (ignoring case), using a non disjoint search. + * + * Delegates to `the regexPatterns(pattern)`. + * + * @param pattern The patterns which is expected to have a match against the input of the search. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +@JvmName("regexIgnoringCase") +infix fun CheckerOption.regex(pattern: String): Expect = + this the regexPatterns(pattern) + +/** + * Finishes the specification of the sophisticated `contains` assertion where the given regular expression [patterns] + * are expected to have a match (ignoring case), using a non disjoint search. + * + * By non disjoint is meant that `"aa"` in `"aaaa"` is found three times and not only two times. + * Also notice, that it does not search for unique matches. Meaning, if the input of the search is `"ab"` and + * [RegexPatterns] is defined as `regexPatterns("a(b)?", "a(b)?")` as well, then both match, + * even though they match the same sequence in the input of the search. + * Use an option such as [atLeast], [atMost] and [exactly] to control the number of occurrences you expect. + * + * Meaning you might want to use: + * `contains o ignoring case exactly 2 the regex "a(b)?"` + * instead of: + * `contains o ignoring case atLeast 1 the regexPatterns("a(b)?", "a(b)?")` + * + * @param patterns The patterns which are expected to have a match against the input of the search + * -- use the function `regexPatterns(t, ...)` to create a [RegexPatterns]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +@JvmName("regexIgnoringCase") +infix fun CheckerOption.the(patterns: RegexPatterns): Expect = + addAssertion(ExpectImpl.charSequence.contains.regexIgnoringCase(this, patterns.toList())) + +/** + * Finishes the specification of the sophisticated `contains` assertion where the given regular expression [pattern] + * is expected to have at least one match (ignoring case), using a non disjoint search. + * + * Delegates to `atLeast 1 regex pattern`. + * + * @param pattern The patterns which is expected to have a match against the input of the search. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Builder.regex(pattern: String): Expect = + this atLeast 1 regex pattern + +/** + * Finishes the specification of the sophisticated `contains` assertion where the given regular expression [patterns] + * are expected to have at least one match (ignoring case), using a non disjoint search. + * + * Delegates to `atLeast 1 the patterns`. + * + * By non disjoint is meant that `"aa"` in `"aaaa"` is found three times and not only two times. + * Also notice, that it does not search for unique matches. Meaning, if the input of the search is `"ab"` and + * [RegexPatterns] is defined as `regexPatterns("a(b)?", "a(b)?")` as well, then both match, + * even though they match the same sequence in the input of the search. + * Use an option such as [atLeast], [atMost] and [exactly] to control the number of occurrences you expect. + * + * Meaning you might want to use: + * `contains o ignoring case exactly 2 the regex "a(b)?"` + * instead of: + * `contains o ignoring case atLeast 1 the RegexPatterns("a(b)?", "a(b)?")` + * + * @param patterns The patterns which are expected to have a match against the input of the search -- + * use the function `regexPatterns(t, ...)` to create a [RegexPatterns]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Builder.the(patterns: RegexPatterns): Expect = + this atLeast 1 the patterns + +/** + * Finishes the specification of the sophisticated `contains` assertion where all elements of the [expectedIterable] + * shall be searched, using a non disjoint search. + * + * Delegates to `the values(expectedIterable.first(), *expectedIterable.drop(1).toTypedArray())` + * (see [the] for more information). + * + * Notice that a runtime check applies which assures that only [CharSequence], [Number] and [Char] are passed (this + * function expects `Any` for your convenience, so that you can mix [String] and [Int] for instance). + * + * By non disjoint is meant that "aa" in "aaaa" is found three times and not only two times. + * + * @param expectedIterable The [Iterable] whose elements are expected to be contained within the input of the search. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * @throws IllegalArgumentException in case [expectedIterable] is not a [CharSequence], [Number] or [Char] or the given + * [expectedIterable] does not have elements (is empty). + * + * @since 0.11.0 + */ +infix fun CheckerOption.elementsOf( + expectedIterable: Iterable +): Expect { + val (first, rest) = toVarArg(expectedIterable) + return this the Values(first, rest) +} + + +/** + * Finishes the specification of the sophisticated `contains` assertion where all elements of the [expectedIterable] + * shall be searched (ignoring case), using a non disjoint search. + * + * Delegates to `the values(expectedIterable.first(), *expectedIterable.drop(1).toTypedArray())` + * (see [the] for more information). + * + * Notice that a runtime check applies which assures that only [CharSequence], [Number] and [Char] are passed (this + * function expects `Any` for your convenience, so that you can mix [String] and [Int] for instance). + * + * By non disjoint is meant that "aa" in "aaaa" is found three times and not only two times. + * + * @param expectedIterable The [Iterable] whose elements are expected to be contained within the input of the search. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * @throws IllegalArgumentException in case [expectedIterable] is not a [CharSequence], [Number] or [Char] or the given + * [expectedIterable] does not have elements (is empty). + * + * @since 0.11.0 + */ +@JvmName("elementsOfIgnoringCase") +infix fun CheckerOption.elementsOf( + expectedIterable: Iterable +): Expect { + val (first, rest) = toVarArg(expectedIterable) + return this the Values(first, rest) +} + +@JvmName("elementsOfIgnoringCase") +infix fun CharSequenceContains.Builder.elementsOf( + expectedIterable: Iterable +): Expect { + val (first, rest) = toVarArg(expectedIterable) + return this the Values(first, rest) +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/charSequenceContainsSearchBehaviours.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/charSequenceContainsSearchBehaviours.kt new file mode 100644 index 000000000..122367303 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/charSequenceContainsSearchBehaviours.kt @@ -0,0 +1,33 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.NotCheckerOption +import ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.impl.NotCheckerOptionImpl +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains +import ch.tutteli.atrium.domain.creating.charsequence.contains.searchbehaviours.IgnoringCaseSearchBehaviour +import ch.tutteli.atrium.domain.creating.charsequence.contains.searchbehaviours.NoOpSearchBehaviour +import ch.tutteli.atrium.domain.creating.charsequence.contains.searchbehaviours.NotSearchBehaviour + +/** + * Defines that the search behaviour `ignore case` shall be applied to this sophisticated `contains` assertion. + * + * @param case Has to be `case`. + * + * @return The newly created builder. + */ +infix fun CharSequenceContains.Builder.ignoring( + @Suppress("UNUSED_PARAMETER") case: case +): CharSequenceContains.Builder = + ExpectImpl.charSequence.contains.searchBehaviours.ignoringCase(this) + +/** + * Defines that the search behaviour `ignore case` shall be applied to this sophisticated `contains not` assertion. + * + * @param case Has to be `case`. + * + * @return The newly created builder. + */ +infix fun NotCheckerOption.ignoring( + @Suppress("UNUSED_PARAMETER") case: case +): NotCheckerOption = + NotCheckerOptionImpl(containsBuilder ignoring case) diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/collectionAssertions.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/collectionAssertions.kt index 9819a0631..8b2524975 100644 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/collectionAssertions.kt +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/collectionAssertions.kt @@ -6,34 +6,39 @@ import ch.tutteli.atrium.domain.builders.ExpectImpl /** * Expects that the subject of the assertion (a [Collection]) is an empty [Collection]. * - * @return This assertion container to support a fluent API. + * @param empty Use the pseudo-keyword `empty`. + * + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ -infix fun > Expect.toBe(@Suppress("UNUSED_PARAMETER") Empty: Empty) = +infix fun > Expect.toBe(@Suppress("UNUSED_PARAMETER") empty: empty) = addAssertion(ExpectImpl.collection.isEmpty(this)) /** * Expects that the subject of the assertion (a [Collection]) is not an empty [Collection]. * - * @return This assertion container to support a fluent API. + * @param empty Use the pseudo-keyword `empty`. + * + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ -infix fun > Expect.notToBe(@Suppress("UNUSED_PARAMETER") Empty: Empty) = +infix fun > Expect.notToBe(@Suppress("UNUSED_PARAMETER") empty: empty) = addAssertion(ExpectImpl.collection.isNotEmpty(this)) /** * Creates an [Expect] for the property [Collection.size] of the subject of the assertion, * so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. */ val > Expect.size get(): Expect = ExpectImpl.collection.size(this).getExpectOfFeature() /** * Expects that the property [Collection.size] of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ infix fun > Expect.size(assertionCreator: Expect.() -> Unit): Expect = diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/comparableAssertions.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/comparableAssertions.kt new file mode 100644 index 000000000..1e25a5d7d --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/comparableAssertions.kt @@ -0,0 +1,45 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl + +/** + * Expects that the subject of the assertion is less than [expected]. + * The comparison is carried out with [Comparable.compareTo]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.isLessThan(expected: T) = + addAssertion(ExpectImpl.comparable.isLessThan(this, expected)) + +/** + * Expects that the subject of the assertion is less than or equal [expected]. + * The comparison is carried out with [Comparable.compareTo]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.isLessThanOrEqual(expected: T) = + addAssertion(ExpectImpl.comparable.isLessOrEquals(this, expected)) + +/** + * Expects that the subject of the assertion is greater than [expected]. + * The comparison is carried out with [Comparable.compareTo]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.isGreaterThan(expected: T) = + addAssertion(ExpectImpl.comparable.isGreaterThan(this, expected)) + +/** + * Expects that the subject of the assertion is greater than or equal [expected]. + * The comparison is carried out with [Comparable.compareTo]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.isGreaterThanOrEqual(expected: T) = + addAssertion(ExpectImpl.comparable.isGreaterOrEquals(this, expected)) + diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/All.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/All.kt new file mode 100644 index 000000000..56752df0b --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/All.kt @@ -0,0 +1,13 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating + +import ch.tutteli.atrium.domain.builders.utils.VarArgHelper + +/** + * Parameter object to express `T, vararg T`. + * + * Use the function `all(t, ...)` to create this representation. + */ +class All internal constructor( + override val expected: T, + override val otherExpected: Array +) : VarArgHelper diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/Entries.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/Entries.kt new file mode 100644 index 000000000..e1155d70d --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/Entries.kt @@ -0,0 +1,38 @@ +@file:Suppress("DEPRECATION" /* TODO remove suppress with 1.0.0 */) + +package ch.tutteli.atrium.api.infix.en_GB.creating + +import ch.tutteli.atrium.assertions.Assertion +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.utils.Group +import ch.tutteli.atrium.domain.builders.utils.GroupWithNullableEntries +import ch.tutteli.atrium.domain.builders.utils.GroupWithoutNullableEntries +import ch.tutteli.atrium.domain.builders.utils.VarArgHelper +import ch.tutteli.kbox.glue + +/** + * Parameter object to express a [Group] of identification lambdas. + * + * It is also used to express `(Expect.() -> Unit)?, vararg (Expect.() -> Unit)?` at other places the infix-api. + * + * In case `null` is used for an identification lambda then it is expected that the corresponding entry + * is `null` as well. + * + * Use the function `entries({ ... }, ...)` to create this representation. + * + * @param assertionCreatorOrNull The identification lambda identifying the entry where an entry is considered + * to be identified if it holds all [Assertion]s the lambda might create. + * In case it is defined as `null`, then an entry is identified if it is `null` as well. + * @param otherAssertionCreatorsOrNulls A variable amount of additional identification lambdas or `null`s. + */ +class Entries internal constructor( + val assertionCreatorOrNull: (Expect.() -> Unit)?, + val otherAssertionCreatorsOrNulls: Array.() -> Unit)?> +) : GroupWithoutNullableEntries<(Expect.() -> Unit)?>, + GroupWithNullableEntries<(Expect.() -> Unit)?>, + VarArgHelper<(Expect.() -> Unit)?> { + override val expected get() = assertionCreatorOrNull + override val otherExpected get() = otherAssertionCreatorsOrNulls + + override fun toList(): List<(Expect.() -> Unit)?> = assertionCreatorOrNull glue otherAssertionCreatorsOrNulls +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/Entry.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/Entry.kt new file mode 100644 index 000000000..6e8b3be6e --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/Entry.kt @@ -0,0 +1,28 @@ +@file:Suppress("DEPRECATION" /* TODO remove suppress with 1.0.0 */) +package ch.tutteli.atrium.api.infix.en_GB.creating + +import ch.tutteli.atrium.assertions.Assertion +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.utils.Group +import ch.tutteli.atrium.domain.builders.utils.GroupWithNullableEntries +import ch.tutteli.atrium.domain.builders.utils.GroupWithoutNullableEntries + +/** + * Parameter object to express a [Group] with a single identification lambda. + * + * In case `null` is used for the identification lambda then it is expected that the corresponding entry + * is `null` as well. + * + * Use the function `entry { ... }` to create this representation. + * + * @param assertionCreatorOrNull The identification lambda identifying the entry where an entry is considered + * to be identified if it holds all [Assertion]s the lambda creates. + * In case it is defined as `null`, then an entry is identified if it is `null` as well. + */ +data class Entry internal constructor( + val assertionCreatorOrNull: (Expect.() -> Unit)? +) : GroupWithoutNullableEntries<(Expect.() -> Unit)?>, + GroupWithNullableEntries<(Expect.() -> Unit)?> { + + override fun toList(): List<(Expect.() -> Unit)?> = listOf(assertionCreatorOrNull) +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/IndexWithCreator.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/IndexWithCreator.kt new file mode 100644 index 000000000..d6a35f764 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/IndexWithCreator.kt @@ -0,0 +1,14 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating + +import ch.tutteli.atrium.creating.Expect + + +/** + * Parameter object which combines an [index] of type [Int] with an [assertionCreator] which defines assertions for + * a resulting feature of type [E]. + * + * Use the function `index(Int) { ... }` to create this representation. + * + * @since 0.11.0 + */ +data class IndexWithCreator internal constructor(val index: Int, val assertionCreator: Expect.() -> Unit) diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/KeyWithCreator.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/KeyWithCreator.kt new file mode 100644 index 000000000..1529b2746 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/KeyWithCreator.kt @@ -0,0 +1,14 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating + +import ch.tutteli.atrium.creating.Expect + +/** + * Parameter object which combines an [key] of type [K] with an [assertionCreator] which defines assertions for + * a resulting feature of type [V]. + * + * Use the function `key(...) { ... }` to create this representation where the first parameter corresponds + * to the [key] and the second is the [assertionCreator]. + * + * @since 0.11.0 + */ +data class KeyWithCreator internal constructor(val key: K, val assertionCreator: Expect.() -> Unit) diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/Pairs.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/Pairs.kt new file mode 100644 index 000000000..3f352d9e6 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/Pairs.kt @@ -0,0 +1,13 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating + +import ch.tutteli.atrium.domain.builders.utils.VarArgHelper + +/** + * Parameter object to express `Pair, vararg Pair`. + * + * Use the function `pairs(x to y, ...)` to create this representation. + */ +class Pairs internal constructor( + override val expected: Pair, + override val otherExpected: Array> +) : VarArgHelper> diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/PresentWithCreator.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/PresentWithCreator.kt new file mode 100644 index 000000000..68cd2df3b --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/PresentWithCreator.kt @@ -0,0 +1,13 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating + +import ch.tutteli.atrium.creating.Expect + +/** + * Parameter object which represents a present value (e.g. to represent a present `Optional`) with an element type [E] + * combined with an [assertionCreator] which defines assertions for the element. + * + * Use the function `present { ... }` to create this representation. + * + * @since 0.11.0 + */ +data class PresentWithCreator internal constructor(val assertionCreator: Expect.() -> Unit) diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/RegexPatterns.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/RegexPatterns.kt new file mode 100644 index 000000000..6d66c5828 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/RegexPatterns.kt @@ -0,0 +1,14 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating + +import ch.tutteli.atrium.domain.builders.utils.VarArgHelper + +/** + * Parameter object to express `String, vararg String` in the infix-api. + * + * Use the function `regexPatterns("pattern", ...)` to create this representation. + */ +class RegexPatterns internal constructor(pattern: String, otherPatterns: Array) : + VarArgHelper { + override val expected = pattern + override val otherExpected = otherPatterns +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/SuccessWithCreator.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/SuccessWithCreator.kt new file mode 100644 index 000000000..8ea1e0972 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/SuccessWithCreator.kt @@ -0,0 +1,12 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating + +import ch.tutteli.atrium.creating.Expect + +/** + * Parameter object that takes [assertionCreator] which defines assertions for a resulting feature of type [E]. + * + * Use the function `success { ... }` to create a [SuccessWithCreator]. + * + * @since 0.11.0 + */ +data class SuccessWithCreator internal constructor(val assertionCreator: Expect.() -> Unit); diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/Value.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/Value.kt new file mode 100644 index 000000000..f7b33e80a --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/Value.kt @@ -0,0 +1,16 @@ +@file:Suppress("DEPRECATION" /* TODO remove suppress with 1.0.0 */) +package ch.tutteli.atrium.api.infix.en_GB.creating + +import ch.tutteli.atrium.domain.builders.utils.Group +import ch.tutteli.atrium.domain.builders.utils.GroupWithNullableEntries +import ch.tutteli.atrium.domain.builders.utils.GroupWithoutNullableEntries + +/** + * Represents a [Group] with a single value. + * + * Use the function `value(t)` to create this representation. + */ +data class Value internal constructor(val expected: T) : GroupWithNullableEntries, + GroupWithoutNullableEntries { + override fun toList() = listOf(expected) +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/Values.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/Values.kt new file mode 100644 index 000000000..12f68efba --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/Values.kt @@ -0,0 +1,23 @@ +@file:Suppress("DEPRECATION" /* TODO remove suppress with 1.0.0 */) + +package ch.tutteli.atrium.api.infix.en_GB.creating + +import ch.tutteli.atrium.domain.builders.utils.Group +import ch.tutteli.atrium.domain.builders.utils.GroupWithNullableEntries +import ch.tutteli.atrium.domain.builders.utils.GroupWithoutNullableEntries +import ch.tutteli.atrium.domain.builders.utils.VarArgHelper + +/** + * Represents a [Group] of multiple values. + * + * Use the function `values(t, ...)` to create this representation. + * + * Note, [Values] will be made invariant once Kotlin 1.4 is out and Atrium depends on it (most likely with 1.0.0) + */ +//TODO remove `out` with Kotlin 1.4 (most likely with Atrium 1.0.0) +class Values internal constructor( + override val expected: T, + override val otherExpected: Array +) : GroupWithoutNullableEntries, GroupWithNullableEntries, VarArgHelper { + override fun toList(): List = super.toList() +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/AtLeastCheckerOption.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/AtLeastCheckerOption.kt new file mode 100644 index 000000000..3b6cc2866 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/AtLeastCheckerOption.kt @@ -0,0 +1,14 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders + +import ch.tutteli.atrium.domain.builders.creating.charsequence.contains.builders.WithTimesCheckerOption +import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains + +/** + * Represents the extension point for another option after a `contains at least`-check within a sophisticated + * `contains` assertion building process for [CharSequence]. + * + * @param T The input type of the search. + * @param S The search behaviour which should be applied for the input of the search. + */ +interface AtLeastCheckerOption + : WithTimesCheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/AtMostCheckerOption.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/AtMostCheckerOption.kt new file mode 100644 index 000000000..b9b942050 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/AtMostCheckerOption.kt @@ -0,0 +1,13 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders + +import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains + +/** + * Represents the extension point for another option after a `contains at least once but at most`-check within + * a sophisticated `contains` assertion building process for [CharSequence]. + * + * @param T The input type of the search. + * @param S The search behaviour which should be applied for the input of the search. + */ +interface AtMostCheckerOption + : CharSequenceContains.CheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/ButAtMostCheckerOption.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/ButAtMostCheckerOption.kt new file mode 100644 index 000000000..a67f28ad4 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/ButAtMostCheckerOption.kt @@ -0,0 +1,13 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders + +import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains + +/** + * Represents the extension point for another option after a `contains at least but at most`-check within + * a sophisticated `contains` assertion building process for [CharSequence]. + * + * @param T The input type of the search. + * @param S The search behaviour which should be applied for the input of the search. + */ +interface ButAtMostCheckerOption + : CharSequenceContains.CheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/ExactlyCheckerOption.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/ExactlyCheckerOption.kt new file mode 100644 index 000000000..f0175cbe2 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/ExactlyCheckerOption.kt @@ -0,0 +1,13 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders + +import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains + +/** + * Represents the extension point for another option after a `contains exactly`-check within + * a sophisticated `contains` assertion building process for [CharSequence]. + * + * @param T The input type of the search. + * @param S The search behaviour which should be applied for the input of the search. + */ +interface ExactlyCheckerOption + : CharSequenceContains.CheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/NotCheckerOption.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/NotCheckerOption.kt new file mode 100644 index 000000000..7895f6c3e --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/NotCheckerOption.kt @@ -0,0 +1,13 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders + +import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains + +/** + * Represents the extension point for another option after a `contains not at all`-check within + * a sophisticated `contains` assertion building process for [CharSequence]. + * + * @param T The input type of the search. + * @param S The search behaviour which should be applied for the input of the search. + */ +interface NotCheckerOption + : CharSequenceContains.CheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/NotOrAtMostCheckerOption.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/NotOrAtMostCheckerOption.kt new file mode 100644 index 000000000..105459299 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/NotOrAtMostCheckerOption.kt @@ -0,0 +1,13 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders + +import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains + +/** + * Represents the extension point for another option after a `contains not or at most`-check within + * a sophisticated `contains` assertion building process for [CharSequence]. + * + * @param T The input type of the search. + * @param S The search behaviour which should be applied for the input of the search. + */ +interface NotOrAtMostCheckerOption + : CharSequenceContains.CheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/impl/AtLeastCheckerOptionImpl.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/impl/AtLeastCheckerOptionImpl.kt new file mode 100644 index 000000000..5e56d0909 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/impl/AtLeastCheckerOptionImpl.kt @@ -0,0 +1,30 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.impl + +import ch.tutteli.atrium.api.infix.en_GB.atLeast +import ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.AtLeastCheckerOption +import ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.impl.StaticName.nameContainsNotValuesFun +import ch.tutteli.atrium.domain.builders.creating.charsequence.contains.builders.AtLeastCheckerOptionBase +import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains + +/** + * Represents the builder of a `contains at least`-check within the fluent API of a sophisticated + * `contains` assertion for [CharSequence]. + * + * @param T The input type of the search. + * @param S The search behaviour which should be applied for the input of the search. + * + * @constructor Represents the builder of a `contains at least` check within the fluent API of a sophisticated + * `contains` assertion for [CharSequence]. + * @param times The number which the check will compare against the actual number of times an expected object is + * found in the input of the search. + * @param containsBuilder The previously used [CharSequenceContains.Builder]. + */ +internal class AtLeastCheckerOptionImpl( + times: Int, + containsBuilder: CharSequenceContains.Builder +) : AtLeastCheckerOptionBase( + times, + containsBuilder, + nameContainsNotValuesFun, + { "`${containsBuilder::atLeast.name} $it`" } +), AtLeastCheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/impl/AtMostCheckerOptionImpl.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/impl/AtMostCheckerOptionImpl.kt new file mode 100644 index 000000000..8448bceae --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/impl/AtMostCheckerOptionImpl.kt @@ -0,0 +1,34 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.impl + +import ch.tutteli.atrium.api.infix.en_GB.atLeast +import ch.tutteli.atrium.api.infix.en_GB.atMost +import ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.AtMostCheckerOption +import ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.impl.StaticName.nameContainsNotValuesFun +import ch.tutteli.atrium.api.infix.en_GB.exactly +import ch.tutteli.atrium.domain.builders.creating.charsequence.contains.builders.AtMostCheckerOptionBase +import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains + +/** + * Represents the builder of a `contains at least once but at most` check within the fluent API of a + * sophisticated `contains` assertion for [CharSequence]. + * + * @param T The input type of the search. + * @param S The search behaviour which should be applied for the input of the search. + * + * @constructor Represents the builder of a `contains at least once but at most` check within the fluent API of a + * sophisticated `contains` assertion for [CharSequence]. + * @param times The number which the check will compare against the actual number of times an expected object is + * found in the input of the search. + * @param containsBuilder The previously used [CharSequenceContains.Builder]. + */ +internal class AtMostCheckerOptionImpl( + times: Int, + containsBuilder: CharSequenceContains.Builder +) : AtMostCheckerOptionBase( + times, + containsBuilder, + nameContainsNotValuesFun, + { "`${containsBuilder::atMost.name} $it`" }, + { "`${containsBuilder::atLeast.name} $it`" }, + { "`${containsBuilder::exactly.name} $it`" } +), AtMostCheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/impl/ButAtMostCheckerOptionImpl.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/impl/ButAtMostCheckerOptionImpl.kt new file mode 100644 index 000000000..f9a03551a --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/impl/ButAtMostCheckerOptionImpl.kt @@ -0,0 +1,40 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.impl + +import ch.tutteli.atrium.api.infix.en_GB.atLeast +import ch.tutteli.atrium.api.infix.en_GB.atMost +import ch.tutteli.atrium.api.infix.en_GB.butAtMost +import ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.AtLeastCheckerOption +import ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.ButAtMostCheckerOption +import ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.impl.StaticName.nameContainsNotValuesFun +import ch.tutteli.atrium.api.infix.en_GB.exactly +import ch.tutteli.atrium.domain.builders.creating.charsequence.contains.builders.ButAtMostCheckerOptionBase +import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains + +/** + * Represents the builder of the second step of a `contains at least but at most` check within the + * fluent API of a sophisticated `contains` assertion for [CharSequence]. + * + * @param T The input type of the search. + * @param S The search behaviour which should be applied to the input of the search. + * + * @constructor Represents the builder of the second step of a `contains at least but at most` check within the + * fluent API of a sophisticated `contains` assertion for [CharSequence]. + * @param times The number which the check will compare against the actual number of times an expected object is + * found in the input of the search. + * @param containsBuilder The previously used [CharSequenceContains.Builder]. + */ +internal class ButAtMostCheckerOptionImpl( + times: Int, + atLeastBuilder: AtLeastCheckerOption, + containsBuilder: CharSequenceContains.Builder +) : ButAtMostCheckerOptionBase( + times, + atLeastBuilder, + containsBuilder, + nameContainsNotValuesFun, + { l, u -> "`${containsBuilder::atLeast.name} $l ${atLeastBuilder::butAtMost.name} $u`" }, + { "`${containsBuilder::atMost.name} $it`" }, + { "`${containsBuilder::atLeast.name} $it`" }, + { "`${atLeastBuilder::butAtMost.name} $it`" }, + { "`${containsBuilder::exactly.name} $it`" } +), ButAtMostCheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/impl/ExactlyCheckerOptionImpl.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/impl/ExactlyCheckerOptionImpl.kt new file mode 100644 index 000000000..f5ee5d6a3 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/impl/ExactlyCheckerOptionImpl.kt @@ -0,0 +1,30 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.impl + +import ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.ExactlyCheckerOption +import ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.impl.StaticName.nameContainsNotValuesFun +import ch.tutteli.atrium.api.infix.en_GB.exactly +import ch.tutteli.atrium.domain.builders.creating.charsequence.contains.builders.ExactlyCheckerOptionBase +import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains + +/** + * Represents the builder of a `contains exactly` check within the fluent API of a sophisticated + * `contains` assertion for [CharSequence]. + * + * @param T The input type of the search. + * @param S The search behaviour which should be applied for the input of the search. + * + * @constructor Represents the builder of a `contains exactly` check within the fluent API of a sophisticated + * `contains` assertion for [CharSequence]. + * @param times The number which the check will compare against the actual number of times an expected object is + * found in the input of the search. + * @param containsBuilder The previously used [CharSequenceContains.Builder]. + */ +internal class ExactlyCheckerOptionImpl( + times: Int, + containsBuilder: CharSequenceContains.Builder +) : ExactlyCheckerOptionBase( + times, + containsBuilder, + nameContainsNotValuesFun, + { "`${containsBuilder::exactly.name} $it`" } +), ExactlyCheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/impl/NotCheckerOptionImpl.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/impl/NotCheckerOptionImpl.kt new file mode 100644 index 000000000..81aac3823 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/impl/NotCheckerOptionImpl.kt @@ -0,0 +1,21 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.impl + +import ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.NotCheckerOption +import ch.tutteli.atrium.domain.builders.creating.charsequence.contains.builders.NotCheckerOptionBase +import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains + +/** + * Represents the builder of a `contains not at all` check within the fluent API of a sophisticated + * `contains` assertion for [CharSequence]. + * + * @param T The input type of the search. + * @param S The search behaviour which should be applied for the input of the search. + * + * @constructor Represents the builder of a `contains not at all` check within the fluent API of a sophisticated + * `contains` assertion for [CharSequence]. + * @param containsBuilder The previously used [CharSequenceContains.Builder]. + */ +internal class NotCheckerOptionImpl( + containsBuilder: CharSequenceContains.Builder +) : NotCheckerOptionBase(containsBuilder), + NotCheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/impl/NotOrAtMostCheckerOptionImpl.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/impl/NotOrAtMostCheckerOptionImpl.kt new file mode 100644 index 000000000..4e9569c70 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/impl/NotOrAtMostCheckerOptionImpl.kt @@ -0,0 +1,30 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.impl + +import ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.NotOrAtMostCheckerOption +import ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.impl.StaticName.nameContainsNotValuesFun +import ch.tutteli.atrium.api.infix.en_GB.notOrAtMost +import ch.tutteli.atrium.domain.builders.creating.charsequence.contains.builders.NotOrAtMostCheckerOptionBase +import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains + +/** + * Represents the builder of a `contains not or at most` check within the fluent API of a + * sophisticated `contains` assertion for [CharSequence]. + * + * @param T The input type of the search. + * @param S The search behaviour which should be applied for the input of the search. + * + * @constructor Represents the builder of a `contains not or at most` check within the fluent API of a + * sophisticated `contains` assertion for [CharSequence]. + * @param times The number which the check will compare against the actual number of times an expected object is + * found in the input of the search. + * @param containsBuilder The previously used [CharSequenceContains.Builder]. + */ +internal class NotOrAtMostCheckerOptionImpl( + times: Int, + containsBuilder: CharSequenceContains.Builder +) : NotOrAtMostCheckerOptionBase( + times, + containsBuilder, + nameContainsNotValuesFun, + { "`${containsBuilder::notOrAtMost.name} $it`" } +), NotOrAtMostCheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/impl/nameContainsNotFun.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/impl/nameContainsNotFun.kt new file mode 100644 index 000000000..df9e8c296 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/charsequence/contains.builders/impl/nameContainsNotFun.kt @@ -0,0 +1,17 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.impl + +import ch.tutteli.atrium.api.infix.en_GB.creating.Values +import ch.tutteli.atrium.api.infix.en_GB.containsNot +import ch.tutteli.atrium.creating.Expect +import kotlin.reflect.KFunction2 + +internal object StaticName { + val nameContainsNotValuesFun: String = { + val f: KFunction2, Values, Expect> = + Expect::containsNot + //TODO use once https://youtrack.jetbrains.com/issue/KT-38013 is fixed (there are other places where "values" is hard-coded) +// val values : KFunction2, Values> = ::values +// "`${f.name} ${values.name}`" + "`${f.name} values`" + }() +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/feature/Feature.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/feature/Feature.kt new file mode 100644 index 000000000..8627efa1e --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/feature/Feature.kt @@ -0,0 +1,18 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.feature + +import kotlin.reflect.KProperty1 + +/** + * Parameter object which contains a [description] of a feature along with an [extractor] + * which actually extracts the feature out of a subject of an assertion. + * + * Use `of(K..., ...) { ... }` to create this representation where the first argument is the extractor in form of a + * [KProperty1] or a `KFunctionX` and the remaining arguments are the required arguments in case of a `KFunctionX` + * where `X` > 1. + * + * @property description The description of the feature. + * @property extractor The extractor which extracts the feature out of the subject of the assertion. + + * @since 0.11.0 + */ +data class Feature internal constructor(val description: String, val extractor: (T) -> R) diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/feature/FeatureWithCreator.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/feature/FeatureWithCreator.kt new file mode 100644 index 000000000..b220e414e --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/feature/FeatureWithCreator.kt @@ -0,0 +1,25 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.feature + +import ch.tutteli.atrium.creating.Expect +import kotlin.reflect.KProperty1 + +/** + * Parameter object which contains a [description] of a feature along with an [extractor] + * which actually extracts the feature out of a subject of an assertion + an [assertionCreator] + * which defines assertions for the feature. + * + * Use `of(K..., ...) { ... }` to create this representation where the first argument is the extractor in form of a + * [KProperty1] or a `KFunctionX`, the last an [assertionCreator]-lambda and the remaining arguments in-between the + * required arguments in case of a `KFunctionX` where `X` > 1. + * + * @property description The description of the feature. + * @property extractor The extractor which extracts the feature out of the subject of the assertion. + * @property assertionCreator The `assertionCreator`-lambda which defines assertions for the feature. + * + * @since 0.11.0 + */ +data class FeatureWithCreator internal constructor( + val description: String, + val extractor: (T) -> R, + val assertionCreator: Expect.() -> Unit +) diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/feature/MetaFeatureOptionWithCreator.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/feature/MetaFeatureOptionWithCreator.kt new file mode 100644 index 000000000..b0c4feef2 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/feature/MetaFeatureOptionWithCreator.kt @@ -0,0 +1,22 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.feature + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.creating.MetaFeatureOption +import ch.tutteli.atrium.domain.creating.MetaFeature + +/** + * Parameter object which combines a lambda with a [MetaFeatureOption] receiver (called [provider]) + * and an [assertionCreator]. + * + * Use the function `of({ ... }) { ... }` to create this representation where the first + * argument is a lambda with a [MetaFeatureOption] as receiver which has to create a [MetaFeature] + * where the subject of the assertion is available via implicit parameter `it`. + * Usually you use [f][MetaFeatureOption.f] to create a [MetaFeature], + * e.g. `feature of({ f(it::size) }) { o toBe 3 }` + * + * @since 0.11.0 + */ +data class MetaFeatureOptionWithCreator internal constructor( + val provider: MetaFeatureOption.(T) -> MetaFeature, + val assertionCreator: Expect.() -> Unit +) diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/Order.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/Order.kt new file mode 100644 index 000000000..2767bee16 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/Order.kt @@ -0,0 +1,16 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.iterable + +import ch.tutteli.atrium.domain.builders.utils.Group + +/** + * Parameter object to express `Group, Group, vararg Group` in the infix-api. + * + * Use the function `order(group, group, ...)` to create this representation. + * + * Notice, most probably the type parameter G will be removed in the future, will be fixed to [Group]. + */ +class Order> internal constructor( + val firstGroup: G, + val secondGroup: G, + val otherExpectedGroups: Array +) diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/AtLeastCheckerOption.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/AtLeastCheckerOption.kt new file mode 100644 index 000000000..4823d8e2e --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/AtLeastCheckerOption.kt @@ -0,0 +1,14 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders + +import ch.tutteli.atrium.domain.builders.creating.iterable.contains.builders.WithTimesCheckerOption +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains + +/** + * Represents the extension point for another option after a `contains at least`-check within a sophisticated + * `contains` assertion building process for [Iterable]. + * + * @param T The input type of the search. + * @param S The search behaviour which should be applied for the input of the search. + */ +interface AtLeastCheckerOption, out S : IterableContains.SearchBehaviour> + : WithTimesCheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/AtMostCheckerOption.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/AtMostCheckerOption.kt new file mode 100644 index 000000000..988039ac8 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/AtMostCheckerOption.kt @@ -0,0 +1,14 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders + +import ch.tutteli.atrium.domain.builders.creating.iterable.contains.builders.WithTimesCheckerOption +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains + +/** + * Represents the extension point for another option after a `contains at least once but at most`-check within + * a sophisticated `contains` assertion building process for [Iterable]. + * + * @param T The input type of the search. + * @param S The search behaviour which should be applied for the input of the search. + */ +interface AtMostCheckerOption, out S : IterableContains.SearchBehaviour> + : WithTimesCheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/ButAtMostCheckerOption.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/ButAtMostCheckerOption.kt new file mode 100644 index 000000000..61af9b7ff --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/ButAtMostCheckerOption.kt @@ -0,0 +1,14 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders + +import ch.tutteli.atrium.domain.builders.creating.iterable.contains.builders.WithTimesCheckerOption +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains + +/** + * Represents the extension point for another option after a `contains at least but at most`-check within a + * sophisticated `contains` assertion building process for [Iterable]. + * + * @param T The input type of the search. + * @param S The search behaviour which should be applied for the input of the search. + */ +interface ButAtMostCheckerOption, out S : IterableContains.SearchBehaviour> + : WithTimesCheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/ExactlyCheckerOption.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/ExactlyCheckerOption.kt new file mode 100644 index 000000000..0548bacc4 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/ExactlyCheckerOption.kt @@ -0,0 +1,14 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders + +import ch.tutteli.atrium.domain.builders.creating.iterable.contains.builders.WithTimesCheckerOption +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains + +/** + * Represents the extension point for another option after a `contains exactly`-check within + * a sophisticated `contains` assertion building process for [Iterable]. + * + * @param T The input type of the search. + * @param S The search behaviour which should be applied for the input of the search. + */ +interface ExactlyCheckerOption, out S : IterableContains.SearchBehaviour> + : WithTimesCheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/NotCheckerOption.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/NotCheckerOption.kt new file mode 100644 index 000000000..51819520c --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/NotCheckerOption.kt @@ -0,0 +1,13 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders + +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains + +/** + * Represents the extension point for another option after a `contains not at all`-check within + * a sophisticated `contains` assertion building process for [Iterable]. + * + * @param T The input type of the search. + * @param S The search behaviour which should be applied for the input of the search. + */ +interface NotCheckerOption, out S : IterableContains.SearchBehaviour> + : IterableContains.CheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/NotOrAtMostCheckerOption.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/NotOrAtMostCheckerOption.kt new file mode 100644 index 000000000..fc7900a91 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/NotOrAtMostCheckerOption.kt @@ -0,0 +1,14 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders + +import ch.tutteli.atrium.domain.builders.creating.iterable.contains.builders.WithTimesCheckerOption +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains + +/** + * Represents the extension point for another option after a `contains not or at most`-check within + * a sophisticated `contains` assertion building process for [Iterable]. + * + * @param T The input type of the search. + * @param S The search behaviour which should be applied for the input of the search. + */ +interface NotOrAtMostCheckerOption, out S : IterableContains.SearchBehaviour> + : WithTimesCheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/impl/AtLeastCheckerOptionImpl.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/impl/AtLeastCheckerOptionImpl.kt new file mode 100644 index 000000000..e8d401f1e --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/impl/AtLeastCheckerOptionImpl.kt @@ -0,0 +1,30 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.impl + +import ch.tutteli.atrium.api.infix.en_GB.atLeast +import ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.AtLeastCheckerOption +import ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.impl.StaticName.nameContainsNotValuesFun +import ch.tutteli.atrium.domain.builders.creating.iterable.contains.builders.AtLeastCheckerOptionBase +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains +import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour + +/** + * Represents the builder of a `contains at least` check within the fluent API of a sophisticated + * `contains` assertion for [Iterable]. + * + * @param T The input type of the search. + * + * @constructor Represents the builder of a `contains at least` check within the fluent API of a sophisticated + * `contains` assertion for [Iterable]. + * @param times The number which the check will compare against the actual number of times an expected entry is + * found in the [Iterable]. + * @param containsBuilder The previously used [IterableContains.Builder]. + */ +internal class AtLeastCheckerOptionImpl, out S : InAnyOrderSearchBehaviour>( + times: Int, + containsBuilder: IterableContains.Builder +) : AtLeastCheckerOptionBase( + times, + containsBuilder, + nameContainsNotValuesFun, + { "`${containsBuilder::atLeast.name} $it`" } +), AtLeastCheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/impl/AtMostCheckerOptionImpl.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/impl/AtMostCheckerOptionImpl.kt new file mode 100644 index 000000000..41b681fb8 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/impl/AtMostCheckerOptionImpl.kt @@ -0,0 +1,34 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.impl + +import ch.tutteli.atrium.api.infix.en_GB.atLeast +import ch.tutteli.atrium.api.infix.en_GB.atMost +import ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.AtMostCheckerOption +import ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.impl.StaticName.nameContainsNotValuesFun +import ch.tutteli.atrium.api.infix.en_GB.exactly +import ch.tutteli.atrium.domain.builders.creating.iterable.contains.builders.AtMostCheckerOptionBase +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains +import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour + +/** + * Represents the builder of a `contains at least once but at most` check within the fluent API of a + * sophisticated `contains` assertion for [Iterable]. + * + * @param T The input type of the search. + * + * @constructor Represents the builder of a `contains at least once but at most` check within the fluent API of a + * sophisticated `contains` assertion for [Iterable]. + * @param times The number which the check will compare against the actual number of times an expected entry is + * found in the [Iterable]. + * @param containsBuilder The previously used [IterableContains.Builder]. + */ +internal class AtMostCheckerOptionImpl, out S : InAnyOrderSearchBehaviour>( + times: Int, + containsBuilder: IterableContains.Builder +) : AtMostCheckerOptionBase( + times, + containsBuilder, + nameContainsNotValuesFun, + { "`${containsBuilder::atMost.name} $it`" }, + { "`${containsBuilder::atLeast.name} $it`" }, + { "`${containsBuilder::exactly.name} $it`" } +), AtMostCheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/impl/ButAtMostCheckerOptionImpl.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/impl/ButAtMostCheckerOptionImpl.kt new file mode 100644 index 000000000..6fa22c476 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/impl/ButAtMostCheckerOptionImpl.kt @@ -0,0 +1,40 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.impl + +import ch.tutteli.atrium.api.infix.en_GB.atLeast +import ch.tutteli.atrium.api.infix.en_GB.atMost +import ch.tutteli.atrium.api.infix.en_GB.butAtMost +import ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.AtLeastCheckerOption +import ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.ButAtMostCheckerOption +import ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.impl.StaticName.nameContainsNotValuesFun +import ch.tutteli.atrium.api.infix.en_GB.exactly +import ch.tutteli.atrium.domain.builders.creating.iterable.contains.builders.ButAtMostCheckerOptionBase +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains +import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour + +/** + * Represents the builder of the second step of a `contains at least but at most` check within the + * fluent API of a sophisticated `contains` assertion for [Iterable]. + * + * @param T The input type of the search. + * + * @constructor Represents the builder of the second step of a `contains at least but at most` check within the + * fluent API of a sophisticated `contains` assertion for [Iterable]. + * @param times The number which the check will compare against the actual number of times an expected entry is + * found in the [Iterable]. + * @param containsBuilder The previously used [IterableContains.Builder]. + */ +internal class ButAtMostCheckerOptionImpl, out S : InAnyOrderSearchBehaviour>( + times: Int, + atLeastBuilder: AtLeastCheckerOption, + containsBuilder: IterableContains.Builder +) : ButAtMostCheckerOptionBase( + times, + atLeastBuilder, + containsBuilder, + nameContainsNotValuesFun, + { l, u -> "`${containsBuilder::atLeast.name} $l ${atLeastBuilder::butAtMost.name} $u`" }, + { "`${containsBuilder::atMost.name} $it`" }, + { "`${containsBuilder::atLeast.name} $it`" }, + { "`${atLeastBuilder::butAtMost.name} $it`" }, + { "`${containsBuilder::exactly.name} $it`" } +), ButAtMostCheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/impl/ExactlyCheckerOptionImpl.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/impl/ExactlyCheckerOptionImpl.kt new file mode 100644 index 000000000..7db1d658c --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/impl/ExactlyCheckerOptionImpl.kt @@ -0,0 +1,30 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.impl + +import ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.ExactlyCheckerOption +import ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.impl.StaticName.nameContainsNotValuesFun +import ch.tutteli.atrium.api.infix.en_GB.exactly +import ch.tutteli.atrium.domain.builders.creating.iterable.contains.builders.ExactlyCheckerOptionBase +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains +import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour + +/** + * Represents the builder of a `contains exactly` check within the fluent API of a sophisticated + * `contains` assertion for [Iterable]. + * + * @param T The input type of the search. + * + * @constructor Represents the builder of a `contains exactly` check within the fluent API of a sophisticated + * `contains` assertion for [Iterable]. + * @param times The number which the check will compare against the actual number of times an expected entry is + * found in the [Iterable]. + * @param containsBuilder The previously used [IterableContains.Builder]. + */ +internal class ExactlyCheckerOptionImpl, out S : InAnyOrderSearchBehaviour>( + times: Int, + containsBuilder: IterableContains.Builder +) : ExactlyCheckerOptionBase( + times, + containsBuilder, + nameContainsNotValuesFun, + { "`${containsBuilder::exactly.name} $it`" } +), ExactlyCheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/impl/NotCheckerOptionImpl.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/impl/NotCheckerOptionImpl.kt new file mode 100644 index 000000000..a27e95eca --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/impl/NotCheckerOptionImpl.kt @@ -0,0 +1,22 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.impl + +import ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.NotCheckerOption +import ch.tutteli.atrium.domain.builders.creating.iterable.contains.builders.NotCheckerOptionBase +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains +import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour + +/** + * Represents the builder of a `contains not at all` check within the fluent API of a sophisticated + * `contains` assertion for [Iterable]. + * + * @param T The input type of the search. + * @param S The search behaviour which should be applied for the input of the search. + * + * @constructor Represents the builder of a `contains not at all` check within the fluent API of a sophisticated + * `contains not` assertion for [Iterable]. + * @param containsBuilder The previously used [IterableContains.Builder]. + */ +internal class NotCheckerOptionImpl, out S : InAnyOrderSearchBehaviour>( + containsBuilder: IterableContains.Builder +) : NotCheckerOptionBase(containsBuilder), + NotCheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/impl/NotOrAtMostCheckerOptionImpl.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/impl/NotOrAtMostCheckerOptionImpl.kt new file mode 100644 index 000000000..14ac6cdb1 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/impl/NotOrAtMostCheckerOptionImpl.kt @@ -0,0 +1,30 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.impl + +import ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.NotOrAtMostCheckerOption +import ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.impl.StaticName.nameContainsNotValuesFun +import ch.tutteli.atrium.api.infix.en_GB.notOrAtMost +import ch.tutteli.atrium.domain.builders.creating.iterable.contains.builders.NotOrAtMostCheckerOptionBase +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains +import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour + +/** + * Represents the builder of a `contains not or at most` check within the fluent API of a + * sophisticated `contains` assertion for [Iterable]. + * + * @param T The input type of the search. + * + * @constructor Represents the builder of a `contains at least once but at most` check within the fluent API of a + * sophisticated `contains` assertion for [Iterable]. + * @param times The number which the check will compare against the actual number of times an expected entry is + * found in the [Iterable]. + * @param containsBuilder The previously used [IterableContains.Builder]. + */ +internal class NotOrAtMostCheckerOptionImpl, out S : InAnyOrderSearchBehaviour>( + times: Int, + containsBuilder: IterableContains.Builder +) : NotOrAtMostCheckerOptionBase( + times, + containsBuilder, + nameContainsNotValuesFun, + { "`${containsBuilder::notOrAtMost.name} $it`" } +), NotOrAtMostCheckerOption diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/impl/nameContainsNotFun.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/impl/nameContainsNotFun.kt new file mode 100644 index 000000000..06a1796f0 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/iterable/contains/builders/impl/nameContainsNotFun.kt @@ -0,0 +1,28 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.impl + +import ch.tutteli.atrium.api.infix.en_GB.containsNot +import ch.tutteli.atrium.api.infix.en_GB.creating.Values +import ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.NotCheckerOption +import ch.tutteli.atrium.api.infix.en_GB.o +import ch.tutteli.atrium.api.infix.en_GB.the +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains +import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour +import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.NotSearchBehaviour +import kotlin.reflect.KFunction2 + +internal object StaticName { + val nameContainsNotValuesFun: String = { + val containsNotKf: KFunction2>, o, NotCheckerOption, NotSearchBehaviour>> = + Expect>::containsNot + val theKf: KFunction2< + IterableContains.CheckerOption, InAnyOrderSearchBehaviour>, + Values, + Expect> + > = IterableContains.CheckerOption, InAnyOrderSearchBehaviour>::the + //TODO use once https://youtrack.jetbrains.com/issue/KT-38013 is fixed (there are other places where "values" is hard-coded) +// val values : KFunction2, Values> = ::values +// "`${f.name} ${o::class.simpleName} ${fThe.name} ${values.name}`" + "`${containsNotKf.name} ${o::class.simpleName} ${theKf.name} values`" + }() +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/list/get/builders/ListGetStep.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/list/get/builders/ListGetStep.kt deleted file mode 100644 index 4c1787581..000000000 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/list/get/builders/ListGetStep.kt +++ /dev/null @@ -1,40 +0,0 @@ -package ch.tutteli.atrium.api.infix.en_GB.creating.list.get.builders - -import ch.tutteli.atrium.api.infix.en_GB.creating.list.get.builders.impl.ListGetStepImpl -import ch.tutteli.atrium.creating.Expect - -/** - * Represents the extension point for another step after a `get index`-step within a - * sophisticated `get` assertion building process for [List]. - * - * @param E The element type of the [List]. - * @param T A subtype of [List]. - */ -interface ListGetStep> { - /** - * The [Expect] for which this assertion is created - */ - val expect: Expect - - /** - * The given index which will be used to perform the [List.get]. - */ - val index: Int - - /** - * Makes the assertion that the given [index] is within the bounds of [Expect.subject] and that - * the corresponding entry holds all assertions the given [assertionCreator] might create for it. - * - * @return This [Expect] to support a fluent API. - * @throws AssertionError Might throw an [AssertionError] if a created [Expect]s (by calling [assertionCreator]) - * does not hold. - * @throws IllegalArgumentException in case the given [assertionCreator] did not create a single assertion. - */ - infix fun assertIt(assertionCreator: Expect.() -> Unit): Expect - - companion object { - fun > create(expect: Expect, index: Int): ListGetStep = - ListGetStepImpl(expect, index) - } -} - diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/list/get/builders/impl/ListGetStepImpl.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/list/get/builders/impl/ListGetStepImpl.kt deleted file mode 100644 index b837b17d0..000000000 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/list/get/builders/impl/ListGetStepImpl.kt +++ /dev/null @@ -1,14 +0,0 @@ -package ch.tutteli.atrium.api.infix.en_GB.creating.list.get.builders.impl - -import ch.tutteli.atrium.api.infix.en_GB.creating.list.get.builders.ListGetStep -import ch.tutteli.atrium.creating.Expect -import ch.tutteli.atrium.domain.builders.ExpectImpl - -internal class ListGetStepImpl>( - override val expect: Expect, - override val index: Int -) : ListGetStep { - - override infix fun assertIt(assertionCreator: Expect.() -> Unit): Expect - = expect.addAssertion(ExpectImpl.list.get(expect, index).collect(assertionCreator)) -} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/map/KeyWithValueCreator.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/map/KeyWithValueCreator.kt new file mode 100644 index 000000000..4a26b57c8 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/creating/map/KeyWithValueCreator.kt @@ -0,0 +1,18 @@ +package ch.tutteli.atrium.api.infix.en_GB.creating.map + +import ch.tutteli.atrium.creating.Expect + +/** + * Parameter object to express a key/value [Pair] whose value type is a nullable lambda with an + * [Expect] receiver, which means one can either pass a lambda or `null`. + * + * Use the function `keyValue(x) { ... }` to create this representation. + */ +data class KeyWithValueCreator internal constructor( + val key: K, + val valueAssertionCreatorOrNull: (Expect.() -> Unit)? +) { + fun toPair(): Pair.() -> Unit)?> = key to valueAssertionCreatorOrNull + override fun toString(): String = + "KeyValue(key=$key, value=${if (valueAssertionCreatorOrNull == null) "null" else "lambda"})" +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/expectExtensions.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/expectExtensions.kt new file mode 100644 index 000000000..2ff205b44 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/expectExtensions.kt @@ -0,0 +1,125 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.core.None +import ch.tutteli.atrium.core.coreFactory +import ch.tutteli.atrium.creating.* +import ch.tutteli.atrium.domain.builders.creating.changers.FeatureExtractorBuilder +import ch.tutteli.atrium.domain.builders.creating.changers.FeatureOptions +import ch.tutteli.atrium.domain.builders.reporting.ExpectBuilder +import ch.tutteli.atrium.domain.builders.reporting.ExpectOptions +import ch.tutteli.atrium.reporting.RawString +import ch.tutteli.atrium.reporting.reporter + +@Suppress("DEPRECATION" /* RequiresOptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */) +@Experimental +@Retention(AnnotationRetention.BINARY) +@Target(AnnotationTarget.FUNCTION) +annotation class ExperimentalWithOptions + +/** + * Wraps the given [textRepresentation] into a [RawString] and uses it as representation of the subject + * instead of the representation that has been defined so far (which defaults to the subject itself). + * + * In case [Expect.maybeSubject] is not defined i.e. [None], then the previous representation is used. + */ +@ExperimentalWithOptions +infix fun RootExpect.withRepresentation(textRepresentation: String): Expect = + withOptions { withRepresentation(textRepresentation) } + +/** + * Uses the given [representationProvider] to retrieve a representation which can be based on the current + * subject where it is used as new representation of the subject + * instead of the representation that has been defined so far (which defaults to the subject itself). + * + * Notice, if you want to use text (e.g. a [String]) as representation, + * then wrap it into a [RawString] via [RawString.create] and pass the [RawString] instead. + * If your text does not include the current subject, then we recommend to use the other overload which expects + * a `String` and does the wrapping for you. + * + * In case [Expect.maybeSubject] is not defined i.e. [None], then the previous representation is used. + */ +@ExperimentalWithOptions +infix fun RootExpect.withRepresentation(representationProvider: (T) -> Any): Expect = + withOptions { withRepresentation(representationProvider) } + +/** + * Uses the given [configuration]-lambda to create an [ExpectOptions] which in turn is used + * to override (parts) of the existing configuration. + */ +@ExperimentalWithOptions +infix fun RootExpect.withOptions(configuration: ExpectBuilder.OptionsChooser.() -> Unit): Expect = + withOptions(ExpectBuilder.OptionsChooser.createAndBuild(configuration)) + +//TODO #280 get rid of AssertionChecker, that's one root of a bug (which is more a nice to have but still) roadmap#11 +//in the same go we should get rid of ReportingAssertionContainer.AssertionCheckerDecorator, rename it respectively. +/** + * Uses the given [options] to override (parts) of the existing configuration. + */ +@ExperimentalWithOptions +@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */) +@UseExperimental(ExperimentalExpectConfig::class) +infix fun RootExpect.withOptions(options: ExpectOptions): Expect = + coreFactory.newReportingAssertionContainer( + ReportingAssertionContainer.AssertionCheckerDecorator.create( + options.assertionVerb ?: this.config.description, + this.maybeSubject, + options.representationInsteadOfSubject?.let { provider -> + this.maybeSubject.fold({ null }) { provider(it) } + } ?: this.config.representation, + //TODO #280 reporter should be configurable as well + coreFactory.newThrowingAssertionChecker(options.reporter ?: reporter) + ) + ) + +/** + * Wraps the given [textRepresentation] into a [RawString] and uses it as representation of the subject + * instead of the representation that has been defined so far (which defaults to the subject itself). + * + * In case [Expect.maybeSubject] is not defined i.e. [None], then the previous representation is used. + */ +@ExperimentalWithOptions +infix fun FeatureExpect.withRepresentation(textRepresentation: String): Expect = + withOptions { withRepresentation(textRepresentation) } + +/** + * Uses the given [representationProvider] to retrieve a representation which can be based on the current + * subject where it is used as new representation of the subject + * instead of the representation that has been defined so far (which defaults to the subject itself). + * + * Notice, if you want to use text (e.g. a [String]) as representation, + * then wrap it into a [RawString] via [RawString.create] and pass the [RawString] instead. + * If your text does not include the current subject, then we recommend to use the other overload which expects + * a `String` and does the wrapping for you. + * + * In case [Expect.maybeSubject] is not defined i.e. [None], then the previous representation is used. + */ +@ExperimentalWithOptions +infix fun FeatureExpect.withRepresentation(representationProvider: (R) -> Any): Expect = + withOptions { withRepresentation(representationProvider) } + +/** + * Uses the given [configuration]-lambda to create an [ExpectOptions] which in turn is used + * to override (parts) of the existing configuration. + */ +@ExperimentalWithOptions +infix fun FeatureExpect.withOptions(configuration: FeatureExtractorBuilder.OptionsChooser.() -> Unit): Expect = + withOptions(FeatureExtractorBuilder.OptionsChooser.createAndBuild(configuration)) + +/** + * Uses the given [options] to override (parts) of the existing configuration. + */ +@ExperimentalWithOptions +@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */) +@UseExperimental(ExperimentalExpectConfig::class) +infix fun FeatureExpect.withOptions(options: FeatureOptions): Expect = + coreFactory.newFeatureExpect( + previousExpect, + maybeSubject, + FeatureExpectConfig.create( + options.description ?: config.description, + options.representationInsteadOfFeature?.let { provider -> + this.maybeSubject.fold({ null }) { provider(it) } + } ?: this.config.representation + ), + getAssertions() + ) diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/featureAssertions.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/featureAssertions.kt new file mode 100644 index 000000000..59c7669f6 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/featureAssertions.kt @@ -0,0 +1,335 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.infix.en_GB.creating.feature.Feature +import ch.tutteli.atrium.api.infix.en_GB.creating.feature.FeatureWithCreator +import ch.tutteli.atrium.api.infix.en_GB.creating.feature.MetaFeatureOptionWithCreator +import ch.tutteli.atrium.assertions.AssertionGroup +import ch.tutteli.atrium.core.coreFactory +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.creating.FeatureExpect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.domain.builders.creating.MetaFeatureOption +import ch.tutteli.atrium.domain.creating.MetaFeature +import kotlin.reflect.* + +/** + * Extracts the [property] out of the current subject of the assertion, + * creates a new [Expect] for it and + * returns it so that subsequent calls are based on the feature. + * + * @return The newly created [Expect] for the given [property]. + * + * @since 0.11.0 + */ +infix fun Expect.feature(property: KProperty1): FeatureExpect = + ExpectImpl.feature.property(this, property).getExpectOfFeature() + +/** + * Extracts the value which is returned when calling the method [f] on the current subject of the assertion, + * creates a new [Expect] for it and + * returns it so that subsequent calls are based on the feature. + * + * Use `feature of(...)` in case the method requires parameters or in case you want to define + * an assertion group block for it. + * + * @return The newly created [Expect] for the return value of calling the method [f] + * on the current subject of the assertion. + * + * @since 0.11.0 + */ +infix fun Expect.feature(f: KFunction1): FeatureExpect = + ExpectImpl.feature.f0(this, f).getExpectOfFeature() + +/** + * Extracts a feature out of the current subject of the assertion using the given [Feature.extractor], + * creates a new [Expect] for it and + * returns it so that subsequent calls are based on the feature. + * + * Use `of(K..., ...)` to create a [Feature] where the first argument is the extractor in form of a + * [KProperty1] or a `KFunctionX` and potentially the required arguments for a `KFunctionX` where `X` > 1. + * + * Note, [Feature] will be made invariant once Kotlin 1.4 is out and Atrium depends on it (most likely with 1.0.0) + * + * @param of Use `of(K..., ...)` to create a [Feature] where the first argument is the extractor in form of a + * [KProperty1] or a `KFunctionX` and potentially the required arguments for a `KFunctionX` where `X` > 1. + * + * @return The newly created [Expect] for the extracted feature. + * + * @since 0.11.0 + */ +//TODO remove `in` with Kotlin 1.4 (most likely with Atrium 1.0.0) +infix fun Expect.feature(of: Feature): FeatureExpect = + ExpectImpl.feature.manualFeature(this, of.description, of.extractor).getExpectOfFeature() + +/** + * Extracts a feature out of the current subject of the assertion using the given [FeatureWithCreator.extractor], + * creates a new [Expect] for it, + * applies an assertion group based on the given [FeatureWithCreator.assertionCreator] for the feature and + * returns the initial [Expect] with the current subject. + * + * Use `of(K..., ...) { ... }` to create a [FeatureWithCreator] where the first argument is the extractor in + * form of a [KProperty1] or a `KFunctionX`, the last an `assertionCreator`-lambda and the remaining arguments + * in-between the required arguments in case of a `KFunctionX` where `X` > 1. + * + * Note, [FeatureWithCreator] will be made invariant once Kotlin 1.4 is out and Atrium depends on it (most likely with 1.0.0) + * + * @param of Use `of(K..., ...) { ... }` to create a [FeatureWithCreator] where the first argument is the extractor in + * form of a [KProperty1] or a `KFunctionX`, the last an `assertionCreator`-lambda and the remaining arguments + * in-between the required arguments in case of a `KFunctionX` where `X` > 1. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] in case the created [AssertionGroup] does not hold. + * + * @since 0.11.0 + */ +//TODO remove `in` with Kotlin 1.4 (most likely with Atrium 1.0.0) +infix fun Expect.feature(of: FeatureWithCreator): Expect = + ExpectImpl.feature.manualFeature(this, of.description, of.extractor).addToInitial(of.assertionCreator) + + +/** + * Extracts a feature out of the current subject of the assertion, + * based on the given [provider], + * creates a new [Expect] for it and + * returns it so that subsequent calls are based on the feature. + * + * @param provider Creates a [MetaFeature] where the subject of the assertion is available via + * implicit parameter `it`. Usually you use [f][MetaFeatureOption.f] to create a [MetaFeature], + * e.g. `feature { f(it::size) }` + * + * @return The newly created [Expect] for the extracted feature. + * + * @since 0.11.0 + */ +infix fun Expect.feature(provider: MetaFeatureOption.(T) -> MetaFeature): FeatureExpect = + ExpectImpl.feature.genericSubjectBasedFeature(this) { MetaFeatureOption(this).provider(it) }.getExpectOfFeature() + +/** + * Extracts a feature out of the current subject of the assertion, + * based on the given [MetaFeatureOptionWithCreator] + * creates a new [Expect] for it, + * applies an assertion group based on the given [MetaFeatureOptionWithCreator.assertionCreator] for the feature and + * returns the initial [Expect] with the current subject. + * + * Note that you need to enable the new type inference of Kotlin (or use Kotlin 1.4 and above) in order that Kotlin + * is able to infer the types. + * As workaround you can use the overload which expects `MetaFeatureOption.(T) -> MetaFeature` + * and use `it` after the call (import from the package workaround). For instance: + * + * ``` + * // use + * import ch.tutteli.atrium.api.infix.en_GB.workaround.it + * expect(person) feature { f(it::age) } it { o toBe 20 } + * + * // instead of (which causes problems with Kotlin < 1.4) + * expect(person) feature of({ f(it::age) }) { o toBe 20 } + * ``` + * + * @param of Use the function `of({ ... }) { ... }` to create the [MetaFeatureOptionWithCreator] where the first + * argument is a lambda with a [MetaFeatureOption] as receiver which has to create a [MetaFeature] + * where the subject of the assertion is available via implicit parameter `it`. + * Usually you use [f][MetaFeatureOption.f] to create a [MetaFeature], + * e.g. `feature of({ f(it::size) }) { o toBe 3 }` + * + * @return An [Expect] for the current subject of the assertion. + * @since 0.11.0 + */ +infix fun Expect.feature(of: MetaFeatureOptionWithCreator): Expect = + ExpectImpl.feature.genericSubjectBasedFeature(this) { + MetaFeatureOption(this).(of.provider)(it) + }.addToInitial(of.assertionCreator) + +/** + * Creates a [MetaFeature] using the given [provider] and [description]. + * + * This can be used to create complex features with a custom description or as workaround where Kotlin is not able to + * infer the types properly. + * + * For instance: + * ``` + * expect(person) feature { f("first underage child", it.children.first { it < 18 }) } + * ``` + * + * Note that you can use `feature of("first underage child") { children.first { it < 18 } }` with the new type inference + * enabled (e.g. if you use Kotlin 1.4 or above). + * This method will most likely be removed once Kotlin 1.4 is out (probably with Atrium 1.0) + * + * @return The newly created [MetaFeature]. + */ +@Suppress("unused" /* unused receiver, but that's fine */) +fun MetaFeatureOption.f(description: String, provider: R): MetaFeature = + MetaFeature(description, provider) + +//@formatter:off +/** + * Helper function to create a [Feature] based on a [KFunction2] + arguments. + * + * @return The newly created [Feature]. + */ +fun of(f: KFunction2, a1: A1): Feature = + Feature(formatMethodCall(f, a1)) { f.invoke(it, a1) } + +/** + * Helper function to create a [Feature] based on a [KFunction3] + arguments. + * + * @return The newly created [Feature]. + */ +fun of(f: KFunction3, a1: A1, a2: A2): Feature = + Feature(formatMethodCall(f, a1, a2)) { f.invoke(it, a1, a2) } + +/** + * Helper function to create a [Feature] based on a [KFunction4] + arguments. + * + * @return The newly created [Feature]. + */ +fun of(f: KFunction4, a1: A1, a2: A2, a3: A3): Feature = + Feature(formatMethodCall(f, a1, a2, a3)) { f.invoke(it, a1, a2, a3) } + +/** + * Helper function to create a [Feature] based on a [KFunction5] + arguments. + * + * @return The newly created [Feature]. + */ +fun of(f: KFunction5, a1: A1, a2: A2, a3: A3, a4: A4): Feature = + Feature(formatMethodCall(f, a1, a2, a3, a4)) { f.invoke(it, a1, a2, a3, a4) } + +/** + * Helper function to create a [Feature] based on a [KFunction6] + arguments. + * + * @return The newly created [Feature]. + */ +fun of(f: KFunction6, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5): Feature = + Feature(formatMethodCall(f, a1, a2, a3, a4, a5)) { f.invoke(it, a1, a2, a3, a4, a5) } + +/** + * Helper function to create a [FeatureWithCreator] based on a [KProperty1] + [assertionCreator]. + * + * @return The newly created [FeatureWithCreator]. + */ +fun of(property: KProperty1, assertionCreator: Expect.() -> Unit): FeatureWithCreator = + FeatureWithCreator(property.name, { property.invoke(it) }, assertionCreator) + +/** + * Helper function to create a [FeatureWithCreator] based on a [KFunction1] + [assertionCreator]. + * + * @return The newly created [FeatureWithCreator]. + */ +fun of(f: KFunction1, assertionCreator: Expect.() -> Unit): FeatureWithCreator = + FeatureWithCreator(formatMethodCall(f), { f.invoke(it) }, assertionCreator) + +/** + * Helper function to create a [FeatureWithCreator] based on a [KFunction2] + arguments + [assertionCreator]. + * + * @return The newly created [FeatureWithCreator]. + */ +fun of(f: KFunction2, a1: A1, assertionCreator: Expect.() -> Unit): FeatureWithCreator = + FeatureWithCreator(formatMethodCall(f, a1), { f.invoke(it, a1) }, assertionCreator) + +/** + * Helper function to create a [FeatureWithCreator] based on a [KFunction3] + arguments + [assertionCreator]. + * + * @return The newly created [FeatureWithCreator]. + */ +fun of(f: KFunction3, a1: A1, a2: A2, assertionCreator: Expect.() -> Unit): FeatureWithCreator = + FeatureWithCreator(formatMethodCall(f, a1, a2), { f.invoke(it, a1, a2) }, assertionCreator) + +/** + * Helper function to create a [FeatureWithCreator] based on a [KFunction4] + arguments + [assertionCreator]. + * + * @return The newly created [FeatureWithCreator]. + */ +fun of(f: KFunction4, a1: A1, a2: A2, a3: A3, assertionCreator: Expect.() -> Unit): FeatureWithCreator = + FeatureWithCreator(formatMethodCall(f, a1, a2, a3), { f.invoke(it, a1, a2, a3) }, assertionCreator) + +/** + * Helper function to create a [FeatureWithCreator] based on a [KFunction5] + arguments + [assertionCreator]. + * + * @return The newly created [FeatureWithCreator]. + */ +fun of(f: KFunction5, a1: A1, a2: A2, a3: A3, a4: A4, assertionCreator: Expect.() -> Unit): FeatureWithCreator = + FeatureWithCreator(formatMethodCall(f, a1, a2, a3, a4), { f.invoke(it, a1, a2, a3, a4) }, assertionCreator) + +/** + * Helper function to create a [FeatureWithCreator] based on a [KFunction6] + arguments + [assertionCreator]. + * + * @return The newly created [FeatureWithCreator]. + */ +fun of(f: KFunction6, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, assertionCreator: Expect.() -> Unit): FeatureWithCreator = + FeatureWithCreator(formatMethodCall(f, a1, a2, a3, a4, a5), { f.invoke(it, a1, a2, a3, a4, a5) }, assertionCreator) +//@formatter:on + +private fun formatMethodCall(k: KCallable<*>, vararg args: Any?) = + coreFactory.newMethodCallFormatter().formatCall(k.name, args) + +/** + * Helper function to create a [MetaFeatureOptionWithCreator] based on a lambda with + * [MetaFeatureOption] receiver (has to return a [MetaFeature]) and an [assertionCreator]. + */ +fun of( + provider: MetaFeatureOption.(T) -> MetaFeature, + assertionCreator: Expect.() -> Unit +): MetaFeatureOptionWithCreator = + MetaFeatureOptionWithCreator( + provider, + assertionCreator + ) + +/** + * Creates a [Feature] using the given [extractor] and [description]. + * + * This can be used to create complex features with a custom description or as workaround where Kotlin is not able to + * infer the types properly. + * + * For instance: + * ``` + * expect(person) feature of("first underage child") { children.first { it < 18 } } + * ``` + * + * Note, you need to enable the new type inference of Kotlin (or use Kotlin 1.4 and above) in order that Kotlin + * is able to infer the types. + * As workaround you can use [feature] with the overload which expects `MetaFeatureOption.(T) -> MetaFeature`. + * For instance: + * ``` + * // use + * expect(person) feature { f("first underage child", { it.children.first { it < 18 }) } + * + * // instead of (which causes problems with Kotlin < 1.4) + * expect(person) feature of("first underage child") { children.first { it < 18 } + * ``` + * + * @return The newly created [Feature]. + */ +fun of(description: String, extractor: T.() -> R): Feature = + Feature(description, extractor) + +/** + * Creates a [Feature] using the given [extractor] and [description]. + * + * This can be used to create complex features with a custom description or as workaround where Kotlin is not able to + * infer the types properly. + * + * For instance: + * ``` + * expect(person) feature of("first underage child", { children.first { it < 18 }) { name.toBe("robert) } + * ``` + * + * Note, you need to enable the new type inference of Kotlin (or use Kotlin 1.4 and above) in order that Kotlin + * is able to infer the types. + * As workaround you can use [feature] with the overload which expects `MetaFeatureOption.(T) -> MetaFeature`. + * and use `it` after the call (import from the package workaround). For instance: + * ``` + * // use + * import ch.tutteli.atrium.api.infix.en_GB.workaround.it + * expect(person) feature { f(it::age) } it { o toBe 20 } + * + * // instead of (which causes problems with Kotlin < 1.4) + * expect(person) feature of({ f(it::age) }) { o toBe 20 } + * ``` + * + * @return The newly created [Feature]. + */ +fun of( + description: String, + extractor: T.() -> R, + assertionCreator: Expect.() -> Unit +): FeatureWithCreator = FeatureWithCreator(description, extractor, assertionCreator) diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/fun0Assertions.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/fun0Assertions.kt index e329265c1..ed972a79d 100644 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/fun0Assertions.kt +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/fun0Assertions.kt @@ -10,7 +10,7 @@ import ch.tutteli.atrium.domain.builders.ExpectImpl * For instance `toThrow>` would only check if the subject is a `MyException` without checking if * the element type is actually `String`. * - * @return An assertion container with the new type [TExpected]. + * @return An [Expect] with the new type [TExpected]. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ inline fun Expect Any?>.toThrow(): Expect = @@ -46,7 +46,7 @@ inline fun Expect Any?>.toThrow(): Exp * For instance `toThrow>` would only check if the subject is a `MyException` without checking if * the element type is actually `String`. * - * @return An assertion container with the new type [TExpected]. + * @return An [Expect] with the new type [TExpected]. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ inline infix fun Expect Any?>.toThrow( @@ -58,6 +58,7 @@ inline infix fun Expect Any?>.toThrow( * Expects that no [Throwable] is thrown at all when calling the subject (a lambda with arity 0, i.e. without arguments) * and changes the subject of the assertion to the return value of type [R]. * + * @return An [Expect] with the new type [R]. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ fun R> Expect.notToThrow(): Expect = ExpectImpl.fun0.isNotThrowing(this).getExpectOfFeature() @@ -66,6 +67,7 @@ fun R> Expect.notToThrow(): Expect = ExpectImpl.fun0.isNotTh * Expects that no [Throwable] is thrown at all when calling the subject (a lambda with arity 0, i.e. without arguments) * and that the corresponding return value holds all assertions the given [assertionCreator] creates. * + * @return An [Expect] with the new type [R]. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ infix fun R> Expect.notToThrow( diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/helperFunctions.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/helperFunctions.kt new file mode 100644 index 000000000..3ec6af517 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/helperFunctions.kt @@ -0,0 +1,64 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.infix.en_GB.creating.* +import ch.tutteli.atrium.assertions.Assertion +import ch.tutteli.atrium.creating.Expect + +/** + * Helper function to create an [All] based on the given [t] and [ts] + * -- allows to express `T, vararg T`. + */ +fun all(t: T, vararg ts: T) = All(t, ts) + +/** + * Helper function to create an [Entry] based on the given [assertionCreatorOrNull]. + */ +fun entry(assertionCreatorOrNull: (Expect.() -> Unit)?): Entry = Entry(assertionCreatorOrNull) + +/** + * Helper function to create an [Entries] based on the given [assertionCreatorOrNull] + * and [otherAssertionCreatorsOrNulls] -- allows to express `{ }, vararg { }`. + * + * In case `null` is used for an identification lambda then it is expected that the corresponding entry + * is `null` as well. + * + * @param assertionCreatorOrNull The identification lambda identifying the entry where an entry is considered + * to be identified if it holds all [Assertion]s the lambda might create. + * In case it is defined as `null`, then an entry is identified if it is `null` as well. + * @param otherAssertionCreatorsOrNulls A variable amount of additional identification lambdas or `null`s. + */ +fun entries( + assertionCreatorOrNull: (Expect.() -> Unit)?, + vararg otherAssertionCreatorsOrNulls: (Expect.() -> Unit)? +): Entries = Entries(assertionCreatorOrNull, otherAssertionCreatorsOrNulls) + + +/** + * Helper function to create a [Pairs] based on the given [pair] and [otherPairs] + * -- allows to express `Pair, vararg Pair`. + */ +fun pairs(pair: Pair, vararg otherPairs: Pair): Pairs = Pairs(pair, otherPairs) + +/** + * Helper function to create a [PresentWithCreator] based on the given [assertionCreator]. + */ +fun present(assertionCreator: Expect.() -> Unit) = + PresentWithCreator(assertionCreator) + +/** + * Helper function to create a [SuccessWithCreator] based on the given [assertionCreator]. + */ +fun success(assertionCreator: Expect.() -> Unit) = + SuccessWithCreator(assertionCreator) + +/** + * Helper function to create a [Value] based on the given [value]. + */ +fun value(value: T): Value = Value(value) + +/** + * Helper function to create a [Values] based on the given [value] and [otherValues] + * -- allows to express `T, vararg T`. + */ +fun values(value: T, vararg otherValues: T): Values = Values(value, otherValues) + diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableAssertions.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableAssertions.kt index 86a614c12..43cccb29a 100644 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableAssertions.kt +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableAssertions.kt @@ -1,15 +1,320 @@ package ch.tutteli.atrium.api.infix.en_GB +import ch.tutteli.atrium.api.infix.en_GB.creating.Entries +import ch.tutteli.atrium.api.infix.en_GB.creating.Values +import ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.NotCheckerOption +import ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.impl.NotCheckerOptionImpl import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains +import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.NoOpSearchBehaviour +import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.NotSearchBehaviour + +/** + * Creates an [IterableContains.Builder] based on this [Expect] which allows to define + * more sophisticated `contains` assertions. + * + * @param o The filler object [o]. + * + * @return The newly created builder. + */ +infix fun > Expect.contains( + @Suppress("UNUSED_PARAMETER") o: o +): IterableContains.Builder = ExpectImpl.iterable.containsBuilder(this) + +/** + * Creates an [IterableContains.Builder] based on this [Expect] which allows to define + * more sophisticated `contains not` assertions. + * + * @param o The filler object [o]. + * + * @return The newly created builder. + */ +infix fun > Expect.containsNot( + @Suppress("UNUSED_PARAMETER") o: o +): NotCheckerOption = NotCheckerOptionImpl(ExpectImpl.iterable.containsNotBuilder(this)) + +/** + * Creates an [Expect] for the result of calling `min()` on the subject of the assertion, + * so that further fluent calls are assertions about it. + * + * @param o The filler object [o]. + * + * @return The newly created [Expect] for the extracted feature. + * + * @since 0.11.0 + */ +infix fun , T : Iterable> Expect.min(@Suppress("UNUSED_PARAMETER") o: o): Expect = + ExpectImpl.iterable.min(this).getExpectOfFeature() + +/** + * Expects that the result of calling `min()` on the subject of the assertion + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun , T : Iterable> Expect.min(assertionCreator: Expect.() -> Unit): Expect = + ExpectImpl.iterable.min(this).addToInitial(assertionCreator) + + +/** + * Creates an [Expect] for the result of calling `max()` on the subject of the assertion, + * so that further fluent calls are assertions about it. + * + * @param o The filler object [o]. + * + * @return The newly created [Expect] for the extracted feature. + * + * @since 0.11.0 + */ +infix fun , T : Iterable> Expect.max(@Suppress("UNUSED_PARAMETER") o: o): Expect = + ExpectImpl.iterable.max(this).getExpectOfFeature() + +/** + * Expects that the result of calling `max()` on the subject of the assertion + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun , T : Iterable> Expect.max(assertionCreator: Expect.() -> Unit): Expect = + ExpectImpl.iterable.max(this).addToInitial(assertionCreator) + +/** + * Expects that the subject of the assertion (an [Iterable]) contains the [expected] value. + * + * It is a shortcut for `contains o inAny order atLeast 1 value expected` + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.contains(expected: E) = + it contains o inAny order atLeast 1 value expected + +/** + * Expects that the subject of the assertion (an [Iterable]) contains the expected [values]. + * + * It is a shortcut for `contains o inAny order atLeast 1 the values(...)` + * + * Notice, that it does not search for unique matches. Meaning, if the iterable is `setOf('a', 'b')` and + * [Values] is defined as `values("a", "a")`, then both match, + * even though they match the same sequence in the input of the search. + * Use an option such as [atLeast], [atMost] and [exactly] to control the number of occurrences you expect. + * + * Meaning you might want to use: + * contains o inAny order exactly 2 value 'a'` + * instead of: + * `contains values('a', 'a')` + * + * @param values The values which are expected to be contained within the [Iterable] + * -- use the function `values(t, ...)` to create a [Values]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.contains(values: Values): Expect = + it contains o inAny order atLeast 1 the values + +/** + * Expects that the subject of the assertion (an [Iterable]) contains an entry holding the + * assertions created by [assertionCreatorOrNull] or an entry which is `null` in case [assertionCreatorOrNull] + * is defined as `null`. + * + * It is a shortcut for `contains o inAny order atLeast 1 entry assertionCreatorOrNull` + * + * @param assertionCreatorOrNull The identification lambda which creates the assertions which the entry we are looking + * for has to hold; or in other words, the function which defines whether an entry is the one we are looking for + * or not. In case it is defined as `null`, then an entry is identified if it is `null` as well. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.contains(assertionCreatorOrNull: (Expect.() -> Unit)?): Expect = + it contains o inAny order atLeast 1 entry assertionCreatorOrNull + +/** + * Expects that the subject of the assertion (an [Iterable]) contains an entry holding the + * assertions created by [entries].[assertionCreatorOrNull][Entries.assertionCreatorOrNull] or an entry + * which is `null` in case [entries].[assertionCreatorOrNull][Entries.assertionCreatorOrNull] + * is defined as `null` -- likewise an entry (can be the same) is searched for each of the + * [entries].[otherAssertionCreatorsOrNulls][Entries.otherAssertionCreatorsOrNulls]. + * + * It is a shortcut for `contains o inAny order atLeast 1 the entries({ ... }, ...)` + * + * @param entries The entries which are expected to be contained within the [Iterable] + * -- use the function `entries(t, ...)` to create an [Entries]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.contains(entries: Entries): Expect = + it contains o inAny order atLeast 1 the entries + +/** + * Expects that the subject of the assertion (an [Iterable]) contains only + * the [expected] value. + * + * It is a shortcut for `contains o inGiven order and only value expected` + + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.containsExactly(expected: E): Expect = + it contains o inGiven order and only value expected + +/** + * Expects that the subject of the assertion (an [Iterable]) contains only + * the expected [values] in the defined order. + * + * It is a shortcut for `contains o inGiven order and only the Values(...)` + * + * Note that we might change the signature of this function with the next version + * which will cause a binary backward compatibility break (see + * [#292](https://github.com/robstoll/atrium/issues/292) for more information) + * + * @param values The values which are expected to be contained within the [Iterable] + * -- use the function `values(t, ...)` to create a [Values]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.containsExactly(values: Values): Expect = + it contains o inGiven order and only the values + +/** + * Expects that the subject of the assertion (an [Iterable]) contains only an entry holding + * the assertions created by [assertionCreatorOrNull] or only one entry which is `null` in case [assertionCreatorOrNull] + * is defined as `null`. + * + * It is a shortcut for `contains o inGiven order and only entry assertionCreatorOrNull` + * + * Note that we might change the signature of this function with the next version + * which will cause a binary backward compatibility break (see + * [#292](https://github.com/robstoll/atrium/issues/292) for more information) + * + * @param assertionCreatorOrNull The identification lambda which creates the assertions which the entry we are looking + * for has to hold; or in other words, the function which defines whether an entry is the one we are looking for + * or not. In case it is defined as `null`, then an entry is identified if it is `null` as well. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.containsExactly( + assertionCreatorOrNull: (Expect.() -> Unit)? +): Expect = it contains o inGiven order and only entry assertionCreatorOrNull + +/** + * Expects that the subject of the assertion (an [Iterable]) contains only an entry holding + * the assertions created by [entries].[assertionCreatorOrNull][Entries.assertionCreatorOrNull] or + * `null` in case [entries].[assertionCreatorOrNull][Entries.assertionCreatorOrNull] is defined as `null` + * and likewise an additional entry for each + * [entries].[otherAssertionCreatorsOrNulls][Entries.otherAssertionCreatorsOrNulls] (if given) + * whereas the entries have to appear in the defined order. + * + * It is a shortcut for `contains o inGiven order and only the Entries(...)` + * + * Note that we might change the signature of this function with the next version + * which will cause a binary backward compatibility break (see + * [#292](https://github.com/robstoll/atrium/issues/292) for more information) + * + * @param entries The entries which are expected to be contained within the [Iterable] + * -- use the function `entries(t, ...)` to create an [Entries]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.containsExactly(entries: Entries): Expect = + it contains o inGiven order and only the entries + +/** + * Expects that the subject of the assertion (an [Iterable]) does not contain the [expected] value. + * + * It is a shortcut for `containsNot o value expected` + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.containsNot(expected: E): Expect = + it containsNot o value expected + +/** + * Expects that the subject of the assertion (an [Iterable]) does not contain the expected [values]. + * + * It is a shortcut for `containsNot o the values(...)` + * + * @param values The values which should not be contained within the [Iterable] + * -- use the function `values(t, ...)` to create a [Values]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.containsNot(values: Values): Expect = + it containsNot o the values + + +/** + * Expects that the subject of the assertion (an [Iterable]) contains an entry holding + * the assertions created by [assertionCreatorOrNull] or an entry which is `null` in case [assertionCreatorOrNull] + * is defined as `null`. + * + * It is a shortcut for `contains o inAny order atLeast 1 entry assertionCreatorOrNull` + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.any(assertionCreatorOrNull: (Expect.() -> Unit)?): Expect = + it contains o inAny order atLeast 1 entry assertionCreatorOrNull + + +/** + * Expects that the subject of the assertion (an [Iterable]) does not contain a single entry + * which holds all assertions created by [assertionCreatorOrNull] or does not contain a single entry which is `null` + * in case [assertionCreatorOrNull] is defined as `null`. + * + * It is a shortcut for `containsNot o entry assertionCreatorOrNull` + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.none(assertionCreatorOrNull: (Expect.() -> Unit)?) = + it containsNot o entry assertionCreatorOrNull /** * Expects that the subject of the assertion (an [Iterable]) has at least one element and * that every element holds all assertions created by the [assertionCreatorOrNull] or that all elements are `null` * in case [assertionCreatorOrNull] is defined as `null`. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ infix fun > Expect.all(assertionCreatorOrNull: (Expect.() -> Unit)?) = addAssertion(ExpectImpl.iterable.all(this, assertionCreatorOrNull)) + +/** + * Expects that the subject of the assertion (an [Iterable]) has at least one element. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun > Expect.has(@Suppress("UNUSED_PARAMETER") next: next) = + addAssertion(ExpectImpl.iterable.hasNext(this)) + +/** + * Expects that the subject of the assertion (an [Iterable]) does not have next element. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun > Expect.hasNot(@Suppress("UNUSED_PARAMETER") next: next) = + addAssertion(ExpectImpl.iterable.hasNotNext(this)) diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableContainsCheckers.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableContainsCheckers.kt new file mode 100644 index 000000000..eb3f8c9a2 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableContainsCheckers.kt @@ -0,0 +1,90 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.* +import ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.impl.* +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains +import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour + +/** + * Restricts a `contains` assertion by specifying that the number of occurrences of the entry which we are looking + * for occurs `at least` number of [times] within the [Iterable]. + * + * @param times The number which the check will compare against the actual number of times an expected entry is + * found in the [Iterable]. + * + * @return The newly created builder. + * @throws IllegalArgumentException In case [times] is smaller than zero. + * @throws IllegalArgumentException In case [times] equals to zero; use [containsNot] instead. + */ +infix fun , S : InAnyOrderSearchBehaviour> IterableContains.Builder.atLeast( + times: Int +): AtLeastCheckerOption = AtLeastCheckerOptionImpl(times, this) + +/** + * Restricts a `contains at least` assertion by specifying that the number of occurrences of the entry which we + * are looking for occurs `at most` number of [times] within the [Iterable]. + * + * The resulting restriction will be a `contains at least but at most` assertion. + * + * @param times The number which the check will compare against the actual number of times an expected entry is + * found in the [Iterable]. + * + * @return The newly created builder. + * @throws IllegalArgumentException In case [times] is smaller than zero. + * @throws IllegalArgumentException In case [times] equals to zero; use [containsNot] instead. + * @throws IllegalArgumentException In case [times] of this `at most` restriction equals to the number of the + * `at least` restriction; use the [exactly] restriction instead. + */ +infix fun , S : InAnyOrderSearchBehaviour> AtLeastCheckerOption.butAtMost( + times: Int +): ButAtMostCheckerOption = ButAtMostCheckerOptionImpl(times, this, containsBuilder) + +/** + * Restricts a `contains` assertion by specifying that the number of occurrences of the entry which we + * are looking for occurs `exactly` number of [times] within the [Iterable]. + * + * @param times The number which the check will compare against the actual number of times an expected entry is + * found in the [Iterable]. + * + * @return The newly created builder. + * @throws IllegalArgumentException In case [times] is smaller than zero. + * @throws IllegalArgumentException In case [times] equals to zero; use [containsNot] instead. + */ +infix fun , S : InAnyOrderSearchBehaviour> IterableContains.Builder.exactly( + times: Int +): ExactlyCheckerOption = ExactlyCheckerOptionImpl(times, this) + +/** + * Restricts a `contains` assertion by specifying that the number of occurrences of the entry which we + * are looking for occurs `at least` once but `at most` number of [times] within the [Iterable]. + * + * If you want to use a higher lower bound than one, then use `atLeast(2).butAtMost(3)` instead of `atMost(3)`. + * And in case you want to state that it is either not contained at all or at most a certain number of times, + * then use `notOrAstMost(2)` instead. + * + * @param times The number which the check will compare against the actual number of times an expected entry is + * found in the [Iterable]. + * + * @return The newly created builder. + * @throws IllegalArgumentException In case [times] is smaller than zero. + * @throws IllegalArgumentException In case [times] equals to zero; use [containsNot] instead. + * @throws IllegalArgumentException In case [times] equals to one; use [exactly] instead. + */ +infix fun , S : InAnyOrderSearchBehaviour> IterableContains.Builder.atMost( + times: Int +): AtMostCheckerOption = AtMostCheckerOptionImpl(times, this) + +/** + * Restricts a `contains` assertion by specifying that the number of occurrences of the entry which we + * are looking for occurs `not at all or at most` number of [times] within the [Iterable]. + * + * @param times The number which the check will compare against the actual number of times an expected entry is + * found in the [Iterable]. + * + * @return The newly created builder. + * @throws IllegalArgumentException In case [times] is smaller than zero. + * @throws IllegalArgumentException In case [times] equals to zero; use [containsNot] instead. + */ +infix fun , S : InAnyOrderSearchBehaviour> IterableContains.Builder.notOrAtMost( + times: Int +): NotOrAtMostCheckerOption = NotOrAtMostCheckerOptionImpl(times, this) diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableContainsInAnyOrderCreators.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableContainsInAnyOrderCreators.kt new file mode 100644 index 000000000..4e632370b --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableContainsInAnyOrderCreators.kt @@ -0,0 +1,105 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.infix.en_GB.creating.Values +import ch.tutteli.atrium.api.infix.en_GB.creating.Entries +import ch.tutteli.atrium.creating.AssertionPlant +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.domain.builders.creating.basic.contains.addAssertion +import ch.tutteli.atrium.domain.builders.utils.toVarArg +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains.CheckerOption +import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InAnyOrderSearchBehaviour + +/** + * Finishes the specification of the sophisticated `contains` assertion where the [expected] + * value shall be searched within the [Iterable]. + * + * Delegates to `the values(expected)`. + * + * @param expected The value which is expected to be contained within this [Iterable]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > CheckerOption.value(expected: E): Expect = + this the values(expected) + +/** + * Finishes the specification of the sophisticated `contains` assertion where the expected [values] + * shall be searched within the [Iterable]. + * + * Notice, that it does not search for unique matches. Meaning, if the iterable is `setOf('a', 'b')` and + * [Values] is defined as `values("a", "a")`, then both match, + * even though they match the same sequence in the input of the search. + * Use an option such as [atLeast], [atMost] and [exactly] to control the number of occurrences you expect. + * + * Meaning you might want to use: + * `to contain inAny order exactly 2 value 'a'` + * instead of: + * `to contain inAny order exactly 1 the values('a', 'a')` + * + * @param values The values which are expected to be contained within the [Iterable] + * -- use the function `values(t, ...)` to create a [Values]. + * + * @return The [AssertionPlant] for which the assertion was built to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > CheckerOption.the(values: Values): Expect = + addAssertion(ExpectImpl.iterable.contains.valuesInAnyOrder(this, values.toList())) + +/** + * Finishes the specification of the sophisticated `contains` assertion where an entry shall be searched which either + * holds all assertions [assertionCreatorOrNull] creates or needs to be `null` in case [assertionCreatorOrNull] + * is defined as `null`. + * + * Delegates to `the entries(assertionCreatorOrNull)` + * + * @param assertionCreatorOrNull The identification lambda which creates the assertions which the entry we are looking + * for has to hold; or in other words, the function which defines whether an entry is the one we are looking for + * or not. In case it is defined as `null`, then an entry is identified if it is `null` as well. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > CheckerOption.entry( + assertionCreatorOrNull: (Expect.() -> Unit)? +): Expect = this the entries(assertionCreatorOrNull) + +/** + * Finishes the specification of the sophisticated `contains` assertion where an entry shall be searched which either + * holds all assertions [entries].[assertionCreatorOrNull][Entries.assertionCreatorOrNull] might create or + * needs to be `null` in case [entries].[assertionCreatorOrNull][Entries.otherAssertionCreatorsOrNulls] + * is defined as `null` -- likewise an entry (can be the same) is searched for each of + * the [entries].[otherAssertionCreatorsOrNulls][Entries.otherAssertionCreatorsOrNulls]. + * + * @param entries The entries which are expected to be contained within the [Iterable] + * -- use the function `entries(t, ...)` to create an [Entries]. + * + * @return The [AssertionPlant] for which the assertion was built to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > CheckerOption.the( + entries: Entries +): Expect = addAssertion(ExpectImpl.iterable.contains.entriesInAnyOrder(this, entries.toList())) + +/** + * Finishes the specification of the sophisticated `contains` assertion where all elements of the [expectedIterable] + * shall be searched within the [Iterable]. + * + * Delegates to [values] which also means that it does not search for unique matches + * (see [values] for more information). + * + * @param expectedIterable The [Iterable] whose elements are expected to be contained within this [Iterable]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * @throws IllegalArgumentException in case the given [expectedIterable] does not have elements (is empty). + * + * @since 0.11.0 + */ +inline infix fun > CheckerOption.elementsOf( + expectedIterable: Iterable +): Expect { + val (first, rest) = toVarArg(expectedIterable) + return this the values(first, *rest) +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableContainsInAnyOrderOnlyCreators.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableContainsInAnyOrderOnlyCreators.kt new file mode 100644 index 000000000..f5a116b49 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableContainsInAnyOrderOnlyCreators.kt @@ -0,0 +1,124 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.infix.en_GB.creating.Values +import ch.tutteli.atrium.api.infix.en_GB.creating.Entries +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.domain.builders.creating.basic.contains.addAssertion +import ch.tutteli.atrium.domain.builders.utils.toVarArg +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains.Builder +import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InAnyOrderOnlySearchBehaviour + +/** + * Finishes the specification of the sophisticated `contains` assertion where the [Iterable] needs to contain only the + * [expected] value. + * + * Delegates to `the values(expected)`. + * + * Note that we might change the signature of this function with the next version + * which will cause a binary backward compatibility break (see + * [#292](https://github.com/robstoll/atrium/issues/292) for more information) + * + * @param expected The value which is expected to be contained within the [Iterable]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Builder.value(expected: E): Expect = + this the values(expected) + +/** + * Finishes the specification of the sophisticated `contains` assertion where the expected [values] + * must be contained in [Iterable] but it does not matter in which order. + * + * Note that we might change the signature of this function with the next version + * which will cause a binary backward compatibility break (see + * [#292](https://github.com/robstoll/atrium/issues/292) for more information) + * + * @param values The values which are expected to be contained within the [Iterable] + * -- use the function `values(t, ...)` to create a [Values]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Builder.the(values: Values): Expect = + addAssertion(ExpectImpl.iterable.contains.valuesInAnyOrderOnly(this, values.toList())) + +/** + * Finishes the specification of the sophisticated `contains` assertion where the [Iterable] needs to contain only one + * entry which holds all assertions created by the given [assertionCreatorOrNull] or is `null` in case + * [assertionCreatorOrNull] is defined as `null`. + * + * Delegates to `the entries(assertionCreatorOrNull)` + * + * Note that we might change the signature of this function with the next version + * which will cause a binary backward compatibility break (see + * [#292](https://github.com/robstoll/atrium/issues/292) for more information) + * + * @param assertionCreatorOrNull The identification lambda which creates the assertions which the entry we are looking + * for has to hold; or in other words, the function which defines whether an entry is the one we are looking for + * or not. In case it is defined as `null`, then an entry is identified if it is `null` as well. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Builder.entry( + assertionCreatorOrNull: (Expect.() -> Unit)? +): Expect = this the entries(assertionCreatorOrNull) + +/** + * Finishes the specification of the sophisticated `contains` assertion where an entry needs to be contained in the + * [Iterable] which holds all assertions [entries].[assertionCreatorOrNull][Entries.assertionCreatorOrNull] + * might create or it needs to be `null` in case + * [entries].[assertionCreatorOrNull][Entries.assertionCreatorOrNull] is defined as `null` -- likewise an + * entry for each [entries].[otherAssertionCreatorsOrNulls][Entries.otherAssertionCreatorsOrNulls] needs to + * be contained in the [Iterable] where it does not matter in which order the entries appear but only as many entries + * should be returned by the [Iterable] as assertion creators are defined. + * + * Notice, that a first-wins strategy applies which means your assertion creator lambdas -- which kind of serve as + * identification lambdas -- should be ordered in such a way that the most specific identification lambda appears + * first, not that a less specific lambda wins. For instance, given a `setOf(1, 2)` you should not search for + * `entries({ isGreaterThan(0) }, { toBe(1) })` but for `entries({ toBe(1) }, { isGreaterThan(0) })` + * otherwise `isGreaterThan(0)` matches `1` before `toBe(1)` would match it. As a consequence `toBe(1)` could + * only match the entry which is left -- in this case `2` -- and of course this would fail. + * + * Note that we might change the signature of this function with the next version + * which will cause a binary backward compatibility break (see + * [#292](https://github.com/robstoll/atrium/issues/292) for more information) + * + * @param entries The entries which are expected to be contained within the [Iterable] + * -- use the function `entries(t, ...)` to create an [Entries]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ + +infix fun > Builder.the( + entries: Entries +): Expect = addAssertion(ExpectImpl.iterable.contains.entriesInAnyOrderOnly(this, entries.toList())) + +/** + * Finishes the specification of the sophisticated `contains` assertion where all elements in + * [expectedIterable] need to be contained in [Iterable] where it does not matter in which order but only as + * many entries should be returned by the [Iterable] as values defined. + * + * Delegates to [values]. + * + * Note that we might change the signature of this function with the next version + * which will cause a binary backward compatibility break (see + * [#292](https://github.com/robstoll/atrium/issues/292) for more information) + * + * @param expectedIterable The [Iterable] whose elements are expected to be contained within this [Iterable] + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * @throws IllegalArgumentException in case the given [expectedIterable] does not have elements (is empty). + * + * @since 0.11.0 + */ +inline infix fun > Builder.elementsOf( + expectedIterable: Iterable +): Expect { + val (first, rest) = toVarArg(expectedIterable) + return this the values(first, *rest) +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableContainsInOrderOnlyCreators.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableContainsInOrderOnlyCreators.kt new file mode 100644 index 000000000..921105e6e --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableContainsInOrderOnlyCreators.kt @@ -0,0 +1,116 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.infix.en_GB.creating.Values +import ch.tutteli.atrium.api.infix.en_GB.creating.Entries +import ch.tutteli.atrium.creating.AssertionPlant +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.domain.builders.creating.basic.contains.addAssertion +import ch.tutteli.atrium.domain.builders.utils.toVarArg +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains.Builder +import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InOrderOnlySearchBehaviour + +/** + * Finishes the specification of the sophisticated `contains` assertion where the [Iterable] needs to contain only the + * [expected] value. + * + * Delegates to `the values(expected)`. + * + * Note that we might change the signature of this function with the next version + * which will cause a binary backward compatibility break (see + * [#292](https://github.com/robstoll/atrium/issues/292) for more information) + * + * @param expected The value which is expected to be contained within the [Iterable]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Builder.value(expected: E): Expect = + this the values(expected) + +/** + * Finishes the specification of the sophisticated `contains` assertion where the [Iterable] needs to contain only the + * expected [values] in the specified order. + * + * Note that we might change the signature of this function with the next version + * which will cause a binary backward compatibility break (see + * [#292](https://github.com/robstoll/atrium/issues/292) for more information) + * + * @param values The values which are expected to be contained within the [Iterable] + * -- use the function `values(t, ...)` to create a [Values]. + * + * @return The [AssertionPlant] for which the assertion was built to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Builder.the(values: Values): Expect = + addAssertion(ExpectImpl.iterable.contains.valuesInOrderOnly(this, values.toList())) + +/** + * Finishes the specification of the sophisticated `contains` assertion where the [Iterable] needs to contain only a + * single entry which holds all assertions created by the given [assertionCreatorOrNull] or needs to be `null` + * in case [assertionCreatorOrNull] is defined as `null`. + * + * Delegates to `the entries(assertionCreatorOrNull)`. + * + * Note that we might change the signature of this function with the next version + * which will cause a binary backward compatibility break (see + * [#292](https://github.com/robstoll/atrium/issues/292) for more information) + * + * @param assertionCreatorOrNull The identification lambda which creates the assertions which the entry we are looking + * for has to hold; or in other words, the function which defines whether an entry is the one we are looking for + * or not. In case it is defined as `null`, then an entry is identified if it is `null` as well. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Builder.entry( + assertionCreatorOrNull: (Expect.() -> Unit)? +): Expect = this the entries(assertionCreatorOrNull) + +/** + * Finishes the specification of the sophisticated `contains` assertion where the [Iterable] needs to contain only an + * entry which holds all assertions [entries].[assertionCreatorOrNull][Entries.assertionCreatorOrNull] + * might create or is `null` in case [entries].[assertionCreatorOrNull][Entries.otherAssertionCreatorsOrNulls] + * is defined as `null` and likewise a further entry for each + * [entries].[otherAssertionCreatorsOrNulls][Entries.otherAssertionCreatorsOrNulls] + * (if given) whereas the entries have to appear in the specified order. + * + * Note that we might change the signature of this function with the next version + * which will cause a binary backward compatibility break (see + * [#292](https://github.com/robstoll/atrium/issues/292) for more information) + * + * @param entries The entries which are expected to be contained within the [Iterable] + * -- use the function `entries(t, ...)` to create an [Entries]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Builder.the( + entries: Entries +): Expect = addAssertion(ExpectImpl.iterable.contains.entriesInOrderOnly(this, entries.toList())) + +/** + * Finishes the specification of the sophisticated `contains` assertion where all elements of the [expectedIterable] + * shall be searched within the [Iterable] + * (if given) in the specified order. + * + * Delegates to [values]. + * + * Note that we might change the signature of this function with the next version + * which will cause a binary backward compatibility break (see + * [#292](https://github.com/robstoll/atrium/issues/292) for more information) + * + * @param expectedIterable The [Iterable] whose elements are expected to be contained within this [Iterable]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * @throws IllegalArgumentException in case the given [expectedIterable] does not have elements (is empty). + * + * @since 0.11.0 + */ +inline infix fun > Builder.elementsOf( + expectedIterable: Iterable +): Expect { + val (first, rest) = toVarArg(expectedIterable) + return this the values(first, *rest) +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableContainsInOrderOnlyGroupedCreators.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableContainsInOrderOnlyGroupedCreators.kt new file mode 100644 index 000000000..eda28cbf7 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableContainsInOrderOnlyGroupedCreators.kt @@ -0,0 +1,72 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.infix.en_GB.creating.iterable.Order +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.domain.builders.creating.basic.contains.addAssertion +import ch.tutteli.atrium.domain.builders.utils.Group +import ch.tutteli.atrium.domain.builders.utils.groupsToList +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains.Builder +import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.InOrderOnlyGroupedWithinSearchBehaviour +import kotlin.jvm.JvmName + +/** + * Finishes the specification of the sophisticated `contains` assertion where the expected [Order.firstGroup] as well as + * the [Order.secondGroup] and optionally [Order.otherExpectedGroups] of values need to be + * contained in [Iterable] in the specified order whereas the values within the groups can occur in any order. + * + * @param order A parameter object containing the different groups which have to appear in order in the [Iterable] + * -- use `order(group, group, ...)` to create an [Order] where group is either `value(e)` or `values(e, ...)`; + * so a call could look as follows: `inAny order(values(1, 2), value(2), values(3, 2)) + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Builder.inAny( + order: Order> +): Expect = addAssertion( + ExpectImpl.iterable.contains.valuesInOrderOnlyGrouped( + this, + groupsToList(order.firstGroup, order.secondGroup, order.otherExpectedGroups) + ) +) + +/** + * Helper function to create an [Order] based on the given [firstGroup], [secondGroup] and [otherExpectedGroups]. + */ +fun order( + firstGroup: Group, + secondGroup: Group, + vararg otherExpectedGroups: Group +): Order> = Order(firstGroup, secondGroup, otherExpectedGroups) + +/** + * Finishes the specification of the sophisticated `contains` assertion where the expected [Order.firstGroup] as well as + * the [Order.secondGroup] and optionally [Order.otherExpectedGroups] of identification lambdas, identifying an entry, + * need to be contained in [Iterable] in the specified order whereas the identification lambdas within the groups + * can occur in any order. + * + * An identification lambda can also be defined as `null` in which case it matches an entry which is `null` as well. + * + * @param order A parameter object containing the different groups which have to appear in order in the [Iterable] + * -- use `order(group, group, ...)` to create an [Order] where group is either `entry { ... }` or + * `entries({ ... }, ...)`; so a call could look as follows: + * ``` + * inAny order( + * entry { it toBe 1 }, + * entries({ it lessThan 2 }, {it toBe 3 }) + * ) + * ``` + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +@JvmName("inAnyOrderEntries") +infix fun > Builder.inAny( + order: Order<(Expect.() -> Unit)?, Group<(Expect.() -> Unit)?>> +): Expect = addAssertion( + ExpectImpl.iterable.contains.entriesInOrderOnlyGrouped( + this, + groupsToList(order.firstGroup, order.secondGroup, order.otherExpectedGroups) + ) +) diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableContainsSearchBehaviours.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableContainsSearchBehaviours.kt new file mode 100644 index 000000000..2be9da282 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/iterableContainsSearchBehaviours.kt @@ -0,0 +1,60 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains.Builder +import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.* + +/** + * Defines that the search behaviour "find entries `in any order` in the [Iterable]" shall be applied to this + * sophisticated `contains` in [Iterable] assertion. + * + * @return The newly created builder. + */ +infix fun > Builder.inAny(@Suppress("UNUSED_PARAMETER") order: order) = + ExpectImpl.iterable.contains.searchBehaviours.inAnyOrder(this) + +/** + * Defines that the constraint "`only` the specified entries exist in the [Iterable]" shall be applied to this + * sophisticated `contains` [Iterable] assertion. + * + * @return The newly created builder. + */ +infix fun > Builder.but(@Suppress("UNUSED_PARAMETER") only: only) = + ExpectImpl.iterable.contains.searchBehaviours.inAnyOrderOnly(this) + + +/** + * Defines that the search behaviour "find entries `in order` in the [Iterable]" shall be applied to this + * sophisticated `contains` in [Iterable] assertion. + * + * @return The newly created builder. + */ +infix fun > Builder.inGiven(@Suppress("UNUSED_PARAMETER") order: order) = + ExpectImpl.iterable.contains.searchBehaviours.inOrder(this) + +/** + * Defines that the constraint "`only` the specified entries exist in the [Iterable]" shall be applied to this + * sophisticated `contains in order` [Iterable] assertion. + * + * @return The newly created builder. + */ +infix fun > Builder.and(@Suppress("UNUSED_PARAMETER") only: only) = + ExpectImpl.iterable.contains.searchBehaviours.inOrderOnly(this) + +/** + * Defines that the [Iterable] contains `in order only` groups of entries + * whereas the order within the group is specified as next step. + * + * @return The newly created builder. + */ +infix fun > Builder.grouped(@Suppress("UNUSED_PARAMETER") entries: entries) = + ExpectImpl.iterable.contains.searchBehaviours.inOrderOnlyGrouped(this) + +/** + * A filler word to emphasis that the next step defines the order within expected groups of values. + * + * @return The newly created builder. + */ +infix fun > Builder.within(@Suppress("UNUSED_PARAMETER") group: group) = + ExpectImpl.iterable.contains.searchBehaviours.inOrderOnlyGroupedWithin(this) + diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/keywords.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/keywords.kt index 33f1e47a6..f4e0726b0 100644 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/keywords.kt +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/keywords.kt @@ -1,4 +1,5 @@ @file:Suppress("ClassName") + package ch.tutteli.atrium.api.infix.en_GB /** @@ -8,47 +9,113 @@ package ch.tutteli.atrium.api.infix.en_GB * (see toBe). */ interface Keyword -internal const val ERR_KEYWORD_GIVEN_COLLECTION_ASSUMED = "This call will most probably fail at runtime because the given subject is not a collection as you might have assumed. If you really want to compare the subject against the keyword, then cast the keyword to Any" + +//TODO not used yet, should be used though +internal const val ERR_KEYWORD_GIVEN_COLLECTION_ASSUMED = + "This call will most probably fail at runtime because the given subject is not a collection as you might have assumed. If you really want to compare the subject against the keyword, then cast the keyword to Any" /** - * Represents a helper construct which allows to express emptiness. - * It can be used for a parameter less function so that it has one parameter and thus can be used as infix function. + * A helper construct to allow expressing assertions about a path being a regular file. + * It can be used for a parameterless function so that it has one parameter and thus can be used as infix function. */ -object Empty: Keyword +object aRegularFile : Keyword + +/** + * A helper construct to allow expressing assertions about a path being a directory. + * It can be used for a parameterless function so that it has one parameter and thus can be used as infix function. + */ +object aDirectory : Keyword /** * Represents a helper construct which allows to express blankness. - * It can be used for a parameter less function so that it has one parameter and thus can be used as infix function. + * It can be used for a parameterless function so that it has one parameter and thus can be used as infix function. */ -object Blank: Keyword - -/** - * Represents the pseudo keyword `contain` as in [to] `contain`. - */ -object contain: Keyword +object blank : Keyword /** * Represents the pseudo keyword `case` as in [ignoring] `case`. + * It can be used for a parameterless function so that it has one parameter and thus can be used as infix function. */ -object case: Keyword +object case : Keyword + +/** + * Represents a helper construct which allows to express emptiness. + * It can be used for a parameterless function so that it has one parameter and thus can be used as infix function. + */ +object empty : Keyword /** * Represents the pseudo keyword `entries` as in [grouped] `entries`. + * It can be used for a parameterless function so that it has one parameter and thus can be used as infix function. */ -object entries: Keyword +object entries : Keyword + +/** + * A helper construct to allow expressing assertions about path existence. + * It can be used for a parameterless function so that it has one parameter and thus can be used as infix function. + */ +object exist : Keyword /** * Represents the pseudo keyword `group` as in [within] `group`. + * It can be used for a parameterless function so that it has one parameter and thus can be used as infix function. */ -object group: Keyword +object group : Keyword + +/** + * Represents the pseudo keyword `next` as in [has] `next`. + * It can be used for a parameterless function so that it has one parameter and thus can be used as infix function. + * + * @since 0.11.0 + */ +object next : Keyword + +/** + * Represents a filler, a pseudo keyword where there isn't really a good keyword. + * A reader should skip this filler without reading it. For instance, `contains o atLeast 1...` should be read as + * `contains at least once...` + * + * It can be used for a parameterless function so that it has one parameter and thus can be used as infix function. + * + * @since 0.11.0 + */ +object o : Keyword /** * Represents the pseudo keyword `only` as in [and] `only`. + * It can be used for a parameterless function so that it has one parameter and thus can be used as infix function. */ -object only: Keyword +object only : Keyword /** * Represents the pseudo keyword `order` as in [inAny] `order`. + * It can be used for a parameterless function so that it has one parameter and thus can be used as infix function. */ -object order: Keyword +object order : Keyword +/** + * Represents a helper construct which allows to express presence. + * It can be used for a parameterless function so that it has one parameter and thus can be used as infix function. + */ +object present : Keyword + + +/** + * A helper construct to allow expressing assertions about a path being readable. + * It can be used for a parameterless function so that it has one parameter and thus can be used as infix function. + */ +object readable : Keyword + +/** + * Represents the pseudo keyword `success` as in [toBe] `success. + * It can be used for a parameterless function so that it has one parameter and thus can be used as infix function. + * + * @since 0.11.0 + */ +object success : Keyword + +/** + * A helper construct to allow expressing assertions about a path being writable. + * It can be used for a parameterless function so that it has one parameter and thus can be used as infix function. + */ +object writable : Keyword diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/listAssertions.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/listAssertions.kt index 01344b2d9..dec25d4fd 100644 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/listAssertions.kt +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/listAssertions.kt @@ -1,6 +1,6 @@ package ch.tutteli.atrium.api.infix.en_GB -import ch.tutteli.atrium.api.infix.en_GB.creating.list.get.builders.ListGetStep +import ch.tutteli.atrium.api.infix.en_GB.creating.IndexWithCreator import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.domain.builders.ExpectImpl @@ -9,15 +9,27 @@ import ch.tutteli.atrium.domain.builders.ExpectImpl * returns an [Expect] for the element at that position. * * @return The newly created [Expect] for the element at position [index]. - * @throws AssertionError if the given [index] is out of bound. + * @throws AssertionError Might throw an [AssertionError] if the given [index] is out of bound. */ infix fun > Expect.get(index: Int): Expect = ExpectImpl.list.get(this, index).getExpectOfFeature() /** - * Prepares the assertion about the return value of calling [get][List.get] with the given [index]. + * Expects that the given [index][IndexWithCreator.index] is within the bounds of the subject of the assertion + * (a [List]) and that the element at that position holds all assertions the given + * [IndexWithCreator.assertionCreator] creates for it. * - * @return A fluent builder to finish the assertion. + * Use the function `index(Int) { ... }` to create an [IndexWithCreator]. + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the given [index] is out of bound or + * if the assertion made is not correct. */ -infix fun > Expect.get(index: Index): ListGetStep = - ListGetStep.create(this, index.index) +infix fun > Expect.get(index: IndexWithCreator): Expect = + ExpectImpl.list.get(this, index.index).addToInitial(index.assertionCreator) + +/** + * Helper function to create an [IndexWithCreator] based on the given [index] and [assertionCreator]. + */ +fun index(index: Int, assertionCreator: Expect.() -> Unit) = + IndexWithCreator(index, assertionCreator) diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/mapAssertions.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/mapAssertions.kt new file mode 100644 index 000000000..eb4b08eb7 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/mapAssertions.kt @@ -0,0 +1,214 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.infix.en_GB.creating.All +import ch.tutteli.atrium.api.infix.en_GB.creating.Pairs +import ch.tutteli.atrium.api.infix.en_GB.creating.map.KeyWithValueCreator +import ch.tutteli.atrium.api.infix.en_GB.creating.KeyWithCreator +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl + +/** + * Expects that the subject of the assertion (a [Map]) contains a key as defined by [keyValuePair]'s [Pair.first] + * with a corresponding value as defined by [keyValuePair]'s [Pair.second] + * + * Delegates to 'contains Pairs(keyValuePair)'. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.contains(keyValuePair: Pair) = + it contains pairs(keyValuePair) + +/** + * Expects the subject of the assertion (a [Map]) contains for each entry in [keyValuePairs], + * a key as defined by that entry's [Pair.first] with a corresponding value as defined by entry's [Pair.second]. + * + * Notice, that it does not search for unique matches. Meaning, if the map is `mapOf('a' to 1)` and one of the [Pair] + * in [keyValuePairs] is defined as `'a' to 1` and another one is defined as `'a' to 1` as well, then both match, + * even though they match the same entry. + * + * @param keyValuePairs The key-value [Pairs] expected to be contained within this [Map] + * -- use the function `pairs(x to y, ...)` to create a [Pairs]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.contains(keyValuePairs: Pairs): Expect = + addAssertion(ExpectImpl.map.contains(this, keyValuePairs.toList())) + +/** + * Expects that the subject of the assertion (a [Map]) contains a key as defined by [keyValue]'s [KeyWithValueCreator.key] + * with a corresponding value which either holds all assertions [keyValue]'s + * [KeyWithValueCreator.valueAssertionCreatorOrNull] creates or needs to be `null` in case + * [KeyWithValueCreator.valueAssertionCreatorOrNull] is defined as `null` + * + * @param keyValue The [KeyWithValueCreator] whose key is expected to be contained within this [Map] and + * where the corresponding value holds all assertions the [KeyWithValueCreator.valueAssertionCreatorOrNull] creates + * or needs to be `null` in case [KeyWithValueCreator.valueAssertionCreatorOrNull] is defined as `null` + * -- use the function `keyValue(x) { ... }` to create a [KeyWithValueCreator]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +inline infix fun > Expect.contains(keyValue: KeyWithValueCreator): Expect = + it contains all(keyValue) + +/** + * Helper function to create a [KeyWithValueCreator] based on the given [key] and [valueAssertionCreatorOrNull] + * -- allows to express `Pair, vararg Pair`. + */ +fun keyValue(key: K, valueAssertionCreatorOrNull: (Expect.() -> Unit)?): KeyWithValueCreator = + KeyWithValueCreator(key, valueAssertionCreatorOrNull) + +/** + * Expects that the subject of the assertion (a [Map]) contains for each [KeyWithValueCreator] in [keyValues], + * a key as defined by [KeyWithValueCreator.key] with a corresponding value which either holds all + * assertions [KeyWithValueCreator]'s [KeyWithValueCreator.valueAssertionCreatorOrNull] creates or needs to be `null` in case + * [KeyWithValueCreator.valueAssertionCreatorOrNull] is defined as `null` + * + * Notice, that it does not search for unique matches. Meaning, if the map is `mapOf('a' to 1)` and one [KeyWithValueCreator] in + * [keyValues] is defined as `Key('a') { isGreaterThan(0) }` and another one is defined as `Key('a') { isLessThan(2) }` + * , then both match, even though they match the same entry. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +inline infix fun > Expect.contains(keyValues: All>) = + addAssertion(ExpectImpl.map.containsKeyWithValueAssertions(this, V::class, keyValues.toList().map { it.toPair() })) + +/** + * Expects that the subject of the assertion (a [Map]) contains the given [key]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.containsKey(key: K) = addAssertion(ExpectImpl.map.containsKey(this, key)) + +/** + * Expects that the subject of the assertion (a [Map]) does not contain the given [key]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.containsNotKey(key: K) = + addAssertion(ExpectImpl.map.containsNotKey(this, key)) + +/** + * Expects that the subject of the assertion (a [Map]) contains the given [key], + * creates an [Expect] for the corresponding value and returns the newly created assertion container, + * so that further fluent calls are assertions about it. + * + * @return The newly created [Expect] for the extracted feature. + * @throws AssertionError Might throw an [AssertionError] if the given [key] does not exist. + */ +infix fun > Expect.getExisting(key: K): Expect = + ExpectImpl.map.getExisting(this, key).getExpectOfFeature() + +/** + * Expects that the subject of the assertion (a [Map]) contains the given [key] and that + * the corresponding value holds all assertions the given [KeyWithCreator.assertionCreator] creates for it. + * + * @param key Use the function `key(...) { ... }` to create a [KeyWithCreator] where the first parameter corresponds + * to the key and the second is the `assertionCreator`-lambda + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] the given [key] does not exist or + * if the assertion made is not correct. + */ +infix fun > Expect.getExisting(key: KeyWithCreator): Expect = + ExpectImpl.map.getExisting(this, key.key).addToInitial(key.assertionCreator) + +/** + * Helper function to create an [KeyWithCreator] based on the given [key] and [assertionCreator]. + */ +fun key(key: K, assertionCreator: Expect.() -> Unit) = + KeyWithCreator(key, assertionCreator) + + +/** + * Creates an [Expect] for the property [Map.keys] of the subject of the assertion, + * so that further fluent calls are assertions about it. + * + * @return The newly created [Expect] for the extracted feature. + */ +val > Expect.keys: Expect> + get() = ExpectImpl.feature.property(this, Map::keys).getExpectOfFeature() + +/** + * Expects that the property [Map.keys] of the subject of the assertion + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.keys(assertionCreator: Expect>.() -> Unit): Expect = + ExpectImpl.feature.property(this, Map::keys).addToInitial(assertionCreator) + +/** + * Expects that the subject of the assertion (a [Map]) is an empty [Map]. + * + * @param empty Use the pseudo-keyword `empty`. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.toBe(@Suppress("UNUSED_PARAMETER") empty: empty) = + addAssertion(ExpectImpl.map.isEmpty(this)) + +/** + * Expects that the subject of the assertion (a [Map]) is not an empty [Map]. + * + * @param empty Use the pseudo-keyword `empty`. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.notToBe(@Suppress("UNUSED_PARAMETER") empty: empty) = + addAssertion(ExpectImpl.map.isNotEmpty(this)) + +/** + * Creates an [Expect] for the property [Map.values] of the subject of the assertion, + * so that further fluent calls are assertions about it. + * + * @return The newly created [Expect] for the extracted feature. + */ +val > Expect.values: Expect> + get() = ExpectImpl.feature.property(this, Map::values).getExpectOfFeature() + +/** + * Expects that the property [Map.keys] of the subject of the assertion + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun > Expect.values(assertionCreator: Expect>.() -> Unit): Expect = + ExpectImpl.feature.property(this, Map::values).addToInitial(assertionCreator) + +/** + * Turns `Expect>` into `Expect>>`. + * + * The transformation as such is not reflected in reporting. + * Use `feature { f(it::entries) }` if you want to show the transformation in reporting. + * + * @return The newly created [Expect] for the transformed subject. + */ +infix fun > Expect.asEntries( + @Suppress("UNUSED_PARAMETER") o: o +): Expect>> = ExpectImpl.changeSubject(this).unreported { it.entries } + +/** + * Turns `Expect>` into `Expect>>` and expects that it holds all assertions the given + * [assertionCreator] creates for it. + * + * The transformation as such is not reflected in reporting. + * Use `feature { f(it::entries) }` if you want to show the transformation in reporting. + * + * @return An [Expect] for the current subject of the assertion. + */ +infix fun > Expect.asEntries( + assertionCreator: Expect>>.() -> Unit +): Expect = apply { asEntries(o).addAssertionsCreatedBy(assertionCreator) } + diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/mapEntryAssertions.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/mapEntryAssertions.kt index 47ba49797..b4fc7adce 100644 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/mapEntryAssertions.kt +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/mapEntryAssertions.kt @@ -11,7 +11,7 @@ import ch.tutteli.atrium.domain.builders.ExpectImpl * block. Yet, the actual behaviour depends on implementation - could also be fail fast for instance or augment * reporting etc. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ infix fun > Expect.isKeyValue(keyValuePair: Pair): Expect = @@ -21,16 +21,17 @@ infix fun > Expect.isKeyValue(keyValuePair: Pair> Expect.key: Expect get() = ExpectImpl.map.entry.key(this).getExpectOfFeature() /** * Expects that the property [Map.Entry.key] of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ infix fun > Expect.key(assertionCreator: Expect.() -> Unit): Expect = @@ -40,16 +41,17 @@ infix fun > Expect.key(assertionCreator: Expect. * Creates an [Expect] for the property [Map.Entry.value] of the subject of the assertion, * so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. */ val > Expect.value: Expect get() = ExpectImpl.map.entry.value(this).getExpectOfFeature() /** * Expects that the property [Map.Entry.value] of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ infix fun > Expect.value(assertionCreator: Expect.() -> Unit): Expect = diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/pairAssertions.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/pairAssertions.kt index e9ee467b8..825476346 100644 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/pairAssertions.kt +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/pairAssertions.kt @@ -7,15 +7,17 @@ import ch.tutteli.atrium.domain.builders.ExpectImpl * Creates an [Expect] for the property [Pair.first] of the subject of the assertion, * so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. */ -val > Expect.first get() : Expect = ExpectImpl.pair.first(this).getExpectOfFeature() +val > Expect.first: Expect + get() = ExpectImpl.pair.first(this).getExpectOfFeature() /** * Expects that the property [Pair.first] of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ infix fun > Expect.first(assertionCreator: Expect.() -> Unit): Expect = @@ -25,15 +27,17 @@ infix fun > Expect.first(assertionCreator: Expect.() * Creates an [Expect] for the property [Pair.second] of the subject of the assertion, * so that further fluent calls are assertions about it. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. */ -val > Expect.second get() : Expect = ExpectImpl.pair.second(this).getExpectOfFeature() +val > Expect.second: Expect + get() = ExpectImpl.pair.second(this).getExpectOfFeature() /** * Expects that the property [Pair.second] of the subject of the assertion - * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. */ infix fun > Expect.second(assertionCreator: Expect.() -> Unit): Expect = diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/parameterObjects.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/parameterObjects.kt deleted file mode 100644 index 227adbe66..000000000 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/parameterObjects.kt +++ /dev/null @@ -1,6 +0,0 @@ -package ch.tutteli.atrium.api.infix.en_GB - -/** - * Wrapper for a single index -- can be used as distinguishable type for an overload where Int is already in use. - */ -data class Index(val index: Int) diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/sequenceAssertions.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/sequenceAssertions.kt index 3275f15b5..e0bfb2a98 100644 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/sequenceAssertions.kt +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/sequenceAssertions.kt @@ -1,4 +1,5 @@ -import ch.tutteli.atrium.creating.AssertionPlant +package ch.tutteli.atrium.api.infix.en_GB + import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.domain.builders.ExpectImpl.changeSubject @@ -6,21 +7,22 @@ import ch.tutteli.atrium.domain.builders.ExpectImpl.changeSubject * Turns `Expect>` into `Expect>`. * * The transformation as such is not reflected in reporting. - * Use `feature(Sequence::asIterable)` if you want to show the transformation in reporting. + * Use `feature { f(it::asIterable) }` if you want to show the transformation in reporting. * * @return The newly created [Expect] for the transformed subject. */ -fun > Expect.asIterable(): Expect> - = changeSubject(this).unreported { it.asIterable() } +infix fun > Expect.asIterable( + @Suppress("UNUSED_PARAMETER") o: o +): Expect> = changeSubject(this).unreported { it.asIterable() } /** * Expects that the subject of the assertion holds all assertions the given [assertionCreator] creates for * the subject as [Iterable]. * * The transformation as such is not reflected in reporting. - * Use `feature(Sequence::asIterable, assertionCreator)` if you want to show the transformation in reporting. + * Use `feature of({ f(it::asIterable) }, assertionCreator)` if you want to show the transformation in reporting. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. */ infix fun > Expect.asIterable(assertionCreator: Expect>.() -> Unit): Expect = - apply { asIterable().addAssertionsCreatedBy(assertionCreator) } + apply { asIterable(o).addAssertionsCreatedBy(assertionCreator) } diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/throwableAssertions.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/throwableAssertions.kt new file mode 100644 index 000000000..3ccba991a --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/throwableAssertions.kt @@ -0,0 +1,85 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.infix.en_GB.creating.Values +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl + +/** + * Expects that the property [Throwable.message] of the subject of the assertion is not null, + * creates an [Expect] for it and returns it. + * + * @return The newly created [Expect] for the property [Throwable.message] of the subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +val Expect.message: Expect + get() = it feature Throwable::message notToBeNull o + +/** + * Expects that the property [Throwable.message] of the subject of the assertion is not null and + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Expect.message(assertionCreator: Expect.() -> Unit): Expect = + it feature of(Throwable::message) { it notToBeNull assertionCreator } + +/** + * Expects that the property [Throwable.message] of the subject of the assertion is not null and contains + * [expected]'s [toString] representation using a non disjoint search. + ** + * Notice that a runtime check applies which assures that only [CharSequence], [Number] and [Char] are passed + * (this function expects `Any` for your convenience, so that you can mix [String] and [Int] for instance). + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Expect.messageContains(expected: Any): Expect = + this messageContains values(expected) + +/** + * Expects that the property [Throwable.message] of the subject of the assertion is not null and contains + * [values]'s [toString] representation using a non disjoint search. + ** + * Notice that a runtime check applies which assures that only [CharSequence], [Number] and [Char] are passed + * (this function expects `Any` for your convenience, so that you can mix [String] and [Int] for instance). + * + * @param values The values which are expected to be contained within [Throwable.message] + * -- use the function `values(t, ...)` to create a [Values]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + */ +infix fun Expect.messageContains(values: Values): Expect = + message { contains(values) } + +/** + * Expects that the property [Throwable.cause] of the subject *is a* [TExpected] (the same type or a sub-type), + * creates an [Expect] of the [TExpected] type for it and returns it. + * + * @return The newly created [Expect] for the property [Throwable.cause] of the subject of the assertion + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +inline fun Expect.cause(): Expect = + ExpectImpl.throwable.cause(this, TExpected::class).getExpectOfFeature() + +/** + * + * Expects that the property [Throwable.cause] of the subject *is a* [TExpected] (the same type or a sub-type) and + * holds all assertions the given [assertionCreator] creates for it and returns this assertion container. + * + * Notice, in contrast to other assertion functions which expect an [assertionCreator], this function returns not + * [Expect] of the initial type, which was some type `T `, but an [Expect] of the specified type [TExpected]. + * + * @return This assertion container to support a fluent API. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +inline infix fun Expect.cause( + noinline assertionCreator: Expect.() -> Unit +): Expect = + ExpectImpl.throwable.cause(this, TExpected::class).addToFeature(assertionCreator) diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/workaround/anyAssertions.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/workaround/anyAssertions.kt new file mode 100644 index 000000000..2c0b63365 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/workaround/anyAssertions.kt @@ -0,0 +1,25 @@ +package ch.tutteli.atrium.api.infix.en_GB.workaround + +import ch.tutteli.atrium.api.infix.en_GB.and +import ch.tutteli.atrium.creating.Expect + +/** + * Can be used to create a group of sub assertions when using the fluent API. + * + * Intended to be used in combination with feature assertions where Kotlin < 1.4 is not able to infer the correct type. + * For instance: + * ``` + * // use + * expect(person) feature { f(it::age) } it { o toBe 20 } + * + * // instead of (which causes problems with Kotlin < 1.4) + * expect(person) feature of({ f(it::age) }) { o toBe 20 } + * ``` + * + * Note that this workaround will be removed in some minor version after a major version with Kotlin 1.4 support + * (most likely with Atrium v1.1.0 where Atrium v1.0.0 requires Kotlin 1.4) + * + * @return An [Expect] for the current subject of the assertion. + */ +@Suppress("NOTHING_TO_INLINE" /* inline so that one does not actually call `it` on binary level */) +inline infix fun Expect.it(noinline assertionCreator: Expect.() -> Unit): Expect = and(assertionCreator) diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/AnyAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/AnyAssertionsSpec.kt index 899e3abc2..dd9b69d48 100644 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/AnyAssertionsSpec.kt +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/AnyAssertionsSpec.kt @@ -1,100 +1,130 @@ package ch.tutteli.atrium.api.infix.en_GB -//class AnyAssertionsSpec : ch.tutteli.atrium.specs.integration.AnyAssertionsSpec( -// fun1(Expect::toBe).name to Companion::toBe, +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.fun1 +import ch.tutteli.atrium.specs.integration.AnyAssertionsSpec +import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter +import ch.tutteli.atrium.specs.withNullableSuffix +import kotlin.reflect.KFunction2 - //TODO adjust the following lines -> also use `fun1<...>(...).name to Companion:...` => see CollectionAssertionsSpec - //we use `fun...` do distinguish between potential overloads but want to see the infix API in action +class AnyAssertionsSpec : ch.tutteli.atrium.specs.integration.AnyAssertionsSpec( + fun1(Expect::toBe), + fun1(Expect::toBe), + fun1(Expect::toBe), + fun1(Expect::toBe), + fun1(Expect::notToBe), + fun1(Expect::notToBe), + fun1(Expect::notToBe).withNullableSuffix(), + fun1(Expect::notToBe).withNullableSuffix(), + fun1(Expect::isSameAs), + fun1(Expect::isSameAs), + fun1(Expect::isSameAs).withNullableSuffix(), + fun1(Expect::isSameAs).withNullableSuffix(), + fun1(Expect::isNotSameAs), + fun1(Expect::isNotSameAs), + fun1(Expect::isNotSameAs).withNullableSuffix(), + fun1(Expect::isNotSameAs).withNullableSuffix(), -// fun1(Expect::toBe), -// fun2(Expect::toBe, suffix = " nullable").name to Companion::toBeNullableInt, -// fun2( -// Expect::toBe, -// suffix = " nullable" -// ).name to Companion::toBeNullableDataClass, -// fun1(Expect::notToBe), -// fun1(Expect::notToBe), -// fun1(Expect::notToBe, suffix = " nullable"), -// fun1(Expect::notToBe, suffix = " nullable"), -// fun1(Expect::isSameAs), -// fun1(Expect::isSameAs), -// fun1(Expect::isSameAs, suffix = " nullable"), -// fun1(Expect::isSameAs, suffix = " nullable"), -// fun1(Expect::isNotSameAs), -// fun1(Expect::isNotSameAs), -// fun1(Expect::isNotSameAs, suffix = " nullable"), -// fun1(Expect::isNotSameAs, suffix = " nullable"), -// -// "${Expect::toBe.name}(null)" to Companion::toBeNull, -// fun1(Expect::toBeNullIfNullGivenElse), -// "isA" to Companion::isAFeature, -// "isA" to Companion::isAStringToInt, -// "isA" to Companion::isAStringToInt, -// "isA" to Companion::isAString, -// "isA" to Companion::isACharSequence, -// "isA" to Companion::isASubType, -// "isA" to Companion::isAIntLess, -// "notToBeNull" to Companion::notToBeNull, -// Companion::notToBeNullLess, -// Companion::notToBeNullGreaterAndLess, + "${Expect::toBe.name}(null)" to Companion::toBeNull, + fun1(Expect::toBeNullIfNullGivenElse), + "isA" to Companion::isAFeature, + "isA" to Companion::isAStringToInt, + "isA" to Companion::isAStringToInt, + "isA" to Companion::isAString, + "isA" to Companion::isACharSequence, + "isA" to Companion::isASubType, + "isA" to Companion::isAIntLess, + "notToBeNull" to Companion::notToBeNull, + Companion::notToBeNullLess, + Companion::notToBeNullGreaterAndLess, -// getAndImmediatePair(), -// getAndLazyPair() -//) { + getAndImmediatePair(), + getAndLazyPair() +) { -// companion object { + companion object : WithAsciiReporter(){ + private fun toBeNull(expect: Expect) = expect toBe null -// private fun toBe(expect: Expect, a: Int): Expect = -// expect toBe a + @Suppress("RemoveExplicitTypeArguments") + private fun isAFeature(expect: Expect): Expect = expect.isA() - //TODO adjust the following to infix API as well -// private fun toBeNullableInt(expect: Expect, a: Int?): Expect = -// expect.toBe(a) -// -// private fun toBeNullableDataClass(expect: Expect, a: DataClass?): Expect = -// expect.toBe(a) -// -// private fun toBeNull(expect: Expect) = expect.toBe(null) -// -// private fun isAFeature(expect: Expect): Expect = expect.isA() -// -// private val andImmediate: KProperty1, Expect> = Expect::and -// fun getAndImmediatePair(): Pair.() -> Expect> = andImmediate.name to Expect::and -// -// private val andLazyName: KFunction2, Expect.() -> Unit, Expect> = Expect::and -// fun getAndLazyPair(): Pair.(Expect.() -> Unit) -> Expect> = -// andLazyName.name to Expect::and -// -// private inline fun isA( -// expect: Expect<*>, -// noinline assertionCreator: Expect.() -> Unit -// ) = expect.isA(assertionCreator) -// -// //TODO get rid of different overloads as soon as https://youtrack.jetbrains.com/issue/KT-19884 is fixed -// private fun isAStringToInt(expect: Expect<*>, assertionCreator: Expect.() -> Unit) = -// isA(expect, assertionCreator) -// -// private fun isAString(expect: Expect<*>, assertionCreator: Expect.() -> Unit) = -// isA(expect, assertionCreator) -// -// private fun isACharSequence(expect: Expect<*>, assertionCreator: Expect.() -> Unit) = -// isA(expect, assertionCreator) -// -// private fun isASubType(expect: Expect<*>, assertionCreator: Expect.() -> Unit) = -// isA(expect, assertionCreator) -// -// private fun isAIntLess(expect: Expect, number: Int) = expect.isA { isLessThan(number) } -// -// private fun notToBeNull(expect: Expect, assertionCreator: Expect.() -> Unit) = -// expect.notToBeNull(assertionCreator) -// -// private fun notToBeNullLess(expect: Expect, number: Int) = -// expect.notToBeNull { isLessThan(number) } -// -// private fun notToBeNullGreaterAndLess(expect: Expect, lowerBound: Int, upperBound: Int) = -// expect.notToBeNull { -// isGreaterThan(lowerBound) -// isLessThan(upperBound) -// } -// } -//} + private fun getAndImmediatePair(): Pair.() -> Expect> = + "non existing in infix" to { e: Expect -> e } + + private val andLazyName: KFunction2, Expect.() -> Unit, Expect> = Expect::and + private fun getAndLazyPair(): Pair.(Expect.() -> Unit) -> Expect> = + andLazyName.name to Expect::and + + private inline fun isA( + expect: Expect<*>, + noinline assertionCreator: Expect.() -> Unit + ) = expect.isA(assertionCreator) + + //TODO get rid of different overloads as soon as https://youtrack.jetbrains.com/issue/KT-19884 is fixed + private fun isAStringToInt(expect: Expect<*>, assertionCreator: Expect.() -> Unit) = + isA(expect, assertionCreator) + + private fun isAString(expect: Expect<*>, assertionCreator: Expect.() -> Unit) = + isA(expect, assertionCreator) + + private fun isACharSequence(expect: Expect<*>, assertionCreator: Expect.() -> Unit) = + isA(expect, assertionCreator) + + private fun isASubType(expect: Expect<*>, assertionCreator: Expect.() -> Unit) = + isA(expect, assertionCreator) + + private fun isAIntLess(expect: Expect, number: Int) = + expect.isA { it isLessThan number } + + private fun notToBeNull(expect: Expect, assertionCreator: Expect.() -> Unit) = + expect notToBeNull assertionCreator + + private fun notToBeNullLess(expect: Expect, number: Int) = + expect.notToBeNull { isLessThan(number) } + + private fun notToBeNullGreaterAndLess(expect: Expect, lowerBound: Int, upperBound: Int) = + expect.notToBeNull { + it isGreaterThan lowerBound + it isLessThan upperBound + } + } + + @Suppress("unused") + fun ambiguityTest() { + val a1: Expect = notImplemented() + val a1b: Expect = notImplemented() + + a1 toBe 1 + a1 toBe 1.2 + a1 notToBe 1 + a1 notToBe 1.2 + a1 isSameAs 1 + a1 isSameAs 1.2 + a1 isNotSameAs 1 + a1 isNotSameAs 1.2 + a1.isA() + a1.isA {} + + a1b toBe 1 + a1b toBe 1.2 + a1b notToBe 1 + a1b notToBe 1.2 + a1b isSameAs 1 + a1b isSameAs 1.2 + a1b isNotSameAs 1 + a1b isNotSameAs 1.2 + a1b.isA() + a1b.isA {} + + a1b notToBeNull o toBe 1 + a1b notToBeNull {} + + a1 and o toBe 1 + a1 and { it toBe 1 } + } + + //regression for #298, should compile without the need for E : Any or List + @Suppress("unused") + fun Expect>.firstIs(value: E) = it get index(0) { it toBe value } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/ArrayAsListAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/ArrayAsListAssertionsSpec.kt new file mode 100644 index 000000000..a01f1d6e2 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/ArrayAsListAssertionsSpec.kt @@ -0,0 +1,84 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.notImplemented + +class ArrayAsListAssertionsSpec : ch.tutteli.atrium.specs.integration.ArrayAsListAssertionsSpec( + "asList", + Companion::arrayInt, + Companion::byteArray, + Companion::charArray, + Companion::shortArray, + Companion::intArray, + Companion::longArray, + Companion::floatArray, + Companion::doubleArray, + Companion::booleanArray, + + Companion::arrayIntWithCreator, + Companion::byteArrayWithCreator, + Companion::charArrayWithCreator, + Companion::shortArrayWithCreator, + Companion::intArrayWithCreator, + Companion::longArrayWithCreator, + Companion::floatArrayWithCreator, + Companion::doubleArrayWithCreator, + Companion::booleanArrayWithCreator +) { + + companion object { + fun arrayInt(expect: Expect>) = expect asList o + fun byteArray(expect: Expect) = expect asList o + fun charArray(expect: Expect) = expect asList o + fun shortArray(expect: Expect) = expect asList o + fun intArray(expect: Expect) = expect asList o + fun longArray(expect: Expect) = expect asList o + fun floatArray(expect: Expect) = expect asList o + fun doubleArray(expect: Expect) = expect asList o + fun booleanArray(expect: Expect) = expect asList o + + fun arrayIntWithCreator(expect: Expect>, assertionCreator: Expect>.() -> Unit) = + expect asList { assertionCreator() } + fun byteArrayWithCreator(expect: Expect, assertionCreator: Expect>.() -> Unit) = + expect asList { assertionCreator() } + fun charArrayWithCreator(expect: Expect, assertionCreator: Expect>.() -> Unit) = + expect asList { assertionCreator() } + fun shortArrayWithCreator(expect: Expect, assertionCreator: Expect>.() -> Unit) = + expect asList { assertionCreator() } + fun intArrayWithCreator(expect: Expect, assertionCreator: Expect>.() -> Unit) = + expect asList { assertionCreator() } + fun longArrayWithCreator(expect: Expect, assertionCreator: Expect>.() -> Unit) = + expect asList { assertionCreator() } + fun floatArrayWithCreator(expect: Expect, assertionCreator: Expect>.() -> Unit) = + expect asList { assertionCreator() } + fun doubleArrayWithCreator(expect: Expect, assertionCreator: Expect>.() -> Unit) = + expect asList { assertionCreator() } + fun booleanArrayWithCreator(expect: Expect, assertionCreator: Expect>.() -> Unit) = + expect asList { assertionCreator() } + } + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + var a1: Expect> = notImplemented() + var a2: Expect> = notImplemented() + var a1b: Expect> = notImplemented() + var a2b: Expect> = notImplemented() + + var star: Expect> = notImplemented() + + a1 asList o + a2 asList o + + a1 = a1 asList { } + a2 = a2 asList { } + + a1b asList o + a2b asList o + + a1b = a1b asList { } + a2b = a2b asList { } + + star asList o + star = star asList { } + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceAssertionsSpec.kt new file mode 100644 index 000000000..0dacab299 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceAssertionsSpec.kt @@ -0,0 +1,50 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.fun1 +import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter + +class CharSequenceAssertionsSpec : ch.tutteli.atrium.specs.integration.CharSequenceAssertionsSpec( + "toBe ${empty::class.simpleName}" to Companion::toBeEmpty, + "notToBe ${empty::class.simpleName}" to Companion::notToBeEmpty, + "notToBe ${blank::class.simpleName}" to Companion::notToBeBlank, + fun1(Expect::startsWith), + fun1(Expect::startsWith), + fun1(Expect::startsNotWith), + fun1(Expect::startsNotWith), + fun1(Expect::endsWith), + fun1(Expect::endsWith), + fun1(Expect::endsNotWith), + fun1(Expect::endsNotWith), + fun1(Expect::matches), + fun1(Expect::mismatches) +) { + companion object : WithAsciiReporter(){ + private fun toBeEmpty(expect: Expect) = expect toBe empty + private fun notToBeEmpty(expect: Expect) = expect notToBe empty + private fun notToBeBlank(expect: Expect) = expect notToBe blank + } + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + val a1: Expect = notImplemented() + + a1 toBe empty + a1 notToBe empty + a1 notToBe blank + + a1 startsWith "expected" + a1 startsNotWith "expected" + a1 endsWith "expected" + a1 endsNotWith "expected" + + a1 startsWith 'a' + a1 startsNotWith 'a' + a1 endsWith 'a' + a1 endsNotWith 'a' + + a1 matches Regex("a") + a1 mismatches Regex("a") + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsAtLeastAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsAtLeastAssertionsSpec.kt new file mode 100644 index 000000000..0c0948b22 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsAtLeastAssertionsSpec.kt @@ -0,0 +1,186 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.verbs.internal.expect +import ch.tutteli.atrium.creating.Expect +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.describe + +class CharSequenceContainsAtLeastAssertionsSpec : Spek({ + include(object : ch.tutteli.atrium.specs.integration.CharSequenceContainsAtLeastAssertionsSpec( + getAtLeastValuesTriple(), + getAtLeastIgnoringCaseValuesTriple(), + getAtLeastButAtMostValuesTriple(), + getAtLeastBustAtMostIgnoringCaseValuesTriple(), + getContainsNotPair(), + getExactlyPair(), + CharSequenceContainsAtLeastAssertionsSpec.Companion::getErrorMsgAtLeastButAtMost, + "* ", "- " + ) {}) + + include(object : ch.tutteli.atrium.specs.integration.CharSequenceContainsAtLeastAssertionsSpec( + getAtLeastElementsOfTriple(), + getAtLeastIgnoringCaseElementsOfTriple(), + getAtLeastButAtMostElementsOfTriple(), + getAtLeastButAtMostIgnoringCaseElementsOfTriple(), + getContainsNotPair(), + getExactlyPair(), + CharSequenceContainsAtLeastAssertionsSpec.Companion::getErrorMsgAtLeastButAtMost, + "* ", "- " + ) {}) + + include(object : Spek({ + describe("atLeast 1 elementsOf") { + it("passing an empty iterable throws an IllegalArgumentException") { + expect { + expect("test") contains o atLeast 1 elementsOf emptyList() + }.toThrow { it messageContains "Iterable without elements are not allowed" } + } + } + describe("ignoring case elementsOf") { + it("passing an empty iterable throws an IllegalArgumentException") { + expect { + expect("test") contains o ignoring case elementsOf emptyList() + }.toThrow { it messageContains "Iterable without elements are not allowed" } + } + } + describe("ignoring case atLeast 1 elementsOf") { + it("passing an empty iterable throws an IllegalArgumentException") { + expect { + expect("test") contains o ignoring case atLeast 1 elementsOf emptyList() + }.toThrow { it messageContains "Iterable without elements are not allowed" } + } + } + }) {}) +}) { + + companion object : CharSequenceContainsSpecBase() { + + private val atLeastDescr = { what: String, times: String -> "$contains $what $atLeast $times" } + internal fun getAtLeastValuesTriple() = + atLeastDescr to ("$contains o $atLeast" to Companion::containsAtLeast) + + private fun containsAtLeast( + expect: Expect, + atLeast: Int, + a: Any, + aX: Array + ): Expect = + if (aX.isEmpty()) expect contains o atLeast atLeast value a + else expect contains o atLeast atLeast the values(a, *aX) + + internal fun getAtLeastElementsOfTriple() = + atLeastDescr to ("$contains o $atLeast" to Companion::containsAtLeastElementsOf) + + private fun containsAtLeastElementsOf( + expect: Expect, + atLeast: Int, + a: Any, + aX: Array + ): Expect = + expect contains o atLeast atLeast elementsOf listOf(a, *aX) + + private val atLeastIgnoringCaseDescr = + { what: String, times: String -> "$contains o $ignoringCase $what $atLeast $times" } + + private fun getAtLeastIgnoringCaseValuesTriple() = + atLeastIgnoringCaseDescr to ("$contains o $ignoringCase $atLeast" to Companion::containsAtLeastIgnoringCaseValues) + + private fun containsAtLeastIgnoringCaseValues( + expect: Expect, + atLeast: Int, + a: Any, + aX: Array + ): Expect = + if (aX.isEmpty()) { + if (atLeast == 1) expect contains o ignoring case value a + else expect contains o ignoring case atLeast atLeast value a + } else { + if (atLeast == 1) expect contains o ignoring case the values(a, *aX) + else expect contains o ignoring case atLeast atLeast the values(a, *aX) + } + + private fun getAtLeastIgnoringCaseElementsOfTriple() = + atLeastIgnoringCaseDescr to ("$contains o $ignoringCase $atLeast" to Companion::containsAtLeastIgnoringCaseElementsOf) + + private fun containsAtLeastIgnoringCaseElementsOf( + expect: Expect, + atLeast: Int, + a: Any, + aX: Array + ): Expect = + if (aX.isEmpty()) { + if (atLeast == 1) expect contains o ignoring case elementsOf listOf(a) + else expect contains o ignoring case atLeast atLeast elementsOf listOf(a) + } else { + if (atLeast == 1) expect contains o ignoring case elementsOf listOf(a, *aX) + else expect contains o ignoring case atLeast atLeast elementsOf listOf(a, *aX) } + + private val atLeastButAtMostDescr = { what: String, timesAtLeast: String, timesAtMost: String -> + "$contains o $what $atLeast $timesAtLeast $butAtMost $timesAtMost" + } + + private fun getAtLeastButAtMostElementsOfTriple() = + atLeastButAtMostDescr to ("$contains o $atLeast o $butAtMost" to Companion::containsAtLeastButAtMostElementsOf) + + private fun containsAtLeastButAtMostElementsOf( + expect: Expect, + atLeast: Int, + butAtMost: Int, + a: Any, + aX: Array + ) = expect contains o atLeast atLeast butAtMost butAtMost elementsOf listOf(a, *aX) + + private fun getAtLeastButAtMostValuesTriple() = + atLeastButAtMostDescr to ("$contains o $atLeast o $butAtMost" to Companion::containsAtLeastButAtMostValues) + + private fun containsAtLeastButAtMostValues( + expect: Expect, + atLeast: Int, + butAtMost: Int, + a: Any, + aX: Array + ) = + if (aX.isEmpty()) expect contains o atLeast atLeast butAtMost butAtMost value a + else expect contains o atLeast atLeast butAtMost butAtMost the values(a, *aX) + + private val atLeastButAtMostIgnoringCaseDescr = { what: String, timesAtLeast: String, timesAtMost: String -> + "$contains $ignoringCase $what $atLeast $timesAtLeast $butAtMost $timesAtMost" + } + + private fun getAtLeastBustAtMostIgnoringCaseValuesTriple() = + atLeastButAtMostIgnoringCaseDescr to ("$contains o $ignoringCase $atLeast $butAtMost" to Companion::containsAtLeastButAtMostIgnoringCaseValues) + + private fun containsAtLeastButAtMostIgnoringCaseValues( + expect: Expect, + atLeast: Int, + butAtMost: Int, + a: Any, + aX: Array + ) = + if (aX.isEmpty()) expect contains o ignoring case atLeast atLeast butAtMost butAtMost value a + else expect contains o ignoring case atLeast atLeast butAtMost butAtMost the values(a, *aX) + + private fun getAtLeastButAtMostIgnoringCaseElementsOfTriple() = + atLeastButAtMostIgnoringCaseDescr to ("$contains o $ignoringCase $atLeast $butAtMost" to Companion::containsAtLeastButAtMostIgnoringCaseElementsOf) + + private fun containsAtLeastButAtMostIgnoringCaseElementsOf( + expect: Expect, + atLeast: Int, + butAtMost: Int, + a: Any, + aX: Array + ) = expect contains o ignoring case atLeast atLeast butAtMost butAtMost elementsOf listOf(a, *aX) + + private fun getContainsNotPair() = containsNotValues to Companion::getErrorMsgContainsNot + + private fun getErrorMsgContainsNot(times: Int) = "use `$containsNotValues` instead of `$atLeast $times`" + + private fun getExactlyPair() = exactly to Companion::getErrorMsgExactly + + private fun getErrorMsgExactly(times: Int) = + "use `$exactly $times` instead of `$atLeast $times $butAtMost $times`" + + internal fun getErrorMsgAtLeastButAtMost(timesAtLeast: Int, timesButAtMost: Int) = + "specifying `$butAtMost $timesButAtMost` does not make sense if `$atLeast $timesAtLeast` was used before" + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsAtMostAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsAtMostAssertionsSpec.kt new file mode 100644 index 000000000..eb0b2438b --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsAtMostAssertionsSpec.kt @@ -0,0 +1,42 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect + + +class CharSequenceContainsAtMostAssertionsSpec : + ch.tutteli.atrium.specs.integration.CharSequenceContainsAtMostAssertionsSpec( + getAtMostTriple(), + getAtMostIgnoringCaseTriple(), + getContainsNotPair(), + getExactlyPair(), + "* ", "- " + ) { + + companion object : CharSequenceContainsSpecBase() { + + private fun getAtMostTriple() = + { what: String, times: String -> "$contains $what $atMost $times" } to + ("$contains o $atMost" to Companion::containsAtMost) + + private fun containsAtMost(expect: Expect, atMost: Int, a: Any, aX: Array) = + if (aX.isEmpty()) expect contains o atMost atMost value a + else expect contains o atMost atMost the values(a, *aX) + + private fun getAtMostIgnoringCaseTriple() = + { what: String, times: String -> "$contains $ignoringCase $what $atMost $times" } to + ("$contains o $ignoringCase $atMost" to Companion::containsAtMostIgnoringCase) + + private fun containsAtMostIgnoringCase(expect: Expect, atMost: Int, a: Any, aX: Array) = + if (aX.isEmpty()) expect contains o ignoring case atMost atMost value a + else expect contains o ignoring case atMost atMost the values(a, *aX) + + private fun getContainsNotPair() = containsNotValues to Companion::getErrorMsgContainsNot + + private fun getErrorMsgContainsNot(times: Int) = "use `$containsNotValues` instead of `$atMost $times`" + + private fun getExactlyPair() = exactly to Companion::getErrorMsgExactly + + private fun getErrorMsgExactly(times: Int) = + "use `$exactly $times` instead of `$atMost $times`; `$atMost $times` defines implicitly `$atLeast $times` as well" + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsContainsNotAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsContainsNotAssertionsSpec.kt new file mode 100644 index 000000000..a9e1261f9 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsContainsNotAssertionsSpec.kt @@ -0,0 +1,56 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.fun2 +import ch.tutteli.atrium.specs.notImplemented +import org.spekframework.spek2.Spek + +class CharSequenceContainsContainsNotAssertionsSpec : Spek({ + + include(object : ch.tutteli.atrium.specs.integration.CharSequenceContainsContainsNotAssertionsSpec( + getContainsPair(), + getContainsNotPair(), + "* ", "- ", ">> ", + "[Atrium][Builder]" + ) {}) + + include(object : ch.tutteli.atrium.specs.integration.CharSequenceContainsContainsNotAssertionsSpec( + getContainsShortcutPair(), + getContainsNotShortcutPair(), + "* ", "- ", ">> ", + "[Atrium][Shortcut]" + ) {}) +}) { + companion object : CharSequenceContainsSpecBase() { + + private fun getContainsPair() = "$contains o $atLeast 1 value/the Values" to Companion::containsBuilder + + private fun containsBuilder(expect: Expect, a: Any, aX: Array) = + if (aX.isEmpty()) expect contains o atLeast 1 value a + else expect contains o atLeast 1 the values(a, *aX) + + private fun getContainsNotPair() = "$containsNot o $atLeast 1 value/the Values" to Companion::containsNotBuilder + private fun containsNotBuilder(expect: Expect, a: Any, aX: Array) = + if (aX.isEmpty()) expect containsNot o value a + else expect containsNot o the values(a, *aX) + + private fun getContainsShortcutPair() = fun2>(Companion::contains) + private fun getContainsNotShortcutPair() = fun2>(Companion::containsNot) + + private fun contains(expect: Expect, a: Any, aX: Array) = + if (aX.isEmpty()) expect contains a + else expect contains values(a, *aX) + + private fun containsNot(expect: Expect, a: Any, aX: Array) = + if (aX.isEmpty()) expect containsNot a + else expect containsNot values(a, *aX) + } + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + val a1: Expect = notImplemented() + + a1 contains values(1, "a", 'c') + a1 containsNot values(1, "a", 'c') + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsExactlyAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsExactlyAssertionsSpec.kt new file mode 100644 index 000000000..821d38682 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsExactlyAssertionsSpec.kt @@ -0,0 +1,40 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect + +class CharSequenceContainsExactlyAssertionsSpec : + ch.tutteli.atrium.specs.integration.CharSequenceContainsExactlyAssertionsSpec( + getExactlyTriple(), + getExactlyIgnoringCaseTriple(), + getContainsNotPair(), + "* ", "- " + ) { + + companion object : CharSequenceContainsSpecBase() { + + private fun getExactlyTriple() = + { what: String, times: String -> "$contains $what $exactly $times" } to + ("$contains o $exactly" to Companion::containsExactly) + + private fun containsExactly(expect: Expect, exactly: Int, a: Any, aX: Array) = + if (aX.isEmpty()) expect contains o exactly exactly value a + else expect contains o exactly exactly the values(a, *aX) + + private fun getExactlyIgnoringCaseTriple() = + { what: String, times: String -> "$contains $ignoringCase $what $exactly $times" } to + ("$contains o $ignoringCase $exactly" to Companion::containsExactlyIgnoringCase) + + + private fun containsExactlyIgnoringCase( + expect: Expect, + exactly: Int, + a: Any, + aX: Array + ) = + if (aX.isEmpty()) expect contains o ignoring case exactly exactly value a + else expect contains o ignoring case exactly exactly the values(a, *aX) + + private fun getContainsNotPair() = containsNotValues to Companion::getErrorMsgContainsNot + private fun getErrorMsgContainsNot(times: Int) = "use `$containsNotValues` instead of `$exactly $times`" + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsNotAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsNotAssertionsSpec.kt new file mode 100644 index 000000000..3f02be243 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsNotAssertionsSpec.kt @@ -0,0 +1,29 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect + +class CharSequenceContainsNotAssertionsSpec : ch.tutteli.atrium.specs.integration.CharSequenceContainsNotAssertionsSpec( + getContainsNotTriple(), + getContainsNotIgnoringCaseTriple(), + "* ", "- " +) { + + companion object : CharSequenceContainsSpecBase() { + + private fun getContainsNotTriple() = + { what: String -> "$containsNotValues $what" } to + (containsNotValues to Companion::containsNotFun) + + private fun containsNotFun(expect: Expect, a: Any, aX: Array) = + if (aX.isEmpty()) expect containsNot o value a + else expect containsNot o the values(a, *aX) + + private fun getContainsNotIgnoringCaseTriple() = + { what: String -> "$containsNotValues $ignoringCase $what" } to + ("$containsNotValues o $ignoringCase" to Companion::containsNotIgnoringCase) + + private fun containsNotIgnoringCase(expect: Expect, a: Any, aX: Array) = + if (aX.isEmpty()) expect containsNot o ignoring case value a + else expect containsNot o ignoring case the values(a, *aX) + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsNotOrAtMostAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsNotOrAtMostAssertionsSpec.kt new file mode 100644 index 000000000..ddbbb88d2 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsNotOrAtMostAssertionsSpec.kt @@ -0,0 +1,42 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect + +class CharSequenceContainsNotOrAtMostAssertionsSpec : + ch.tutteli.atrium.specs.integration.CharSequenceContainsNotOrAtMostAssertionsSpec( + getNotOrAtMostTriple(), + getNotOrAtMostIgnoringCaseTriple(), + getContainsNotPair(), + "* ", "- " + ) { + + companion object : CharSequenceContainsSpecBase() { + + private fun getNotOrAtMostTriple() = + { what: String, times: String -> "$contains $what $notOrAtMost $times" } to + ("$contains o $notOrAtMost" to Companion::containsNotOrAtMost) + + private fun containsNotOrAtMost(expect: Expect, atMost: Int, a: Any, aX: Array) = + if (aX.isEmpty()) expect contains o notOrAtMost atMost value a + else expect contains o notOrAtMost atMost the values(a, *aX) + + private fun getNotOrAtMostIgnoringCaseTriple() = + { what: String, times: String -> "$contains $ignoringCase $what $notOrAtMost $times" } to + ("$contains o $ignoringCase $notOrAtMost" to Companion::containsNotOrAtMostIgnoringCase) + + private fun containsNotOrAtMostIgnoringCase( + expect: Expect, + atMost: Int, + a: Any, + aX: Array + ) = + if (aX.isEmpty()) expect contains o ignoring case notOrAtMost atMost value a + else expect contains o ignoring case notOrAtMost atMost the values(a, *aX) + + + private fun getContainsNotPair() = containsNotValues to Companion::getErrorMsgContainsNot + + private fun getErrorMsgContainsNot(times: Int) = "use `$containsNotValues` instead of `$notOrAtMost $times`" + + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsRegexAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsRegexAssertionsSpec.kt new file mode 100644 index 000000000..2b2075e50 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsRegexAssertionsSpec.kt @@ -0,0 +1,139 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import org.spekframework.spek2.Spek + +class CharSequenceContainsRegexAssertionsSpec : Spek({ + include(StringSpec) + include(RegexSpec) +}) { + object StringSpec : ch.tutteli.atrium.specs.integration.CharSequenceContainsRegexAssertionsSpec( + getNameContainsRegex(), + getAtLeastTripleString(), + getAtLeastIgnoringCaseTripleString(), + getShortcutTripleString(), + getAtMostTripleString(), + getAtMostIgnoringCaseTripleString(), + "* ", "- ", + "[StringSpec] " + ) + + object RegexSpec : ch.tutteli.atrium.specs.integration.CharSequenceContainsRegexAssertionsSpec( + getNameContainsRegex(), + getAtLeastTripleRegex(), + getAtLeastIgnoringCaseTripleString(), + getShortcutTripleRegex(), + getAtMostTripleRegex(), + getAtMostIgnoringCaseTripleString(), + "* ", "- ", + "[RegexSpec] " + ) + + companion object : CharSequenceContainsSpecBase() { + + private fun getNameContainsRegex() = "$contains with search mode $regex" + + private fun getAtLeastTripleString() = + { what: String, times: String -> "$contains $what $atLeast $times" } to + ("$contains o $atLeast $regex" to ::containsAtLeastString) + + private fun getAtLeastTripleRegex() = + { what: String, times: String -> "$contains $what $atLeast $times" } to + ("$contains o $atLeast $regex" to ::containsAtLeastRegex) + + private fun containsAtLeastString( + expect: Expect, + atLeast: Int, + a: String, + aX: Array + ) = + if (aX.isEmpty()) expect contains o atLeast atLeast regex a + else expect contains o atLeast atLeast the regexPatterns(a, *aX) + + private fun containsAtLeastRegex(expect: Expect, atLeast: Int, a: String, aX: Array) = + if (aX.isEmpty()) expect contains o atLeast atLeast matchFor Regex(a) + else expect contains o atLeast atLeast matchFor all(Regex(a), *aX.map { it.toRegex() }.toTypedArray()) + + private fun getAtLeastIgnoringCaseTripleString() = + { what: String, times: String -> "$contains $ignoringCase $what $atLeast $times" } to + ("$contains o $atLeast $ignoringCase $regex" to ::containsAtLeastIgnoringCase) + + private fun containsAtLeastIgnoringCase( + expect: Expect, + atLeast: Int, + a: String, + aX: Array + ) = + if (aX.isEmpty()) { + if (atLeast == 1) expect contains o ignoring case regex a + else expect contains o ignoring case atLeast atLeast regex a + } else { + if (atLeast == 1) expect contains o ignoring case the regexPatterns(a, *aX) + else expect contains o ignoring case atLeast atLeast the regexPatterns(a, *aX) + } + + private fun getShortcutTripleString() = + { what: String, times: String -> "$contains $what $atLeast $times" } to + (containsRegex to ::containsShortcutString) + + private fun getShortcutTripleRegex() = + { what: String, times: String -> "$contains $what $atLeast $times" } to + (containsRegex to ::containsShortcutRegex) + + private fun containsShortcutString( + expect: Expect, + a: String, + aX: Array + ) = + if (aX.isEmpty()) expect containsRegex a + else expect containsRegex regexPatterns(a, *aX) + + private fun containsShortcutRegex( + expect: Expect, + a: String, + aX: Array + ) = + if (aX.isEmpty()) expect contains Regex(a) + else expect contains all(Regex(a), *aX.map { it.toRegex() }.toTypedArray()) + + + private fun getAtMostTripleString() = + { what: String, times: String -> "$contains $what $atMost $times" } to + ("$contains o $atMost $regex" to ::containsAtMostString) + + private fun getAtMostTripleRegex() = + { what: String, times: String -> "$contains $what $atMost $times" } to + ("$contains o $atMost $regex" to ::containsAtMostRegex) + + private fun containsAtMostString( + expect: Expect, + atMost: Int, + a: String, + aX: Array + ) = + if (aX.isEmpty()) expect contains o atMost atMost regex a + else expect contains o atMost atMost the regexPatterns(a, *aX) + + private fun getAtMostIgnoringCaseTripleString() = + { what: String, times: String -> "$contains $ignoringCase $what $atMost $times" } to + ("$contains o $ignoringCase $atMost $regex" to ::containsAtMostIgnoringCase) + + private fun containsAtMostRegex( + expect: Expect, + atMost: Int, + a: String, + aX: Array + ) = + if (aX.isEmpty()) expect contains o atMost atMost matchFor Regex(a) + else expect contains o atMost atMost matchFor all(Regex(a), *aX.map { it.toRegex() }.toTypedArray()) + + private fun containsAtMostIgnoringCase( + expect: Expect, + atMost: Int, + a: String, + aX: Array + ) = + if (aX.isEmpty()) expect contains o ignoring case atMost atMost regex a + else expect contains o ignoring case atMost atMost the regexPatterns(a, *aX) + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsSpecBase.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsSpecBase.kt new file mode 100644 index 000000000..40ac3128a --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CharSequenceContainsSpecBase.kt @@ -0,0 +1,100 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.infix.en_GB.creating.Values +import ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.AtLeastCheckerOption +import ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders.NotCheckerOption +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.creating.charsequence.contains.CharSequenceContains +import ch.tutteli.atrium.domain.creating.charsequence.contains.searchbehaviours.NoOpSearchBehaviour +import ch.tutteli.atrium.domain.creating.charsequence.contains.searchbehaviours.NotSearchBehaviour +import ch.tutteli.atrium.specs.fun1 +import ch.tutteli.atrium.specs.name +import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter +import kotlin.reflect.KFunction2 + +abstract class CharSequenceContainsSpecBase : WithAsciiReporter() { + private val containsProp: KFunction2, o, CharSequenceContains.Builder> = + Expect::contains + protected val contains = containsProp.name + private val containsNotProp: KFunction2, o, NotCheckerOption> = + Expect::containsNot + protected val containsNot = containsNotProp.name + + private val containsNotFun: KFunction2, Any, Expect> = Expect::containsNot + protected val containsNotValues = "${containsNotFun.name} values" + protected val containsRegex = fun1(Expect::containsRegex).name + protected val atLeast = CharSequenceContains.Builder<*, *>::atLeast.name + protected val butAtMost = AtLeastCheckerOption<*, *>::butAtMost.name + protected val exactly = CharSequenceContains.Builder<*, *>::exactly.name + protected val atMost = CharSequenceContains.Builder<*, *>::atMost.name + protected val notOrAtMost = CharSequenceContains.Builder<*, *>::notOrAtMost.name + private val regexKFun: KFunction2< + CharSequenceContains.CheckerOption<*, NoOpSearchBehaviour>, + String, + Expect<*> + > = CharSequenceContains.CheckerOption<*, NoOpSearchBehaviour>::regex + protected val regex = regexKFun.name + protected val ignoringCase = + "${CharSequenceContains.Builder<*, NoOpSearchBehaviour>::ignoring.name} ${case::class.simpleName}" + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + val a1: Expect = notImplemented() + + a1 contains o atLeast 1 value 1 + a1 contains o atMost 2 the values("a", 1) + a1 contains o notOrAtMost 2 regex "h|b" + a1 contains o exactly 2 the regexPatterns("h|b", "b") + a1 contains o atLeast 2 matchFor Regex("bla") + a1 contains o atLeast 2 matchFor all(Regex("bla"), Regex("b")) + a1 contains o atLeast 2 elementsOf listOf(1, 2) + + a1 containsNot o value "a" + a1 containsNot o the values("a", 'b') + a1 containsNot o regex "a" + a1 containsNot o the regexPatterns("a", "bl") + a1 containsNot o matchFor Regex("a") + a1 containsNot o matchFor all(Regex("a"), Regex("bl")) + a1 containsNot o elementsOf listOf(1, 2) + + a1 contains o ignoring case atLeast 1 value "a" + a1 contains o ignoring case atLeast 1 the values("a", 'b') + a1 contains o ignoring case atLeast 1 regex "a" + a1 contains o ignoring case atLeast 1 the regexPatterns("a", "bl") + // not supported on purpose as one can specify an ignore case flag for Regex + // and hence these would be a second way to do the same thing + //a1 contains o ignoring case atLeast 1 matchFor Regex("a") + //a1 contains o ignoring case atLeast 1 matchFor all(Regex("a"), Regex("bl")) + a1 contains o ignoring case atLeast 1 elementsOf listOf(1, 2) + + a1 containsNot o ignoring case value "a" + a1 containsNot o ignoring case the values("a", 'b') + a1 containsNot o ignoring case regex "a" + a1 containsNot o ignoring case the regexPatterns("a", "bl") + // not supported on purpose as one can specify an ignore case flag for Regex + // and hence these would be a second way to do the same thing + //a1 containsNot o ignoring case matchFor Regex("a") + //a1 containsNot o ignoring case matchFor all(Regex("a"), Regex("bl")) + a1 containsNot o ignoring case elementsOf listOf(1, 2) + + // skip atLeast + a1 contains o ignoring case value "a" + a1 contains o ignoring case the values("a", 'b') + a1 contains o ignoring case regex "a" + a1 contains o ignoring case the regexPatterns("a", "bl") + // not supported on purpose as one can specify an ignore case flag for Regex + // and hence these would be a second way to do the same thing + //a1 contains o ignoring case matchFor Regex("a") + //a1 contains o ignoring case matchFor all(Regex("a"), Regex("bl")) + a1 contains o ignoring case elementsOf listOf("a", 2) + + a1 and { it contains o atLeast 1 value 1 } + a1 and { it contains o atMost 2 the values("a", 1) } + a1 and { it contains o notOrAtMost 2 regex "h|b" } + a1 and { it contains o exactly 2 the regexPatterns("h|b", "b") } + a1 and { it contains o atLeast 2 matchFor Regex("bla") } + a1 and { it contains o atLeast 2 matchFor all(Regex("bla"), Regex("b")) } + a1 and { it contains o atLeast 2 elementsOf listOf(1, 2) } + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CollectionAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CollectionAssertionsSpec.kt index 6c83d9016..95aa1b235 100644 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CollectionAssertionsSpec.kt +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CollectionAssertionsSpec.kt @@ -1,37 +1,34 @@ package ch.tutteli.atrium.api.infix.en_GB -import ch.tutteli.atrium.api.infix.en_GB.testutils.WithAsciiReporter import ch.tutteli.atrium.creating.Expect -import ch.tutteli.atrium.reporting.ReporterFactory -import ch.tutteli.atrium.specs.fun1 -import ch.tutteli.atrium.specs.name import ch.tutteli.atrium.specs.notImplemented - +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter class CollectionAssertionsSpec : ch.tutteli.atrium.specs.integration.CollectionAssertionsSpec( - fun1, Empty>(Expect>::toBe).name to Companion::isEmpty, - fun1, Empty>(Expect>::notToBe).name to Companion::isNotEmpty + "toBe ${empty::class.simpleName}" to Companion::isEmpty, + "notToBe ${empty::class.simpleName}" to Companion::isNotEmpty ) { companion object : WithAsciiReporter() { + private fun isEmpty(expect: Expect>) = expect toBe empty + private fun isNotEmpty(expect: Expect>) = expect notToBe empty - fun isEmpty(expect: Expect>) = expect toBe Empty - fun isNotEmpty(expect: Expect>) = expect notToBe Empty } @Suppress("unused", "UNUSED_VALUE") private fun ambiguityTest() { - val a1: Expect> = notImplemented() - val a1b: Expect> = notImplemented() + val a1: Expect> = notImplemented() + val a1b: Expect> = notImplemented() val star: Expect> = notImplemented() - a1 toBe Empty - a1 notToBe Empty + a1 toBe empty + a1 notToBe empty - a1b toBe Empty - a1b notToBe Empty + a1b toBe empty + a1b notToBe empty - star toBe Empty - star notToBe Empty + star toBe empty + star notToBe empty } } + diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CollectionFeatureAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CollectionFeatureAssertionsSpec.kt index 62a713a9f..343a24db3 100644 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CollectionFeatureAssertionsSpec.kt +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/CollectionFeatureAssertionsSpec.kt @@ -1,27 +1,23 @@ package ch.tutteli.atrium.api.infix.en_GB -import ch.tutteli.atrium.api.infix.en_GB.testutils.WithAsciiReporter import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.specs.fun1 -import ch.tutteli.atrium.specs.name import ch.tutteli.atrium.specs.notImplemented import ch.tutteli.atrium.specs.property +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter class CollectionFeatureAssertionsSpec : ch.tutteli.atrium.specs.integration.CollectionFeatureAssertionsSpec( property, Int>(Expect>::size), - fun1, Expect.() -> Unit>(Expect>::size).name to Companion::size + fun1, Expect.() -> Unit>(Expect>::size) ) { - companion object : WithAsciiReporter() { - fun size(expect: Expect>, assertionCreator: Expect.() -> Unit) = - expect size { assertionCreator() } - } + companion object : WithAsciiReporter() @Suppress("unused", "UNUSED_VALUE") private fun ambiguityTest() { - var a1: Expect> = notImplemented() - var a1b: Expect> = notImplemented() + var a1: Expect> = notImplemented() + var a1b: Expect> = notImplemented() - var star: Expect> = notImplemented() + var star: Expect> = notImplemented() a1.size a1 = a1 size { } diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/ComparableAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/ComparableAssertionsSpec.kt new file mode 100644 index 000000000..e079777ef --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/ComparableAssertionsSpec.kt @@ -0,0 +1,22 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.fun1 +import ch.tutteli.atrium.specs.notImplemented + +class ComparableAssertionsSpec : ch.tutteli.atrium.specs.integration.ComparableAssertionsSpec( + fun1(Expect::isLessThan), + fun1(Expect::isLessThanOrEqual), + fun1(Expect::isGreaterThan), + fun1(Expect::isGreaterThanOrEqual) +) { + + @Suppress("unused") + fun ambiguityTest() { + val a1: Expect = notImplemented() + a1 isLessThan 1 + a1 isLessThanOrEqual 1 + a1 isGreaterThan 1 + a1 isGreaterThanOrEqual 1 + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/FeatureAssertionsBoundedReferenceAlternativeSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/FeatureAssertionsBoundedReferenceAlternativeSpec.kt new file mode 100644 index 000000000..f98a20180 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/FeatureAssertionsBoundedReferenceAlternativeSpec.kt @@ -0,0 +1,127 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.infix.en_GB.workaround.it +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.integration.TestData +import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter + +class FeatureAssertionsBoundedReferenceAlternativeSpec : ch.tutteli.atrium.specs.integration.FeatureAssertionsSpec( + propertyImmediate, + propertyLazy, + f0Immediate, + f1Immediate, + f2Immediate, + f3Immediate, + f4Immediate, + f5Immediate, + f0Lazy, + f1Lazy, + f2Lazy, + f3Lazy, + f4Lazy, + f5Lazy, + + propertyNullableDoesNotHold, + f0NullableDoesNotHold, + f1NullableDoesNotHold, + f2NullableDoesNotHold, + f3NullableDoesNotHold, + f4NullableDoesNotHold, + f5NullableDoesNotHold, + + propertyNullableHolds, + f0NullableHolds, + f1NullableHolds, + f2NullableHolds, + f3NullableHolds, + f4NullableHolds, + f5NullableHolds, + + propertyLazyWithNestedImmediate, + propertyLazyWithNestedLazy, + + propertyEmptyAssertionCreator, + f0EmptyAssertionCreator, + f1EmptyAssertionCreator, + f2EmptyAssertionCreator, + f3EmptyAssertionCreator, + f4EmptyAssertionCreator, + f5EmptyAssertionCreator, + + isAbleToEvaluateDescription = false +) { + + //TODO remove type parameters for `of` with Kotiln 1.4 including parentheses (make the calls infix again + companion object : WithAsciiReporter() { + //@formatter:off + val propertyImmediate: F = { it feature { p(it::nonNullValue) } contains "hello" } + val propertyLazy: F = { it feature of({ p(it::nonNullValue) }) { it contains "hello" } } + val f0Immediate: F = { it feature { f0(it::return0) } contains "hello" } + val f1Immediate: F = { it feature { f1(it::return1, "a") } contains "hello" } + val f2Immediate: F = { it feature { f2(it::return2, "a", 1) } contains "hello" } + val f3Immediate: F = { it feature { f3(it::return3, "a", 1, true) } contains "hello" } + val f4Immediate: F = { it feature { f4(it::return4, "a", 1, true, 1.2) } contains "hello" } + val f5Immediate: F = { it feature { f5(it::return5, "a", 1, true, 1.2, 'b') } contains "hello" } + val f0Lazy: F = { it feature of({ f0(it::return0) }) { it contains "hello" } } + val f1Lazy: F = { it feature of({ f1(it::return1, "a") }) { it contains "hello" } } + val f2Lazy: F = { it feature of({ f2(it::return2, "a", 1) }) { it contains "hello" } } + val f3Lazy: F = { it feature of({ f3(it::return3, "a", 1, true) }) { it contains "hello" } } + val f4Lazy: F = { it feature of({ f4(it::return4, "a", 1, true, 1.2) }) { it contains "hello" } } + val f5Lazy: F = { it feature of({ f5(it::return5, "a", 1, true, 1.2, 'b') }) { it contains "hello" } } + + val propertyNullableDoesNotHold: F = { it feature { p(it::nullableValue) } toBe null } + val f0NullableDoesNotHold: F = { it feature { f0(it::returnNullable0) } toBe null } + val f1NullableDoesNotHold: F = { it feature { f1(it::returnNullable1, "a") } toBe null } + val f2NullableDoesNotHold: F = { it feature { f2(it::returnNullable2, "a", 1) } toBe null } + val f3NullableDoesNotHold: F = { it feature { f3(it::returnNullable3, "a", 1, true) } toBe null } + val f4NullableDoesNotHold: F = { it feature { f4(it::returnNullable4, "a", 1, true, 1.2) } toBe null } + val f5NullableDoesNotHold: F = { it feature { f5(it::returnNullable5, "a", 1, true, 1.2, 'b') } toBe null } + + val propertyNullableHolds: F = { it feature { p(it::nullableValue) } notToBeNull { it toBe 1 } } + val f0NullableHolds: F = { it feature { f0(it::returnNullable0) } notToBeNull { it toBe 1 } } + val f1NullableHolds: F = { it feature { f1(it::returnNullable1, "a") } notToBeNull { it toBe 1 } } + val f2NullableHolds: F = { it feature { f2(it::returnNullable2, "a", 1) } notToBeNull { it toBe 1 } } + val f3NullableHolds: F = { it feature { f3(it::returnNullable3, "a", 1, true) } notToBeNull { it toBe 1 } } + val f4NullableHolds: F = { it feature { f4(it::returnNullable4, "a", 1, true, 1.2) } notToBeNull { it toBe 1 } } + val f5NullableHolds: F = { it feature { f5(it::returnNullable5, "a", 1, true, 1.2, 'b') } notToBeNull { it toBe 1 } } + //@formatter:on + + val propertyLazyWithNestedImmediate: F = { + it feature { p(it::nonNullValue) } it { + it feature { p(it::length) } toBe 12 + } + } + val propertyLazyWithNestedLazy: F = { + it feature { p(it::nonNullValue) } it { + it feature { p(it::length) } it { it toBe 12 } + } + } + + val propertyEmptyAssertionCreator: F = { it feature of({ p(it::nonNullValue) }) {} } + val f0EmptyAssertionCreator: F = { it feature of({ f0(it::return0) }) {} } + val f1EmptyAssertionCreator: F = { it feature of({ f1(it::return1, "a") }) {} } + val f2EmptyAssertionCreator: F = { it feature of({ f2(it::return2, "a", 1) }) {} } + val f3EmptyAssertionCreator: F = { it feature of({ f3(it::return3, "a", 1, true) }) {} } + val f4EmptyAssertionCreator: F = { it feature of({ f4(it::return4, "a", 1, true, 1.2) }) {} } + val f5EmptyAssertionCreator: F = + { it feature (of({ f5(it::return5, "a", 1, true, 1.2, 'b') }) {}) } + } + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + val a1: Expect> = notImplemented() + val a1b: Expect> = notImplemented() + + val star: Expect> = notImplemented() + + a1 feature { p(it::size) } + a1 feature { p(it::size) } it {} + + a1b feature { p(it::size) } + a1b feature { p(it::size) } it {} + + star feature { p(it::size) } + star feature { p(it::size) } it {} + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/FeatureAssertionsBoundedReferenceSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/FeatureAssertionsBoundedReferenceSpec.kt new file mode 100644 index 000000000..c384f8abb --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/FeatureAssertionsBoundedReferenceSpec.kt @@ -0,0 +1,130 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.infix.en_GB.workaround.it +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.integration.TestData +import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter + +internal typealias F = Expect.() -> Unit + +class FeatureAssertionsBoundedReferenceSpec : ch.tutteli.atrium.specs.integration.FeatureAssertionsSpec( + propertyImmediate, + propertyLazy, + f0Immediate, + f1Immediate, + f2Immediate, + f3Immediate, + f4Immediate, + f5Immediate, + f0Lazy, + f1Lazy, + f2Lazy, + f3Lazy, + f4Lazy, + f5Lazy, + + propertyNullableDoesNotHold, + f0NullableDoesNotHold, + f1NullableDoesNotHold, + f2NullableDoesNotHold, + f3NullableDoesNotHold, + f4NullableDoesNotHold, + f5NullableDoesNotHold, + + propertyNullableHolds, + f0NullableHolds, + f1NullableHolds, + f2NullableHolds, + f3NullableHolds, + f4NullableHolds, + f5NullableHolds, + + propertyLazyWithNestedImmediate, + propertyLazyWithNestedLazy, + + propertyEmptyAssertionCreator, + f0EmptyAssertionCreator, + f1EmptyAssertionCreator, + f2EmptyAssertionCreator, + f3EmptyAssertionCreator, + f4EmptyAssertionCreator, + f5EmptyAssertionCreator, + + isAbleToEvaluateDescription = false +) { + + //TODO remove type parameters for `of` with Kotiln 1.4 including parentheses (make the calls infix again + companion object : WithAsciiReporter() { + //@formatter:off + val propertyImmediate: F = { it feature { f(it::nonNullValue) } contains "hello" } + val propertyLazy: F = { it feature of({ f(it::nonNullValue) }) { it contains "hello" } } + val f0Immediate: F = { it feature { f(it::return0) } contains "hello" } + val f1Immediate: F = { it feature { f(it::return1, "a") } contains "hello" } + val f2Immediate: F = { it feature { f(it::return2, "a", 1) } contains "hello" } + val f3Immediate: F = { it feature { f(it::return3, "a", 1, true) } contains "hello" } + val f4Immediate: F = { it feature { f(it::return4, "a", 1, true, 1.2) } contains "hello" } + val f5Immediate: F = { it feature { f(it::return5, "a", 1, true, 1.2, 'b') } contains "hello" } + val f0Lazy: F = { it feature of({ f(it::return0) }) { it contains "hello" } } + val f1Lazy: F = { it feature of({ f(it::return1, "a") }) { it contains "hello" } } + val f2Lazy: F = { it feature of({ f(it::return2, "a", 1) }) { it contains "hello" } } + val f3Lazy: F = { it feature of({ f(it::return3, "a", 1, true) }) { it contains "hello" } } + val f4Lazy: F = { it feature of({ f(it::return4, "a", 1, true, 1.2) }) { it contains "hello" } } + val f5Lazy: F = { it feature of({ f(it::return5, "a", 1, true, 1.2, 'b') }) { it contains "hello" } } + + val propertyNullableDoesNotHold: F = { it feature { f(it::nullableValue) } toBe null } + val f0NullableDoesNotHold: F = { it feature { f(it::returnNullable0) } toBe null } + val f1NullableDoesNotHold: F = { it feature { f(it::returnNullable1, "a") } toBe null } + val f2NullableDoesNotHold: F = { it feature { f(it::returnNullable2, "a", 1) } toBe null } + val f3NullableDoesNotHold: F = { it feature { f(it::returnNullable3, "a", 1, true) } toBe null } + val f4NullableDoesNotHold: F = { it feature { f(it::returnNullable4, "a", 1, true, 1.2) } toBe null } + val f5NullableDoesNotHold: F = { it feature { f(it::returnNullable5, "a", 1, true, 1.2, 'b') } toBe null } + + val propertyNullableHolds: F = { it feature { f(it::nullableValue) } notToBeNull { it toBe 1 } } + val f0NullableHolds: F = { it feature { f(it::returnNullable0) } notToBeNull { it toBe 1 } } + val f1NullableHolds: F = { it feature { f(it::returnNullable1, "a") } notToBeNull { it toBe 1 } } + val f2NullableHolds: F = { it feature { f(it::returnNullable2, "a", 1) } notToBeNull { it toBe 1 } } + val f3NullableHolds: F = { it feature { f(it::returnNullable3, "a", 1, true) } notToBeNull { it toBe 1 } } + val f4NullableHolds: F = { it feature { f(it::returnNullable4, "a", 1, true, 1.2) } notToBeNull { it toBe 1 } } + val f5NullableHolds: F = { it feature { f(it::returnNullable5, "a", 1, true, 1.2, 'b') } notToBeNull { it toBe 1 } } + //@formatter:on + + val propertyLazyWithNestedImmediate: F = { + it feature of({ f(it::nonNullValue) }) { + feature { f(it::length) } toBe 12 + } + } + val propertyLazyWithNestedLazy: F = { + it feature of({ f(it::nonNullValue) }) { + feature { f(it::length) } it { it toBe 12 } + } + } + + val propertyEmptyAssertionCreator: F = { it feature of({ f(it::nonNullValue) }) {} } + val f0EmptyAssertionCreator: F = { it feature of({ f(it::return0) }) {} } + val f1EmptyAssertionCreator: F = { it feature of({ f(it::return1, "a") }) {} } + val f2EmptyAssertionCreator: F = { it feature of({ f(it::return2, "a", 1) }) {} } + val f3EmptyAssertionCreator: F = { it feature of({ f(it::return3, "a", 1, true) }) {} } + val f4EmptyAssertionCreator: F = { it feature of({ f(it::return4, "a", 1, true, 1.2) }) {} } + val f5EmptyAssertionCreator: F = + { it feature of({ f(it::return5, "a", 1, true, 1.2, 'b') }) {} } + } + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + val a1: Expect> = notImplemented() + val a1b: Expect> = notImplemented() + + val star: Expect> = notImplemented() + + a1 feature { f(it::size) } + a1 feature { f(it::size) } it {} + + a1b feature { f(it::size) } + a1b feature { f(it::size) } it {} + + star feature { f(it::size) } + star feature { f(it::size) } it {} + } +} + diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/FeatureAssertionsClassReferenceSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/FeatureAssertionsClassReferenceSpec.kt new file mode 100644 index 000000000..5eb91a462 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/FeatureAssertionsClassReferenceSpec.kt @@ -0,0 +1,126 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.integration.TestData +import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter + +class FeatureAssertionsClassReferenceSpec : ch.tutteli.atrium.specs.integration.FeatureAssertionsSpec( + propertyImmediate, + propertyLazy, + return0ValueImmediate, + return1ValueImmediate, + return2ValueImmediate, + return3ValueImmediate, + return4ValueImmediate, + return5ValueImmediate, + return0ValueLazy, + return1ValueLazy, + return2ValueLazy, + return3ValueLazy, + return4ValueLazy, + return5ValueLazy, + + propertyNullableDoesNotHold, + return0ValueNullableDoesNotHold, + return1ValueNullableDoesNotHold, + return2ValueNullableDoesNotHold, + return3ValueNullableDoesNotHold, + return4ValueNullableDoesNotHold, + return5ValueNullableDoesNotHold, + + propertyNullableHolds, + return0ValueNullableHolds, + return1ValueNullableHolds, + return2ValueNullableHolds, + return3ValueNullableHolds, + return4ValueNullableHolds, + return5ValueNullableHolds, + + propertyLazyWithNestedImmediate, + propertyLazyWithNestedLazy, + + propertyEmptyAssertionCreator, + f0EmptyAssertionCreator, + f1EmptyAssertionCreator, + f2EmptyAssertionCreator, + f3EmptyAssertionCreator, + f4EmptyAssertionCreator, + f5EmptyAssertionCreator, + + isAbleToEvaluateDescription = true +) { + + //TODO remove type parameters for `of` with Kotiln 1.4 including parentheses (make the calls infix again + companion object : WithAsciiReporter() { + //@formatter:off + val propertyImmediate: F = { it feature TestData::nonNullValue contains "hello" } + val propertyLazy: F = { it feature of(TestData::nonNullValue) { it contains "hello" } } + val return0ValueImmediate: F = { it feature TestData::return0 contains "hello" } + val return1ValueImmediate: F = { it feature of(TestData::return1, "a") contains "hello" } + val return2ValueImmediate: F = { it feature of(TestData::return2, "a", 1) contains "hello" } + val return3ValueImmediate: F = { it feature of(TestData::return3, "a", 1, true) contains "hello" } + val return4ValueImmediate: F = { it feature of(TestData::return4, "a", 1, true, 1.2) contains "hello" } + val return5ValueImmediate: F = { it feature of(TestData::return5, "a", 1, true, 1.2, 'b') contains "hello" } + val return0ValueLazy: F = { it feature of(TestData::return0) { contains("hello") } } + val return1ValueLazy: F = { it feature of(TestData::return1, "a") { contains("hello") } } + val return2ValueLazy: F = { it feature of(TestData::return2, "a", 1) { contains("hello") } } + val return3ValueLazy: F = { it feature of(TestData::return3, "a", 1, true) { contains("hello") } } + val return4ValueLazy: F = { it feature of(TestData::return4, "a", 1, true, 1.2) { contains("hello") } } + val return5ValueLazy: F = { it feature of(TestData::return5, "a", 1, true, 1.2, 'b') { contains("hello") } } + + val propertyNullableDoesNotHold: F = { it feature TestData::nullableValue toBe null } + val return0ValueNullableDoesNotHold: F = { it feature TestData::returnNullable0 toBe null } + val return1ValueNullableDoesNotHold: F = { it feature of(TestData::returnNullable1, "a") toBe null } + val return2ValueNullableDoesNotHold: F = { it feature of(TestData::returnNullable2, "a", 1) toBe null } + val return3ValueNullableDoesNotHold: F = { it feature of(TestData::returnNullable3, "a", 1, true) toBe null } + val return4ValueNullableDoesNotHold: F = { it feature of(TestData::returnNullable4, "a", 1, true, 1.2) toBe null } + val return5ValueNullableDoesNotHold: F = { it feature of(TestData::returnNullable5, "a", 1, true, 1.2, 'b') toBe null } + + val propertyNullableHolds: F = { it feature TestData::nullableValue notToBeNull { it toBe 1 } } + val return0ValueNullableHolds: F = { it feature TestData::returnNullable0 notToBeNull { it toBe 1 } } + val return1ValueNullableHolds: F = { it feature of(TestData::returnNullable1, "a") notToBeNull { it toBe 1 } } + val return2ValueNullableHolds: F = { it feature of(TestData::returnNullable2, "a", 1) notToBeNull { it toBe 1 } } + val return3ValueNullableHolds: F = { it feature of(TestData::returnNullable3, "a", 1, true) notToBeNull { it toBe 1 } } + val return4ValueNullableHolds: F = { it feature of(TestData::returnNullable4, "a", 1, true, 1.2) notToBeNull { it toBe 1 } } + val return5ValueNullableHolds: F = { it feature of(TestData::returnNullable5, "a", 1, true, 1.2, 'b') notToBeNull { it toBe 1 } } + //@formatter:on + + val propertyLazyWithNestedImmediate: F = { + it feature of(TestData::nonNullValue) { + it feature String::length toBe 12 + } + } + val propertyLazyWithNestedLazy: F = { + it feature of(TestData::nonNullValue) { + it feature of(String::length) { it toBe (12) } + } + } + + val propertyEmptyAssertionCreator: F = { it feature of(TestData::nonNullValue) {} } + val f0EmptyAssertionCreator: F = { it feature of(TestData::return0) {} } + val f1EmptyAssertionCreator: F = { it feature of(TestData::return1, "a") {} } + val f2EmptyAssertionCreator: F = { it feature of(TestData::return2, "a", 1) {} } + val f3EmptyAssertionCreator: F = { it feature of(TestData::return3, "a", 1, true) {} } + val f4EmptyAssertionCreator: F = { it feature of(TestData::return4, "a", 1, true, 1.2) {} } + val f5EmptyAssertionCreator: F = { it feature of(TestData::return5, "a", 1, true, 1.2, 'b') {} } + } + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + val a1: Expect> = notImplemented() + val a1b: Expect> = notImplemented() + + val star: Expect> = notImplemented() + + a1 feature Collection<*>::size + a1 feature of(Collection<*>::size) {} + + a1b feature Collection<*>::size + a1b feature of(Collection<*>::size) {} + + star feature Collection<*>::size + star feature of(Collection<*>::size) {} + } +} + diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/FeatureAssertionsManualSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/FeatureAssertionsManualSpec.kt new file mode 100644 index 000000000..e2514dbdb --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/FeatureAssertionsManualSpec.kt @@ -0,0 +1,119 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.infix.en_GB.workaround.it +import ch.tutteli.atrium.specs.integration.TestData +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter + + +class FeatureAssertionsManualSpec : ch.tutteli.atrium.specs.integration.FeatureAssertionsSpec( + propertyImmediate, + propertyLazy, + f0Immediate, + f1Immediate, + f2Immediate, + f3Immediate, + f4Immediate, + f5Immediate, + f0Lazy, + f1Lazy, + f2Lazy, + f3Lazy, + f4Lazy, + f5Lazy, + + propertyNullableDoesNotHold, + f0NullableDoesNotHold, + f1NullableDoesNotHold, + f2NullableDoesNotHold, + f3NullableDoesNotHold, + f4NullableDoesNotHold, + f5NullableDoesNotHold, + + propertyNullableHolds, + f0NullableHolds, + f1NullableHolds, + f2NullableHolds, + f3NullableHolds, + f4NullableHolds, + f5NullableHolds, + + propertyLazyWithNestedImmediate, + propertyLazyWithNestedLazy, + + propertyEmptyAssertionCreator, + f0EmptyAssertionCreator, + f1EmptyAssertionCreator, + f2EmptyAssertionCreator, + f3EmptyAssertionCreator, + f4EmptyAssertionCreator, + f5EmptyAssertionCreator, + + isAbleToEvaluateDescription = false +) { + //TODO remove type parameters for `of` with Kotiln 1.4 including parentheses (make the calls infix again + companion object : WithAsciiReporter() { + //@formatter:off + val propertyImmediate: F = { it feature { f("nonNullValue", it.nonNullValue) } contains "hello" } + + val propertyLazy: F = { it feature(of({ f("nonNullValue", it.nonNullValue) }) { it contains "hello" }) } + val f0Immediate: F = { it feature { f("return0()", it.return0()) } contains "hello" } + val f1Immediate: F = { it feature { f("return1(\"a\")", it.return1("a")) } contains "hello" } + val f2Immediate: F = { it feature { f("return2(\"a\", 1)", it.return2("a", 1)) } contains "hello" } + val f3Immediate: F = { it feature { f("return3(\"a\", 1, true)", it.return3("a", 1, true)) } contains "hello" } + val f4Immediate: F = { it feature { f("return4(\"a\", 1, true, 1.2)", it.return4("a", 1, true, 1.2)) } contains "hello" } + val f5Immediate: F = { it feature { f("return5(\"a\", 1, true, 1.2, 'b')", it.return5("a", 1, true, 1.2, 'b')) } contains "hello" } + val f0Lazy: F = { it feature of({ f("return0()", it.return0()) }) { it contains "hello" } } + val f1Lazy: F = { it feature of({ f("return1(\"a\")", it.return1("a")) }) { it contains "hello" } } + val f2Lazy: F = { it feature of({ f("return2(\"a\", 1)", it.return2("a", 1)) }) { it contains "hello" } } + val f3Lazy: F = { it feature of({ f("return3(\"a\", 1, true)", it.return3("a", 1, true)) }) { it contains "hello" } } + val f4Lazy: F = { it feature of({ f("return4(\"a\", 1, true, 1.2)", it.return4("a", 1, true, 1.2)) }) { it contains "hello" } } + val f5Lazy: F = { it feature of({ f("return5(\"a\", 1, true, 1.2, 'b')", it.return5("a", 1, true, 1.2, 'b')) }) { it contains "hello" } } + + val propertyNullableDoesNotHold: F = { it feature { f("nullableValue", it.nullableValue) } toBe null } + val f0NullableDoesNotHold: F = { it feature { f("returnNullable0()", it.returnNullable0()) } toBe null } + val f1NullableDoesNotHold: F = { it feature { f("returnNullable1(\"a\")", it.returnNullable1("a")) } toBe null } + val f2NullableDoesNotHold: F = { it feature { f("returnNullable2(\"a\", 1)", it.returnNullable2("a", 1)) } toBe null } + val f3NullableDoesNotHold: F = { it feature { f("returnNullable3(\"a\", 1, true)", it.returnNullable3("a", 1, true)) } toBe null } + val f4NullableDoesNotHold: F = { it feature { f("returnNullable4(\"a\", 1, true, 1.2)", it.returnNullable4("a", 1, true, 1.2)) } toBe null } + val f5NullableDoesNotHold: F = { it feature { f("returnNullable5(\"a\", 1, true, 1.2, 'b')", it.returnNullable5("a", 1, true, 1.2, 'b')) } toBe null } + + val propertyNullableHolds: F = { it feature { f("nullableValue", it.nullableValue) } notToBeNull { it toBe 1 } } + val f0NullableHolds: F = { it feature { f("returnNullable0()", it.returnNullable0()) } notToBeNull { it toBe 1 } } + val f1NullableHolds: F = { it feature { f("returnNullable1(\"a\")", it.returnNullable1("a")) } notToBeNull { it toBe 1 } } + val f2NullableHolds: F = { it feature { f("returnNullable2(\"a\", 1)", it.returnNullable2("a", 1)) } notToBeNull { it toBe 1 } } + val f3NullableHolds: F = { it feature { f("returnNullable3(\"a\", 1, true)", it.returnNullable3("a", 1, true)) } notToBeNull { it toBe 1 } } + val f4NullableHolds: F = { it feature { f("returnNullable4(\"a\", 1, true, 1.2)", it.returnNullable4("a", 1, true, 1.2)) } notToBeNull { it toBe 1 } } + val f5NullableHolds: F = { it feature { f("returnNullable5(\"a\", 1, true, 1.2, 'b')", it.returnNullable5("a", 1, true, 1.2, 'b')) } notToBeNull { it toBe 1 } } + //@formatter:on + + val propertyLazyWithNestedImmediate: F = { + it feature of({ f("nonNullValue", it.nonNullValue) }) { + feature { f("length", it.length) } toBe 12 + } + } + val propertyLazyWithNestedLazy: F = { + it feature of({ f("nonNullValue", it.nonNullValue) }) { + feature { f("length", it.length) } it { it toBe 12 } + } + } + + val propertyEmptyAssertionCreator: F = + { it feature of({ f("nonNullValue", it.nonNullValue) }) {} } + val f0EmptyAssertionCreator: F = { it feature of({ f("return0()", it.return0()) }) {} } + val f1EmptyAssertionCreator: F = + { it feature of({ f("return1(\"a\")", it.return1("a")) }) {} } + val f2EmptyAssertionCreator: F = + { it feature of({ f("return2(\"a\", 1)", it.return2("a", 1)) }) {} } + val f3EmptyAssertionCreator: F = + { it feature of({ f("return3(\"a\", 1, true)", it.return3("a", 1, true)) }) {} } + val f4EmptyAssertionCreator: F = + { it feature of({ f("return4(\"a\", 1, true, 1.2)", it.return4("a", 1, true, 1.2)) }) {} } + val f5EmptyAssertionCreator: F = + { + it feature of({ + f("return5(\"a\", 1, true, 1.2, 'b')", it.return5("a", 1, true, 1.2, 'b')) + }) {} + } + } +} + diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/FeatureWorstCaseTest.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/FeatureWorstCaseTest.kt new file mode 100644 index 000000000..7d69a4bd0 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/FeatureWorstCaseTest.kt @@ -0,0 +1,27 @@ +@file:Suppress("UNUSED_PARAMETER", "unused") + +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.verbs.internal.expect +import kotlin.js.JsName + +class WorstCase { + + val propAndFun: Int = 1 + @JsName("propFun") + fun propAndFun(): Int = 1 + + fun overloaded(): Int = 1 + fun overloaded(b: Boolean): Int = 1 +} + + +@Suppress(/* requires new type inference */ "RemoveExplicitTypeArguments") +fun testOverloadAmbiguity() { + expect(WorstCase()) { + feature { p(it::propAndFun) } + feature { f0(it::propAndFun) } + feature { f0(it::overloaded) } + feature { f1(it::overloaded, true) } + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/Fun0AssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/Fun0AssertionsSpec.kt index 9c6f7db72..6c53d3f42 100644 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/Fun0AssertionsSpec.kt +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/Fun0AssertionsSpec.kt @@ -1,26 +1,27 @@ package ch.tutteli.atrium.api.infix.en_GB -import ch.tutteli.atrium.api.infix.en_GB.testutils.WithAsciiReporter import ch.tutteli.atrium.creating.Expect -import ch.tutteli.atrium.reporting.ReporterFactory +import ch.tutteli.atrium.specs.feature0 +import ch.tutteli.atrium.specs.feature1 import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter +import ch.tutteli.atrium.specs.withFeatureSuffix class Fun0AssertionsSpec : ch.tutteli.atrium.specs.integration.Fun0AssertionsSpec( - "toThrow (feature)" to Companion::toThrowFeature, + ("toThrow" to Companion::toThrowFeature).withFeatureSuffix(), "toThrow" to Companion::toThrow, - "notToThrow (feature)" to Companion::notToThrowFeature, - "notToThrow" to Companion::notToThrow, + feature0<() -> Int, Int>(Expect<() -> Int>::notToThrow), + feature1<() -> Int, Expect.() -> Unit, Int>(Expect<() -> Int>::notToThrow), "- ", "» " ) { companion object : WithAsciiReporter() { + private fun toThrowFeature(expect: Expect Any?>) = + expect.toThrow() - fun toThrowFeature(expect: Expect Any?>) = expect.toThrow() - fun toThrow(expect: Expect Any?>, assertionCreator: Expect.() -> Unit) = - expect.toThrow { assertionCreator() } - - fun notToThrowFeature(expect: Expect<() -> Int>) = expect.notToThrow() - fun notToThrow(expect: Expect<() -> Int>, assertionCreator: Expect.() -> Unit) = - expect.notToThrow { assertionCreator() } + private fun toThrow( + expect: Expect Any?>, + assertionCreator: Expect.() -> Unit + ) = expect.toThrow { assertionCreator() } } @Suppress("unused", "UNUSED_VALUE", "UNUSED_VARIABLE") @@ -41,3 +42,4 @@ class Fun0AssertionsSpec : ch.tutteli.atrium.specs.integration.Fun0AssertionsSpe val r8: Expect = a2.notToThrow {} } } + diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableAllAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableAllAssertionsSpec.kt index db4b521b1..48caa24d3 100644 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableAllAssertionsSpec.kt +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableAllAssertionsSpec.kt @@ -1,38 +1,30 @@ package ch.tutteli.atrium.api.infix.en_GB -import ch.tutteli.atrium.api.infix.en_GB.testutils.WithAsciiReporter import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.specs.fun1 -import ch.tutteli.atrium.specs.name import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter +import ch.tutteli.atrium.specs.withNullableSuffix class IterableAllAssertionsSpec : ch.tutteli.atrium.specs.integration.IterableAllAssertionsSpec( - fun1(Expect>::all).name to Companion::all, - fun1(Expect>::all).name to Companion::allNullable, + fun1(Expect>::all), + fun1(Expect>::all).withNullableSuffix(), "* ", "(!) ", "- ", "» ", ">> ", "=> " ) { - companion object : WithAsciiReporter() { - fun all(expect: Expect>, assertionCreator: Expect.() -> Unit) = - expect all assertionCreator - - fun allNullable(expect: Expect>, assertionCreator: (Expect.() -> Unit)?) = - expect all assertionCreator - } + companion object : WithAsciiReporter() @Suppress("unused", "UNUSED_VALUE") private fun ambiguityTest() { - var a1: Expect> = notImplemented() - var a1b: Expect> = notImplemented() + var a1: Expect> = notImplemented() + var a1b: Expect> = notImplemented() var star: Expect> = notImplemented() - a1 = a1.all {} + a1 = a1 all {} - a1b = a1b.all {} - a1b = a1b.all(null) + a1b = a1b all {} + a1b = a1b all null - star = star.all {} + star = star all {} } } - - diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableAnyAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableAnyAssertionsSpec.kt new file mode 100644 index 000000000..03d3584ed --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableAnyAssertionsSpec.kt @@ -0,0 +1,111 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.specs.fun1 +import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.withNullableSuffix +import org.spekframework.spek2.Spek +import kotlin.reflect.KFunction2 + +class IterableAnyAssertionsSpec : Spek({ + include(PredicateSpec) + include(BuilderSpec) + include(ShortcutSpec) + include(SequenceSpec) +}) { + object PredicateSpec : ch.tutteli.atrium.specs.integration.IterableAnyAssertionsSpec( + fun1(Expect>::any), + fun1(Expect>::any).withNullableSuffix(), + "* ", + "[Atrium][Predicate] " + ) + + object BuilderSpec : ch.tutteli.atrium.specs.integration.IterableAnyAssertionsSpec( + getContainsPair(), + getContainsNullablePair().withNullableSuffix(), + "* ", + "[Atrium][Builder] " + ) + + object ShortcutSpec : ch.tutteli.atrium.specs.integration.IterableAnyAssertionsSpec( + getContainsShortcutPair(), + getContainsNullableShortcutPair().withNullableSuffix(), + "* ", + "[Atrium][Shortcut] " + ) + + object SequenceSpec : ch.tutteli.atrium.specs.integration.IterableAnyAssertionsSpec( + getContainsSequencePair(), + getContainsNullableSequencePair().withNullableSuffix(), + "* ", + "[Atrium][Sequence] " + ) + + companion object : IterableContainsSpecBase() { + fun getContainsPair() = + "$contains $filler $inAnyOrder $atLeast 1 entry" to Companion::containsInAnyOrderEntry + + private fun containsInAnyOrderEntry(expect: Expect>, a: Expect.() -> Unit) = + expect contains o inAny order atLeast 1 entry a + + fun getContainsNullablePair() = + "$contains $filler $inAnyOrder $atLeast 1 entry" to Companion::containsNullableEntry + + private fun containsNullableEntry(expect: Expect>, a: (Expect.() -> Unit)?) = + expect contains o inAny order atLeast 1 entry a + + private val containsShortcutFun: KFunction2>, Expect.() -> Unit, Expect>> = + Expect>::contains + + fun getContainsShortcutPair() = containsShortcutFun.name to Companion::containsInAnyOrderEntryShortcut + + private fun containsInAnyOrderEntryShortcut(expect: Expect>, a: Expect.() -> Unit) = + expect contains a + + private val containsShortcutNullableFun: KFunction2>, (Expect.() -> Unit)?, Expect>> = + Expect>::contains + + fun getContainsNullableShortcutPair() = + containsShortcutNullableFun.name to Companion::containsNullableEntryShortcut + + private fun containsNullableEntryShortcut( + expect: Expect>, + a: (Expect.() -> Unit)? + ) = expect contains a + + + private fun getContainsSequencePair() = + "asSequence().${Sequence<*>::asIterable.name}() ${containsShortcutFun.name}" to Companion::containsInAnyOrderEntrySequence + + private fun containsInAnyOrderEntrySequence(expect: Expect>, a: Expect.() -> Unit) = + ExpectImpl.changeSubject(expect).unreported { it.asSequence() } asIterable o contains a + + fun getContainsNullableSequencePair() = + "asSequence().${Sequence<*>::asIterable.name}() ${containsShortcutNullableFun.name}" to Companion::containsNullableEntrySequence + + private fun containsNullableEntrySequence( + expect: Expect>, + a: (Expect.() -> Unit)? + ) = ExpectImpl.changeSubject(expect).unreported { it.asSequence() } asIterable o contains a + } + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + var a1: Expect> = notImplemented() + var a1b: Expect> = notImplemented() + + var star: Expect> = notImplemented() + + a1 = a1 any {} + a1 = a1 contains {} + + a1b = a1b any {} + a1b = a1b any null + a1b = a1b contains {} + a1b = a1b contains (null as Double?) + + star = star any {} + star = star contains {} + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableAssertionsSpec.kt new file mode 100644 index 000000000..b20531ca9 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableAssertionsSpec.kt @@ -0,0 +1,39 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter +import kotlin.reflect.KFunction2 + +class IterableAssertionsSpec : ch.tutteli.atrium.specs.integration.IterableAssertionsSpec( + getHasNextPair(), + getHasNotNextPair() +) { + companion object : WithAsciiReporter() { + private val has: KFunction2>, next, Expect>> = Expect>::has + private fun getHasNextPair() = "${has.name} ${next::class.simpleName}" to Companion::hasNext + private fun hasNext(expect: Expect>) = expect has next + + private val hasNot: KFunction2>, next, Expect>> = + Expect>::hasNot + + private fun getHasNotNextPair() = "${hasNot.name} ${next::class.simpleName}" to Companion::hasNotNext + private fun hasNotNext(expect: Expect>) = expect hasNot next + } + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + var a1: Expect> = notImplemented() + var a1b: Expect> = notImplemented() + var star: Expect> = notImplemented() + + a1 = a1 has next + a1 = a1 hasNot next + + a1b = a1b has next + a1b = a1b hasNot next + + star = star has next + star = star hasNot next + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderAtLeast1ElementsOfAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderAtLeast1ElementsOfAssertionsSpec.kt new file mode 100644 index 000000000..38716fd5e --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderAtLeast1ElementsOfAssertionsSpec.kt @@ -0,0 +1,46 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.verbs.internal.expect +import ch.tutteli.atrium.creating.Expect +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.describe + +class IterableContainsInAnyOrderAtLeast1ElementsOfAssertionsSpec : Spek({ + include(BuilderSpec) + + describe("elementsOf") { + it("passing an empty iterable throws an IllegalArgumentException") { + expect { + expect(listOf(1, 2)) contains o inAny order atLeast 1 elementsOf listOf() + }.toThrow() + } + } +}) { + object BuilderSpec : ch.tutteli.atrium.specs.integration.IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec( + getContainsPair(), + getContainsNullablePair(), + "* ", + "[Atrium][Builder] " + ) + + companion object : IterableContainsSpecBase() { + fun getContainsPair() = + "$contains $filler $inAnyOrder $atLeast 1 $inAnyOrderElementsOf" to Companion::containsValues + + private fun containsValues( + expect: Expect>, + a: Double, + aX: Array + ): Expect> = expect contains o inAny order atLeast 1 elementsOf listOf(a, *aX) + + fun getContainsNullablePair() = + "$contains $filler $inAnyOrder $atLeast 1 $inAnyOrderElementsOf" to Companion::containsNullableValues + + private fun containsNullableValues( + expect: Expect>, + a: Double?, + aX: Array + ): Expect> = expect contains o inAny order atLeast 1 elementsOf listOf(a, *aX) + + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderAtLeast1EntriesAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderAtLeast1EntriesAssertionsSpec.kt new file mode 100644 index 000000000..78849e7b7 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderAtLeast1EntriesAssertionsSpec.kt @@ -0,0 +1,75 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import org.spekframework.spek2.Spek +import kotlin.reflect.KFunction2 + +class IterableContainsInAnyOrderAtLeast1EntriesAssertionsSpec : Spek({ + include(BuilderSpec) + include(ShortcutSpec) +}) { + object BuilderSpec : ch.tutteli.atrium.specs.integration.IterableContainsInAnyOrderAtLeast1EntriesAssertionsSpec( + getContainsPair(), + getContainsNullablePair(), + "* ", + "[Atrium][Builder] " + ) + + object ShortcutSpec : ch.tutteli.atrium.specs.integration.IterableContainsInAnyOrderAtLeast1EntriesAssertionsSpec( + getContainsShortcutPair(), + getContainsNullableShortcutPair(), + "* ", + "[Atrium][Shortcut] " + ) + + companion object : IterableContainsSpecBase() { + fun getContainsPair() = + "$contains $filler $inAnyOrder $atLeast 1 $inAnyOrderEntries" to Companion::containsInAnyOrderEntries + + private fun containsInAnyOrderEntries( + expect: Expect>, + a: Expect.() -> Unit, + aX: Array.() -> Unit> + ): Expect> = + if (aX.isEmpty()) expect contains o inAny order atLeast 1 entry a + else expect contains o inAny order atLeast 1 the entries(a, *aX) + + fun getContainsNullablePair() = + "$contains $filler $inAnyOrder $atLeast 1 $inAnyOrderEntries" to Companion::containsNullableEntries + + private fun containsNullableEntries( + expect: Expect>, + a: (Expect.() -> Unit)?, + aX: Array.() -> Unit)?> + ): Expect> = + if (aX.isEmpty()) expect contains o inAny order atLeast 1 entry a + else expect contains o inAny order atLeast 1 the entries(a, *aX) + + + private val containsShortcutFun: KFunction2>, Expect.() -> Unit, Expect>> = + Expect>::contains + + fun getContainsShortcutPair() = containsShortcutFun.name to Companion::containsInAnyOrderEntriesShortcut + + private fun containsInAnyOrderEntriesShortcut( + expect: Expect>, + a: Expect.() -> Unit, + aX: Array.() -> Unit> + ): Expect> = + if (aX.isEmpty()) expect contains a + else expect contains entries(a, *aX) + + private val containsEntriesFun: KFunction2>, (Expect.() -> Unit)?, Expect>> = + Expect>::contains + + fun getContainsNullableShortcutPair() = containsEntriesFun.name to Companion::containsNullableEntriesShortcut + + private fun containsNullableEntriesShortcut( + expect: Expect>, + a: (Expect.() -> Unit)?, + aX: Array.() -> Unit)?> + ): Expect> = + if (aX.isEmpty()) expect contains a + else expect contains entries(a, *aX) + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec.kt new file mode 100644 index 000000000..76ec10a79 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec.kt @@ -0,0 +1,77 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import org.spekframework.spek2.Spek +import kotlin.reflect.KFunction2 + +class IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec : Spek({ + include(BuilderSpec) + include(ShortcutSpec) +}) { + object BuilderSpec : ch.tutteli.atrium.specs.integration.IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec( + getContainsPair(), + getContainsNullablePair(), + "* ", + "[Atrium][Builder] " + ) + + object ShortcutSpec : ch.tutteli.atrium.specs.integration.IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec( + getContainsShortcutPair(), + getContainsNullableShortcutPair(), + "* ", + "[Atrium][Shortcut] " + ) + + companion object : IterableContainsSpecBase() { + fun getContainsPair() = + "$contains $filler $inAnyOrder $atLeast 1 $inAnyOrderValues" to Companion::containsValues + + private fun containsValues( + expect: Expect>, + a: Double, + aX: Array + ): Expect> = + if (aX.isEmpty()) expect contains o inAny order atLeast 1 value a + else expect contains o inAny order atLeast 1 the values(a, *aX) + + fun getContainsNullablePair() = + "$contains $filler $inAnyOrder $atLeast 1 $inAnyOrderValues" to Companion::containsNullableValues + + private fun containsNullableValues( + expect: Expect>, + a: Double?, + aX: Array + ): Expect> = + if (aX.isEmpty()) expect contains o inAny order atLeast 1 value a + else expect contains o inAny order atLeast 1 the values(a, *aX) + + + private val containsFun: KFunction2>, Double, Expect>> = + Expect>::contains + + fun getContainsShortcutPair() = containsFun.name to Companion::containsValuesShortcut + + private fun containsValuesShortcut( + expect: Expect>, + a: Double, + aX: Array + ): Expect> = + if (aX.isEmpty()) expect contains a + else expect contains values(a, *aX) + + + private val containsNullableFun: KFunction2>, Double?, Expect>> = + Expect>::contains + + fun getContainsNullableShortcutPair() = containsNullableFun.name to Companion::containsNullableValuesShortcut + + private fun containsNullableValuesShortcut( + expect: Expect>, + a: Double?, + aX: Array + ): Expect> = + if (aX.isEmpty()) expect contains a + else expect contains values(a, *aX) + + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderAtLeastValuesAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderAtLeastValuesAssertionsSpec.kt new file mode 100644 index 000000000..0368a99b3 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderAtLeastValuesAssertionsSpec.kt @@ -0,0 +1,55 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect + +class IterableContainsInAnyOrderAtLeastValuesAssertionsSpec : + ch.tutteli.atrium.specs.integration.IterableContainsInAnyOrderAtLeastValuesAssertionSpec( + getAtLeastTriple(), + getAtLeastButAtMostTriple(), + getContainsNotPair(), + getExactlyPair(), + Companion::getErrorMsgAtLeastButAtMost, + "* " + ) { + + companion object : IterableContainsSpecBase() { + + internal fun getAtLeastTriple() = + { what: String, times: String -> "$contains $what in any order $atLeast $times" } to + ("$contains $filler $inAnyOrder $atLeast" to Companion::containsAtLeast) + + private fun containsAtLeast( + expect: Expect>, + atLeast: Int, + a: Double, + aX: Array + ): Expect> = + if (aX.isEmpty()) expect contains o inAny order atLeast atLeast value a + else expect contains o inAny order atLeast atLeast the values(a, *aX) + + + private fun getAtLeastButAtMostTriple() = + { what: String, timesAtLeast: String, timesAtMost: String -> "$contains $what $atLeast $timesAtLeast $butAtMost $timesAtMost" } to + ("$contains $filler $atLeast $butAtMost" to Companion::containsAtLeastButAtMost) + + private fun containsAtLeastButAtMost( + expect: Expect>, + atLeast: Int, + butAtMost: Int, + a: Double, + aX: Array + ) = expect contains o inAny order atLeast atLeast butAtMost butAtMost the values(a, *aX) + + private fun getContainsNotPair() = containsNot to Companion::getErrorMsgContainsNot + + private fun getErrorMsgContainsNot(times: Int) = "use `$containsNot` instead of `$atLeast $times`" + + private fun getExactlyPair() = exactly to Companion::getErrorMsgExactly + + private fun getErrorMsgExactly(times: Int) = + "use `$exactly $times` instead of `$atLeast $times $butAtMost $times`" + + internal fun getErrorMsgAtLeastButAtMost(timesAtLeast: Int, timesButAtMost: Int) = + "specifying `$butAtMost $timesButAtMost` does not make sense if `$atLeast $timesAtLeast` was used before" + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderAtMostValuesAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderAtMostValuesAssertionsSpec.kt new file mode 100644 index 000000000..b352121a4 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderAtMostValuesAssertionsSpec.kt @@ -0,0 +1,33 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect + +class IterableContainsInAnyOrderAtMostValuesAssertionsSpec : + ch.tutteli.atrium.specs.integration.IterableContainsInAnyOrderAtMostValuesAssertionSpec( + getAtMostTriple(), + getContainsNotPair(), + getExactlyPair(), + "* " + ) { + + companion object : IterableContainsSpecBase() { + + private fun getAtMostTriple() = + { what: String, times: String -> "$contains $what $atMost $times" } to + ("$contains $filler $inAnyOrder $atMost" to Companion::containsAtMost) + + private fun containsAtMost(expect: Expect>, atMost: Int, a: Double, aX: Array) = + if(aX.isEmpty()) expect contains o inAny order atMost atMost value a + else expect contains o inAny order atMost atMost the values(a, *aX) + + + private fun getContainsNotPair() = containsNot to Companion::getErrorMsgContainsNot + + private fun getErrorMsgContainsNot(times: Int) = "use `$containsNot` instead of `$atMost $times`" + + private fun getExactlyPair() = exactly to Companion::getErrorMsgExactly + + private fun getErrorMsgExactly(times: Int) = + "use `$exactly $times` instead of `$atMost $times`; `$atMost $times` defines implicitly `$atLeast $times` as well" + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderExactlyValuesAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderExactlyValuesAssertionsSpec.kt new file mode 100644 index 000000000..0359da21a --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderExactlyValuesAssertionsSpec.kt @@ -0,0 +1,32 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect + +class IterableContainsInAnyOrderExactlyValuesAssertionsSpec : + ch.tutteli.atrium.specs.integration.IterableContainsInAnyOrderExactlyValuesAssertionsSpec( + getExactlyTriple(), + getContainsNotPair(), + "* " + ) { + + companion object : IterableContainsSpecBase() { + + private fun getExactlyTriple() = + { what: String, times: String -> "$contains $what $exactly $times" } to + ("$contains $filler $inAnyOrder $exactly" to Companion::containsExactly) + + private fun containsExactly( + expect: Expect>, + exactly: Int, + a: Double, + aX: Array + ): Expect> = + if (aX.isEmpty()) expect contains o inAny order exactly exactly value a + else expect contains o inAny order exactly exactly the values(a, *aX) + + private fun getContainsNotPair() = containsNot to Companion::getErrorMsgContainsNot + + private fun getErrorMsgContainsNot(times: Int) = "use `$containsNot` instead of `$exactly $times`" + + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderNotOrAtMostValuesAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderNotOrAtMostValuesAssertionsSpec.kt new file mode 100644 index 000000000..b604411be --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderNotOrAtMostValuesAssertionsSpec.kt @@ -0,0 +1,32 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect + +class IterableContainsInAnyOrderNotOrAtMostValuesAssertionsSpec : + ch.tutteli.atrium.specs.integration.IterableContainsInAnyOrderNotOrAtMostValuesAssertionsSpec( + getNotOrAtMostTriple(), + getContainsNotPair(), + "* " + ) { + + companion object : IterableContainsSpecBase() { + + private fun getNotOrAtMostTriple() = + { what: String, times: String -> "$contains $what $notOrAtMost $times" } to + ("$contains $filler $notOrAtMost" to Companion::containsNotOrAtMost) + + private fun containsNotOrAtMost( + expect: Expect>, + atMost: Int, + a: Double, + aX: Array + ) = + if (aX.isEmpty()) expect contains o inAny order notOrAtMost atMost value a + else expect contains o inAny order notOrAtMost atMost the values(a, *aX) + + private fun getContainsNotPair() = containsNot to Companion::getErrorMsgContainsNot + + private fun getErrorMsgContainsNot(times: Int) = "use `$containsNot` instead of `$notOrAtMost $times`" + + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderOnlyElementsOfAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderOnlyElementsOfAssertionsSpec.kt new file mode 100644 index 000000000..44caf4220 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderOnlyElementsOfAssertionsSpec.kt @@ -0,0 +1,44 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.verbs.internal.expect +import ch.tutteli.atrium.creating.Expect +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.describe + +class IterableContainsInAnyOrderOnlyElementsOfAssertionSpec : Spek({ + include(BuilderSpec) + + describe("elementsOf") { + it("passing an empty iterable throws an IllegalArgumentException") { + expect { + expect(listOf(1, 2)) contains o inAny order but only elementsOf listOf() + }.toThrow() + } + } +}) { + object BuilderSpec : ch.tutteli.atrium.specs.integration.IterableContainsInAnyOrderOnlyValuesAssertionsSpec( + getContainsPair(), + getContainsNullablePair(), + "* ", "(/) ", "(x) ", "(!) ", "- ", "» " + ) + + companion object : IterableContainsSpecBase() { + fun getContainsPair() = + "$contains $filler $inAnyOrder $butOnly $inAnyOrderOnlyElementsOf" to Companion::getContainsValues + + private fun getContainsValues( + expect: Expect>, + a: Double, + aX: Array + ): Expect> = expect contains o inAny order but only elementsOf listOf(a, *aX) + + fun getContainsNullablePair() = + "$contains $filler $inAnyOrder $butOnly $inAnyOrderOnlyElementsOf" to Companion::getContainsNullableValues + + private fun getContainsNullableValues( + expect: Expect>, + a: Double?, + aX: Array + ): Expect> = expect contains o inAny order but only elementsOf listOf(a, *aX) + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderOnlyEntriesAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderOnlyEntriesAssertionsSpec.kt new file mode 100644 index 000000000..4e38603d9 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderOnlyEntriesAssertionsSpec.kt @@ -0,0 +1,36 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect + +class IterableContainsInAnyOrderOnlyEntriesAssertionsSpec : + ch.tutteli.atrium.specs.integration.IterableContainsInAnyOrderOnlyEntriesAssertionsSpec( + getContainsPair(), + getContainsNullablePair(), + "* ", "(/) ", "(x) ", "(!) ", "- ", "» " + ) { + companion object : IterableContainsSpecBase() { + fun getContainsPair() = + "$contains $filler $inAnyOrder $butOnly $inAnyOrderOnlyEntries" to Companion::containsInAnyOrderOnlyEntries + + private fun containsInAnyOrderOnlyEntries( + expect: Expect>, + a: Expect.() -> Unit, + aX: Array.() -> Unit> + ): Expect> = + if (aX.isEmpty()) expect contains o inAny order but only entry a + else expect contains o inAny order but only the entries(a, *aX) + + + fun getContainsNullablePair() = + "$contains $filler $inAnyOrder $butOnly $inAnyOrderOnlyEntries" to Companion::containsInAnyOrderOnlyNullableEntries + + private fun containsInAnyOrderOnlyNullableEntries( + expect: Expect>, + a: (Expect.() -> Unit)?, + aX: Array.() -> Unit)?> + ): Expect> = + if (aX.isEmpty()) expect contains o inAny order but only entry a + else expect contains o inAny order but only the entries(a, *aX) + + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderOnlyValuesAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderOnlyValuesAssertionsSpec.kt new file mode 100644 index 000000000..c3c3cefef --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInAnyOrderOnlyValuesAssertionsSpec.kt @@ -0,0 +1,36 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect + +class IterableContainsInAnyOrderOnlyValuesAssertionsSpec : + ch.tutteli.atrium.specs.integration.IterableContainsInAnyOrderOnlyValuesAssertionsSpec( + getContainsPair(), + getContainsNullablePair(), + "* ", "(/) ", "(x) ", "(!) ", "- " + ) { + companion object : IterableContainsSpecBase() { + fun getContainsPair() = + "$contains $filler $inAnyOrder $butOnly $inAnyOrderOnlyValues" to Companion::containsInAnyOrderOnlyValues + + private fun containsInAnyOrderOnlyValues( + expect: Expect>, + a: Double, + aX: Array + ): Expect> = + if (aX.isEmpty()) expect contains o inAny order but only value a + else expect contains o inAny order but only the values(a, *aX) + + + fun getContainsNullablePair() = + "$contains $filler $inAnyOrder $butOnly $inAnyOrderOnlyValues" to Companion::containsInAnyOrderOnlyNullableValues + + private fun containsInAnyOrderOnlyNullableValues( + expect: Expect>, + a: Double?, + aX: Array + ): Expect> = + if (aX.isEmpty()) expect contains o inAny order but only value a + else expect contains o inAny order but only the values(a, *aX) + + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInOrderOnlyElementsOfAssertionSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInOrderOnlyElementsOfAssertionSpec.kt new file mode 100644 index 000000000..3ce54fc7d --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInOrderOnlyElementsOfAssertionSpec.kt @@ -0,0 +1,36 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import org.spekframework.spek2.Spek + +class IterableContainsInOrderOnlyElementsOfAssertionSpec : Spek({ + include(BuilderSpec) +}) { + object BuilderSpec : ch.tutteli.atrium.specs.integration.IterableContainsInOrderOnlyValuesAssertionsSpec( + getContainsPair(), + getContainsNullablePair(), + "* ", "(/) ", "(x) ", "(!) ", "- ", ">> ", "=> ", + "[Atrium][Builder] " + ) + + companion object : IterableContainsSpecBase() { + fun getContainsPair() = + "$contains $filler $inOrder $andOnly $inOrderElementsOf" to Companion::containsInOrderOnlyValues + + private fun containsInOrderOnlyValues( + expect: Expect>, + a: Double, + aX: Array + ): Expect> = expect contains o inGiven order and only elementsOf listOf(a, *aX) + + fun getContainsNullablePair() = + "$contains $filler $inOrder $andOnly $inOrderElementsOf" to Companion::containsInOrderOnlyNullableValues + + private fun containsInOrderOnlyNullableValues( + expect: Expect>, + a: Double?, + aX: Array + ): Expect> = expect contains o inGiven order and only elementsOf listOf(a, *aX) + } +} + diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInOrderOnlyEntriesAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInOrderOnlyEntriesAssertionsSpec.kt new file mode 100644 index 000000000..77419490b --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInOrderOnlyEntriesAssertionsSpec.kt @@ -0,0 +1,82 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import org.spekframework.spek2.Spek +import kotlin.reflect.KFunction2 + +class IterableContainsInOrderOnlyEntriesAssertionsSpec : Spek({ + + include(BuilderSpec) + include(ShortcutSpec) + +}) { + object BuilderSpec : ch.tutteli.atrium.specs.integration.IterableContainsInOrderOnlyEntriesAssertionsSpec( + getContainsPair(), + getContainsNullablePair(), + "* ", "(/) ", "(x) ", "(!) ", "- ", "» ", ">> ", "=> ", + "[Atrium][Builder] " + ) + + object ShortcutSpec : ch.tutteli.atrium.specs.integration.IterableContainsInOrderOnlyEntriesAssertionsSpec( + getContainsShortcutPair(), + getContainsNullableShortcutPair(), + "* ", "(/) ", "(x) ", "(!) ", "- ", "» ", ">> ", "=> ", + "[Atrium][Shortcut] " + ) + + companion object : IterableContainsSpecBase() { + fun getContainsPair() = + "$contains $filler $inOrder $andOnly $inOrderOnlyEntries" to Companion::containsInOrderOnly + + private fun containsInOrderOnly( + expect: Expect>, + a: Expect.() -> Unit, + aX: Array.() -> Unit> + ): Expect> = + if (aX.isEmpty()) expect contains o inGiven order and only entry a + else expect contains o inGiven order and only the entries(a, *aX) + + fun getContainsNullablePair() = + "$contains $filler $inOrder $andOnly $inOrderOnlyEntries" to Companion::containsInOrderOnlyNullableEntriesPair + + private fun containsInOrderOnlyNullableEntriesPair( + expect: Expect>, + a: (Expect.() -> Unit)?, + aX: Array.() -> Unit)?> + ): Expect> = + if (aX.isEmpty()) expect contains o inGiven order and only entry a + else expect contains o inGiven order and only the entries(a, *aX) + + private val containsShortcutFun: KFunction2>, Expect.() -> Unit, Expect>> = + Expect>::containsExactly + + fun getContainsShortcutPair() = containsShortcutFun.name to Companion::containsInOrderOnlyEntriesShortcut + + private fun containsInOrderOnlyEntriesShortcut( + expect: Expect>, + a: Expect.() -> Unit, + aX: Array.() -> Unit> + ): Expect> = + if (aX.isEmpty()) expect containsExactly { a() } + else expect containsExactly entries(a, *aX) + + private val containsNullableShortcutFun: KFunction2>, (Expect.() -> Unit)?, Expect>> = + Expect>::containsExactly + + fun getContainsNullableShortcutPair() = + containsNullableShortcutFun.name to Companion::containsInOrderOnlyNullableEntriesShortcut + + private fun containsInOrderOnlyNullableEntriesShortcut( + expect: Expect>, + a: (Expect.() -> Unit)?, + aX: Array.() -> Unit)?> + ): Expect> = + if (aX.isEmpty()) { + //TODO should work without cast, remove as soon as KT-6591 is fixed - (with Kotlin 1.4) + if (a == null) expect containsExactly a as Double? + else expect containsExactly { a() } + } else { + expect containsExactly entries(a, *aX) + } + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInOrderOnlyGroupedEntriesAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInOrderOnlyGroupedEntriesAssertionsSpec.kt new file mode 100644 index 000000000..902631744 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInOrderOnlyGroupedEntriesAssertionsSpec.kt @@ -0,0 +1,34 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.utils.Group + +class IterableContainsInOrderOnlyGroupedEntriesAssertionsSpec : + ch.tutteli.atrium.specs.integration.IterableContainsInOrderOnlyGroupedEntriesAssertionsSpec( + getContainsPair(), + Companion::groupFactory, + "* ", "(/) ", "(x) ", "(!) ", "- ", "» ", ">> ", "=> ", + "[Atrium][Builder] " + ) { + companion object : IterableContainsSpecBase() { + fun getContainsPair() = + "$contains $filler $inOrder $andOnly $grouped $within $withinInAnyOrder" to Companion::containsInOrderOnlyGroupedInAnyOrderEntries + + private fun containsInOrderOnlyGroupedInAnyOrderEntries( + expect: Expect>, + a1: Group<(Expect.() -> Unit)?>, + a2: Group<(Expect.() -> Unit)?>, + aX: Array.() -> Unit)?>> + ): Expect> = + expect contains o inGiven order and only grouped entries within group inAny order(a1, a2, *aX) + + private fun groupFactory(groups: Array.() -> Unit)?>) = + when (groups.size) { + 0 -> object : Group<(Expect.() -> Unit)?> { + override fun toList() = listOf.() -> Unit>() + } + 1 -> entry(groups[0]) + else -> entries(groups[0], *groups.drop(1).toTypedArray()) + } + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInOrderOnlyGroupedValuesAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInOrderOnlyGroupedValuesAssertionsSpec.kt new file mode 100644 index 000000000..b0ec0b05e --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInOrderOnlyGroupedValuesAssertionsSpec.kt @@ -0,0 +1,57 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.utils.Group + +class IterableContainsInOrderOnlyGroupedValuesAssertionsSpec : + ch.tutteli.atrium.specs.integration.IterableContainsInOrderOnlyGroupedValuesAssertionsSpec( + getContainsPair(), + Companion::groupFactory, + getContainsNullablePair(), + Companion::nullableGroupFactory, + "* ", "(/) ", "(x) ", "(!) ", "- ", ">> ", "=> ", + "[Atrium][Builder] " + ) { + companion object : IterableContainsSpecBase() { + fun getContainsPair() = + "$contains $filler $inOrder $andOnly $grouped $within $withinInAnyOrder" to Companion::containsInOrderOnlyGroupedInAnyOrderValues + + private fun containsInOrderOnlyGroupedInAnyOrderValues( + expect: Expect>, + a1: Group, + a2: Group, + aX: Array> + ): Expect> = + expect contains o inGiven order and only grouped entries within group inAny order(a1, a2, *aX) + + private fun groupFactory(groups: Array): Group = + when (groups.size) { + 0 -> object : Group { + override fun toList() = listOf() + } + 1 -> value(groups[0]) + else -> values(groups[0], *groups.drop(1).toTypedArray()) + } + + + fun getContainsNullablePair() = + "$contains $filler $inOrder $andOnly $grouped $within $withinInAnyOrder" to Companion::containsInOrderOnlyGroupedInAnyOrderNullableValues + + private fun containsInOrderOnlyGroupedInAnyOrderNullableValues( + expect: Expect>, + a1: Group, + a2: Group, + aX: Array> + ): Expect> = + expect contains o inGiven order and only grouped entries within group inAny order(a1, a2, *aX) + + private fun nullableGroupFactory(groups: Array): Group = + when (groups.size) { + 0 -> object : Group { + override fun toList() = listOf() + } + 1 -> value(groups[0]) + else -> values(groups[0], *groups.drop(1).toTypedArray()) + } + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInOrderOnlyValuesAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInOrderOnlyValuesAssertionsSpec.kt new file mode 100644 index 000000000..08affe3d0 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsInOrderOnlyValuesAssertionsSpec.kt @@ -0,0 +1,78 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import org.spekframework.spek2.Spek +import kotlin.reflect.KFunction2 + +class IterableContainsInOrderOnlyValuesAssertionsSpec : Spek({ + + include(BuilderSpec) + include(ShortcutSpec) + +}) { + object BuilderSpec : ch.tutteli.atrium.specs.integration.IterableContainsInOrderOnlyValuesAssertionsSpec( + getContainsPair(), + getContainsNullablePair(), + "* ", "(/) ", "(x) ", "(!) ", "- ", ">> ", "=> ", + "[Atrium][Builder] " + ) + + object ShortcutSpec : ch.tutteli.atrium.specs.integration.IterableContainsInOrderOnlyValuesAssertionsSpec( + getContainsShortcutPair(), + getContainsNullableShortcutPair(), + "* ", "(/) ", "(x) ", "(!) ", "- ", ">> ", "=> ", + "[Atrium][Shortcut] " + ) + + companion object : IterableContainsSpecBase() { + fun getContainsPair() = + "$contains $filler $inOrder $andOnly $inOrderOnlyValues" to Companion::containsInOrderOnlyValues + + private fun containsInOrderOnlyValues( + expect: Expect>, + a: Double, + aX: Array + ): Expect> = + if (aX.isEmpty()) expect contains o inGiven order and only value a + else expect contains o inGiven order and only the values(a, *aX) + + fun getContainsNullablePair() = + "$contains $filler $inOrder $andOnly $inOrderOnlyValues" to Companion::containsInOrderOnlyNullableValues + + private fun containsInOrderOnlyNullableValues( + expect: Expect>, + a: Double?, + aX: Array + ): Expect> = + if (aX.isEmpty()) expect contains o inGiven order and only value a + else expect contains o inGiven order and only the values(a, *aX) + + private val containsShortcutFun: KFunction2>, Double, Expect>> = + Expect>::containsExactly + + fun getContainsShortcutPair() = containsShortcutFun.name to Companion::containsInOrderOnlyValuesShortcut + + private fun containsInOrderOnlyValuesShortcut( + expect: Expect>, + a: Double, + aX: Array + ): Expect> = + if (aX.isEmpty()) expect containsExactly a + else expect containsExactly values(a, *aX) + + private val containsNullableShortcutFun: KFunction2>, Double?, Expect>> = + Expect>::containsExactly + + fun getContainsNullableShortcutPair() = + containsNullableShortcutFun.name to Companion::containsInOrderOnlyNullableValuesShortcut + + private fun containsInOrderOnlyNullableValuesShortcut( + expect: Expect>, + a: Double?, + aX: Array + ): Expect> = + if (aX.isEmpty()) expect containsExactly a + else expect containsExactly values(a, *aX) + } +} + diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsNotEntriesAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsNotEntriesAssertionsSpec.kt new file mode 100644 index 000000000..c2c02a757 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsNotEntriesAssertionsSpec.kt @@ -0,0 +1,35 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.withNullableSuffix + +class IterableContainsNotEntriesAssertionsSpec : + ch.tutteli.atrium.specs.integration.IterableContainsNotEntriesAssertionsSpec( + getContainsNotPair(), + getContainsNotNullablePair().withNullableSuffix(), + "* ", "(/) ", "(x) ", "- ", "» ", ">> ", "=> ", + "[Atrium][Builder] " + ) { + companion object : IterableContainsSpecBase() { + + private fun getContainsNotPair() = containsNot to Companion::containsNotFun + + private fun containsNotFun( + expect: Expect>, + a: Expect.() -> Unit, + aX: Array.() -> Unit> + ): Expect> = + if (aX.isEmpty()) expect containsNot o entry a + else expect containsNot o the entries(a, *aX) + + private fun getContainsNotNullablePair() = containsNot to Companion::containsNotNullableFun + + private fun containsNotNullableFun( + expect: Expect>, + a: (Expect.() -> Unit)?, + aX: Array.() -> Unit)?> + ): Expect> = + if (aX.isEmpty()) expect containsNot o entry a + else expect containsNot o the entries(a, *aX) + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsNotValuesAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsNotValuesAssertionsSpec.kt new file mode 100644 index 000000000..1ac89a197 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsNotValuesAssertionsSpec.kt @@ -0,0 +1,59 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import org.spekframework.spek2.Spek +import kotlin.reflect.KFunction2 + +class IterableContainsNotValuesAssertionsSpec : Spek({ + + include(BuilderSpec) + include(ShortcutSpec) + +}) { + + object BuilderSpec : ch.tutteli.atrium.specs.integration.IterableContainsNotValuesAssertionsSpec( + getContainsNotPair(), + getContainsNotNullablePair(), + "* ", "(/) ", "(x) ", "- ", ">> ", "=> ", + "[Atrium][Builder] " + ) + + object ShortcutSpec : ch.tutteli.atrium.specs.integration.IterableContainsNotValuesAssertionsSpec( + getContainsNotShortcutPair(), + getContainsNotNullablePair(), + "* ", "(/) ", "(x) ", "- ", ">> ", "=> ", + "[Atrium][Shortcut] " + ) + + companion object : IterableContainsSpecBase() { + + private fun getContainsNotPair() = containsNot to Companion::containsNotFun + + private fun containsNotFun( + expect: Expect>, + a: Double, + aX: Array + ): Expect> = + if (aX.isEmpty()) expect containsNot o value a + else expect containsNot o the values(a, *aX) + + private fun getContainsNotNullablePair() = containsNot to Companion::containsNotNullableFun + + private fun containsNotNullableFun( + expect: Expect>, + a: Double?, + aX: Array + ): Expect> = + if (aX.isEmpty()) expect containsNot o value a + else expect containsNot o the values(a, *aX) + + private val containsNotShortcutFun: KFunction2>, Double, Expect>> = + Expect>::containsNot + + private fun getContainsNotShortcutPair() = containsNotShortcutFun.name to Companion::containsNotShortcut + + private fun containsNotShortcut(expect: Expect>, a: Double, aX: Array) = + if (aX.isEmpty()) expect containsNot a + else expect containsNot values(a, *aX) + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsSpecBase.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsSpecBase.kt new file mode 100644 index 000000000..140e5ce4a --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableContainsSpecBase.kt @@ -0,0 +1,325 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.infix.en_GB.creating.Values +import ch.tutteli.atrium.api.infix.en_GB.creating.iterable.Order +import ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.AtLeastCheckerOption +import ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders.NotCheckerOption +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.utils.Group +import ch.tutteli.atrium.domain.creating.iterable.contains.IterableContains +import ch.tutteli.atrium.domain.creating.iterable.contains.searchbehaviours.* +import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter +import kotlin.reflect.KFunction2 + +abstract class IterableContainsSpecBase : WithAsciiReporter() { + private val Values = "values" + private val Entries = "entries" + + //@formatter:off + protected val atLeast = IterableContains.Builder<*, *, InAnyOrderSearchBehaviour>::atLeast.name + protected val butAtMost = AtLeastCheckerOption<*, *, InAnyOrderSearchBehaviour>::butAtMost.name + protected val exactly = IterableContains.Builder<*, *, InAnyOrderSearchBehaviour>::exactly.name + protected val atMost = IterableContains.Builder<*, *, InAnyOrderSearchBehaviour>::atMost.name + protected val notOrAtMost = IterableContains.Builder<*, *, InAnyOrderSearchBehaviour>::notOrAtMost.name + protected val inAnyOrder = "${IterableContains.Builder<*, Iterable<*>, NoOpSearchBehaviour>::inAny.name} ${order::class.simpleName}" + protected val butOnly = "${IterableContains.Builder, InAnyOrderSearchBehaviour>::but.name} ${only::class.simpleName}" + private val theInAnyOrderFun: KFunction2, InAnyOrderSearchBehaviour>, Values, Expect>> + = IterableContains.CheckerOption, InAnyOrderSearchBehaviour>::the + private val theInAnyOrder = theInAnyOrderFun.name + protected val inAnyOrderEntries = "$theInAnyOrder $Entries" + protected val inAnyOrderValues = "$theInAnyOrder $Values" + protected val inAnyOrderElementsOf = IterableContains.CheckerOption, InAnyOrderSearchBehaviour>::elementsOf.name + + private val theInAnyOrderOnlyFun: KFunction2, InAnyOrderOnlySearchBehaviour>, Values, Expect>> + = IterableContains.Builder, InAnyOrderOnlySearchBehaviour>::the + private val theInAnyOrderOnly = theInAnyOrderOnlyFun.name + protected val inAnyOrderOnlyValues = "$theInAnyOrderOnly $Values" + protected val inAnyOrderOnlyEntries = "$theInAnyOrderOnly $Entries" + protected val inAnyOrderOnlyElementsOf = IterableContains.Builder, InAnyOrderOnlySearchBehaviour>::elementsOf.name + + protected val inOrder = "${IterableContains.Builder<*, Iterable<*>, NoOpSearchBehaviour>::inGiven.name} ${order::class.simpleName}" + protected val andOnly = "${IterableContains.Builder, InOrderSearchBehaviour>::and.name} ${only::class.simpleName}" + private val theInOrderOnlyFun: KFunction2, InOrderOnlySearchBehaviour>, Values, Expect>> + = IterableContains.Builder, InOrderOnlySearchBehaviour>::the + private val theInOrderOnly = theInOrderOnlyFun.name + protected val inOrderOnlyValues = "$theInOrderOnly $Values" + protected val inOrderOnlyEntries = "$theInOrderOnly $Entries" + protected val inOrderElementsOf = IterableContains.Builder, InOrderOnlySearchBehaviour>::elementsOf.name + protected val grouped = "${IterableContains.Builder<*, *, InOrderOnlySearchBehaviour>::grouped.name} ${entries::class.simpleName}" + protected val within = IterableContains.Builder<*, *, InOrderOnlyGroupedSearchBehaviour>::within.name + private val withinInAnyOrderFun : KFunction2, InOrderOnlyGroupedWithinSearchBehaviour>, Order>, Expect>> + = IterableContains.Builder, InOrderOnlyGroupedWithinSearchBehaviour>::inAny + protected val withinInAnyOrder = withinInAnyOrderFun.name + //@formatter:on + + protected val filler = o::class.simpleName + private val containsProp: KFunction2>, o, IterableContains.Builder, NoOpSearchBehaviour>> = + Expect>::contains + protected val contains = containsProp.name + private val containsNotProp: KFunction2>, o, NotCheckerOption, NotSearchBehaviour>> = + Expect>::containsNot + protected val containsNot = "${containsNotProp.name} $filler $inAnyOrderValues" + + @Suppress("unused") + private fun ambiguityTest() { + val list: Expect> = notImplemented() + val nullableList: Expect> = notImplemented() + val subList: Expect> = notImplemented() + val star: Expect> = notImplemented() + + list contains 1 + list contains 1f + list contains values(1, 2f) + list contains {} + list contains entries({}, {}) + list containsNot 1 + list containsNot 1f + list containsNot values(1, 2f) + list containsNot o entry {} + list containsNot o the entries({}, {}) + + subList contains 1 + subList contains 1f; subList contains values(1, 2f) + subList contains {} + subList contains entries({}, {}) + subList containsNot 1 + subList containsNot 1f + subList containsNot values(1, 2f) + subList containsNot o entry {} + subList containsNot o the entries({}, {}) + + nullableList contains 1 + nullableList contains 1f + nullableList contains values(1, 2f) + nullableList contains {} + nullableList contains entries({}, {}) + nullableList containsNot 1 + nullableList containsNot 1f + nullableList containsNot values(1, 2f) + nullableList containsNot o entry {} + nullableList containsNot o the entries({}, {}) + //TODO should work without cast, remove as soon as KT-6591 is fixed - (with Kotlin 1.4) + nullableList contains null as Number? + nullableList contains entries(null, {}) + nullableList contains entries({}, null) + nullableList contains entries(null, null) + //TODO should work without cast, remove as soon as KT-6591 is fixed - (with Kotlin 1.4) + nullableList containsNot null as Number? + nullableList containsNot o the entries(null, {}) + nullableList containsNot o the entries({}, null) + nullableList containsNot o the entries(null, null) + + star contains 1 + star contains 1f + star contains values(1, 2f) + star contains {} + star contains entries({}, {}) + star containsNot 1 + star containsNot 1f + star containsNot values(1, 2f) + star containsNot o entry {} + star containsNot o the entries({}, {}) + //TODO should work without cast, remove as soon as KT-6591 is fixed - (with Kotlin 1.4) + star contains (null as Number?) + star contains entries(null, {}) + star contains entries({}, null) + star contains entries(null, null) + //TODO should work without cast, remove as soon as KT-6591 is fixed - (with Kotlin 1.4) + star containsNot (null as Number?) + star containsNot o the entries(null, {}) + star containsNot o the entries({}, null) + star containsNot o the entries(null, null) + + list containsExactly 1 + list containsExactly values(1, 2f) + list containsExactly {} + list containsExactly entries({}, {}) + + subList containsExactly 1 + subList containsExactly values(1, 2f) + subList containsExactly {} + subList containsExactly entries({}, {}) + + nullableList containsExactly 1 + nullableList containsExactly values(1, 2f) + nullableList containsExactly {} + nullableList containsExactly entries({}, {}) + //TODO should work without cast, remove as soon as KT-6591 is fixed - (with Kotlin 1.4) + nullableList containsExactly (null as (Expect.() -> Unit)?) + nullableList containsExactly entries({}, null) + nullableList containsExactly entries(null, {}) + nullableList containsExactly entries(null, null) + + star containsExactly 1 + star containsExactly values(1, 2f) + star containsExactly {} + star containsExactly entries({}, {}) + //TODO should work without cast, remove as soon as KT-6591 is fixed - (with Kotlin 1.4) + star containsExactly (null as (Expect.() -> Unit)?) + star containsExactly entries({}, null) + star containsExactly entries(null, {}) + star containsExactly entries(null, null) + + list contains o inAny order atLeast 1 value 1 + list contains o inAny order atLeast 1 the values(2, 1) + list contains o inAny order atLeast 1 entry {} + list contains o inAny order atLeast 1 the entries({}, {}) + list contains o inAny order atLeast 1 elementsOf listOf(1, 2) + subList contains o inAny order atLeast 1 value 1 + subList contains o inAny order atLeast 1 the values(2, 1) + subList contains o inAny order atLeast 1 entry {} + subList contains o inAny order atLeast 1 the entries({}, {}) + subList contains o inAny order atLeast 1 elementsOf listOf(1, 2) + nullableList contains o inAny order atLeast 1 value 1 + nullableList contains o inAny order atLeast 1 the values(2, 1) + nullableList contains o inAny order atLeast 1 entry {} + nullableList contains o inAny order atLeast 1 the entries({}, {}) + nullableList contains o inAny order atLeast 1 elementsOf listOf(1, 2) + nullableList contains o inAny order atLeast 1 value null + nullableList contains o inAny order atLeast 1 the values(null, 1) + nullableList contains o inAny order atLeast 1 the values(2, null) + nullableList contains o inAny order atLeast 1 the values(null, null) + nullableList contains o inAny order atLeast 1 entry null + nullableList contains o inAny order atLeast 1 the entries(null, {}) + nullableList contains o inAny order atLeast 1 the entries({}, null) + nullableList contains o inAny order atLeast 1 the entries(null, null) + star contains o inAny order atLeast 1 value 1 + star contains o inAny order atLeast 1 the values(2, 1) + star contains o inAny order atLeast 1 entry {} + star contains o inAny order atLeast 1 the entries({}, {}) + star contains o inAny order atLeast 1 elementsOf listOf(1, 2) + star contains o inAny order atLeast 1 value null + star contains o inAny order atLeast 1 the values(null, 1) + star contains o inAny order atLeast 1 the values(2, null) + star contains o inAny order atLeast 1 the values(null, null) + star contains o inAny order atLeast 1 entry null + star contains o inAny order atLeast 1 the entries(null, {}) + star contains o inAny order atLeast 1 the entries({}, null) + star contains o inAny order atLeast 1 the entries(null, null) + + list contains o inAny order but only value 1 + list contains o inAny order but only the values(2, 1) + list contains o inAny order but only entry {} + list contains o inAny order but only the entries({}, {}) + list contains o inAny order but only elementsOf listOf(1, 2) + subList contains o inAny order but only value 1 + subList contains o inAny order but only the values(2, 1) + subList contains o inAny order but only entry {} + subList contains o inAny order but only the entries({}, {}) + subList contains o inAny order but only elementsOf listOf(1, 2) + nullableList contains o inAny order but only value 1 + nullableList contains o inAny order but only the values(2, 1) + nullableList contains o inAny order but only entry {} + nullableList contains o inAny order but only the entries({}, {}) + nullableList contains o inAny order but only elementsOf listOf(1, 2) + nullableList contains o inAny order but only value null + nullableList contains o inAny order but only the values(null, 1) + nullableList contains o inAny order but only the values(2, null) + nullableList contains o inAny order but only the values(null, null) + nullableList contains o inAny order but only entry null + nullableList contains o inAny order but only the entries(null, {}) + nullableList contains o inAny order but only the entries({}, null) + nullableList contains o inAny order but only the entries(null, null) + star contains o inAny order but only value 1 + star contains o inAny order but only the values(2, 1) + star contains o inAny order but only entry {} + star contains o inAny order but only the entries({}, {}) + star contains o inAny order but only elementsOf listOf(1, 2) + star contains o inAny order but only value null + star contains o inAny order but only the values(null, 1) + star contains o inAny order but only the values(2, null) + star contains o inAny order but only the values(null, null) + star contains o inAny order but only entry null + star contains o inAny order but only the entries(null, {}) + star contains o inAny order but only the entries({}, null) + star contains o inAny order but only the entries(null, null) + + list contains o inGiven order and only value 1 + list contains o inGiven order and only the values(2, 1) + list contains o inGiven order and only entry {} + list contains o inGiven order and only the entries({}, {}) + list contains o inGiven order and only elementsOf listOf(1, 2) + subList contains o inGiven order and only value 1 + subList contains o inGiven order and only the values(2, 1) + subList contains o inGiven order and only entry {} + subList contains o inGiven order and only the entries({}, {}) + subList contains o inGiven order and only elementsOf listOf(1, 2) + nullableList contains o inGiven order and only value 1 + nullableList contains o inGiven order and only the values(2, 1) + nullableList contains o inGiven order and only entry {} + nullableList contains o inGiven order and only the entries({}, {}) + nullableList contains o inGiven order and only elementsOf listOf(1, 2) + nullableList contains o inGiven order and only value null + nullableList contains o inGiven order and only the values(null, 1) + nullableList contains o inGiven order and only the values(2, null) + nullableList contains o inGiven order and only the values(null, null) + nullableList contains o inGiven order and only entry null + nullableList contains o inGiven order and only the entries(null, {}) + nullableList contains o inGiven order and only the entries({}, null) + nullableList contains o inGiven order and only the entries(null, null) + star contains o inGiven order and only value 1 + star contains o inGiven order and only the values(2, 1) + star contains o inGiven order and only entry {} + star contains o inGiven order and only the entries({}, {}) + star contains o inGiven order and only elementsOf listOf(1, 2) + star contains o inGiven order and only value null + star contains o inGiven order and only the values(null, 1) + star contains o inGiven order and only the values(2, null) + star contains o inGiven order and only the values(null, null) + star contains o inGiven order and only entry null + star contains o inGiven order and only the entries(null, {}) + star contains o inGiven order and only the entries({}, null) + star contains o inGiven order and only the entries(null, null) + + list contains o inGiven order and only grouped entries within group inAny order( + value(1), + values(1f), + values(1f, 1) + ) + subList contains o inGiven order and only grouped entries within group inAny order( + value(1), + values(1f), + values(1f, 1) + ) + nullableList contains o inGiven order and only grouped entries within group inAny order( + value(null), + values(null), + values(null, 2), + values(1, null), + values(null, null) + ) + star contains o inGiven order and only grouped entries within group inAny order( + value(null), + values(null), + values(null, 2), + values(1, null), + values(null, null) + ) + + list contains o inGiven order and only grouped entries within group inAny order( + entry {}, + entries({}), + entries({}, {}) + ) + subList contains o inGiven order and only grouped entries within group inAny order( + entry {}, + entries({}), + entries({}, {}) + ) + nullableList contains o inGiven order and only grouped entries within group inAny order( + entry(null), + entries(null), + entries(null, {}), + entries({}, null), + entries(null, null) + ) + star contains o inGiven order and only grouped entries within group inAny order( + entry(null), + entries(null), + entries(null, {}), + entries({}, null), + entries(null, null) + ) + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableFeatureAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableFeatureAssertionsSpec.kt new file mode 100644 index 000000000..4810a1f10 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableFeatureAssertionsSpec.kt @@ -0,0 +1,36 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.feature1 +import ch.tutteli.atrium.specs.fun1 +import ch.tutteli.atrium.specs.name +import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter + +class IterableFeatureAssertionsSpec : ch.tutteli.atrium.specs.integration.IterableFeatureAssertionsSpec( + minFeaturePair(), + fun1, Expect.() -> Unit>(Expect>::min), + maxFeaturePair(), + fun1, Expect.() -> Unit>(Expect>::max) +) { + companion object : WithAsciiReporter() { + private fun minFeaturePair() = feature1, o, Int>(Expect>::min).name to ::minFeature + private fun minFeature(expect: Expect>) = expect min o + + private fun maxFeaturePair() = feature1, o, Int>(Expect>::min).name to ::maxFeature + private fun maxFeature(expect: Expect>) = expect max o + } + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + var a1: Expect> = notImplemented() + //nullable not supported by min/max or rather T : Comparable does not exist for T? (one cannot implement an interface for the nullable type) + //same for Iterable<*> + + a1 min o toBe 2 + a1 max o toBe 3 + + a1 = a1 min { } + a1 = a1 max { } + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableNoneAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableNoneAssertionsSpec.kt new file mode 100644 index 000000000..887c35b60 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/IterableNoneAssertionsSpec.kt @@ -0,0 +1,60 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.fun1 +import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.withNullableSuffix +import org.spekframework.spek2.Spek + +class IterableNoneAssertionsSpec : Spek({ + + include(PredicateSpec) + include(BuilderSpec) + +}) { + object PredicateSpec : ch.tutteli.atrium.specs.integration.IterableNoneAssertionsSpec( + fun1(Expect>::none), + fun1(Expect>::none).withNullableSuffix(), + "* ", "(/) ", "(x) ", "- ", "» ", ">> ", "=> ", + "[Atrium][Predicate] " + ) + + object BuilderSpec : ch.tutteli.atrium.specs.integration.IterableNoneAssertionsSpec( + getContainsNotPair(), + getContainsNotNullablePair().withNullableSuffix(), + "* ", "(/) ", "(x) ", "- ", "» ", ">> ", "=> ", + "[Atrium][Builder] " + ) + + companion object : IterableContainsSpecBase() { + + private fun getContainsNotPair() = containsNot to Companion::containsNotFun + + private fun containsNotFun(expect: Expect>, a: Expect.() -> Unit) = + expect containsNot o entry a + + private fun getContainsNotNullablePair() = containsNot to Companion::containsNotNullableFun + + private fun containsNotNullableFun(expect: Expect>, a: (Expect.() -> Unit)?) = + expect containsNot o entry a + } + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + var a1: Expect> = notImplemented() + var a1b: Expect> = notImplemented() + + var star: Expect> = notImplemented() + + a1 = a1.none {} + a1 = a1 containsNot o entry {} + + a1b = a1b none {} + a1b = a1b none null + a1b = a1b containsNot o entry {} + a1b = a1b containsNot o entry null + + star = star.none {} + star = star containsNot o entry {} + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/ListFeatureAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/ListFeatureAssertionsSpec.kt index 03f3f9fd0..1c70fce8d 100644 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/ListFeatureAssertionsSpec.kt +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/ListFeatureAssertionsSpec.kt @@ -1,56 +1,47 @@ package ch.tutteli.atrium.api.infix.en_GB -import ch.tutteli.atrium.api.infix.en_GB.creating.list.get.builders.ListGetStep -import ch.tutteli.atrium.api.infix.en_GB.testutils.WithAsciiReporter import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.specs.feature1 -import ch.tutteli.atrium.specs.name +import ch.tutteli.atrium.specs.fun2 import ch.tutteli.atrium.specs.notImplemented -import kotlin.reflect.KFunction2 +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter +import ch.tutteli.atrium.specs.withNullableSuffix +import kotlin.jvm.JvmName class ListFeatureAssertionsSpec : ch.tutteli.atrium.specs.integration.ListFeatureAssertionsSpec( - feature1, Int, Int>(Expect>::get).name to Companion::get, - getIndexPair(), - feature1, Int, Int?>(Expect>::get).name to Companion::getNullable, - getIndexNullablePair() + feature1, Int, Int>(Expect>::get), + fun2, Int, Expect.() -> Unit>(Companion::get), + feature1, Int, Int?>(Expect>::get).withNullableSuffix(), + fun2, Int, Expect.() -> Unit>(Companion::get).withNullableSuffix() ) { - companion object : WithAsciiReporter() { - fun get(expect: Expect>, index: Int) = expect get index - fun getNullable(expect: Expect>, index: Int) = expect get index - fun getIndexPair() = getIndexFun.name to ::getIndex - private val getIndexFun: KFunction2>, Index, ListGetStep>> = - Expect>::get + private fun get(expect: Expect>, index: Int, assertionCreator: Expect.() -> Unit) = + expect get index(index) { assertionCreator() } - private fun getIndex(expect: Expect>, index: Int, assertionCreator: Expect.() -> Unit) = - expect get Index(index) assertIt { assertionCreator() } - - fun getIndexNullablePair() = getIndexNullableFun.name to ::getIndexNullable - private val getIndexNullableFun: KFunction2>, Index, ListGetStep>> = - Expect>::get - - private fun getIndexNullable( + @JvmName("getNullable") + private fun get( expect: Expect>, index: Int, assertionCreator: Expect.() -> Unit - ) = expect get Index(index) assertIt { assertionCreator() } + ) = expect get index(index) { assertionCreator() } + } @Suppress("unused", "UNUSED_VALUE") private fun ambiguityTest() { - var a1: Expect> = notImplemented() - var a1b: Expect> = notImplemented() + var a1: Expect> = notImplemented() + var a1b: Expect> = notImplemented() - var star: Expect> = notImplemented() + var star: Expect> = notImplemented() a1 get 1 - a1 = a1 get Index(1) assertIt { } + a1 = a1 get index(1) { } a1b get 1 - a1b = a1b get Index(1) assertIt { } + a1b = a1b get index(1) { } star get 1 - star = star get Index(1) assertIt { } + star = star get index(1) { } } } diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/MapAsEntriesAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/MapAsEntriesAssertionsSpec.kt new file mode 100644 index 000000000..55fe45a82 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/MapAsEntriesAssertionsSpec.kt @@ -0,0 +1,51 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.feature1 +import ch.tutteli.atrium.specs.fun1 +import ch.tutteli.atrium.specs.name +import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter + +class MapAsEntriesAssertionsSpec : ch.tutteli.atrium.specs.integration.MapAsEntriesAssertionsSpec( + asEntriesPair(), + fun1, Expect>>.() -> Unit>(Expect>::asEntries) +) { + + companion object : WithAsciiReporter() { + fun asEntriesPair() = + feature1, o, Set>>(Expect>::asEntries).name to ::asEntriesFeature + + fun asEntriesFeature(expect: Expect>) = expect asEntries o + } + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + var map: Expect> = notImplemented() + var subMap: Expect> = notImplemented() + var nullableKeyMap: Expect> = notImplemented() + var nullableValueMap: Expect> = notImplemented() + var nullableKeyValueMap: Expect> = notImplemented() + var readOnlyNullableKeyValueMap: Expect> = notImplemented() + + var starKeyMap: Expect> = notImplemented() + var starValueMap: Expect> = notImplemented() + + map asEntries o + subMap asEntries o + nullableKeyMap asEntries o + nullableValueMap asEntries o + nullableKeyValueMap asEntries o + readOnlyNullableKeyValueMap asEntries o + + map = map asEntries {} + subMap = subMap asEntries {} + nullableKeyMap = nullableKeyMap asEntries {} + nullableValueMap = nullableValueMap asEntries {} + nullableKeyValueMap = nullableKeyValueMap asEntries {} + readOnlyNullableKeyValueMap = readOnlyNullableKeyValueMap asEntries {} + + starKeyMap = starKeyMap asEntries {} + starValueMap = starValueMap asEntries {} + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/MapAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/MapAssertionsSpec.kt new file mode 100644 index 000000000..0be210564 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/MapAssertionsSpec.kt @@ -0,0 +1,247 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.utils.mapArguments +import ch.tutteli.atrium.specs.fun1 +import ch.tutteli.atrium.specs.integration.mfun2 +import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter +import ch.tutteli.atrium.specs.withNullableSuffix +import kotlin.jvm.JvmName + +class MapAssertionsSpec : ch.tutteli.atrium.specs.integration.MapAssertionsSpec( + mfun2(Companion::contains), + mfun2(Companion::contains).withNullableSuffix(), + mfun2.() -> Unit>(Companion::contains), + mfun2.() -> Unit)?>(Companion::contains).withNullableSuffix(), + fun1, String>(Companion::containsKey), + fun1, String?>(Companion::containsKey).withNullableSuffix(), + fun1, String>(Companion::containsNotKey), + fun1, String?>(Companion::containsNotKey).withNullableSuffix(), + "toBe ${empty::class.simpleName}" to Companion::isEmpty, + "notToBe ${empty::class.simpleName}" to Companion::isNotEmpty +) { + companion object : WithAsciiReporter() { + + private fun contains( + expect: Expect>, + pair: Pair, + otherPairs: Array> + ): Expect> = + if (otherPairs.isEmpty()) expect contains (pair.first to pair.second) + else expect contains pairs(pair, *otherPairs) + + @JvmName("containsNullable") + private fun contains( + expect: Expect>, + pair: Pair, + otherPairs: Array> + ): Expect> = + if (otherPairs.isEmpty()) expect contains (pair.first to pair.second) + else expect contains pairs(pair, *otherPairs) + + @JvmName("containsKeyWithValueAssertions") + private fun contains( + expect: Expect>, + keyValue: Pair.() -> Unit>, + otherKeyValues: Array.() -> Unit>> + ): Expect> = + if (otherKeyValues.isEmpty()) expect contains keyValue(keyValue.first, keyValue.second) + else mapArguments(keyValue, otherKeyValues) + .to { keyValue(it.first, it.second) } + .let { (first, others) -> expect contains all(first, *others) } + + @JvmName("containsKeyWithNullableValueAssertions") + private fun contains( + expect: Expect>, + keyValue: Pair.() -> Unit)?>, + otherKeyValues: Array.() -> Unit)?>> + ): Expect> = + if (otherKeyValues.isEmpty()) expect contains keyValue(keyValue.first, keyValue.second) + else mapArguments(keyValue, otherKeyValues) + .to { keyValue(it.first, it.second) } + .let { (first, others) -> expect contains all(first, *others) } + + private fun containsKey(expect: Expect>, key: String) = + expect containsKey key + + @JvmName("containsKeyNullable") + private fun containsKey(expect: Expect>, key: String?) = + expect containsKey key + + private fun containsNotKey(expect: Expect>, key: String) = + expect containsNotKey key + + @JvmName("containsNotKeyNullable") + private fun containsNotKey(expect: Expect>, key: String?) = + expect containsNotKey key + + private fun isEmpty(expect: Expect>) = expect toBe empty + + private fun isNotEmpty(expect: Expect>) = expect notToBe empty + + } + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + var map: Expect> = notImplemented() + var subMap: Expect> = notImplemented() + var nullableKeyMap: Expect> = notImplemented() + var nullableValueMap: Expect> = notImplemented() + var nullableKeyValueMap: Expect> = notImplemented() + var readOnlyNullableKeyValueMap: Expect> = notImplemented() + var starMap: Expect> = notImplemented() + + map contains (1 to "a") + map contains pairs(1 to "a", 2 to "b") + map contains keyValue(1) {} + map contains all(keyValue(1) {}, keyValue(2) {}) + map contains pairs(1.0 to StringBuilder("a")) + map contains pairs(12f to "a", 2L to StringBuilder("b")) + map contains keyValue(1) {} + map contains all(keyValue(1) {}, keyValue(2) {}) + subMap contains (1 to "a") + subMap contains pairs(1 to "a", 2 to "b") + subMap contains keyValue(1) {} + subMap contains all(keyValue(1) {}, keyValue(2) {}) + subMap contains (1.0 to StringBuilder("a")) + subMap contains pairs(12f to "a", 2L to StringBuilder("b")) + subMap contains keyValue(1) {} + subMap contains all(keyValue(1) {}, keyValue(2) {}) + + nullableKeyMap contains (1 to "a") + nullableKeyMap contains pairs(1 to "a", 2 to "b") + nullableKeyMap contains keyValue(1) {} + nullableKeyMap contains all(keyValue(1) {}, keyValue(2) {}) + nullableKeyMap contains (null to "a") + nullableKeyMap contains pairs(null to "a", null to "b") + nullableKeyMap contains pairs(null to "a", 2 to "b") + nullableKeyMap contains (keyValue(null) {}) + nullableKeyMap contains all(keyValue(null) {}, keyValue(null) {}) + nullableKeyMap contains all(keyValue(null) {}, keyValue(2) {}) + + nullableValueMap contains (1 to "a") + nullableValueMap contains pairs(1 to "a", 2 to "b") + nullableValueMap contains keyValue(1) {} + nullableValueMap contains all(keyValue(1) {}, keyValue(2) {}) + nullableValueMap contains (1 to null) + nullableValueMap contains pairs(1 to null, 2 to null) + nullableValueMap contains pairs(1 to null, 2 to "a") + nullableValueMap contains (keyValue(1, null)) + nullableValueMap contains all(keyValue(1, null), keyValue(2, null)) + nullableValueMap contains all(keyValue(1, null), keyValue(2) {}) + nullableKeyValueMap contains (1 to "a") + nullableKeyValueMap contains pairs(1 to "a", 2 to "b") + nullableKeyValueMap contains keyValue(1) {} + nullableKeyValueMap contains all(keyValue(1) {}, keyValue(2) {}) + + nullableKeyValueMap contains (null to "a") + nullableKeyValueMap contains pairs(null to "a", null to "b") + nullableKeyValueMap contains pairs(null to "a", 2 to "b") + nullableKeyValueMap contains (keyValue(null) {}) + nullableKeyValueMap contains all(keyValue(null) {}, keyValue(null) {}) + nullableKeyValueMap contains all(keyValue(null) {}, keyValue(2) {}) + + nullableKeyValueMap contains (1 to null) + nullableKeyValueMap contains pairs(1 to null, 2 to null) + nullableKeyValueMap contains pairs(1 to null, 2 to "a") + nullableKeyValueMap contains (keyValue(1, null)) + nullableKeyValueMap contains all(keyValue(1, null), keyValue(2, null)) + nullableKeyValueMap contains all(keyValue(1, null), keyValue(2) {}) + + nullableKeyValueMap contains (null to null) + nullableKeyValueMap contains pairs(null to null, null to null) + nullableKeyValueMap contains pairs(1 to null, null to "a") + nullableKeyValueMap contains (keyValue(null, null)) + nullableKeyValueMap contains all(keyValue(null, null), keyValue(null, null)) + nullableKeyValueMap contains all(keyValue(1, null), keyValue(null) {}) + + readOnlyNullableKeyValueMap contains (1 to "a") + readOnlyNullableKeyValueMap contains pairs(1 to "a", 2 to "b") + readOnlyNullableKeyValueMap contains keyValue(1) {} + readOnlyNullableKeyValueMap contains all(keyValue(1) {}, keyValue(2) {}) + + readOnlyNullableKeyValueMap contains (null to "a") + readOnlyNullableKeyValueMap contains pairs(null to "a", null to "b") + readOnlyNullableKeyValueMap contains pairs(null to "a", 2 to "b") + readOnlyNullableKeyValueMap contains (keyValue(null) {}) + readOnlyNullableKeyValueMap contains all(keyValue(null) {}, keyValue(null) {}) + readOnlyNullableKeyValueMap contains all(keyValue(null) {}, keyValue(2) {}) + + readOnlyNullableKeyValueMap contains (1 to null) + readOnlyNullableKeyValueMap contains pairs(1 to null, 2 to null) + readOnlyNullableKeyValueMap contains pairs(1 to null, 2 to "a") + readOnlyNullableKeyValueMap contains (keyValue(1, null)) + readOnlyNullableKeyValueMap contains all(keyValue(1, null), keyValue(2, null)) + readOnlyNullableKeyValueMap contains all(keyValue(1, null), keyValue(2) {}) + + readOnlyNullableKeyValueMap contains (null to null) + readOnlyNullableKeyValueMap contains pairs(null to null, null to null) + readOnlyNullableKeyValueMap contains pairs(1 to null, null to "a") + readOnlyNullableKeyValueMap contains (keyValue(null, null)) + readOnlyNullableKeyValueMap contains all(keyValue(null, null), keyValue(null, null)) + readOnlyNullableKeyValueMap contains all(keyValue(1, null), keyValue(null) {}) + + readOnlyNullableKeyValueMap contains (1 to "a") + readOnlyNullableKeyValueMap contains pairs(1 to "a", 2 to "b") + readOnlyNullableKeyValueMap contains keyValue(1) {} + readOnlyNullableKeyValueMap contains all(keyValue(1) {}, keyValue(2) {}) + + starMap contains (null to "a") + starMap contains pairs(null to "a", null to "b") + starMap contains pairs(null to "a", 2 to "b") + starMap contains (keyValue(null) {}) + starMap contains all(keyValue(null) {}, keyValue(null) {}) + starMap contains all(keyValue(null) {}, keyValue(2) {}) + + starMap contains (1 to null) + starMap contains pairs(1 to null, 2 to null) + starMap contains pairs(1 to null, 2 to "a") + starMap contains (keyValue(1, null)) + starMap contains all(keyValue(1, null), keyValue(2, null)) + starMap contains all(keyValue(1, null), keyValue(2) {}) + + starMap contains (null to null) + starMap contains pairs(null to null, null to null) + starMap contains pairs(1 to null, null to "a") + starMap contains (keyValue(null, null)) + starMap contains all(keyValue(null, null), keyValue(null, null)) + starMap contains all(keyValue(1, null), keyValue(null) {}) + + map containsKey 1 + map containsKey 1f + subMap containsKey 1 + subMap containsKey 1f + nullableKeyMap containsKey 1 + nullableKeyMap containsKey 1f + readOnlyNullableKeyValueMap containsKey 1 + readOnlyNullableKeyValueMap containsKey 1f + + map containsNotKey 1 + map containsNotKey 1f + subMap containsNotKey 1 + subMap containsNotKey 1f + nullableKeyMap containsNotKey 1 + nullableKeyMap containsNotKey 1f + readOnlyNullableKeyValueMap containsNotKey 1 + readOnlyNullableKeyValueMap containsNotKey 1f + + + map = map toBe empty + subMap = subMap toBe empty + nullableKeyMap = nullableKeyMap toBe empty + nullableValueMap = nullableValueMap toBe empty + nullableKeyValueMap = nullableKeyValueMap toBe empty + readOnlyNullableKeyValueMap = readOnlyNullableKeyValueMap toBe empty + starMap = starMap toBe empty + + map = map notToBe empty + subMap = subMap notToBe empty + nullableKeyMap = nullableKeyMap notToBe empty + nullableValueMap = nullableValueMap notToBe empty + nullableKeyValueMap = nullableKeyValueMap notToBe empty + readOnlyNullableKeyValueMap = readOnlyNullableKeyValueMap notToBe empty + starMap = starMap notToBe empty + + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/MapEntryAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/MapEntryAssertionsSpec.kt index 9455bcfc0..116e485fc 100644 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/MapEntryAssertionsSpec.kt +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/MapEntryAssertionsSpec.kt @@ -1,20 +1,22 @@ package ch.tutteli.atrium.api.infix.en_GB -import ch.tutteli.atrium.api.infix.en_GB.testutils.WithAsciiReporter import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.specs.fun1 import ch.tutteli.atrium.specs.name import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter +import ch.tutteli.atrium.specs.withNullableSuffix class MapEntryAssertionsSpec : ch.tutteli.atrium.specs.integration.MapEntryAssertionsSpec( fun1(Expect>::isKeyValue).name to Companion::isKeyValue, - fun1(Expect>::isKeyValue).name to Companion::isKeyValueNullable + (fun1(Expect>::isKeyValue).name to Companion::isKeyValueNullable).withNullableSuffix() ) { companion object : WithAsciiReporter() { - fun isKeyValue(expect: Expect>, key: String, value: Int) = + + private fun isKeyValue(expect: Expect>, key: String, value: Int) = expect isKeyValue (key to value) - fun isKeyValueNullable(expect: Expect>, key: String?, value: Int?) = + private fun isKeyValueNullable(expect: Expect>, key: String?, value: Int?) = expect isKeyValue (key to value) } diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/MapEntryFeatureAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/MapEntryFeatureAssertionsSpec.kt index 2c79d3b73..de6704534 100644 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/MapEntryFeatureAssertionsSpec.kt +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/MapEntryFeatureAssertionsSpec.kt @@ -1,10 +1,10 @@ package ch.tutteli.atrium.api.infix.en_GB -import ch.tutteli.atrium.api.infix.en_GB.testutils.WithAsciiReporter import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.specs.fun1 import ch.tutteli.atrium.specs.notImplemented import ch.tutteli.atrium.specs.property +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter class MapEntryFeatureAssertionsSpec : ch.tutteli.atrium.specs.integration.MapEntryFeatureAssertionsSpec( property, String>(Expect>::key), diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/MapFeatureAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/MapFeatureAssertionsSpec.kt new file mode 100644 index 000000000..b910e13d8 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/MapFeatureAssertionsSpec.kt @@ -0,0 +1,53 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.* +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter +import kotlin.jvm.JvmName + +class MapFeatureAssertionsSpec : ch.tutteli.atrium.specs.integration.MapFeatureAssertionsSpec( + property, Set>(Expect>::keys), + fun1, Expect>.() -> Unit>(Expect>::keys), + property, Collection>(Expect>::values), + fun1, Expect>.() -> Unit>(Expect>::values), + feature1, String, Int>(Expect>::getExisting), + fun2, String, Expect.() -> Unit>(Companion::getExisting), + feature1, String?, Int?>(Expect>::getExisting).withNullableSuffix(), + fun2, String?, Expect.() -> Unit>(Companion::getExisting).withNullableSuffix() +) { + companion object : WithAsciiReporter() { + + private fun getExisting( + expect: Expect>, + key: String, + assertionCreator: Expect.() -> Unit + ): Expect> = expect getExisting key(key) { assertionCreator() } + + @JvmName("getExistingNullable") + private fun getExisting( + expect: Expect>, + key: String?, + assertionCreator: Expect.() -> Unit + ): Expect> = expect getExisting key(key) { assertionCreator() } + + } + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + var a1: Expect> = notImplemented() + var a2: Expect> = notImplemented() + var a3: Expect> = notImplemented() + var star: Expect> = notImplemented() + + //TODO ideally this would not work as the map has not defined the key to be out + a1 getExisting 1 + a2 getExisting 1 + a3 getExisting null as String? + star getExisting "a" + + a1 = a1 getExisting key("a") { } + a2 = a2 getExisting key(1) { } + a3 = a3 getExisting key(null) { } + star = star getExisting key("a") { } + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/PairFeatureAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/PairFeatureAssertionsSpec.kt index d7d201fc6..9dad34b8e 100644 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/PairFeatureAssertionsSpec.kt +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/PairFeatureAssertionsSpec.kt @@ -1,35 +1,22 @@ package ch.tutteli.atrium.api.infix.en_GB -import ch.tutteli.atrium.api.infix.en_GB.testutils.WithAsciiReporter import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.specs.fun1 -import ch.tutteli.atrium.specs.name import ch.tutteli.atrium.specs.notImplemented import ch.tutteli.atrium.specs.property +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter class PairFeatureAssertionsSpec : ch.tutteli.atrium.specs.integration.PairFeatureAssertionsSpec( property, String>(Expect>::first), - fun1, Expect.() -> Unit>(Expect>::first).name to Companion::first, + fun1, Expect.() -> Unit>(Expect>::first), property, Int>(Expect>::second), - fun1, Expect.() -> Unit>(Expect>::second).name to Companion::second, + fun1, Expect.() -> Unit>(Expect>::second), property, String?>(Expect>::first), - fun1, Expect.() -> Unit>(Expect>::first).name to Companion::firstNullable, + fun1, Expect.() -> Unit>(Expect>::first), property, Int?>(Expect>::second), - fun1, Expect.() -> Unit>(Expect>::second).name to Companion::secondNullable + fun1, Expect.() -> Unit>(Expect>::second) ) { - companion object : WithAsciiReporter() { - fun first(expect: Expect>, assertionCreator: Expect.() -> Unit) = - expect first { assertionCreator() } - - fun second(expect: Expect>, assertionCreator: Expect.() -> Unit) = - expect second { assertionCreator() } - - fun firstNullable(expect: Expect>, assertionCreator: Expect.() -> Unit) = - expect first { assertionCreator() } - - fun secondNullable(expect: Expect>, assertionCreator: Expect.() -> Unit) = - expect second { assertionCreator() } - } + companion object : WithAsciiReporter() @Suppress("unused", "UNUSED_VALUE") private fun ambiguityTest() { diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/ThrowableAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/ThrowableAssertionsSpec.kt new file mode 100644 index 000000000..27ab3c86a --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/ThrowableAssertionsSpec.kt @@ -0,0 +1,56 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.* +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter + +class ThrowableAssertionsSpec : ch.tutteli.atrium.specs.integration.ThrowableAssertionsSpec( + property(Expect::message), + fun1.() -> Unit>(Expect::message), + fun2(Companion::messageContains), + ("cause" to Companion::causeFeature).withFeatureSuffix(), + "cause" to Companion::cause +) { + + companion object : WithAsciiReporter() { + + private fun messageContains( + expect: Expect, + expected: Any, + vararg otherExpected: Any + ): Expect = + if (otherExpected.isEmpty()) expect messageContains expected + else expect messageContains values( + expected, + *otherExpected + ) + + @Suppress("RemoveExplicitTypeArguments") + private fun causeFeature(expect: Expect): Expect = + expect.cause() + + @Suppress("RemoveExplicitTypeArguments") + private fun cause( + expect: Expect, + assertionCreator: Expect.() -> Unit + ) = expect.cause(assertionCreator) + } + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + var a1: Expect = notImplemented() + + a1.message + a1 = a1 message {} + a1 = a1 messageContains "a" + a1 = a1 messageContains 'a' + a1 = a1 messageContains values( + "a", + 1, + 'b' + ) + + a1.cause() + a1.cause { message { } } + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/bigDecimalAssertions.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/bigDecimalAssertions.kt new file mode 100644 index 000000000..c917bb4ab --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/bigDecimalAssertions.kt @@ -0,0 +1,148 @@ +@file:Suppress("JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE" /* TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed */) + +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.domain.builders.bigDecimal +import ch.tutteli.atrium.domain.builders.creating.PleaseUseReplacementException +import java.math.BigDecimal + +/** + * Deprecated as it would compare the subject against [expected] including scale + * -- many developers are not aware of that. + * + * Use [isNumericallyEqualTo] if you expect that the following assertion holds: + * ``` + * expect(BigDecimal("10").toBe(BigDecimal("10.0")) + * ``` + * However, if you expect it to be wrong (because `BigDecimal.scale` differ), then use [isEqualIncludingScale]. + */ +@Deprecated( + "Use `isNumericallyEqualTo` if you expect that the following assertion holds:\n" + + "`expect(BigDecimal(\"10\")).toBe(BigDecimal(\"10.0\"))`\n" + + "However, if you expect it to be wrong (because `BigDecimal.scale` differ), then use `isEqualIncludingScale`.", + ReplaceWith("isNumericallyEqualTo(expected) or isEqualIncludingScale(expected)") +) +@Suppress("UNUSED_PARAMETER", "unused") +infix fun Expect.toBe(expected: T): Nothing = throw PleaseUseReplacementException( + "BigDecimal.equals() compares also BigDecimal.scale, which you might not be aware of.\n" + + "If you know it and want that `scale` is included in the comparison, then use `isEqualIncludingScale`." +) + +@Suppress("UNUSED_PARAMETER", "unused") +@JvmName("toBeNullable") +@Deprecated( + "Use `isNumericallyEqualTo` if you expect that the following assertion holds:\n" + + "`expect(BigDecimal(\"10\")).toBe(BigDecimal(\"10.0\"))`\n" + + "However, if you expect it to be wrong (because `BigDecimal.scale` differ), then use `isEqualIncludingScale`.", + ReplaceWith("isNumericallyEqualTo(expected) or isEqualIncludingScale(expected)") +) +infix fun Expect.toBe(expected: T): Nothing = throw PleaseUseReplacementException( + "BigDecimal.equals() compares also BigDecimal.scale, which you might not be aware of.\n" + + "If you know it and want that `scale` is included in the comparison, then use `isEqualIncludingScale`." +) + +/** + * Expects that the subject of the assertion (a [BigDecimal]) is `null`. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + */ +@JvmName("toBeNull") +infix fun Expect.toBe(expected: Nothing?): Expect = + addAssertion(ExpectImpl.any.toBe(this, expected)) + +/** + * Deprecated as it would compare the subject against [expected] including scale + * -- many developers are not aware of that. + * + * Use [isNotNumericallyEqualTo] if you expect that the following assertion is wrong: + * ``` + * expect(BigDecimal("10").notToBe(BigDecimal("10.0")) + * ``` + * However, if you expect it to be wrong (because `BigDecimal.scale` differ), then use [isNotEqualIncludingScale]. + */ +@Deprecated( + "Use `isNotNumericallyEqualTo` if you expect that the following assertion is wrong:\n" + + "`expect(BigDecimal(\"10\")).notToBe(BigDecimal(\"10.0\"))`\n" + + "However, if you expect it to hold (because `BigDecimal.scale` differ), then use `isNotEqualIncludingScale`.", + ReplaceWith("isNotNumericallyEqualTo(expected) or isNotEqualIncludingScale(expected)") +) +@Suppress("UNUSED_PARAMETER", "unused") +infix fun Expect.notToBe(expected: T): Nothing = throw PleaseUseReplacementException( + "BigDecimal.equals() compares also BigDecimal.scale, which you might not be aware of.\n" + + "If you know it and want that `scale` is included in the comparison, then use `isNotEqualIncludingScale`." +) + +/** + * Expects that the subject of the assertion (a [BigDecimal]) is numerically equal to [expected]. + * + * By numerically is meant that it will not compare [BigDecimal.scale] (or in other words, + * it uses `compareTo(expected) == 0`) + * + * Most of the time you want to use this function instead of [isEqualIncludingScale] because + * [isEqualIncludingScale] compares [BigDecimal.scale]. + * Following the two functions compared: + * - `expect(BigDecimal("10")).isEqualIncludingScale(BigDecimal("10.0"))` does not hold. + * - `expect(BigDecimal("10")).isNumericallyEqualTo(BigDecimal("10.0"))` holds. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + */ +infix fun Expect.isNumericallyEqualTo(expected: T) = + addAssertion(ExpectImpl.bigDecimal.isNumericallyEqualTo(this, expected)) + +/** + * Expects that the subject of the assertion (a [BigDecimal]) is not numerically equal to [expected]. + * + * By numerically is meant that it will not compare [BigDecimal.scale] (or in other words, + * it uses `compareTo(expected) != 0`) + * + * Most of the time you want to use this function instead of [isNotEqualIncludingScale] because + * [isNotEqualIncludingScale] compares [BigDecimal.scale]. + * Following the two functions compared: + * - `expect(BigDecimal("10")).isNotEqualIncludingScale(BigDecimal("10.0"))` holds. + * - `expect(BigDecimal("10")).isNotNumericallyEqualTo(BigDecimal("10.0"))` does not hold. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + */ +infix fun Expect.isNotNumericallyEqualTo(expected: T) = + addAssertion(ExpectImpl.bigDecimal.isNotNumericallyEqualTo(this, expected)) + + +/** + * Expects that the subject of the assertion (a [BigDecimal]) is equal to [expected] including [BigDecimal.scale]. + * + * Most of the time you want to use [isNumericallyEqualTo] which does not compare [BigDecimal.scale] + * in contrast to this function. + * Following the two functions compared: + * - `expect(BigDecimal("10")).isEqualIncludingScale(BigDecimal("10.0"))` does not hold. + * - `expect(BigDecimal("10")).isNumericallyEqualTo(BigDecimal("10.0"))` holds. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + */ +infix fun Expect.isEqualIncludingScale(expected: T) = + addAssertion(ExpectImpl.bigDecimal.isEqualIncludingScale(this, expected, this::isNumericallyEqualTo.name)) + +/** + * Expects that the subject of the assertion (a [BigDecimal]) is not equal to [expected] including [BigDecimal.scale]. + * + * Most of the time you want to use [isNotNumericallyEqualTo] which does not compare [BigDecimal.scale] + * in contrast to this function. + * Following the two functions compared: + * - `expect(BigDecimal("10")).isNotEqualIncludingScale(BigDecimal("10.0"))` holds. + * - `expect(BigDecimal("10")).isNotNumericallyEqualTo(BigDecimal("10.0"))` does not hold. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + */ +infix fun Expect.isNotEqualIncludingScale(expected: T) = + addAssertion(ExpectImpl.bigDecimal.isNotEqualIncludingScale(this, expected)) diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-jvm/src/module/module-info.java b/apis/infix-en_GB/atrium-api-infix-en_GB-jvm/src/module/module-info.java index ac21a37b6..921dbaa27 100644 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-jvm/src/module/module-info.java +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-jvm/src/module/module-info.java @@ -3,7 +3,12 @@ module ch.tutteli.atrium.api.infix.en_GB { requires kotlin.stdlib; -// exports ch.tutteli.atrium.api.infix.en_GB; -// exports ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders; -// exports ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders; + exports ch.tutteli.atrium.api.infix.en_GB; + exports ch.tutteli.atrium.api.infix.en_GB.creating; + exports ch.tutteli.atrium.api.infix.en_GB.creating.charsequence.contains.builders; + exports ch.tutteli.atrium.api.infix.en_GB.creating.feature; + exports ch.tutteli.atrium.api.infix.en_GB.creating.iterable; + exports ch.tutteli.atrium.api.infix.en_GB.creating.iterable.contains.builders; + exports ch.tutteli.atrium.api.infix.en_GB.creating.map; + exports ch.tutteli.atrium.api.infix.en_GB.workaround; } diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/BigDecimalAssertionsSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/BigDecimalAssertionsSpec.kt new file mode 100644 index 000000000..1f4be3d7d --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/BigDecimalAssertionsSpec.kt @@ -0,0 +1,51 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.api.verbs.internal.expect +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.fun1 +import ch.tutteli.atrium.specs.integration.BigDecimalAssertionsSpec +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.describe +import java.math.BigDecimal + +class BigDecimalAssertionsSpec : Spek({ + include(object : BigDecimalAssertionsSpec( + fun1(Companion::toBeBigDecimal), + fun1(Companion::toBeNullable), + fun1(Companion::toBeNull), + Expect::toBe, + fun1(Companion::notToBe), + Expect::notToBe, + fun1(Companion::isNumericallyEqualTo), + fun1(Companion::isNotNumericallyEqualTo), + fun1(Companion::isEqualIncludingScale), + fun1(Companion::isNotEqualIncludingScale) + ) {}) + + describe("fun toBe for BigDecimal? and subject is null") { + it("chooses the correct overload if `null` is passed, does not throw") { + expect(null as BigDecimal?) toBe null + } + } +}) { + companion object { + @Suppress("DEPRECATION") + fun toBeBigDecimal(expect: Expect, a: BigDecimal): Nothing = expect toBe a + + @Suppress("DEPRECATION") + fun toBeNullable(expect: Expect, a: BigDecimal?): Nothing = expect toBe a + + fun toBeNull(expect: Expect, nothing: Nothing?) = expect toBe nothing + + @Suppress("DEPRECATION") + fun notToBe(expect: Expect, a: BigDecimal): Nothing = expect notToBe a + + fun isNumericallyEqualTo(expect: Expect, a: BigDecimal) = expect isNumericallyEqualTo a + + fun isNotNumericallyEqualTo(expect: Expect, a: BigDecimal) = expect isNotNumericallyEqualTo a + + fun isEqualIncludingScale(expect: Expect, a: BigDecimal) = expect isEqualIncludingScale a + + fun isNotEqualIncludingScale(expect: Expect, a: BigDecimal) = expect isNotEqualIncludingScale a + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/Fun0AssertionsJvmSpec.kt b/apis/infix-en_GB/atrium-api-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/Fun0AssertionsJvmSpec.kt new file mode 100644 index 000000000..57347f264 --- /dev/null +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/Fun0AssertionsJvmSpec.kt @@ -0,0 +1,22 @@ +package ch.tutteli.atrium.api.infix.en_GB + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.feature0 +import ch.tutteli.atrium.specs.feature1 +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter +import ch.tutteli.atrium.specs.withFeatureSuffix + +class Fun0AssertionsJvmSpec : ch.tutteli.atrium.specs.integration.Fun0AssertionsJvmSpec( + ("toThrow" to Companion::toThrowFeature).withFeatureSuffix(), + "toThrow" to Companion::toThrow, + feature0<() -> Int, Int>(Expect<() -> Int>::notToThrow), + feature1<() -> Int, Expect.() -> Unit, Int>(Expect<() -> Int>::notToThrow), + "- ", "» " +) { + + companion object : WithAsciiReporter() { + fun toThrowFeature(expect: Expect Any?>) = expect.toThrow() + fun toThrow(expect: Expect Any?>, assertionCreator: Expect.() -> Unit) = + expect.toThrow { assertionCreator() } + } +} diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-jvm/src/test/resources/META-INF/services/ch.tutteli.atrium.reporting.ReporterFactory b/apis/infix-en_GB/atrium-api-infix-en_GB-jvm/src/test/resources/META-INF/services/ch.tutteli.atrium.reporting.ReporterFactory index 5a5897fe2..111322a35 100644 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-jvm/src/test/resources/META-INF/services/ch.tutteli.atrium.reporting.ReporterFactory +++ b/apis/infix-en_GB/atrium-api-infix-en_GB-jvm/src/test/resources/META-INF/services/ch.tutteli.atrium.reporting.ReporterFactory @@ -1 +1 @@ -ch.tutteli.atrium.api.infix.en_GB.testutils.AsciiBulletPointReporterFactory +ch.tutteli.atrium.specs.testutils.AsciiBulletPointReporterFactory diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/chronoLocalDateAssertions.kt b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/chronoLocalDateAssertions.kt new file mode 100644 index 000000000..0683b00b5 --- /dev/null +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/chronoLocalDateAssertions.kt @@ -0,0 +1,69 @@ +@file:Suppress("JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE" /* TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed */) + +package ch.tutteli.atrium.api.infix.en_GB.jdk8 + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.domain.builders.chronoLocalDate +import java.time.chrono.ChronoLocalDate + +/** + * Expects that the subject of the assertion (a [ChronoLocalDate]) + * is before the [expected] [ChronoLocalDate]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.isBefore(expected: ChronoLocalDate): Expect = + addAssertion(ExpectImpl.chronoLocalDate.isBefore(this, expected)) + +/** + * Expects that the subject of the assertion (a [ChronoLocalDate]) + * is before or equal the [expected] [ChronoLocalDate]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.isBeforeOrEqual(expected: ChronoLocalDate): Expect = + addAssertion(ExpectImpl.chronoLocalDate.isBeforeOrEquals(this, expected)) + + +/** + * Expects that the subject of the assertion (a [ChronoLocalDate]) + * is after the [expected] [ChronoLocalDate]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.isAfter(expected: ChronoLocalDate): Expect = + addAssertion(ExpectImpl.chronoLocalDate.isAfter(this, expected)) + +/** + * Expects that the subject of the assertion (a [ChronoLocalDate]) + * is after or equal the [expected] [ChronoLocalDate]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.isAfterOrEqual(expected: ChronoLocalDate): Expect = + addAssertion(ExpectImpl.chronoLocalDate.isAfterOrEquals(this, expected)) + +/** + * Expects that the subject of the assertion (a [ChronoLocalDate]) + * is equal to the [expected] [ChronoLocalDate]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.isEqual(expected: ChronoLocalDate): Expect = + addAssertion(ExpectImpl.chronoLocalDate.isEqual(this, expected)) diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/chronoLocalDateTimeAssertions.kt b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/chronoLocalDateTimeAssertions.kt new file mode 100644 index 000000000..2a94385d9 --- /dev/null +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/chronoLocalDateTimeAssertions.kt @@ -0,0 +1,73 @@ +@file:Suppress("JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE" /* TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed */) + +package ch.tutteli.atrium.api.infix.en_GB.jdk8 + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.domain.builders.chronoLocalDateTime +import java.time.chrono.ChronoLocalDate +import java.time.chrono.ChronoLocalDateTime + +/** + * Expects that the subject of the assertion (a [ChronoLocalDateTime]) + * is before the [expected] [ChronoLocalDateTime]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun > Expect.isBefore(expected: ChronoLocalDateTime<*>): Expect = + addAssertion(ExpectImpl.chronoLocalDateTime.isBefore(this, expected)) + +/** + * Expects that the subject of the assertion (a [ChronoLocalDateTime]) + * is before or equal the [expected] [ChronoLocalDateTime]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun > Expect.isBeforeOrEqual( + expected: ChronoLocalDateTime<*> +): Expect = addAssertion(ExpectImpl.chronoLocalDateTime.isBeforeOrEquals(this, expected)) + +/** + * Expects that the subject of the assertion (a [ChronoLocalDateTime]) + * is after the [expected] [ChronoLocalDateTime]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun > Expect.isAfter( + expected: ChronoLocalDateTime<*> +): Expect = addAssertion(ExpectImpl.chronoLocalDateTime.isAfter(this, expected)) + +/** + * Expects that the subject of the assertion (a [ChronoLocalDateTime]) + * is after or equal the [expected] [ChronoLocalDateTime]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun > Expect.isAfterOrEqual( + expected: ChronoLocalDateTime<*> +): Expect = addAssertion(ExpectImpl.chronoLocalDateTime.isAfterOrEquals(this, expected)) + +/** + * Expects that the subject of the assertion (a [ChronoLocalDateTime]) + * is equal to the [expected] [ChronoLocalDateTime]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun > Expect.isEqual( + expected: ChronoLocalDateTime<*> +): Expect = addAssertion(ExpectImpl.chronoLocalDateTime.isEqual(this, expected)) diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/chronoZonedDateTimeAssertions.kt b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/chronoZonedDateTimeAssertions.kt new file mode 100644 index 000000000..79c990409 --- /dev/null +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/chronoZonedDateTimeAssertions.kt @@ -0,0 +1,74 @@ +@file:Suppress("JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE" /* TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed */) + +package ch.tutteli.atrium.api.infix.en_GB.jdk8 + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.domain.builders.chronoZonedDateTime +import java.time.chrono.ChronoLocalDate +import java.time.chrono.ChronoZonedDateTime + +/** + * Expects that the subject of the assertion (a [ChronoZonedDateTime]) + * is before the [expected] [ChronoZonedDateTime]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun > Expect.isBefore( + expected: ChronoZonedDateTime<*> +): Expect = addAssertion(ExpectImpl.chronoZonedDateTime.isBefore(this, expected)) + +/** + * Expects that the subject of the assertion (a [ChronoZonedDateTime]) + * is before or equals the [expected] [ChronoZonedDateTime]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun > Expect.isBeforeOrEqual( + expected: ChronoZonedDateTime<*> +): Expect = addAssertion(ExpectImpl.chronoZonedDateTime.isBeforeOrEqual(this, expected)) + +/** + * Expects that the subject of the assertion (a [ChronoZonedDateTime]) + * is after the [expected] [ChronoZonedDateTime]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun > Expect.isAfter( + expected: ChronoZonedDateTime<*> +): Expect = addAssertion(ExpectImpl.chronoZonedDateTime.isAfter(this, expected)) + +/** + * Expects that the subject of the assertion (a [ChronoZonedDateTime]) + * is after or equal the [expected] [ChronoZonedDateTime]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun > Expect.isAfterOrEqual( + expected: ChronoZonedDateTime<*> +): Expect = addAssertion(ExpectImpl.chronoZonedDateTime.isAfterOrEqual(this, expected)) + +/** + * Expects that the subject of the assertion (a [ChronoZonedDateTime]) + * is equal to the [expected] [ChronoZonedDateTime]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun > Expect.isEqual( + expected: ChronoZonedDateTime<*> +): Expect = addAssertion(ExpectImpl.chronoZonedDateTime.isEqual(this, expected)) diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/creating/path/PathWithCreator.kt b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/creating/path/PathWithCreator.kt new file mode 100644 index 000000000..f8043478a --- /dev/null +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/creating/path/PathWithCreator.kt @@ -0,0 +1,15 @@ +@file:Suppress("JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE" /* TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed */) + +package ch.tutteli.atrium.api.infix.en_GB.jdk8.creating.path + +import ch.tutteli.atrium.creating.Expect + +/** + * Parameter object which combines an [path] (as [String]) with an [assertionCreator] which defines assertions for + * a resulting feature of type [E]. + * + * Use the function `path(String) { ... }` to create this representation. + * + * @since 0.11.0 + */ +data class PathWithCreator internal constructor(val path: String, val assertionCreator: Expect.() -> Unit) diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/fileAssertions.kt b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/fileAssertions.kt new file mode 100644 index 000000000..6dba66a94 --- /dev/null +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/fileAssertions.kt @@ -0,0 +1,37 @@ +@file:Suppress("JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE" /* TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed */) + +package ch.tutteli.atrium.api.infix.en_GB.jdk8 + +import ch.tutteli.atrium.api.infix.en_GB.o +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import java.io.File +import java.nio.file.Path + +/** + * Turns `Expect` into `Expect`. + * + * The transformation as such is not reflected in reporting. + * Use `feature File::toPath` if you want to show the transformation in reporting. + * + * @return The newly created [Expect] for the transformed subject. + * + * @since 0.11.0 + */ +infix fun Expect.asPath( + @Suppress("UNUSED_PARAMETER") o: o +): Expect = ExpectImpl.changeSubject(this).unreported { it.toPath() } + +/** + * Expects that the subject of the assertion holds all assertions the given [assertionCreator] creates for + * the subject as [Path]. + * + * The transformation as such is not reflected in reporting. + * Use `feature of(File::toPath, assertionCreator)` if you want to show the transformation in reporting. + * + * @return An [Expect] for the current subject of the assertion. + * + * @since 0.11.0 + */ +infix fun Expect.asPath(assertionCreator: Expect.() -> Unit): Expect = + apply { asPath(o).addAssertionsCreatedBy(assertionCreator) } diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/localDateAssertions.kt b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/localDateAssertions.kt new file mode 100644 index 000000000..31d4efc4f --- /dev/null +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/localDateAssertions.kt @@ -0,0 +1,109 @@ +@file:Suppress( + "FINAL_UPPER_BOUND" /* remove once https://youtrack.jetbrains.com/issue/KT-34257 is fixed */, + "JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE" /* TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed */ +) + +package ch.tutteli.atrium.api.infix.en_GB.jdk8 + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.domain.builders.localDate +import java.time.DayOfWeek +import java.time.LocalDate + +/** + * Creates an [Expect] for the property [LocalDate.year][LocalDate.getYear] of the subject of the assertion, + * so that further fluent calls are assertions about it. + * + * @return The newly created [Expect] for the extracted feature. + * + * @since 0.11.0 + */ +val Expect.year: Expect + get() = ExpectImpl.localDate.year(this).getExpectOfFeature() + +/** + * Expects that the property [LocalDate.year][LocalDate.getYear]of the subject of the assertion + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.year(assertionCreator: Expect.() -> Unit): Expect = + ExpectImpl.localDate.year(this).addToInitial(assertionCreator) + +/** + * Creates an [Expect] for the property [LocalDate.monthValue][LocalDate.getMonthValue] of the subject of the assertion, + * so that further fluent calls are assertions about it. + * + * @return The newly created [Expect] for the extracted feature. + * + * @since 0.11.0 + */ +val Expect.month: Expect + get() = ExpectImpl.localDate.month(this).getExpectOfFeature() + +/** + * Expects that the property [LocalDate.monthValue][LocalDate.getMonthValue] of the subject of the assertion + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.month(assertionCreator: Expect.() -> Unit): Expect = + ExpectImpl.localDate.month(this).addToInitial(assertionCreator) + +/** + * Creates an [Expect] for the property [LocalDate.getDayOfWeek] of the subject of the assertion, + * so that further fluent calls are assertions about it. + * + * @return The newly created [Expect] for the extracted feature. + * + * @since 0.11.0 + */ +val Expect.dayOfWeek: Expect + get() = ExpectImpl.localDate.dayOfWeek(this).getExpectOfFeature() + +/** + * Expects that the property [LocalDate.getDayOfWeek] of the subject of the assertion + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.dayOfWeek(assertionCreator: Expect.() -> Unit): Expect = + ExpectImpl.localDate.dayOfWeek(this).addToInitial(assertionCreator) + + +/** + * Creates an [Expect] for the property [LocalDate.dayOfMonth][LocalDate.getDayOfMonth] of the subject of the assertion, + * so that further fluent calls are assertions about it. + * + * @return The newly created [Expect] for the extracted feature. + * + * @since 0.11.0 + */ +val Expect.day: Expect + get() = ExpectImpl.localDate.day(this).getExpectOfFeature() + +/** + * Expects that the property [LocalDate.dayOfMonth][LocalDate.getDayOfMonth] of the subject of the assertion + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.day(assertionCreator: Expect.() -> Unit): Expect = + ExpectImpl.localDate.day(this).addToInitial(assertionCreator) diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/localDateTimeAssertions.kt b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/localDateTimeAssertions.kt new file mode 100644 index 000000000..dfc33a3ee --- /dev/null +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/localDateTimeAssertions.kt @@ -0,0 +1,109 @@ +@file:Suppress( + "FINAL_UPPER_BOUND" /* remove once https://youtrack.jetbrains.com/issue/KT-34257 is fixed */, + "JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE" /* TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed */ +) + +package ch.tutteli.atrium.api.infix.en_GB.jdk8 + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.domain.builders.localDateTime +import java.time.DayOfWeek +import java.time.LocalDateTime + +/** + * Creates an [Expect] for the property [LocalDateTime.year][[LocalDateTime.getYear] of the subject of the assertion, + * so that further fluent calls are assertions about it. + * + * @return The newly created [Expect] for the extracted feature. + * + * @since 0.11.0 + */ +val Expect.year: Expect + get() = ExpectImpl.localDateTime.year(this).getExpectOfFeature() + +/** + * Expects that the property [LocalDateTime.year][LocalDateTime.getYear] of the subject of the assertion + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.year(assertionCreator: Expect.() -> Unit): Expect = + ExpectImpl.localDateTime.year(this).addToInitial(assertionCreator) + +/** + * Creates an [Expect] for the property [LocalDateTime.monthValue][LocalDateTime.getMonthValue] + * of the subject of the assertion, so that further fluent calls are assertions about it. + * + * @return The newly created [Expect] for the extracted feature. + * + * @since 0.11.0 + */ +val Expect.month: Expect + get() = ExpectImpl.localDateTime.month(this).getExpectOfFeature() + +/** + * Expects that the property [LocalDateTime.monthValue][LocalDateTime.getMonthValue]of the subject of the assertion + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.month(assertionCreator: Expect.() -> Unit): Expect = + ExpectImpl.localDateTime.month(this).addToInitial(assertionCreator) + +/** + * Creates an [Expect] for the property [LocalDateTime.dayOfWeek][LocalDateTime.getDayOfWeek] + * of the subject of the assertion, so that further fluent calls are assertions about it. + * + * @return The newly created [Expect] for the extracted feature. + * + * @since 0.11.0 + */ +val Expect.dayOfWeek: Expect + get() = ExpectImpl.localDateTime.dayOfWeek(this).getExpectOfFeature() + +/** + * Expects that the property [LocalDateTime.dayOfWeek][LocalDateTime.getDayOfWeek]of the subject of the assertion + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.dayOfWeek(assertionCreator: Expect.() -> Unit): Expect = + ExpectImpl.localDateTime.dayOfWeek(this).addToInitial(assertionCreator) + +/** + * Creates an [Expect] for the property [LocalDateTime.dayOfMonth][LocalDateTime.getDayOfMonth] + * of the subject of the assertion, so that further fluent calls are assertions about it. + * + * @return The newly created [Expect] for the extracted feature. + * + * @since 0.11.0 + */ +val Expect.day: Expect + get() = ExpectImpl.localDateTime.day(this).getExpectOfFeature() + +/** + * Expects that the property [LocalDateTime.dayOfMonth][LocalDateTime.getDayOfMonth] of the subject of the assertion + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.day(assertionCreator: Expect.() -> Unit): Expect = + ExpectImpl.localDateTime.day(this).addToInitial(assertionCreator) + diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/optionalAssertions.kt b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/optionalAssertions.kt new file mode 100644 index 000000000..c3d111a1e --- /dev/null +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/optionalAssertions.kt @@ -0,0 +1,52 @@ +@file:Suppress("JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE" /* TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed */) + +package ch.tutteli.atrium.api.infix.en_GB.jdk8 + +import ch.tutteli.atrium.api.infix.en_GB.empty +import ch.tutteli.atrium.api.infix.en_GB.present +import ch.tutteli.atrium.api.infix.en_GB.creating.PresentWithCreator +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.domain.builders.optional +import java.util.* + +/** + * Expects that the subject of the assertion (an [Optional]) is empty (not present). + * + * Shortcut for more or less something like `feature(Optional::isEmpty) { toBe(true) }` + * depends on the underlying implementation though. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun > Expect.toBe(@Suppress("UNUSED_PARAMETER") empty: empty) = + addAssertion(ExpectImpl.optional.isEmpty(this)) + +/** + * Expects that the subject of the assertion (an [Optional]) is present + * and returns an [Expect] for the inner type [E]. + * + * Shortcut for more or less something like `feature(Optional::get)` but with error handling; yet it + * depends on the underlying implementation though. + * + * @return The newly created [Expect] for the inner type [E]. + * @throws AssertionError Might throw an [AssertionError] if the given assertion is not a success. + * + * @since 0.11.0 + */ +infix fun > Expect.toBe(@Suppress("UNUSED_PARAMETER") present: present) = + ExpectImpl.optional.isPresent(this).getExpectOfFeature() + +/** + * Expects that the subject of the assertion (an [Optional]) is present and + * that it holds all assertions the given [PresentWithCreator.assertionCreator] creates. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the given assertions are not success. + * + * @since 0.11.0 + */ +infix fun > Expect.toBe(present: PresentWithCreator): Expect = + ExpectImpl.optional.isPresent(this).addToInitial(present.assertionCreator) diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/pathAssertions.kt b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/pathAssertions.kt new file mode 100644 index 000000000..83af113a3 --- /dev/null +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/pathAssertions.kt @@ -0,0 +1,298 @@ +@file:Suppress("JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE" /* TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed */) + +package ch.tutteli.atrium.api.infix.en_GB.jdk8 + +import ch.tutteli.atrium.api.infix.en_GB.* +import ch.tutteli.atrium.api.infix.en_GB.jdk8.creating.path.PathWithCreator +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.domain.builders.path +import java.nio.file.Path + +/** + * Expects that the subject of the assertion (a [Path]) starts with the [expected] [Path]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.startsWith(expected: Path): Expect = + addAssertion(ExpectImpl.path.startsWith(this, expected)) + +/** + * Expects that the subject of the assertion (a [Path]) does not start with the [expected] [Path]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.startsNotWith(expected: Path): Expect = + addAssertion(ExpectImpl.path.startsNotWith(this, expected)) + +/** + * Expects that the subject of the assertion (a [Path]) ends with the expected [Path]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.endsWith(expected: Path): Expect = + addAssertion(ExpectImpl.path.endsWith(this, expected)) + +/** + * Expects that the subject of the assertion (a [Path]) does not end with the expected [Path]; + * + * @param expected The [Path] provided to the assertion + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.endsNotWith(expected: Path): Expect = + addAssertion(ExpectImpl.path.endsNotWith(this, expected)) + +/** + * Expects that the subject of the assertion (a [Path]) exists; + * meaning that there is a file system entry at the location the [Path] points to. + * + * This matcher _resolves_ symbolic links. Therefore, if a symbolic link exists at the location the subject points to, + * then the search will continue at that location. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.to(@Suppress("UNUSED_PARAMETER") exist: exist): Expect = + addAssertion(ExpectImpl.path.exists(this)) + +/** + * Expects that the subject of the assertion (a [Path]) does not exist; + * meaning that there is no file system entry at the location the [Path] points to. + * + * This matcher _resolves_ symbolic links. Therefore, if a symbolic link exists at the location the subject points to, + * then the search will continue at that location. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.notTo(@Suppress("UNUSED_PARAMETER") exist: exist): Expect = + addAssertion(ExpectImpl.path.existsNot(this)) + +/** + * Creates an [Expect] for the property [Path.fileNameAsString][ch.tutteli.niok.fileNameAsString] + * (provided via [niok](https://github.com/robstoll/niok)) of the subject of the assertion, + * so that further fluent calls are assertions about it. + * + * @return The newly created [Expect] for the extracted feature. + * + * @since 0.11.0 + */ +val Expect.fileName: Expect + get() = ExpectImpl.path.fileName(this).getExpectOfFeature() + +/** + * Expects that the property [Path.fileNameAsString][ch.tutteli.niok.fileNameAsString] + * (provided via [niok](https://github.com/robstoll/niok)) of the subject of the assertion + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.fileName(assertionCreator: Expect.() -> Unit): Expect = + ExpectImpl.path.fileName(this).addToInitial(assertionCreator) + +/** + * Creates an [Expect] for the property [Path.fileNameWithoutExtension][ch.tutteli.niok.fileNameWithoutExtension] + * (provided via [niok](https://github.com/robstoll/niok)) of the subject of the assertion, + * so that further fluent calls are assertions about it. + * + * @return The newly created [Expect] for the extracted feature. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +val Expect.fileNameWithoutExtension: Expect + get() = ExpectImpl.path.fileNameWithoutExtension(this).getExpectOfFeature() + +/** + * Expects that the property [Path.fileNameWithoutExtension][ch.tutteli.niok.fileNameWithoutExtension] + * (provided via [niok](https://github.com/robstoll/niok)) + * of the subject of the assertion holds all assertions the given [assertionCreator] creates for it + * and returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.fileNameWithoutExtension(assertionCreator: Expect.() -> Unit): Expect = + ExpectImpl.path.fileNameWithoutExtension(this).addToInitial(assertionCreator) + +/** + * Expects that this [Path] has a [parent][Path.getParent] and creates an [Expect] for it, + * so that further fluent calls are assertions about it. + * + * @return The newly created [Expect] for the extracted feature. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +val Expect.parent: Expect + get() = ExpectImpl.path.parent(this).getExpectOfFeature() + +/** + * Expects that this [Path] has a [parent][Path.getParent], that the parent holds all assertions the + * given [assertionCreator] creates for it and returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.parent(assertionCreator: Expect.() -> Unit): Expect = + ExpectImpl.path.parent(this).addToInitial(assertionCreator) + +/** + * Expects that [other] resolves against this [Path] and creates an [Expect] for the resolved [Path] + * so that further fluent calls are assertions about it. + * + * @return The newly created [Expect] for the extracted feature. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.resolve(other: String): Expect = + ExpectImpl.path.resolve(this, other).getExpectOfFeature() + +/** + * Expects that [PathWithCreator.path] resolves against this [Path], that the resolved [Path] holds all assertions the + * given [PathWithCreator.assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * Use the function `path(String) { ... }` to create a [PathWithCreator]. + * + * @return The newly created [Expect] for the extracted feature. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.resolve(path: PathWithCreator): Expect = + ExpectImpl.path.resolve(this, path.path).addToInitial(path.assertionCreator) + +/** + * Helper function to create a [PathWithCreator] based on the given [path] and [assertionCreator]. + */ +fun path(path: String, assertionCreator: Expect.() -> Unit) = PathWithCreator(path, assertionCreator) + +/** + * Expects that the subject of the assertion (a [Path]) is readable; + * meaning that there is a file system entry at the location the [Path] points to and + * that the current thread has the permission to read from it. + * + * This matcher _resolves_ symbolic links. + * Therefore, if a symbolic link exists at the location the subject points to, + * search will continue at the location the link points at. + * + * This assertion is not atomic with respect to concurrent file system operations on the paths the assertions works on. + * Its result, in particular its extended explanations, may be wrong if such concurrent file system operations + * take place. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.toBe(@Suppress("UNUSED_PARAMETER") readable: readable): Expect = + addAssertion(ExpectImpl.path.isReadable(this)) + +/** + * Expects that the subject of the assertion (a [Path]) is writable; + * meaning that there is a file system entry at the location the [Path] points to and + * that the current thread has the permission to write to it. + * + * This matcher _resolves_ symbolic links. + * Therefore, if a symbolic link exists at the location the subject points to, search will continue + * at the location the link points at. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.toBe(@Suppress("UNUSED_PARAMETER") writable: writable): Expect = + addAssertion(ExpectImpl.path.isWritable(this)) + +/** + * Expects that the subject of the assertion (a [Path]) is a file; + * meaning that there is a file system entry at the location the [Path] points to and that is a regular file. + * + * This matcher _resolves_ symbolic links. + * Therefore, if a symbolic link exists at the location the subject points to, search will continue + * at the location the link points at. + * + * This assertion is not atomic with respect to concurrent file system operations on the paths the assertions works on. + * Its result, in particular its extended explanations, may be wrong if such concurrent file system operations + * take place. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.toBe(@Suppress("UNUSED_PARAMETER") aRegularFile: aRegularFile): Expect = + addAssertion(ExpectImpl.path.isRegularFile(this)) + +/** + * Expects that the subject of the assertion (a [Path]) is a directory; + * meaning that there is a file system entry at the location the [Path] points to and that is a directory. + * + * This matcher _resolves_ symbolic links. + * Therefore, if a symbolic link exists at the location the subject points to, search will continue + * at the location the link points at. + * + * This assertion is not atomic with respect to concurrent file system operations on the paths the assertions works on. + * Its result, in particular its extended explanations, may be wrong if such concurrent file system operations + * take place. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.toBe(@Suppress("UNUSED_PARAMETER") aDirectory: aDirectory): Expect = + addAssertion(ExpectImpl.path.isDirectory(this)) + +/** + * Creates an [Expect] for the property [Path.extension][ch.tutteli.niok.extension] + * (provided via [niok](https://github.com/robstoll/niok)) of the subject of the assertion, + * so that further fluent calls are assertions about it. + * + * @return The newly created [Expect] for the extracted feature. + * + * @since 0.11.0 + */ +val Expect.extension: Expect + get() = ExpectImpl.path.extension(this).getExpectOfFeature() + +/** + * Expects that the property [Path.extension][ch.tutteli.niok.extension] + * (provided via [niok](https://github.com/robstoll/niok)) of the subject of the assertion + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.extension(assertionCreator: Expect.() -> Unit): Expect = + ExpectImpl.path.extension(this).addToInitial(assertionCreator) diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/zonedDateTimeAssertions.kt b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/zonedDateTimeAssertions.kt new file mode 100644 index 000000000..df74e96e5 --- /dev/null +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/zonedDateTimeAssertions.kt @@ -0,0 +1,108 @@ +@file:Suppress( + "FINAL_UPPER_BOUND" /* remove once https://youtrack.jetbrains.com/issue/KT-34257 is fixed */, + "JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE" /* TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed */ +) + +package ch.tutteli.atrium.api.infix.en_GB.jdk8 + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.domain.builders.zonedDateTime +import java.time.DayOfWeek +import java.time.ZonedDateTime + +/** + * Creates an [Expect] for the property [ZonedDateTime.year][ZonedDateTime.getYear] of the subject of the assertion, + * so that further fluent calls are assertions about it. + * + * @return The newly created [Expect] for the extracted feature. + * + * @since 0.11.0 + */ +val Expect.year: Expect + get() = ExpectImpl.zonedDateTime.year(this).getExpectOfFeature() + +/** + * Expects that the property [ZonedDateTime.year][ZonedDateTime.getYear] of the subject of the assertion + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.year(assertionCreator: Expect.() -> Unit): Expect = + ExpectImpl.zonedDateTime.year(this).addToInitial(assertionCreator) + +/** + * Creates an [Expect] for the property [ZonedDateTime.monthValue][ZonedDateTime.getMonthValue] + * of the subject of the assertion, so that further fluent calls are assertions about it. + * + * @return The newly created [Expect] for the extracted feature. + * + * @since 0.11.0 + */ +val Expect.month: Expect + get() = ExpectImpl.zonedDateTime.month(this).getExpectOfFeature() + +/** + * Expects that the property [ZonedDateTime.monthValue][ZonedDateTime.getMonthValue] of the subject of the assertion + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.month(assertionCreator: Expect.() -> Unit): Expect = + ExpectImpl.zonedDateTime.month(this).addToInitial(assertionCreator) + +/** + * Creates an [Expect] for the property [ZonedDatetime.dayOfWeek][ZonedDateTime.getDayOfWeek] + * of the subject of the assertion, so that further fluent calls are assertions about it. + * + * @return The newly created [Expect] for the extracted feature. + * + * @since 0.11.0 + */ +val Expect.dayOfWeek: Expect + get() = ExpectImpl.zonedDateTime.dayOfWeek(this).getExpectOfFeature() + +/** + * Expects that the property [ZonedDatetime.dayOfWeek][ZonedDateTime.getDayOfWeek] of the subject of the assertion + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.dayOfWeek(assertionCreator: Expect.() -> Unit): Expect = + ExpectImpl.zonedDateTime.dayOfWeek(this).addToInitial(assertionCreator) + +/** + * Creates an [Expect] for the property [ZonedDateTime.dayOfMonth][ZonedDateTime.getDayOfMonth] + * of the subject of the assertion, so that further fluent calls are assertions about it. + * + * @return The newly created [Expect] for the extracted feature. + * + * @since 0.11.0 + */ +val Expect.day: Expect + get() = ExpectImpl.zonedDateTime.day(this).getExpectOfFeature() + +/** + * Expects that the property [ZonedDateTime.dayOfMonth][ZonedDateTime.getDayOfMonth] of the subject of the assertion + * holds all assertions the given [assertionCreator] creates for it and + * returns an [Expect] for the current subject of the assertion. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +infix fun Expect.day(assertionCreator: Expect.() -> Unit): Expect = + ExpectImpl.zonedDateTime.day(this).addToInitial(assertionCreator) diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/module/module-info.java b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/module/module-info.java index f583f55a2..26d81d3a6 100644 --- a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/module/module-info.java +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/module/module-info.java @@ -1,9 +1,11 @@ module ch.tutteli.atrium.api.infix.en_GB.jdk8 { + requires ch.tutteli.atrium.api.infix.en_GB; requires ch.tutteli.atrium.domain.builders; requires ch.tutteli.kbox; requires ch.tutteli.niok; requires kotlin.stdlib; requires java.base; -// exports ch.tutteli.atrium.api.infix.en_GB.jdk8; + exports ch.tutteli.atrium.api.infix.en_GB.jdk8; + exports ch.tutteli.atrium.api.infix.en_GB.jdk8.creating.path; } diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/ChronoLocalDateAssertionsSpec.kt b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/ChronoLocalDateAssertionsSpec.kt new file mode 100644 index 000000000..b7b850146 --- /dev/null +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/ChronoLocalDateAssertionsSpec.kt @@ -0,0 +1,59 @@ +package ch.tutteli.atrium.api.infix.en_GB.jdk8 + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.fun1 +import ch.tutteli.atrium.specs.notImplemented +import java.time.LocalDate +import java.time.chrono.ChronoLocalDate +import java.time.chrono.JapaneseDate + +class ChronoLocalDateAssertionsSpec : ch.tutteli.atrium.specs.integration.ChronoLocalDateAssertionSpec( + fun1(Expect::isBefore), + fun1(Expect::isBeforeOrEqual), + fun1(Expect::isAfter), + fun1(Expect::isAfterOrEqual), + fun1(Expect::isEqual) +) { + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + val chronoLocalDate: ChronoLocalDate = notImplemented() + var a1: Expect = notImplemented() + var a2: Expect = notImplemented() + + a1 = a1 isBefore LocalDate.now() + a1 = a1 isBeforeOrEqual LocalDate.now() + a1 = a1 isAfter LocalDate.now() + a1 = a1 isAfterOrEqual LocalDate.now() + a1 = a1 isEqual LocalDate.now() + + a2 = a2 isBefore LocalDate.now() + a2 = a2 isBeforeOrEqual LocalDate.now() + a2 = a2 isAfter LocalDate.now() + a2 = a2 isAfterOrEqual LocalDate.now() + a2 = a2 isEqual LocalDate.now() + + a1 = a1 isBefore JapaneseDate.now() + a1 = a1 isBeforeOrEqual JapaneseDate.now() + a1 = a1 isAfter JapaneseDate.now() + a1 = a1 isAfterOrEqual JapaneseDate.now() + a1 = a1 isEqual JapaneseDate.now() + + a2 = a2 isBefore JapaneseDate.now() + a2 = a2 isBeforeOrEqual JapaneseDate.now() + a2 = a2 isAfter JapaneseDate.now() + a2 = a2 isAfterOrEqual JapaneseDate.now() + a2 = a2 isEqual JapaneseDate.now() + + a1 = a1 isBefore chronoLocalDate + a1 = a1 isBeforeOrEqual chronoLocalDate + a1 = a1 isAfter chronoLocalDate + a1 = a1 isAfterOrEqual chronoLocalDate + a1 = a1 isEqual chronoLocalDate + + a2 = a2 isBefore chronoLocalDate + a2 = a2 isBeforeOrEqual chronoLocalDate + a2 = a2 isAfter chronoLocalDate + a2 = a2 isAfterOrEqual chronoLocalDate + a2 = a2 isEqual chronoLocalDate + } +} diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/ChronoLocalDateTimeAssertionSpec.kt b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/ChronoLocalDateTimeAssertionSpec.kt new file mode 100644 index 000000000..8db4f832d --- /dev/null +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/ChronoLocalDateTimeAssertionSpec.kt @@ -0,0 +1,75 @@ +package ch.tutteli.atrium.api.infix.en_GB.jdk8 + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.fun1 +import ch.tutteli.atrium.specs.notImplemented +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.chrono.ChronoLocalDate +import java.time.chrono.ChronoLocalDateTime + +class ChronoLocalDateTimeAssertionSpec : ch.tutteli.atrium.specs.integration.ChronoLocalDateTimeAssertionSpec( + fun1(Expect>::isBefore), + fun1(Expect>::isBeforeOrEqual), + fun1(Expect>::isAfter), + fun1(Expect>::isAfterOrEqual), + fun1(Expect>::isEqual) +) { + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + val chronoLocalDateTime: ChronoLocalDateTime<*> = notImplemented() + var a1: Expect> = notImplemented() + var a2: Expect> = notImplemented() + var a3: Expect> = notImplemented() + var a4: Expect = notImplemented() + + a1 = a1 isBefore LocalDateTime.now() + a1 = a1 isBeforeOrEqual LocalDateTime.now() + a1 = a1 isAfter LocalDateTime.now() + a1 = a1 isAfterOrEqual LocalDateTime.now() + a1 = a1 isEqual LocalDateTime.now() + + a2 = a2 isBefore LocalDateTime.now() + a2 = a2 isBeforeOrEqual LocalDateTime.now() + a2 = a2 isAfter LocalDateTime.now() + a2 = a2 isAfterOrEqual LocalDateTime.now() + a2 = a2 isEqual LocalDateTime.now() + + a3 = a3 isBefore LocalDateTime.now() + a3 = a3 isBeforeOrEqual LocalDateTime.now() + a3 = a3 isAfter LocalDateTime.now() + a3 = a3 isAfterOrEqual LocalDateTime.now() + a3 = a3 isEqual LocalDateTime.now() + + a4 = a4 isBefore LocalDateTime.now() + a4 = a4 isBeforeOrEqual LocalDateTime.now() + a4 = a4 isAfter LocalDateTime.now() + a4 = a4 isAfterOrEqual LocalDateTime.now() + a4 = a4 isEqual LocalDateTime.now() + + a1 = a1 isBefore chronoLocalDateTime + a1 = a1 isBeforeOrEqual chronoLocalDateTime + a1 = a1 isAfter chronoLocalDateTime + a1 = a1 isAfterOrEqual chronoLocalDateTime + a1 = a1 isEqual chronoLocalDateTime + + a2 = a2 isBefore chronoLocalDateTime + a2 = a2 isBeforeOrEqual chronoLocalDateTime + a2 = a2 isAfter chronoLocalDateTime + a2 = a2 isAfterOrEqual chronoLocalDateTime + a2 = a2 isEqual chronoLocalDateTime + + a3 = a3 isBefore chronoLocalDateTime + a3 = a3 isBeforeOrEqual chronoLocalDateTime + a3 = a3 isAfter chronoLocalDateTime + a3 = a3 isAfterOrEqual chronoLocalDateTime + a3 = a3 isEqual chronoLocalDateTime + + a4 = a4 isBefore chronoLocalDateTime + a4 = a4 isBeforeOrEqual chronoLocalDateTime + a4 = a4 isAfter chronoLocalDateTime + a4 = a4 isAfterOrEqual chronoLocalDateTime + a4 = a4 isEqual chronoLocalDateTime + } +} diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/ChronoZonedDateTimeAssertionSpec.kt b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/ChronoZonedDateTimeAssertionSpec.kt new file mode 100644 index 000000000..ecebc17d6 --- /dev/null +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/ChronoZonedDateTimeAssertionSpec.kt @@ -0,0 +1,76 @@ +package ch.tutteli.atrium.api.infix.en_GB.jdk8 + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.fun1 +import ch.tutteli.atrium.specs.notImplemented +import java.time.LocalDate +import java.time.ZonedDateTime +import java.time.chrono.ChronoLocalDate +import java.time.chrono.ChronoZonedDateTime + +class ChronoZonedDateTimeAssertionSpec : ch.tutteli.atrium.specs.integration.ChronoZonedDateTimeAssertionSpec( + fun1(Expect>::isBefore), + fun1(Expect>::isBeforeOrEqual), + fun1(Expect>::isAfter), + fun1(Expect>::isAfterOrEqual), + fun1(Expect>::isEqual) +) { + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + val chronoZonedDateTime: ChronoZonedDateTime<*> = notImplemented() + var a1: Expect> = notImplemented() + var a2: Expect> = notImplemented() + var a3: Expect> = notImplemented() + var a4: Expect = notImplemented() + + + a1 = a1 isBefore ZonedDateTime.now() + a1 = a1 isBeforeOrEqual ZonedDateTime.now() + a1 = a1 isAfter ZonedDateTime.now() + a1 = a1 isAfterOrEqual ZonedDateTime.now() + a1 = a1 isEqual ZonedDateTime.now() + + a2 = a2 isBefore ZonedDateTime.now() + a2 = a2 isBeforeOrEqual ZonedDateTime.now() + a2 = a2 isAfter ZonedDateTime.now() + a2 = a2 isAfterOrEqual ZonedDateTime.now() + a2 = a2 isEqual ZonedDateTime.now() + + a3 = a3 isBefore ZonedDateTime.now() + a3 = a3 isBeforeOrEqual ZonedDateTime.now() + a3 = a3 isAfter ZonedDateTime.now() + a3 = a3 isAfterOrEqual ZonedDateTime.now() + a3 = a3 isEqual ZonedDateTime.now() + + a4 = a4 isBefore ZonedDateTime.now() + a4 = a4 isBeforeOrEqual ZonedDateTime.now() + a4 = a4 isAfter ZonedDateTime.now() + a4 = a4 isAfterOrEqual ZonedDateTime.now() + a4 = a4 isEqual ZonedDateTime.now() + + + a1 = a1 isBefore chronoZonedDateTime + a1 = a1 isBeforeOrEqual chronoZonedDateTime + a1 = a1 isAfter chronoZonedDateTime + a1 = a1 isAfterOrEqual chronoZonedDateTime + a1 = a1 isEqual chronoZonedDateTime + + a2 = a2 isBefore chronoZonedDateTime + a2 = a2 isBeforeOrEqual chronoZonedDateTime + a2 = a2 isAfter chronoZonedDateTime + a2 = a2 isAfterOrEqual chronoZonedDateTime + a2 = a2 isEqual chronoZonedDateTime + + a3 = a3 isBefore chronoZonedDateTime + a3 = a3 isBeforeOrEqual chronoZonedDateTime + a3 = a3 isAfter chronoZonedDateTime + a3 = a3 isAfterOrEqual chronoZonedDateTime + a3 = a3 isEqual chronoZonedDateTime + + a4 = a4 isBefore chronoZonedDateTime + a4 = a4 isBeforeOrEqual chronoZonedDateTime + a4 = a4 isAfter chronoZonedDateTime + a4 = a4 isAfterOrEqual chronoZonedDateTime + a4 = a4 isEqual chronoZonedDateTime + } +} diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/FileAsPathAssertionsSpec.kt b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/FileAsPathAssertionsSpec.kt new file mode 100644 index 000000000..e3da3d421 --- /dev/null +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/FileAsPathAssertionsSpec.kt @@ -0,0 +1,21 @@ +package ch.tutteli.atrium.api.infix.en_GB.jdk8 + +import ch.tutteli.atrium.api.infix.en_GB.o +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter +import java.io.File + +class FileAsPathAssertionsSpec : ch.tutteli.atrium.specs.integration.FileAsPathAssertionsSpec( + Expect::asPath +) { + companion object : WithAsciiReporter() + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + var a1: Expect = notImplemented() + + a1 asPath o + a1 = a1 asPath { } + } +} diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/LocalDateFeatureAssertionsSpec.kt b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/LocalDateFeatureAssertionsSpec.kt new file mode 100644 index 000000000..7355cb2e7 --- /dev/null +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/LocalDateFeatureAssertionsSpec.kt @@ -0,0 +1,37 @@ +package ch.tutteli.atrium.api.infix.en_GB.jdk8 + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.fun1 +import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.property +import java.time.DayOfWeek +import java.time.LocalDate + +class LocalDateFeatureAssertionsSpec : ch.tutteli.atrium.specs.integration.LocalDateFeatureAssertionsSpec( + property(Expect::year), + fun1.() -> Unit>(Expect::year), + property(Expect::month), + fun1.() -> Unit>(Expect::month), + property(Expect::day), + fun1.() -> Unit>(Expect::day), + property(Expect::dayOfWeek), + fun1.() -> Unit>(Expect::dayOfWeek) +) { + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + var a1: Expect = notImplemented() + + a1.year + a1 = a1 year { } + + a1.month + a1 = a1 month { } + + a1.dayOfWeek + a1 = a1 dayOfWeek { } + + a1.day + a1 = a1 day { } + } +} + diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/LocalDateTimeFeatureAssertionsSpec.kt b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/LocalDateTimeFeatureAssertionsSpec.kt new file mode 100644 index 000000000..02a2a8f60 --- /dev/null +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/LocalDateTimeFeatureAssertionsSpec.kt @@ -0,0 +1,36 @@ +package ch.tutteli.atrium.api.infix.en_GB.jdk8 + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.fun1 +import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.property +import java.time.DayOfWeek +import java.time.LocalDateTime + +class LocalDateTimeFeatureAssertionsSpec : ch.tutteli.atrium.specs.integration.LocalDateTimeFeatureAssertionsSpec( + property(Expect::year), + fun1.() -> Unit>(Expect::year), + property(Expect::month), + fun1.() -> Unit>(Expect::month), + property(Expect::day), + fun1.() -> Unit>(Expect::day), + property(Expect::dayOfWeek), + fun1.() -> Unit>(Expect::dayOfWeek) +) { + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + var a1: Expect = notImplemented() + + a1.year + a1 = a1 year { } + + a1.month + a1 = a1 month { } + + a1.day + a1 = a1 day { } + + a1.dayOfWeek + a1 = a1 dayOfWeek { } + } +} diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/OptionalAssertionsSpec.kt b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/OptionalAssertionsSpec.kt new file mode 100644 index 000000000..2fc497b83 --- /dev/null +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/OptionalAssertionsSpec.kt @@ -0,0 +1,46 @@ +package ch.tutteli.atrium.api.infix.en_GB.jdk8 + +import ch.tutteli.atrium.api.infix.en_GB.empty +import ch.tutteli.atrium.api.infix.en_GB.present +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.feature0 +import ch.tutteli.atrium.specs.fun0 +import ch.tutteli.atrium.specs.fun1 +import ch.tutteli.atrium.specs.integration.OptionalAssertionsSpec +import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter +import java.util.* + +class OptionalAssertionsSpec : OptionalAssertionsSpec( + fun0(Companion::toBeEmpty), + feature0(Companion::toBePresentFeature), + fun1(Companion::toBePresent) +) { + companion object : WithAsciiReporter() { + private fun toBeEmpty(expect: Expect>) = expect toBe empty + private fun toBePresent(expect: Expect>, assertionCreator: Expect.() -> Unit) = + expect toBe present(assertionCreator) + + private fun toBePresentFeature(expect: Expect>) = expect toBe present + } + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + var o1: Expect> = notImplemented() + var o1b: Expect> = notImplemented() + + var star: Expect> = notImplemented() + + o1 = o1 toBe empty + o1b = o1b toBe empty + star = star toBe empty + o1 toBe present + o1b toBe present + // following is not supported on purpose as we don't know what type the element is in this case + //star toBe Present + o1 toBe present {} + o1b toBe present {} + // following is not supported on purpose as we don't know what type the element is in this case + //star toBe present {} + } +} diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/PathAssertionsSpec.kt b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/PathAssertionsSpec.kt new file mode 100644 index 000000000..f34a6cfca --- /dev/null +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/PathAssertionsSpec.kt @@ -0,0 +1,51 @@ +package ch.tutteli.atrium.api.infix.en_GB.jdk8 + +import ch.tutteli.atrium.api.infix.en_GB.* +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.fun1 +import ch.tutteli.atrium.specs.name +import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter +import java.nio.file.Path +import java.nio.file.Paths + +class PathAssertionsSpec : ch.tutteli.atrium.specs.integration.PathAssertionsSpec( + fun1(Expect::to).name to Companion::exists, + fun1(Expect::notTo).name to Companion::existsNot, + fun1(Expect::startsWith), + fun1(Expect::startsNotWith), + fun1(Expect::endsWith), + fun1(Expect::endsNotWith), + fun1(Expect::toBe).name to Companion::isReadable, + fun1(Expect::toBe).name to Companion::isWritable, + fun1(Expect::toBe).name to Companion::isRegularFile, + fun1(Expect::toBe).name to Companion::isDirectory +) { + companion object : WithAsciiReporter() { + + private fun exists(expect: Expect) = expect to exist + private fun existsNot(expect: Expect) = expect notTo exist + private fun isReadable(expect: Expect) = expect toBe readable + private fun isWritable(expect: Expect) = expect toBe writable + private fun isRegularFile(expect: Expect) = expect toBe aRegularFile + private fun isDirectory(expect: Expect) = expect toBe aDirectory + } + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + val a1: Expect = notImplemented() + + a1 to exist + a1 notTo exist + a1 startsWith Paths.get("a") + a1 startsNotWith Paths.get("a") + a1 endsWith Paths.get("a") + a1 endsNotWith Paths.get("a") + a1 toBe readable + a1 toBe writable + a1 toBe aRegularFile + a1 toBe aDirectory + } +} + +class DummyPath(path: Path) : Path by path diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/PathFeatureAssertionsSpec.kt b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/PathFeatureAssertionsSpec.kt new file mode 100644 index 000000000..9cc4619fa --- /dev/null +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/PathFeatureAssertionsSpec.kt @@ -0,0 +1,49 @@ +package ch.tutteli.atrium.api.infix.en_GB.jdk8 + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.* +import ch.tutteli.atrium.specs.testutils.WithAsciiReporter +import java.nio.file.Path + +class PathFeatureAssertionsSpec : ch.tutteli.atrium.specs.integration.PathFeatureAssertionsSpec( + property(Expect::parent), + fun1.() -> Unit>(Expect::parent), + feature1(Expect::resolve), + fun2(Companion::resolve), + property(Expect::fileName), + fun1.() -> Unit>(Expect::fileName), + property(Expect::fileNameWithoutExtension), + fun1.() -> Unit>(Expect::fileNameWithoutExtension), + property(Expect::extension), + fun1.() -> Unit>(Expect::extension) +) { + companion object : WithAsciiReporter() { + + private fun resolve( + expect: Expect, + other: String, + assertionCreator: Expect.() -> Unit + ): Expect = expect resolve path(other) { assertionCreator() } + } + + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + val a1: Expect = notImplemented() + + a1.fileName + a1 fileName {} + + a1.fileNameWithoutExtension + a1 fileNameWithoutExtension {} + + a1.extension + a1 extension {} + + a1.parent + a1 parent {} + + a1 resolve "test" + a1 resolve path("test") {} + } +} + diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/ZonedDateTimeFeatureAssertionsSpec.kt b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/ZonedDateTimeFeatureAssertionsSpec.kt new file mode 100644 index 000000000..ba168a1ab --- /dev/null +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/jdk8/ZonedDateTimeFeatureAssertionsSpec.kt @@ -0,0 +1,36 @@ +package ch.tutteli.atrium.api.infix.en_GB.jdk8 + +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.fun1 +import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.property +import java.time.DayOfWeek +import java.time.ZonedDateTime + +class ZonedDateTimeFeatureAssertionsSpec : ch.tutteli.atrium.specs.integration.ZonedDateTimeFeatureAssertionsSpec( + property(Expect::year), + fun1.() -> Unit>(Expect::year), + property(Expect::month), + fun1.() -> Unit>(Expect::month), + property(Expect::day), + fun1.() -> Unit>(Expect::day), + property(Expect::dayOfWeek), + fun1.() -> Unit>(Expect::dayOfWeek) +) { + @Suppress("unused", "UNUSED_VALUE") + private fun ambiguityTest() { + var a1: Expect = notImplemented() + + a1.year + a1 = a1 year { } + + a1.month + a1 = a1 month { } + + a1.dayOfWeek + a1 = a1 dayOfWeek { } + + a1.day + a1 = a1 day { } + } +} diff --git a/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/resources/META-INF/services/ch.tutteli.atrium.reporting.ReporterFactory b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/resources/META-INF/services/ch.tutteli.atrium.reporting.ReporterFactory new file mode 100644 index 000000000..111322a35 --- /dev/null +++ b/apis/infix-en_GB/extensions/jdk8/atrium-api-infix-en_GB-jdk8-jvm/src/test/resources/META-INF/services/ch.tutteli.atrium.reporting.ReporterFactory @@ -0,0 +1 @@ +ch.tutteli.atrium.specs.testutils.AsciiBulletPointReporterFactory diff --git a/apis/infix-en_GB/extensions/kotlin_1_3/atrium-api-infix-en_GB-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/kotlin_1_3/resultAssertions.kt b/apis/infix-en_GB/extensions/kotlin_1_3/atrium-api-infix-en_GB-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/kotlin_1_3/resultAssertions.kt new file mode 100644 index 000000000..57259ca55 --- /dev/null +++ b/apis/infix-en_GB/extensions/kotlin_1_3/atrium-api-infix-en_GB-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/api/infix/en_GB/kotlin_1_3/resultAssertions.kt @@ -0,0 +1,59 @@ +package ch.tutteli.atrium.api.infix.en_GB.kotlin_1_3 + +import ch.tutteli.atrium.api.infix.en_GB.creating.SuccessWithCreator +import ch.tutteli.atrium.api.infix.en_GB.success +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.domain.builders.kotlin_1_3.result + +/** + * Expects that the subject of the assertion (a [Result]) is a Success + * and returns an [Expect] for the inner type [E]. + * + * @return The newly created [Expect] if the given assertion is success + * @throws AssertionError Might throw an [AssertionError] if the given assertion is not a success. + * + * @since 0.11.0 + */ +infix fun > Expect.toBe(@Suppress("UNUSED_PARAMETER") success: success): Expect = + ExpectImpl.result.isSuccess(this).getExpectOfFeature() + +/** + * Expects that the subject of the assertion (a [Result]]) is a Success and + * that it holds all assertions the given [SuccessWithCreator.assertionCreator] creates. + * + * Use the function `success { ... }` to create a [SuccessWithCreator]. + * + * @return An [Expect] for the current subject of the assertion. + * @throws AssertionError Might throw an [AssertionError] if the given assertions are not success. + * + * @since 0.11.0 + */ +infix fun > Expect.toBe(success: SuccessWithCreator): Expect = + ExpectImpl.result.isSuccess(this).addToInitial(success.assertionCreator) + +/** + * Expects that the subject of the assertion (a [Result]) is a Failure and + * that it encapsulates an exception of type [TExpected]. + * + * @return An [Expect] with the new type [TExpected] + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +inline fun Expect>.isFailure(): Expect = + ExpectImpl.result.isFailure(this, TExpected::class).getExpectOfFeature() + +/** + * Expects that the subject of the assertion (a [Result]) is a Failure, + * it encapsulates an exception of type [TExpected] and that the exception + * holds all assertions the given [assertionCreator] creates. + * + * @return An [Expect] with the new type [TExpected] + * @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct. + * + * @since 0.11.0 + */ +inline infix fun Expect>.isFailure( + noinline assertionCreator: Expect.() -> Unit +): Expect = ExpectImpl.result.isFailure(this, TExpected::class).addToFeature(assertionCreator) diff --git a/apis/infix-en_GB/extensions/kotlin_1_3/atrium-api-infix-en_GB-kotlin_1_3-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/kotlin_1_3/ResultFeatureAssertionsSpec.kt b/apis/infix-en_GB/extensions/kotlin_1_3/atrium-api-infix-en_GB-kotlin_1_3-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/kotlin_1_3/ResultFeatureAssertionsSpec.kt new file mode 100644 index 000000000..fc8abfdbd --- /dev/null +++ b/apis/infix-en_GB/extensions/kotlin_1_3/atrium-api-infix-en_GB-kotlin_1_3-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/kotlin_1_3/ResultFeatureAssertionsSpec.kt @@ -0,0 +1,66 @@ +package ch.tutteli.atrium.api.infix.en_GB.kotlin_1_3 + +import ch.tutteli.atrium.api.infix.en_GB.success +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.specs.integration.ResultFeatureAssertionsSpec +import ch.tutteli.atrium.specs.notImplemented +import ch.tutteli.atrium.specs.withFeatureSuffix +import ch.tutteli.atrium.specs.withNullableSuffix + +class ResultFeatureAssertionsSpec : ResultFeatureAssertionsSpec( + ("toBe ${success::class::simpleName}" to (Companion::toBeSuccessFeature)).withFeatureSuffix(), + "toBe ${success::class::simpleName}" to Companion::toBeSuccess, + ("toBe ${success::class::simpleName}" to (Companion::toBeSuccessFeatureNullable)).withFeatureSuffix() + .withNullableSuffix(), + ("toBe ${success::class::simpleName}" to (Companion::toBeSuccessNullable)).withNullableSuffix(), + ("isFailure" to Companion::isFailureFeature).withFeatureSuffix(), + "isFailure" to Companion::isFailure +) { + companion object { + private fun toBeSuccessFeature(expect: Expect>) = expect toBe success + private fun isFailureFeature(expect: Expect>) = expect.isFailure() + + private fun toBeSuccessFeatureNullable(expect: Expect>) = expect toBe success + + private fun toBeSuccessNullable( + expect: Expect>, + assertionCreator: Expect.() -> Unit + ) = expect toBe success { assertionCreator() } + + private fun toBeSuccess( + expect: Expect>, + assertionCreator: Expect.() -> Unit + ) = expect toBe success { assertionCreator() } + + private fun isFailure( + expect: Expect>, + assertionCreator: Expect.() -> Unit + ) = expect.isFailure { assertionCreator() } + + @Suppress("unused", "UNUSED_VALUE", "UNUSED_VARIABLE") + private fun ambiguityTest() { + var a1: Expect> = notImplemented() + var a1b: Expect> = notImplemented() + + var star: Expect> = notImplemented() + + a1 toBe success + a1 = a1 toBe success { } + + a1.isFailure() + val r1: Expect = a1.isFailure { } + + a1b toBe success + a1b = a1b toBe success { } + + a1b.isFailure() + val r1b: Expect = a1b.isFailure { } + + star toBe success + star = star toBe success { } + + star.isFailure() + val r3: Expect = star.isFailure { } + } + } +} diff --git a/apis/infix-en_GB/extensions/kotlin_1_3/atrium-api-infix-en_GB-kotlin_1_3-jvm/src/module/module-info.java b/apis/infix-en_GB/extensions/kotlin_1_3/atrium-api-infix-en_GB-kotlin_1_3-jvm/src/module/module-info.java index 5de512531..9049a91e4 100644 --- a/apis/infix-en_GB/extensions/kotlin_1_3/atrium-api-infix-en_GB-kotlin_1_3-jvm/src/module/module-info.java +++ b/apis/infix-en_GB/extensions/kotlin_1_3/atrium-api-infix-en_GB-kotlin_1_3-jvm/src/module/module-info.java @@ -1,7 +1,8 @@ module ch.tutteli.atrium.api.infix.en_GB.kotlin_1_3 { + requires ch.tutteli.atrium.api.infix.en_GB; requires ch.tutteli.atrium.domain.builders.kotlin_1_3; requires ch.tutteli.kbox; requires kotlin.stdlib; -// exports ch.tutteli.atrium.api.infix.en_GB.kotlin_1_3; + exports ch.tutteli.atrium.api.infix.en_GB.kotlin_1_3; } diff --git a/build.gradle b/build.gradle index 4a70010f4..9fd178e25 100644 --- a/build.gradle +++ b/build.gradle @@ -1,24 +1,27 @@ buildscript { - rootProject.version = '0.10.0-SNAPSHOT' + rootProject.version = '0.11.0-SNAPSHOT' rootProject.group = 'ch.tutteli.atrium' def sampleProjectsFun = subprojects.findAll { it.projectDir.path.contains('/samples/') || it.projectDir.path.contains('\\samples\\') } + def toolProjectsFun = subprojects.findAll { + it.projectDir.path.contains('/misc/tools/') || it.projectDir.path.contains('\\misc\\tools\\') + } ext { // main kbox_version = '0.14.3' kbox = { "ch.tutteli.kbox:kbox:$kbox_version" } niok_version = '1.3.4' niok = { "ch.tutteli.niok:niok:$niok_version" } - kotlin_version = '1.3.61' + kotlin_version = '1.3.71' // test jacoco_tool_version = '0.8.5' - junit_platform_version = '1.6.0' - jupiter_version = '5.6.0' + junit_platform_version = '1.6.1' + jupiter_version = '5.6.1' spek_version = '1.1.5' - spek2_version = '2.0.8' + spek2_version = '2.0.10' spekExtensions_version = '1.1.0' spekExtensions = { "ch.tutteli.spek:tutteli-spek-extensions:$spekExtensions_version" } mockk_version = '1.9.3' @@ -32,14 +35,12 @@ buildscript { node_plugin_version = '2.2.0' // gh-pages.gradle - docProjects = subprojects.findAll { + docProjects = (subprojects - sampleProjectsFun - toolProjectsFun).findAll { !it.name.endsWith("-js") && !it.name.endsWith("-android") && !it.name.contains("robstoll") && it.name != "${rootProject.name}-spec" && - !it.name.startsWith("${rootProject.name}-specs") && - !(it.projectDir.path.contains("/samples/") || it.projectDir.path.contains("\\samples\\")) && - !(it.projectDir.path.contains("/misc/tools/") || it.projectDir.path.contains("\\misc\\tools\\")) + !it.name.startsWith("${rootProject.name}-specs") } ghPages_version = rootProject.version srcKotlin = 'src/main/kotlin' @@ -48,11 +49,13 @@ buildscript { sampleProjects = sampleProjectsFun + toolProjects = toolProjectsFun + // jacoco-multi-project.gradle def deprecatedProjects = subprojects.findAll { it.name.endsWith("-deprecated") } jacocoMulti = [ sourceProjects: - (subprojects - deprecatedProjects - sampleProjectsFun).findAll { + (subprojects - deprecatedProjects - sampleProjectsFun - toolProjectsFun).findAll { !it.name.endsWith("-js") && !it.name.endsWith("-android") && // would have two classes with the same name if we add it as project as well, @@ -60,13 +63,11 @@ buildscript { it.name != "${rootProject.name}-translations-de_CH-jvm" && // does not make sense to listen specs in coverage it.name != "${rootProject.name}-spec" && - !it.name.startsWith("${rootProject.name}-specs") && - !(it.projectDir.path.contains("/misc/tools/") || it.projectDir.path.contains("\\misc\\tools\\")) + !it.name.startsWith("${rootProject.name}-specs") }, jacocoProjects: - (subprojects - deprecatedProjects - sampleProjectsFun).findAll { + (subprojects - deprecatedProjects - sampleProjectsFun - toolProjectsFun).findAll { !(it.projectDir.path.contains("/translations/") || it.projectDir.path.contains("\\translations\\")) && - !(it.projectDir.path.contains("/misc/tools/") || it.projectDir.path.contains("\\misc\\tools\\")) && !it.name.endsWith("-common") && !it.name.endsWith("-js") && !it.name.endsWith("-android") && @@ -98,6 +99,16 @@ buildscript { } } } + + //TODO dependencies no longer required once all specs are with spek2 where they are set via spek plugin + spekDep = { closure -> + delegate = closure + testRuntimeOnly "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" + testRuntimeOnly "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" + testImplementation "org.spekframework.spek2:spek-dsl-jvm:$spek2_version", excludeKotlin + testRuntimeOnly "org.spekframework.spek2:spek-runner-junit5:$spek2_version", excludeKotlin + } + } repositories { @@ -211,14 +222,16 @@ configure(jsProjects) { subProject -> } } - -configure(subprojects - commonProjects - jsProjects - sampleProjects) { +def nonCommonJsAndSampleProjects = subprojects - commonProjects - jsProjects - sampleProjects +configure(nonCommonJsAndSampleProjects - toolProjects) { apply plugin: 'ch.tutteli.dokka' apply plugin: 'ch.tutteli.kotlin.module.info' dokka { logging.setLevel(LogLevel.QUIET) } +} +configure(nonCommonJsAndSampleProjects) { compileKotlin { kotlinOptions { languageVersion = '1.2' @@ -257,9 +270,11 @@ configure(apiProjects) { apiProject -> createTestSourcesJarTask(apiProject) } -def bundleSmokeTests = subprojects.findAll { it.name.endsWith('smoke-test') } +def bundleSmokeTests = subprojects.findAll { it.name.contains('-smoke-test') } +//TODO new infix API: remove once we are ready to publish the new API +def newInfixApiModules = subprojects.findAll { it.name.contains('-api-infix') } -configure(subprojects - bundleSmokeTests - sampleProjects) { subproject -> +configure(subprojects - bundleSmokeTests - sampleProjects - toolProjects - newInfixApiModules) { subproject -> apply plugin: 'ch.tutteli.publish' tutteliPublish { @@ -308,7 +323,7 @@ configure(jacocoMulti.jacocoProjects + getAndroidProjects()) { } } -configure(subprojects - sampleProjects) { +configure(subprojects - sampleProjects - toolProjects) { sourceSets { all { languageSettings { @@ -323,25 +338,36 @@ apply from: 'gradle/scripts/gh-pages.gradle' apply from: 'gradle/scripts/jacoco-multi-project.gradle' configure(bundleSmokeTests) { - def bundleUnderTest = it.name.substring(0, it.name.indexOf('-smoke-test')) - Project bundle = project(":$bundleUnderTest-jvm") - description = "Represents a JDK >= 9 smoke test for $bundleUnderTest" + def suffix = "-smoke-test" + def isABundleAndNotExtensionSmokeTest = it.name.endsWith(suffix) + if (isABundleAndNotExtensionSmokeTest) { + def bundleUnderTest = it.name.substring(0, it.name.indexOf(suffix)) + Project bundle = project(":$bundleUnderTest-jvm") - sourceCompatibility = JavaVersion.current() - targetCompatibility = JavaVersion.current() + description = "Represents a JDK >= 9 smoke test for $bundleUnderTest" - ext.jacoco_additional = [bundle] + sourceCompatibility = JavaVersion.current() + targetCompatibility = JavaVersion.current() - sourceSets { - // we are reusing the source from the bundle, so that we do not have to re-invent the spec - test { kotlin { srcDirs += ["${bundle.projectDir}/src/test/kotlin"] } } - } + ext.jacoco_additional = [bundle] - dependencies { - //I don't see how to set up compileTestKotlin with --patch-module, so we have put the module-info.java directly in src/test/kotlin instead - testImplementation bundle - testImplementation prefixedProject('verbs-jvm') + sourceSets { + // we are reusing the source from the bundle, so that we do not have to re-invent the spec + test { kotlin { srcDirs += ["${bundle.projectDir}/src/test/kotlin"] } } + } + + dependencies { + //I don't see how to set up compileTestKotlin with --patch-module, so we have put the module-info.java directly in src/test/kotlin instead + testImplementation bundle + //TODO remove once all specs are with spek2 where they are set via spek plugin + spekDep(delegate) + } + } else { + //TODO remove once all specs are with spek2 where they are set via spek plugin + dependencies { + spekDep(delegate) + } } } @@ -445,7 +471,7 @@ def createJsTestTask(String... subprojectNames) { command = "mocha" args = [compileTestKotlin2Js.outputFile] } - check.dependsOn runMocha + test.dependsOn runMocha } } @@ -511,46 +537,50 @@ configure(subprojects - getJsProjects()) { subproject -> } /* - Release & deploy a commit -------------------------------- -1. change rootProject.version in build.gradle to X.Y.Z -2. update master: - a) point to the tag - 1) search for old version and replace with new, except for samples (gradle, maven and section own assertion verb in README.md) - 2) search for branch/master and replace with branch/vX.Y.Z (coverage in README.md) - 3) adjust branch=master manually, use tag=vX.Y.Z except for travis where you need to use branch=vX.Y.Z - 4) search for `tree/master` and replace it with `tree/vX.Y.Z` (README.md) - 5) search for `latest#/doc` and replace with `X.Y.Z/doc` (README.md and differences.md) - 6) Remove the warning in README.md about taking a sneak peak (copy it, well be added afterwards) - b) Update README -> Use own Assertion Verbs -> link to atriumVerbs if it changed - c) commit & push (modified build.gradle, README.md and differences.md) -3. update github pages: +1. update master: + a) change rootProject.version in build.gradle and in example-pom.xml to X.Y.Z + b) search for old version in README.md and replace with new + c) search for `tree/master` in all .md files and replace it with `tree/vX.Y.Z` + d) search for `latest#/doc` in all .md files and replace with `X.Y.Z/doc` + e) use the release badges in README (comment out the ones for master and uncomment the ones for the release) + f) comment out the warning in README.md about taking a sneak peak + g) commit & push (modified CONTRIBUTING.md, differences.md, example-pom.xml, build.gradle and README.md) + +2. update github pages: +assumes you have a atrium-gh-pages folder on the same level as atrium where the gh-pages branch is checked out a) gr ghPages b) change version number in atrium-gh-pages/latest/index.html c) add new version to atrium-gh-pages/README.md d) commit & push changes -4. deploy to bintray: + +3. deploy to bintray: // CI=true is a temporary work around till https://youtrack.jetbrains.com/issue/KT-29069 is fixed: - a) java -version 2>&1 | grep "version \"9" && CI=true ./gradlew clean publishToBintray + a) java -version 2>&1 | grep "version \"9" && CI=true ./gr clean publishToBintray b) Log in to bintray, check that there are 926 artifacts and publish them c) synchronise to maven central -5. create release on github + +4. create release on github a) git tag vX.Y.Z b) git push origin vX.Y.Z c) Log in to github and create release Prepare next dev cycle ----------------------- -1. change rootProject.version in build.gradle to X.Y.Z-SNAPSHOT -2. point to master - a) search for `tag=vX.Y.Z` and replace it with `branch=master` - b) search for `tree/vX.Y.Z` and replace it with `tree/master` - c) search for `X.Y.Z/doc` and replace with `latest#/doc` -3. update README - a) place the warning about taking a sneak peek back into README - b) update version in the warning to X.Y.Z and update the link as well -4. Use new version in samples (search again for the old-version and replace with new) -5. commit & push changes -6. establish backward compatibility tests for the previous version +1. update samples + a) use newly released version in samples (search again for the old-version and replace with new) + b) commit & push changes + +2. update master: + a) search for `tree/vX.Y.Z` in all .md files and replace it with `tree/master` + b) search for `X.Y.Z/doc` in all .md files and replace with `latest#/doc` + c) use the master badges in README (uncomment them in README and comment out release badges) + d) uncomment the warning about taking a sneak peek in README and revert `tree/master` still point to the tag + e) change rootProject.version in build.gradle to X.Y.Z-SNAPSHOT + f) commit & push changes + +3. establish backward compatibility tests for the previous version + a) add new version at the end of atrium-bc-test/build.gradle + b) commit & push changes */ diff --git a/bundles/atrium-cc-en_UK-robstoll/src/test/kotlin/SmokeSpec.kt b/bundles/atrium-cc-en_UK-robstoll/src/test/kotlin/SmokeSpec.kt index 0433e16ff..2dd4d0b07 100644 --- a/bundles/atrium-cc-en_UK-robstoll/src/test/kotlin/SmokeSpec.kt +++ b/bundles/atrium-cc-en_UK-robstoll/src/test/kotlin/SmokeSpec.kt @@ -9,6 +9,7 @@ import ch.tutteli.atrium.translations.DescriptionBasic import ch.tutteli.atrium.verbs.assertThat import org.jetbrains.spek.api.Spek +//TODO remove with 1.0.0, no need to migrate to Spek 2 object SmokeSpec : Spek({ test("see if `toBe` can be used") { @Suppress("DEPRECATION") diff --git a/bundles/atrium-cc-infix-en_UK-robstoll/build.gradle b/bundles/atrium-cc-infix-en_UK-robstoll/build.gradle index be7298910..19cda7c04 100644 --- a/bundles/atrium-cc-infix-en_UK-robstoll/build.gradle +++ b/bundles/atrium-cc-infix-en_UK-robstoll/build.gradle @@ -3,7 +3,7 @@ description = 'Represents a deprecated convenience module which merely bundles d dependencies { api prefixedProject('verbs-jvm') - api prefixedProject('api-cc-infix-en_GB-jvm') + api prefixedProject('api-infix-en_GB-jvm') api prefixedProject('translations-en_GB-jvm') api prefixedProject('domain-builders-jvm') api prefixedProject('domain-api-jvm') @@ -13,6 +13,7 @@ dependencies { runtimeOnly prefixedProject('core-robstoll-jvm') //TODO remove with 1.0.0 + api prefixedProject('api-cc-infix-en_GB-jvm') api prefixedProject('api-cc-infix-en_UK') implementation prefixedProject('assertions') api prefixedProject('core-api-deprecated') diff --git a/bundles/atrium-cc-infix-en_UK-robstoll/src/test/kotlin/SmokeSpec.kt b/bundles/atrium-cc-infix-en_UK-robstoll/src/test/kotlin/SmokeSpec.kt index 75960dcfe..cf161f31a 100644 --- a/bundles/atrium-cc-infix-en_UK-robstoll/src/test/kotlin/SmokeSpec.kt +++ b/bundles/atrium-cc-infix-en_UK-robstoll/src/test/kotlin/SmokeSpec.kt @@ -9,6 +9,7 @@ import ch.tutteli.atrium.translations.DescriptionBasic import ch.tutteli.atrium.verbs.expect import org.jetbrains.spek.api.Spek +//TODO remove with 1.0.0, no need to migrate to Spek 2 object SmokeSpec : Spek({ test("see if `toBe` can be used") { @Suppress("DEPRECATION") diff --git a/bundles/cc-infix-en_GB-robstoll/atrium-cc-infix-en_GB-robstoll-android/build.gradle b/bundles/cc-infix-en_GB-robstoll/atrium-cc-infix-en_GB-robstoll-android/build.gradle index 57d590243..18ea93ca8 100644 --- a/bundles/cc-infix-en_GB-robstoll/atrium-cc-infix-en_GB-robstoll-android/build.gradle +++ b/bundles/cc-infix-en_GB-robstoll/atrium-cc-infix-en_GB-robstoll-android/build.gradle @@ -10,4 +10,7 @@ dependencies { runtimeOnly prefixedProject('domain-robstoll-android') runtimeOnly prefixedProject('core-robstoll-android') + + // here to ease migration; so that ReplaceWith of @Deprecated works + api prefixedProject('api-infix-en_GB-android') } diff --git a/bundles/cc-infix-en_GB-robstoll/atrium-cc-infix-en_GB-robstoll-common/build.gradle b/bundles/cc-infix-en_GB-robstoll/atrium-cc-infix-en_GB-robstoll-common/build.gradle index dc45fb11c..aede0df06 100644 --- a/bundles/cc-infix-en_GB-robstoll/atrium-cc-infix-en_GB-robstoll-common/build.gradle +++ b/bundles/cc-infix-en_GB-robstoll/atrium-cc-infix-en_GB-robstoll-common/build.gradle @@ -10,4 +10,7 @@ dependencies { runtimeOnly prefixedProject('domain-robstoll-common') runtimeOnly prefixedProject('core-robstoll-common') + + // here to ease migration; so that ReplaceWith of @Deprecated works + api prefixedProject('api-infix-en_GB-common') } diff --git a/bundles/cc-infix-en_GB-robstoll/atrium-cc-infix-en_GB-robstoll-js/build.gradle b/bundles/cc-infix-en_GB-robstoll/atrium-cc-infix-en_GB-robstoll-js/build.gradle index fa6e375bc..6097aa6f1 100644 --- a/bundles/cc-infix-en_GB-robstoll/atrium-cc-infix-en_GB-robstoll-js/build.gradle +++ b/bundles/cc-infix-en_GB-robstoll/atrium-cc-infix-en_GB-robstoll-js/build.gradle @@ -11,4 +11,7 @@ dependencies { //TODO should be runtimeOnly but due to https://youtrack.jetbrains.com/issue/KT-27797 it cannot be implementation prefixedProject('domain-robstoll-js') implementation prefixedProject('core-robstoll-js') + + // here to ease migration; so that ReplaceWith of @Deprecated works + api prefixedProject('api-infix-en_GB-js') } diff --git a/bundles/cc-infix-en_GB-robstoll/atrium-cc-infix-en_GB-robstoll-jvm/build.gradle b/bundles/cc-infix-en_GB-robstoll/atrium-cc-infix-en_GB-robstoll-jvm/build.gradle index fa1e532cc..cd59fee21 100644 --- a/bundles/cc-infix-en_GB-robstoll/atrium-cc-infix-en_GB-robstoll-jvm/build.gradle +++ b/bundles/cc-infix-en_GB-robstoll/atrium-cc-infix-en_GB-robstoll-jvm/build.gradle @@ -10,4 +10,7 @@ dependencies { runtimeOnly prefixedProject('domain-robstoll-jvm') runtimeOnly prefixedProject('core-robstoll-jvm') + + // here to ease migration; so that ReplaceWith of @Deprecated works + api prefixedProject('api-infix-en_GB-jvm') } diff --git a/bundles/fluent-en_GB/atrium-fluent-en_GB-android/build.gradle b/bundles/fluent-en_GB/atrium-fluent-en_GB-android/build.gradle index e1802eff2..1896f706c 100644 --- a/bundles/fluent-en_GB/atrium-fluent-en_GB-android/build.gradle +++ b/bundles/fluent-en_GB/atrium-fluent-en_GB-android/build.gradle @@ -10,6 +10,9 @@ dependencies { runtimeOnly prefixedProject('domain-robstoll-android') runtimeOnly prefixedProject('core-robstoll-android') + + //TODO remove once all specs are with spek2 where they are set via spek plugin + spekDep(delegate) } srcAndResourcesFromJvmProject(project) diff --git a/bundles/fluent-en_GB/atrium-fluent-en_GB-jvm/build.gradle b/bundles/fluent-en_GB/atrium-fluent-en_GB-jvm/build.gradle index d56d7f4c5..7b58b830f 100644 --- a/bundles/fluent-en_GB/atrium-fluent-en_GB-jvm/build.gradle +++ b/bundles/fluent-en_GB/atrium-fluent-en_GB-jvm/build.gradle @@ -10,4 +10,7 @@ dependencies { runtimeOnly prefixedProject('domain-robstoll-jvm') runtimeOnly prefixedProject('core-robstoll-jvm') + + //TODO remove once all specs are with spek2 where they are set via spek plugin + spekDep(delegate) } diff --git a/bundles/fluent-en_GB/atrium-fluent-en_GB-jvm/src/test/kotlin/custom/SmokeSpec.kt b/bundles/fluent-en_GB/atrium-fluent-en_GB-jvm/src/test/kotlin/custom/SmokeSpec.kt index 560c07ec6..c373c5b01 100644 --- a/bundles/fluent-en_GB/atrium-fluent-en_GB-jvm/src/test/kotlin/custom/SmokeSpec.kt +++ b/bundles/fluent-en_GB/atrium-fluent-en_GB-jvm/src/test/kotlin/custom/SmokeSpec.kt @@ -8,7 +8,8 @@ import ch.tutteli.atrium.domain.builders.ExpectImpl import ch.tutteli.atrium.reporting.RawString import ch.tutteli.atrium.reporting.translating.StringBasedTranslatable import ch.tutteli.atrium.translations.DescriptionBasic -import org.jetbrains.spek.api.Spek +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.describe object SmokeSpec : Spek({ test("see if `toBe` can be used") { diff --git a/bundles/fluent-en_GB/atrium-fluent-en_GB-smoke-test/src/test/kotlin/module-info.java b/bundles/fluent-en_GB/atrium-fluent-en_GB-smoke-test/src/test/kotlin/module-info.java index f78ea6879..a3a67b621 100644 --- a/bundles/fluent-en_GB/atrium-fluent-en_GB-smoke-test/src/test/kotlin/module-info.java +++ b/bundles/fluent-en_GB/atrium-fluent-en_GB-smoke-test/src/test/kotlin/module-info.java @@ -5,5 +5,5 @@ module ch.tutteli.atrium.fluent.en_GB.smoke { requires ch.tutteli.atrium.fluent.en_GB; requires kotlin.stdlib; - requires spek.api; + requires spek.dsl.jvm; } diff --git a/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-jdk8/build.gradle b/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-jdk8/build.gradle index c35f7feb8..6e6d2fa96 100644 --- a/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-jdk8/build.gradle +++ b/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-jdk8/build.gradle @@ -7,5 +7,4 @@ dependencies { //I don't see how to set up compileTestKotlin with --patch-module, so we have put the module-info.java directly in src/test/kotlin instead testImplementation prefixedProject('fluent-en_GB-jvm') testImplementation prefixedProject('api-fluent-en_GB-jdk8-jvm') - testImplementation prefixedProject('verbs-jvm') } diff --git a/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-jdk8/src/test/kotlin/custom/SmokeSpec.kt b/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-jdk8/src/test/kotlin/custom/SmokeSpec.kt index 70b242cd2..98766434b 100644 --- a/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-jdk8/src/test/kotlin/custom/SmokeSpec.kt +++ b/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-jdk8/src/test/kotlin/custom/SmokeSpec.kt @@ -9,7 +9,8 @@ import ch.tutteli.atrium.domain.builders.ExpectImpl import ch.tutteli.atrium.reporting.RawString import ch.tutteli.atrium.reporting.translating.StringBasedTranslatable import ch.tutteli.atrium.translations.DescriptionBasic -import org.jetbrains.spek.api.Spek +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.describe import java.nio.file.Paths object SmokeSpec : Spek({ diff --git a/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-jdk8/src/test/kotlin/module-info.java b/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-jdk8/src/test/kotlin/module-info.java index 98e210c6a..9b7496264 100644 --- a/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-jdk8/src/test/kotlin/module-info.java +++ b/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-jdk8/src/test/kotlin/module-info.java @@ -6,5 +6,5 @@ module ch.tutteli.atrium.fluent.en_GB.jdk8.smoke { requires ch.tutteli.atrium.fluent.en_GB; requires ch.tutteli.atrium.api.fluent.en_GB.jdk8; requires kotlin.stdlib; - requires spek.api; + requires spek.dsl.jvm; } diff --git a/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-kotlin_1_3/build.gradle b/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-kotlin_1_3/build.gradle index ef0e94c2e..f0f65dfa3 100644 --- a/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-kotlin_1_3/build.gradle +++ b/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-kotlin_1_3/build.gradle @@ -7,5 +7,5 @@ dependencies { //I don't see how to set up compileTestKotlin with --patch-module, so we have put the module-info.java directly in src/test/kotlin instead testImplementation prefixedProject('fluent-en_GB-jvm') testImplementation prefixedProject('api-fluent-en_GB-kotlin_1_3-jvm') - testImplementation prefixedProject('verbs-jvm') + testRuntimeOnly prefixedProject('domain-robstoll-kotlin_1_3-jvm') } diff --git a/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-kotlin_1_3/src/test/kotlin/custom/SmokeSpec.kt b/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-kotlin_1_3/src/test/kotlin/custom/SmokeSpec.kt index 2e7254ee7..75f7f41c6 100644 --- a/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-kotlin_1_3/src/test/kotlin/custom/SmokeSpec.kt +++ b/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-kotlin_1_3/src/test/kotlin/custom/SmokeSpec.kt @@ -1,5 +1,8 @@ +@file:Suppress("JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE" /* TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed */) + package custom +import ch.tutteli.atrium.api.fluent.en_GB.kotlin_1_3.isSuccess import ch.tutteli.atrium.api.fluent.en_GB.toBe import ch.tutteli.atrium.api.verbs.expect import ch.tutteli.atrium.assertions.Assertion @@ -8,7 +11,7 @@ import ch.tutteli.atrium.domain.builders.ExpectImpl import ch.tutteli.atrium.reporting.RawString import ch.tutteli.atrium.reporting.translating.StringBasedTranslatable import ch.tutteli.atrium.translations.DescriptionBasic -import org.jetbrains.spek.api.Spek +import org.spekframework.spek2.Spek object SmokeSpec : Spek({ test("see if `toBe` can be used") { @@ -16,8 +19,7 @@ object SmokeSpec : Spek({ } test("see if `Result.isSuccess` can be used") { - //TODO activate after isSuccess is implemented - //expect(Result.success(1)).isSuccess { toBe(1) } + expect(Result.success(1)).isSuccess { toBe(1) } } test("see if own assertion function without i18n can be used") { diff --git a/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-kotlin_1_3/src/test/kotlin/module-info.java b/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-kotlin_1_3/src/test/kotlin/module-info.java index ca6d9915e..d18cc3696 100644 --- a/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-kotlin_1_3/src/test/kotlin/module-info.java +++ b/bundles/fluent-en_GB/extensions/atrium-fluent-en_GB-smoke-test-kotlin_1_3/src/test/kotlin/module-info.java @@ -6,5 +6,5 @@ module ch.tutteli.atrium.fluent.en_GB.kotlin_1_3.smoke { requires ch.tutteli.atrium.fluent.en_GB; requires ch.tutteli.atrium.api.fluent.en_GB.kotlin_1_3; requires kotlin.stdlib; - requires spek.api; + requires spek.dsl.jvm; } diff --git a/bundles/infix-en_GB/atrium-infix-en_GB-android/build.gradle b/bundles/infix-en_GB/atrium-infix-en_GB-android/build.gradle new file mode 100644 index 000000000..fe21f751f --- /dev/null +++ b/bundles/infix-en_GB/atrium-infix-en_GB-android/build.gradle @@ -0,0 +1,18 @@ +description = 'Represents a convenience module which merely bundles dependencies for Android.' + +dependencies { + api prefixedProject('verbs-android') + api prefixedProject('api-infix-en_GB-android') + api prefixedProject('translations-en_GB-android') + api prefixedProject('domain-builders-android') + api prefixedProject('domain-api-android') + api prefixedProject('core-api-android') + + runtimeOnly prefixedProject('domain-robstoll-android') + runtimeOnly prefixedProject('core-robstoll-android') + + //TODO remove once all specs are with spek2 where they are set via spek plugin + spekDep(delegate) +} + +srcAndResourcesFromJvmProject(project) diff --git a/bundles/infix-en_GB/atrium-infix-en_GB-common/build.gradle b/bundles/infix-en_GB/atrium-infix-en_GB-common/build.gradle new file mode 100644 index 000000000..89e3094f8 --- /dev/null +++ b/bundles/infix-en_GB/atrium-infix-en_GB-common/build.gradle @@ -0,0 +1,13 @@ +description = 'Represents a convenience module which merely bundles dependencies as common module.' + +dependencies { + api prefixedProject('verbs-common') + api prefixedProject('api-infix-en_GB-common') + api prefixedProject('translations-en_GB-common') + api prefixedProject('domain-builders-common') + api prefixedProject('domain-api-common') + api prefixedProject('core-api-common') + + runtimeOnly prefixedProject('domain-robstoll-common') + runtimeOnly prefixedProject('core-robstoll-common') +} diff --git a/samples/js/jasmine/src/test/kotlin/ch/tutteli/SmokeTest.kt b/bundles/infix-en_GB/atrium-infix-en_GB-common/src/test/kotlin/SmokeTest.kt similarity index 53% rename from samples/js/jasmine/src/test/kotlin/ch/tutteli/SmokeTest.kt rename to bundles/infix-en_GB/atrium-infix-en_GB-common/src/test/kotlin/SmokeTest.kt index 623a166fb..763baff50 100644 --- a/samples/js/jasmine/src/test/kotlin/ch/tutteli/SmokeTest.kt +++ b/bundles/infix-en_GB/atrium-infix-en_GB-common/src/test/kotlin/SmokeTest.kt @@ -1,32 +1,32 @@ -package ch.tutteli - -import ch.tutteli.atrium.api.fluent.en_GB.isLessThan -import ch.tutteli.atrium.api.fluent.en_GB.messageContains -import ch.tutteli.atrium.api.fluent.en_GB.notToThrow -import ch.tutteli.atrium.api.fluent.en_GB.toThrow +import ch.tutteli.atrium.api.infix.en_GB.* +import ch.tutteli.atrium.api.verbs.AssertionVerb +import ch.tutteli.atrium.api.verbs.assert import ch.tutteli.atrium.api.verbs.assertThat +import ch.tutteli.atrium.api.verbs.expect import ch.tutteli.atrium.assertions.Assertion import ch.tutteli.atrium.creating.Expect -import ch.tutteli.atrium.domain.builders.AssertImpl +import ch.tutteli.atrium.domain.builders.ExpectImpl import ch.tutteli.atrium.reporting.RawString import ch.tutteli.atrium.reporting.translating.StringBasedTranslatable -import ch.tutteli.atrium.translations.DescriptionBasic +import ch.tutteli.atrium.translations.DescriptionBasic.IS +import ch.tutteli.atrium.translations.DescriptionBasic.TO_BE import kotlin.test.Test class SmokeTest { + @Test fun toBe_canBeUsed() { - assertThat(1).isLessThan(2) + assertThat(1) toBe 1 } @Test fun assertionFunctionWithoutI18nCanBeUsed() { - assertThat(2).isEven() + assertThat(2) tobe even } @Test fun assertionFunctionWithI18nCanBeUsed() { - assertThat(4).isMultipleOf(2) + assertThat(4) isMultipleOf 2 } @Test @@ -40,8 +40,8 @@ class SmokeTest { fun assertAnExceptionWithAMessageOccurred() { assertThat { throw IllegalArgumentException("oho... hello btw") - }.toThrow{ - messageContains("hello") + }.toThrow { + it messageContains "hello" } } @@ -53,13 +53,16 @@ class SmokeTest { } } -fun Expect.isEven() = - createAndAddAssertion(DescriptionBasic.IS, RawString.create("an even number")) { it % 2 == 0 } +@Suppress("ClassName") +object even -fun Expect.isMultipleOf(base: Int) = addAssertion(_isMultipleOf(this, base)) +infix fun Expect.tobe(@Suppress("UNUSED_PARAMETER") even: even) = + createAndAddAssertion(IS, RawString.create("an even number")) { it % 2 == 0 } -fun _isMultipleOf(expect: Expect, base: Int): Assertion = - AssertImpl.builder.createDescriptive(expect, DescriptionIntAssertions.IS_MULTIPLE_OF, base) { +infix fun Expect.isMultipleOf(base: Int): Expect = addAssertion(isMultipleOf(this, base)) + +private fun isMultipleOf(expect: Expect, base: Int): Assertion = + ExpectImpl.builder.createDescriptive(expect, DescriptionIntAssertions.IS_MULTIPLE_OF, base) { it % base == 0 } diff --git a/bundles/infix-en_GB/atrium-infix-en_GB-js/build.gradle b/bundles/infix-en_GB/atrium-infix-en_GB-js/build.gradle new file mode 100644 index 000000000..6a50e2861 --- /dev/null +++ b/bundles/infix-en_GB/atrium-infix-en_GB-js/build.gradle @@ -0,0 +1,13 @@ +description = 'Represents a convenience module which merely bundles dependencies for the JS platform.' + +dependencies { + api prefixedProject('verbs-js') + api prefixedProject('api-infix-en_GB-js') + api prefixedProject('translations-en_GB-js') + api prefixedProject('domain-builders-js') + api prefixedProject('domain-api-js') + api prefixedProject('core-api-js') + + implementation prefixedProject('domain-robstoll-js') + implementation prefixedProject('core-robstoll-js') +} diff --git a/bundles/infix-en_GB/atrium-infix-en_GB-js/src/main/kotlin/ch/tutteli/atrium/infix/en_GB/dependOnMe.kt b/bundles/infix-en_GB/atrium-infix-en_GB-js/src/main/kotlin/ch/tutteli/atrium/infix/en_GB/dependOnMe.kt new file mode 100644 index 000000000..24c0ea737 --- /dev/null +++ b/bundles/infix-en_GB/atrium-infix-en_GB-js/src/main/kotlin/ch/tutteli/atrium/infix/en_GB/dependOnMe.kt @@ -0,0 +1,15 @@ +package ch.tutteli.atrium.infix.en_GB + +import ch.tutteli.atrium.core.robstoll.dependOn_atrium_core_robstoll +import ch.tutteli.atrium.domain.robstoll.dependOn_atrium_domain_robstoll + +/** + * Dummy function in order that other modules can define a dependency on atrium-infix-en_GB-js + * + * Moreover it has the side effect that a dependency on core-robstoll and domain-robstoll is established. + * This is necessary, as it has only a loosely coupled dependency (via serviceLoader). + */ +fun dependOnAtrium() { + dependOn_atrium_core_robstoll() + dependOn_atrium_domain_robstoll() +} diff --git a/bundles/infix-en_GB/atrium-infix-en_GB-js/src/test/kotlin/ch/tutteli/atrium/infix/en_GB/JsNameAmbiguityTest.kt b/bundles/infix-en_GB/atrium-infix-en_GB-js/src/test/kotlin/ch/tutteli/atrium/infix/en_GB/JsNameAmbiguityTest.kt new file mode 100644 index 000000000..5a43fe4d0 --- /dev/null +++ b/bundles/infix-en_GB/atrium-infix-en_GB-js/src/test/kotlin/ch/tutteli/atrium/infix/en_GB/JsNameAmbiguityTest.kt @@ -0,0 +1,25 @@ +package ch.tutteli.atrium.infix.en_GB + +import ch.tutteli.atrium.api.infix.en_GB.asEntries +import ch.tutteli.atrium.api.infix.en_GB.* +import ch.tutteli.atrium.api.verbs.expect +import kotlin.test.Test + +/** + * As there are bugs related to JsName in Kotlin we should test each to be sure that it works also during runtime. + */ +class JsNameAmbiguityTest { + + @Test + fun toBeNullable() { + expect(null as Int?) toBe null + expect(1 as Int?) toBe 1 + } + + @Test + fun isKeyValueNullable() { + expect(mapOf(1 to null as Int?)).asEntries(o).containsExactly { + it isKeyValue (1 to null) + } + } +} diff --git a/bundles/infix-en_GB/atrium-infix-en_GB-js/src/test/kotlin/testSetup.kt b/bundles/infix-en_GB/atrium-infix-en_GB-js/src/test/kotlin/testSetup.kt new file mode 100644 index 000000000..8b1a8c5a8 --- /dev/null +++ b/bundles/infix-en_GB/atrium-infix-en_GB-js/src/test/kotlin/testSetup.kt @@ -0,0 +1,4 @@ +import ch.tutteli.atrium.infix.en_GB.dependOnAtrium + +@Suppress("unused") +private val establishDependencyToAtrium = dependOnAtrium() diff --git a/bundles/infix-en_GB/atrium-infix-en_GB-jvm/build.gradle b/bundles/infix-en_GB/atrium-infix-en_GB-jvm/build.gradle new file mode 100644 index 000000000..b8296a9b4 --- /dev/null +++ b/bundles/infix-en_GB/atrium-infix-en_GB-jvm/build.gradle @@ -0,0 +1,16 @@ +description = 'Represents a convenience module which merely bundles dependencies for the JVM platform.' + +dependencies { + api prefixedProject('verbs-jvm') + api prefixedProject('api-infix-en_GB-jvm') + api prefixedProject('translations-en_GB-jvm') + api prefixedProject('domain-builders-jvm') + api prefixedProject('domain-api-jvm') + api prefixedProject('core-api-jvm') + + runtimeOnly prefixedProject('domain-robstoll-jvm') + runtimeOnly prefixedProject('core-robstoll-jvm') + + //TODO remove once all specs are with spek2 where they are set via spek plugin + spekDep(delegate) +} diff --git a/bundles/infix-en_GB/atrium-infix-en_GB-jvm/src/module/module-info.java b/bundles/infix-en_GB/atrium-infix-en_GB-jvm/src/module/module-info.java new file mode 100644 index 000000000..4ef639ee2 --- /dev/null +++ b/bundles/infix-en_GB/atrium-infix-en_GB-jvm/src/module/module-info.java @@ -0,0 +1,7 @@ +module ch.tutteli.atrium.infix.en_GB { + requires transitive ch.tutteli.atrium.verbs; + requires transitive ch.tutteli.atrium.api.infix.en_GB; + requires transitive ch.tutteli.atrium.domain.builders; + requires transitive ch.tutteli.atrium.translations.en_GB; + requires kotlin.stdlib; +} diff --git a/bundles/infix-en_GB/atrium-infix-en_GB-jvm/src/test/kotlin/custom/SmokeSpec.kt b/bundles/infix-en_GB/atrium-infix-en_GB-jvm/src/test/kotlin/custom/SmokeSpec.kt new file mode 100644 index 000000000..f0538334a --- /dev/null +++ b/bundles/infix-en_GB/atrium-infix-en_GB-jvm/src/test/kotlin/custom/SmokeSpec.kt @@ -0,0 +1,43 @@ +package custom + +import ch.tutteli.atrium.api.infix.en_GB.toBe +import ch.tutteli.atrium.api.verbs.assertThat +import ch.tutteli.atrium.api.verbs.expect +import ch.tutteli.atrium.assertions.Assertion +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.reporting.RawString +import ch.tutteli.atrium.reporting.translating.StringBasedTranslatable +import ch.tutteli.atrium.translations.DescriptionBasic +import org.spekframework.spek2.Spek + +object SmokeSpec : Spek({ + test("see if `toBe` can be used") { + assertThat(1) toBe 1 + } + + test("see if own assertion function without i18n can be used") { + assertThat(2) tobe even + } + + test("see if own assertion function with i18n can be used") { + assertThat(4) isMultipleOf 2 + } +}) + +@Suppress("ClassName") +object even + +infix fun Expect.tobe(@Suppress("UNUSED_PARAMETER") even: even) = + createAndAddAssertion(DescriptionBasic.IS, RawString.create("an even number")) { it % 2 == 0 } + +infix fun Expect.isMultipleOf(base: Int) = addAssertion(isMultipleOf(this, base)) + +fun isMultipleOf(expect: Expect, base: Int): Assertion = + ExpectImpl.builder.createDescriptive(expect, DescriptionIntAssertions.IS_MULTIPLE_OF, base) { + it % base == 0 + } + +enum class DescriptionIntAssertions(override val value: String) : StringBasedTranslatable { + IS_MULTIPLE_OF("is multiple of") +} diff --git a/bundles/infix-en_GB/atrium-infix-en_GB-smoke-test/src/test/kotlin/module-info.java b/bundles/infix-en_GB/atrium-infix-en_GB-smoke-test/src/test/kotlin/module-info.java new file mode 100644 index 000000000..1f819aa6e --- /dev/null +++ b/bundles/infix-en_GB/atrium-infix-en_GB-smoke-test/src/test/kotlin/module-info.java @@ -0,0 +1,9 @@ +module ch.tutteli.atrium.infix.en_GB.smoke { + // test dependencies are usually defined in build.gradle via --patch-module but that's quite cumbersome and I did + // not get it running in 10 minutes so I am using this, the effect should be the same, the kotlin compiler checks if + // I am using symbols from packages I do not require etc. + + requires ch.tutteli.atrium.infix.en_GB; + requires kotlin.stdlib; + requires spek.dsl.jvm; +} diff --git a/bundles/infix-en_GB/extensions/atrium-infix-en_GB-smoke-test-jdk8/build.gradle b/bundles/infix-en_GB/extensions/atrium-infix-en_GB-smoke-test-jdk8/build.gradle new file mode 100644 index 000000000..07db9d74a --- /dev/null +++ b/bundles/infix-en_GB/extensions/atrium-infix-en_GB-smoke-test-jdk8/build.gradle @@ -0,0 +1,10 @@ +description = "Represents a JDK >= 9 smoke test for atrium-infix-en_GB with jdk8 extension" + +sourceCompatibility = JavaVersion.current() +targetCompatibility = JavaVersion.current() + +dependencies { + //I don't see how to set up compileTestKotlin with --patch-module, so we have put the module-info.java directly in src/test/kotlin instead + testImplementation prefixedProject('infix-en_GB-jvm') + testImplementation prefixedProject('api-infix-en_GB-jdk8-jvm') +} diff --git a/bundles/infix-en_GB/extensions/atrium-infix-en_GB-smoke-test-jdk8/src/test/kotlin/custom/SmokeSpec.kt b/bundles/infix-en_GB/extensions/atrium-infix-en_GB-smoke-test-jdk8/src/test/kotlin/custom/SmokeSpec.kt new file mode 100644 index 000000000..a00b8780a --- /dev/null +++ b/bundles/infix-en_GB/extensions/atrium-infix-en_GB-smoke-test-jdk8/src/test/kotlin/custom/SmokeSpec.kt @@ -0,0 +1,50 @@ +package custom + +import ch.tutteli.atrium.api.infix.en_GB.jdk8.notTo +import ch.tutteli.atrium.api.infix.en_GB.exist +import ch.tutteli.atrium.api.infix.en_GB.toBe +import ch.tutteli.atrium.api.verbs.assert +import ch.tutteli.atrium.assertions.Assertion +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.reporting.RawString +import ch.tutteli.atrium.reporting.translating.StringBasedTranslatable +import ch.tutteli.atrium.translations.DescriptionBasic +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.describe +import java.nio.file.Paths + +object SmokeSpec : Spek({ + test("see if `toBe` can be used") { + assert(1) toBe 1 + } + + test("see if `Path.existsNot` can be used") { + assert(Paths.get("nonExisting")) notTo exist + } + + test("see if own assertion function without i18n can be used") { + assert(2) tobe even + } + + test("see if own assertion function with i18n can be used") { + assert(4) isMultipleOf 2 + } +}) + +@Suppress("ClassName") +object even + +infix fun Expect.tobe(@Suppress("UNUSED_PARAMETER") even: even) = + createAndAddAssertion(DescriptionBasic.IS, RawString.create("an even number")) { it % 2 == 0 } + +infix fun Expect.isMultipleOf(base: Int): Expect = addAssertion(_isMultipleOf(this, base)) + +fun _isMultipleOf(expect: Expect, base: Int): Assertion = + ExpectImpl.builder.createDescriptive(expect, DescriptionIntAssertions.IS_MULTIPLE_OF, base) { + it % base == 0 + } + +enum class DescriptionIntAssertions(override val value: String) : StringBasedTranslatable { + IS_MULTIPLE_OF("is multiple of") +} diff --git a/bundles/infix-en_GB/extensions/atrium-infix-en_GB-smoke-test-jdk8/src/test/kotlin/module-info.java b/bundles/infix-en_GB/extensions/atrium-infix-en_GB-smoke-test-jdk8/src/test/kotlin/module-info.java new file mode 100644 index 000000000..0ff4f7a4d --- /dev/null +++ b/bundles/infix-en_GB/extensions/atrium-infix-en_GB-smoke-test-jdk8/src/test/kotlin/module-info.java @@ -0,0 +1,10 @@ +module ch.tutteli.atrium.infix.en_GB.jdk8.smoke { + // test dependencies are usually defined in build.gradle via --patch-module but that's quite cumbersome and I did + // not get it running in 10 minutes so I am using this, the effect should be the same, the kotlin compiler checks if + // I am using symbols from packages I do not require etc. + + requires ch.tutteli.atrium.infix.en_GB; + requires ch.tutteli.atrium.api.infix.en_GB.jdk8; + requires kotlin.stdlib; + requires spek.dsl.jvm; +} diff --git a/bundles/infix-en_GB/extensions/atrium-infix-en_GB-smoke-test-kotlin_1_3/build.gradle b/bundles/infix-en_GB/extensions/atrium-infix-en_GB-smoke-test-kotlin_1_3/build.gradle new file mode 100644 index 000000000..d5bfa324b --- /dev/null +++ b/bundles/infix-en_GB/extensions/atrium-infix-en_GB-smoke-test-kotlin_1_3/build.gradle @@ -0,0 +1,11 @@ +description = "Represents a JDK >= 9 smoke test for atrium-infix-en_GB with kotlin_1_3 extension" + +sourceCompatibility = JavaVersion.current() +targetCompatibility = JavaVersion.current() + +dependencies { + //I don't see how to set up compileTestKotlin with --patch-module, so we have put the module-info.java directly in src/test/kotlin instead + testImplementation prefixedProject('infix-en_GB-jvm') + testImplementation prefixedProject('api-infix-en_GB-kotlin_1_3-jvm') + testRuntimeOnly prefixedProject('domain-robstoll-kotlin_1_3-jvm') +} diff --git a/bundles/infix-en_GB/extensions/atrium-infix-en_GB-smoke-test-kotlin_1_3/src/test/kotlin/custom/SmokeSpec.kt b/bundles/infix-en_GB/extensions/atrium-infix-en_GB-smoke-test-kotlin_1_3/src/test/kotlin/custom/SmokeSpec.kt new file mode 100644 index 000000000..485335d59 --- /dev/null +++ b/bundles/infix-en_GB/extensions/atrium-infix-en_GB-smoke-test-kotlin_1_3/src/test/kotlin/custom/SmokeSpec.kt @@ -0,0 +1,50 @@ +@file:Suppress("JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE" /* TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed */) + +package custom + +import ch.tutteli.atrium.api.infix.en_GB.kotlin_1_3.toBe +import ch.tutteli.atrium.api.infix.en_GB.toBe +import ch.tutteli.atrium.api.infix.en_GB.success +import ch.tutteli.atrium.api.verbs.expect +import ch.tutteli.atrium.assertions.Assertion +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.reporting.RawString +import ch.tutteli.atrium.reporting.translating.StringBasedTranslatable +import ch.tutteli.atrium.translations.DescriptionBasic +import org.spekframework.spek2.Spek + +object SmokeSpec : Spek({ + test("see if `toBe` can be used") { + expect(1) toBe 1 + } + + test("see if `Result.isSuccess` can be used") { + expect(Result.success(1)) toBe success + } + + test("see if own assertion function without i18n can be used") { + expect(2) tobe even + } + + test("see if own assertion function with i18n can be used") { + expect(4) isMultipleOf 2 + } +}) + +@Suppress("ClassName") +object even + +infix fun Expect.tobe(@Suppress("UNUSED_PARAMETER") even: even) = + createAndAddAssertion(DescriptionBasic.IS, RawString.create("an even number")) { it % 2 == 0 } + +infix fun Expect.isMultipleOf(base: Int): Expect = addAssertion(_isMultipleOf(this, base)) + +fun _isMultipleOf(expect: Expect, base: Int): Assertion = + ExpectImpl.builder.createDescriptive(expect, DescriptionIntAssertions.IS_MULTIPLE_OF, base) { + it % base == 0 + } + +enum class DescriptionIntAssertions(override val value: String) : StringBasedTranslatable { + IS_MULTIPLE_OF("is multiple of") +} diff --git a/bundles/infix-en_GB/extensions/atrium-infix-en_GB-smoke-test-kotlin_1_3/src/test/kotlin/module-info.java b/bundles/infix-en_GB/extensions/atrium-infix-en_GB-smoke-test-kotlin_1_3/src/test/kotlin/module-info.java new file mode 100644 index 000000000..d806926d9 --- /dev/null +++ b/bundles/infix-en_GB/extensions/atrium-infix-en_GB-smoke-test-kotlin_1_3/src/test/kotlin/module-info.java @@ -0,0 +1,10 @@ +module ch.tutteli.atrium.infix.en_GB.kotlin_1_3.smoke { + // test dependencies are usually defined in build.gradle via --patch-module but that's quite cumbersome and I did + // not get it running in 10 minutes so I am using this, the effect should be the same, the kotlin compiler checks if + // I am using symbols from packages I do not require etc. + + requires ch.tutteli.atrium.infix.en_GB; + requires ch.tutteli.atrium.api.infix.en_GB.kotlin_1_3; + requires kotlin.stdlib; + requires spek.dsl.jvm; +} diff --git a/core/api/atrium-core-api-android/build.gradle b/core/api/atrium-core-api-android/build.gradle index da3cfc9ce..70e056563 100644 --- a/core/api/atrium-core-api-android/build.gradle +++ b/core/api/atrium-core-api-android/build.gradle @@ -4,7 +4,8 @@ dependencies { api kbox(), excludeKotlin api kotlinReflect() - testImplementation prefixedProject('cc-infix-en_GB-robstoll-android') + testImplementation prefixedProject('api-infix-en_GB-android') + testImplementation prefixedProject('api-cc-infix-en_GB-android') testImplementation prefixedProject('specs-android') } diff --git a/core/api/atrium-core-api-common/build.gradle b/core/api/atrium-core-api-common/build.gradle index a8e082ba5..8d2b3fd6c 100644 --- a/core/api/atrium-core-api-common/build.gradle +++ b/core/api/atrium-core-api-common/build.gradle @@ -3,6 +3,7 @@ description = 'API of the core of Atrium as common module' dependencies { api "ch.tutteli.kbox:kbox-common:$kbox_version", excludeKotlin + testImplementation prefixedProject('api-infix-en_GB-common') testImplementation prefixedProject('api-cc-infix-en_GB-common') testImplementation prefixedProject('specs-common') } diff --git a/core/api/atrium-core-api-common/src/main/kotlin/ch/tutteli/atrium/core/CoreFactory.kt b/core/api/atrium-core-api-common/src/main/kotlin/ch/tutteli/atrium/core/CoreFactory.kt index d57c0803d..c42419e61 100644 --- a/core/api/atrium-core-api-common/src/main/kotlin/ch/tutteli/atrium/core/CoreFactory.kt +++ b/core/api/atrium-core-api-common/src/main/kotlin/ch/tutteli/atrium/core/CoreFactory.kt @@ -207,6 +207,7 @@ interface CoreFactoryCommon { //TODO #280 add KDoc + @Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */) @UseExperimental(ExperimentalExpectConfig::class) fun newFeatureExpect( previousExpect: Expect, diff --git a/core/api/atrium-core-api-common/src/main/kotlin/ch/tutteli/atrium/creating/CollectingAssertionContainer.kt b/core/api/atrium-core-api-common/src/main/kotlin/ch/tutteli/atrium/creating/CollectingAssertionContainer.kt index 2fa00f288..d3cb2ecf7 100644 --- a/core/api/atrium-core-api-common/src/main/kotlin/ch/tutteli/atrium/creating/CollectingAssertionContainer.kt +++ b/core/api/atrium-core-api-common/src/main/kotlin/ch/tutteli/atrium/creating/CollectingAssertionContainer.kt @@ -4,12 +4,12 @@ import ch.tutteli.atrium.assertions.Assertion /** * Represents a container for [Assertion] which is intended to serve as receiver object for lambdas which create - * [Assertion]s, in which this assertion container collects the assertions created this ways. + * [Assertion]s, in which this [Expect] collects the assertions created this ways. * * This container does not offer reporting capabilities in contrast to [ReportingAssertionContainer]. * It merely offers a method to [getAssertions] (the collected ones). * - * @param T The type of the [subject] of this assertion container. + * @param T The type of the [subject] of this [Expect]. */ interface CollectingAssertionContainer : Expect { diff --git a/core/api/atrium-core-api-common/src/main/kotlin/ch/tutteli/atrium/creating/Expect.kt b/core/api/atrium-core-api-common/src/main/kotlin/ch/tutteli/atrium/creating/Expect.kt index 0852e3cfa..14e4e45a1 100644 --- a/core/api/atrium-core-api-common/src/main/kotlin/ch/tutteli/atrium/creating/Expect.kt +++ b/core/api/atrium-core-api-common/src/main/kotlin/ch/tutteli/atrium/creating/Expect.kt @@ -37,7 +37,7 @@ interface Expect : SubjectProvider { * * @param assertionCreator The receiver function which should create and add assertions to this container. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] depending on the concrete implementation. */ fun addAssertionsCreatedBy(assertionCreator: Expect.() -> Unit): Expect @@ -47,7 +47,7 @@ interface Expect : SubjectProvider { * * @param assertion The assertion which will be added to this container. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * * @throws AssertionError Might throw an [AssertionError] in case [Assertion]s are immediately * evaluated (see [ReportingAssertionContainer]). @@ -63,7 +63,7 @@ interface Expect : SubjectProvider { * @param expected The expected value, e.g., `5` * @param test Indicates whether the assertion holds or fails. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] in case [Assertion]s are immediately * evaluated (see [ReportingAssertionContainer]). */ @@ -78,7 +78,7 @@ interface Expect : SubjectProvider { * @param expected The expected value, e.g., `5` * @param test Indicates whether the assertion holds or fails. * - * @return This assertion container to support a fluent API. + * @return An [Expect] for the current subject of the assertion. * @throws AssertionError Might throw an [AssertionError] in case [Assertion]s are immediately * evaluated (see [ReportingAssertionContainer]). */ diff --git a/core/api/atrium-core-api-common/src/main/kotlin/ch/tutteli/atrium/creating/ExpectConfig.kt b/core/api/atrium-core-api-common/src/main/kotlin/ch/tutteli/atrium/creating/ExpectConfig.kt index d3b876cd8..72fcaf01b 100644 --- a/core/api/atrium-core-api-common/src/main/kotlin/ch/tutteli/atrium/creating/ExpectConfig.kt +++ b/core/api/atrium-core-api-common/src/main/kotlin/ch/tutteli/atrium/creating/ExpectConfig.kt @@ -2,7 +2,7 @@ package ch.tutteli.atrium.creating import ch.tutteli.atrium.reporting.translating.Translatable - +@Suppress("DEPRECATION" /* RequiresOptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */) @Experimental @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.CLASS) diff --git a/core/api/atrium-core-api-common/src/main/kotlin/ch/tutteli/atrium/creating/ReportingAssertionContainer.kt b/core/api/atrium-core-api-common/src/main/kotlin/ch/tutteli/atrium/creating/ReportingAssertionContainer.kt index 7e8ce1214..c3cb9e6c0 100644 --- a/core/api/atrium-core-api-common/src/main/kotlin/ch/tutteli/atrium/creating/ReportingAssertionContainer.kt +++ b/core/api/atrium-core-api-common/src/main/kotlin/ch/tutteli/atrium/creating/ReportingAssertionContainer.kt @@ -17,6 +17,7 @@ interface RootExpect : Expect { /** * The chosen [RootExpectConfig]. */ + @Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */) @UseExperimental(ExperimentalExpectConfig::class) val config: RootExpectConfig } @@ -39,6 +40,7 @@ interface FeatureExpect : Expect { /** * The chosen [FeatureExpectConfig]. */ + @Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */) @UseExperimental(ExperimentalExpectConfig::class) val config: FeatureExpectConfig diff --git a/core/api/atrium-core-api-common/src/test/kotlin/ch/tutteli/atrium/core/polyfills/AtriumPropertyTest.kt b/core/api/atrium-core-api-common/src/test/kotlin/ch/tutteli/atrium/core/polyfills/AtriumPropertyTest.kt index 75aff49f7..d8d731792 100644 --- a/core/api/atrium-core-api-common/src/test/kotlin/ch/tutteli/atrium/core/polyfills/AtriumPropertyTest.kt +++ b/core/api/atrium-core-api-common/src/test/kotlin/ch/tutteli/atrium/core/polyfills/AtriumPropertyTest.kt @@ -1,3 +1,4 @@ +@file:Suppress("DEPRECATION" /* remove once we have migrated to new infix API */) package ch.tutteli.atrium.core.polyfills import ch.tutteli.atrium.api.cc.infix.en_GB.toBe diff --git a/core/api/atrium-core-api-common/src/test/kotlin/ch/tutteli/atrium/core/polyfills/LoadServicesTest.kt b/core/api/atrium-core-api-common/src/test/kotlin/ch/tutteli/atrium/core/polyfills/LoadServicesTest.kt index dad8979c3..c381c7ed1 100644 --- a/core/api/atrium-core-api-common/src/test/kotlin/ch/tutteli/atrium/core/polyfills/LoadServicesTest.kt +++ b/core/api/atrium-core-api-common/src/test/kotlin/ch/tutteli/atrium/core/polyfills/LoadServicesTest.kt @@ -1,3 +1,4 @@ +@file:Suppress("DEPRECATION" /* remove once we have migrated to new infix API */) package ch.tutteli.atrium.core.polyfills import ch.tutteli.atrium.api.cc.infix.en_GB.* diff --git a/core/api/atrium-core-api-common/src/test/kotlin/ch/tutteli/atrium/core/polyfills/LoadSingleServiceTest.kt b/core/api/atrium-core-api-common/src/test/kotlin/ch/tutteli/atrium/core/polyfills/LoadSingleServiceTest.kt index 3ba188cd1..09e1731ea 100644 --- a/core/api/atrium-core-api-common/src/test/kotlin/ch/tutteli/atrium/core/polyfills/LoadSingleServiceTest.kt +++ b/core/api/atrium-core-api-common/src/test/kotlin/ch/tutteli/atrium/core/polyfills/LoadSingleServiceTest.kt @@ -1,3 +1,4 @@ +@file:Suppress("DEPRECATION" /* remove once we have migrated to new infix API */) package ch.tutteli.atrium.core.polyfills import ch.tutteli.atrium.api.cc.infix.en_GB.Values diff --git a/core/api/atrium-core-api-common/src/test/kotlin/ch/tutteli/atrium/core/polyfills/UseSingleServiceTest.kt b/core/api/atrium-core-api-common/src/test/kotlin/ch/tutteli/atrium/core/polyfills/UseSingleServiceTest.kt index 5bb26341e..cecec33a0 100644 --- a/core/api/atrium-core-api-common/src/test/kotlin/ch/tutteli/atrium/core/polyfills/UseSingleServiceTest.kt +++ b/core/api/atrium-core-api-common/src/test/kotlin/ch/tutteli/atrium/core/polyfills/UseSingleServiceTest.kt @@ -1,3 +1,4 @@ +@file:Suppress("DEPRECATION" /* remove once we have migrated to new infix API */) package ch.tutteli.atrium.core.polyfills import ch.tutteli.atrium.api.cc.infix.en_GB.Values diff --git a/core/api/atrium-core-api-common/src/test/kotlin/ch/tutteli/atrium/reporting/AtriumErrorSpec.kt b/core/api/atrium-core-api-common/src/test/kotlin/ch/tutteli/atrium/reporting/AtriumErrorSpec.kt index bd07eac88..2380c1313 100644 --- a/core/api/atrium-core-api-common/src/test/kotlin/ch/tutteli/atrium/reporting/AtriumErrorSpec.kt +++ b/core/api/atrium-core-api-common/src/test/kotlin/ch/tutteli/atrium/reporting/AtriumErrorSpec.kt @@ -1,3 +1,4 @@ +@file:Suppress("DEPRECATION" /* remove once we have migrated to new infix API */) package ch.tutteli.atrium.reporting import ch.tutteli.atrium.api.cc.infix.en_GB.property diff --git a/core/api/atrium-core-api-js/build.gradle b/core/api/atrium-core-api-js/build.gradle index 59ed687f8..b045cbcbe 100644 --- a/core/api/atrium-core-api-js/build.gradle +++ b/core/api/atrium-core-api-js/build.gradle @@ -3,6 +3,7 @@ description = 'API of the core of Atrium for the JS platform.' dependencies { api "ch.tutteli.kbox:kbox-js:$kbox_version", excludeKotlin - testImplementation prefixedProject('cc-infix-en_GB-robstoll-js') + testImplementation prefixedProject('api-infix-en_GB-js') + testImplementation prefixedProject('api-cc-infix-en_GB-js') testImplementation prefixedProject('specs-js') } diff --git a/core/api/atrium-core-api-jvm/build.gradle b/core/api/atrium-core-api-jvm/build.gradle index 6643c8c12..fb9e6a487 100644 --- a/core/api/atrium-core-api-jvm/build.gradle +++ b/core/api/atrium-core-api-jvm/build.gradle @@ -4,6 +4,7 @@ dependencies { api kbox(), excludeKotlin api kotlinReflect() - testImplementation prefixedProject('cc-infix-en_GB-robstoll-jvm') + testImplementation prefixedProject('api-infix-en_GB-jvm') + testImplementation prefixedProject('api-cc-infix-en_GB-jvm') testImplementation prefixedProject('specs-jvm') } diff --git a/core/api/atrium-core-api-jvm/src/main/kotlin/ch/tutteli/atrium/core/polyfills/kClassExtensions.kt b/core/api/atrium-core-api-jvm/src/main/kotlin/ch/tutteli/atrium/core/polyfills/kClassExtensions.kt index a6970b893..416fbbe72 100644 --- a/core/api/atrium-core-api-jvm/src/main/kotlin/ch/tutteli/atrium/core/polyfills/kClassExtensions.kt +++ b/core/api/atrium-core-api-jvm/src/main/kotlin/ch/tutteli/atrium/core/polyfills/kClassExtensions.kt @@ -10,7 +10,18 @@ import kotlin.reflect.full.cast as kotlinCast * (e.g. `int` vs. `Integer`) and returns also a name for anonymous classes. */ actual val KClass<*>.fullName: String - get() = if (!java.isPrimitive) qualifiedName ?: java.name else java.name + get() { + return if (!java.isPrimitive) { + try { + qualifiedName + } catch (_: Throwable) { + // workaround for https://youtrack.jetbrains.com/issue/KT-37656 there are cases where Kotlin does not + // find the class it defined, java.name works though + null + } ?: java.name + } else java.name + } + /** * Returns [KClass.java].[name][Class.name]. diff --git a/core/robstoll-lib/atrium-core-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/core/robstoll/lib/creating/FeatureExpectImpl.kt b/core/robstoll-lib/atrium-core-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/core/robstoll/lib/creating/FeatureExpectImpl.kt index 9b7b76651..1ba232cc9 100644 --- a/core/robstoll-lib/atrium-core-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/core/robstoll/lib/creating/FeatureExpectImpl.kt +++ b/core/robstoll-lib/atrium-core-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/core/robstoll/lib/creating/FeatureExpectImpl.kt @@ -14,6 +14,7 @@ import ch.tutteli.atrium.creating.FeatureExpectConfig class FeatureExpectImpl( override val previousExpect: Expect, override val maybeSubject: Option, + @Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */) @UseExperimental(ExperimentalExpectConfig::class) override val config: FeatureExpectConfig, private val assertionChecker: AssertionChecker, @@ -45,6 +46,7 @@ class FeatureExpectImpl( return this } + @Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */) @UseExperimental(ExperimentalExpectConfig::class) private fun checkAndClearAssertions(): Expect { try { @@ -54,8 +56,7 @@ class FeatureExpectImpl( } finally { clearAssertions() } - return this - } + return this } override fun getAssertions(): List = getCopyOfAssertions() } diff --git a/core/robstoll-lib/atrium-core-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/core/robstoll/lib/creating/ReportingAssertionContainerImpl.kt b/core/robstoll-lib/atrium-core-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/core/robstoll/lib/creating/ReportingAssertionContainerImpl.kt index 7ecea3efb..baa9d635f 100644 --- a/core/robstoll-lib/atrium-core-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/core/robstoll/lib/creating/ReportingAssertionContainerImpl.kt +++ b/core/robstoll-lib/atrium-core-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/core/robstoll/lib/creating/ReportingAssertionContainerImpl.kt @@ -11,7 +11,7 @@ class ReportingAssertionContainerImpl( private val assertionCheckerDecorator: ReportingAssertionContainer.AssertionCheckerDecorator ) : MutableListBasedAssertionContainer(assertionCheckerDecorator.maybeSubject), ReportingAssertionContainer { - + @Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */) @UseExperimental(ExperimentalExpectConfig::class) override val config: RootExpectConfig = RootExpectConfig.create( diff --git a/core/robstoll-lib/atrium-core-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/translating/TranslationSupplierBasedTranslator.kt b/core/robstoll-lib/atrium-core-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/translating/TranslationSupplierBasedTranslator.kt index 15396135a..a30049568 100644 --- a/core/robstoll-lib/atrium-core-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/translating/TranslationSupplierBasedTranslator.kt +++ b/core/robstoll-lib/atrium-core-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/translating/TranslationSupplierBasedTranslator.kt @@ -30,9 +30,10 @@ class TranslationSupplierBasedTranslator( fallbackLocales: List ) : ArgumentsSupportingTranslator(primaryLocale, fallbackLocales) { - override fun translateWithoutArgs(translatable: Translatable): String = - localeOrderDecider.determineOrder(primaryLocale, fallbackLocales) + override fun translateWithoutArgs(translatable: Translatable): String { + return localeOrderDecider.determineOrder(primaryLocale, fallbackLocales) .map { translationSupplier.get(translatable, it) } .firstOrNull { it != null } ?: translatable.getDefault() + } } diff --git a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/checking/FeatureAssertionCheckerSpec.kt b/core/robstoll-lib/atrium-core-robstoll-lib-common/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/checking/FeatureAssertionCheckerSpec.kt similarity index 100% rename from core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/checking/FeatureAssertionCheckerSpec.kt rename to core/robstoll-lib/atrium-core-robstoll-lib-common/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/checking/FeatureAssertionCheckerSpec.kt diff --git a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/checking/ThrowingAssertionCheckerSpec.kt b/core/robstoll-lib/atrium-core-robstoll-lib-common/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/checking/ThrowingAssertionCheckerSpec.kt similarity index 76% rename from core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/checking/ThrowingAssertionCheckerSpec.kt rename to core/robstoll-lib/atrium-core-robstoll-lib-common/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/checking/ThrowingAssertionCheckerSpec.kt index da519a3bc..3da334295 100644 --- a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/checking/ThrowingAssertionCheckerSpec.kt +++ b/core/robstoll-lib/atrium-core-robstoll-lib-common/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/checking/ThrowingAssertionCheckerSpec.kt @@ -1,6 +1,5 @@ package ch.tutteli.atrium.core.robstoll.lib.checking -//TODO #116 migrate spek1 to spek2 - move to common module object ThrowingAssertionCheckerSpec : ch.tutteli.atrium.specs.checking.ThrowingAssertionCheckerSpec( ::ThrowingAssertionChecker ) diff --git a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/OnlyFailureReporterSpec.kt b/core/robstoll-lib/atrium-core-robstoll-lib-common/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/OnlyFailureReporterSpec.kt similarity index 100% rename from core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/OnlyFailureReporterSpec.kt rename to core/robstoll-lib/atrium-core-robstoll-lib-common/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/OnlyFailureReporterSpec.kt diff --git a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextMethodCallFormatterSpec.kt b/core/robstoll-lib/atrium-core-robstoll-lib-common/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextMethodCallFormatterSpec.kt similarity index 76% rename from core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextMethodCallFormatterSpec.kt rename to core/robstoll-lib/atrium-core-robstoll-lib-common/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextMethodCallFormatterSpec.kt index 481c3062c..e5588d584 100644 --- a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextMethodCallFormatterSpec.kt +++ b/core/robstoll-lib/atrium-core-robstoll-lib-common/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextMethodCallFormatterSpec.kt @@ -1,6 +1,5 @@ package ch.tutteli.atrium.core.robstoll.lib.reporting -//TODO #116 migrate spek1 to spek2 - move to common module object TextMethodCallFormatterSpec : ch.tutteli.atrium.specs.reporting.TextMethodCallFormatterSpec( { TextMethodCallFormatter } ) diff --git a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/translating/LocaleOrderDeciderSpec.kt b/core/robstoll-lib/atrium-core-robstoll-lib-common/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/translating/LocaleOrderDeciderSpec.kt similarity index 77% rename from core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/translating/LocaleOrderDeciderSpec.kt rename to core/robstoll-lib/atrium-core-robstoll-lib-common/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/translating/LocaleOrderDeciderSpec.kt index cc9c5c9b8..b0f6197e7 100644 --- a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/translating/LocaleOrderDeciderSpec.kt +++ b/core/robstoll-lib/atrium-core-robstoll-lib-common/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/translating/LocaleOrderDeciderSpec.kt @@ -1,6 +1,5 @@ package ch.tutteli.atrium.core.robstoll.lib.reporting.translating -//TODO #116 migrate spek1 to spek2 - move to common module class LocaleOrderDeciderSpec : ch.tutteli.atrium.specs.reporting.translating.LocaleOrderDeciderSpec( ::CoroutineBasedLocaleOrderDecider ) diff --git a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/AdjustStackSpec.kt b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/AdjustStackSpec.kt index 4133782f1..f365d6ae2 100644 --- a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/AdjustStackSpec.kt +++ b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/AdjustStackSpec.kt @@ -108,8 +108,7 @@ class AdjustStackSpec : Spek({ throwable.addSuppressed(throwable2) adjuster.adjust(throwable) expect(throwable.suppressed).asList().all { - //TODO #31 replace with shortcut fun - feature { f(it::cause) }.notToBeNull { + cause { feature { f(it::stackBacktrace) } .containsNot.entries(containsNotFirst, *containsNotRest) .contains(containsFirst, *containsRest) diff --git a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/AssertionFormatterControllerSpec.kt b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/AssertionFormatterControllerSpec.kt index ffbea9ee7..bafc55138 100644 --- a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/AssertionFormatterControllerSpec.kt +++ b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/AssertionFormatterControllerSpec.kt @@ -1,6 +1,5 @@ package ch.tutteli.atrium.core.robstoll.lib.reporting -//TODO #116 migrate spek1 to spek2 - move to common module object AssertionFormatterControllerSpec : ch.tutteli.atrium.specs.reporting.AssertionFormatterControllerSpec( ::AssertionFormatterControllerImpl ) diff --git a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/DetailedObjectFormatterSpec.kt b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/DetailedObjectFormatterSpec.kt index 5fbadb0b7..139d9dc58 100644 --- a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/DetailedObjectFormatterSpec.kt +++ b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/DetailedObjectFormatterSpec.kt @@ -10,17 +10,11 @@ import ch.tutteli.atrium.reporting.translating.Translator import ch.tutteli.atrium.reporting.translating.UsingDefaultTranslator import ch.tutteli.atrium.specs.reporting.ObjectFormatterSpec import ch.tutteli.atrium.api.verbs.internal.AssertionVerb -import com.nhaarman.mockitokotlin2.doReturn -import com.nhaarman.mockitokotlin2.mock -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.context -import org.jetbrains.spek.api.dsl.describe -import org.jetbrains.spek.api.dsl.it -import org.jetbrains.spek.api.dsl.on -import org.jetbrains.spek.api.include +import io.mockk.* +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.describe import kotlin.reflect.KClass -//TODO #116 migrate spek1 to spek2 - move to common module object DetailedObjectFormatterSpec : Spek({ include(AtriumsObjectFormatterSpec) @@ -28,21 +22,21 @@ object DetailedObjectFormatterSpec : Spek({ describe("format") { - on("a ${Char::class.simpleName}") { + context("a ${Char::class.simpleName}") { val result = testee.format('a') it("returns the ${Char::class.simpleName} in apostrophes") { expect(result).toBe("'a'") } } - on("a ${Boolean::class.simpleName}") { + context("a ${Boolean::class.simpleName}") { it("returns the toString representation of the ${Boolean::class.simpleName}") { expect(testee.format(true)).toBe("true") expect(testee.format(false)).toBe("false") } } - on("a ${String::class.simpleName}") { + context("a ${String::class.simpleName}") { it("returns two quotes including identity hash if empty ${String::class.simpleName}") { val string = "" val result = testee.format(string) @@ -62,7 +56,7 @@ object DetailedObjectFormatterSpec : Spek({ val typeNameAndHash = "including type name and identity hash" - on("a ${CharSequence::class.simpleName} besides ${String::class.simpleName}") { + context("a ${CharSequence::class.simpleName} besides ${String::class.simpleName}") { it("returns two quotes $typeNameAndHash if empty ${CharSequence::class.simpleName}") { val value = StringBuilder("") val result = testee.format(value) @@ -81,18 +75,17 @@ object DetailedObjectFormatterSpec : Spek({ } } - - on("a ${StringBasedRawString::class.simpleName}") { + context("a ${StringBasedRawString::class.simpleName}") { val result = testee.format(RawString.create("hello")) it("returns the containing string") { expect(result).toBe("hello") } } - on("a ${TranslatableBasedRawString::class.simpleName}") { + context("a ${TranslatableBasedRawString::class.simpleName}") { val translation = "es gilt" - val translator = mock { - on { translate(AssertionVerb.EXPECT) } doReturn translation + val translator = mockk { + every { translate(AssertionVerb.EXPECT) } returns translation } val testeeWithMockedTranslation = DetailedObjectFormatter(translator) val result = testeeWithMockedTranslation.format(RawString.create(AssertionVerb.EXPECT)) @@ -101,7 +94,7 @@ object DetailedObjectFormatterSpec : Spek({ } } - on("an enum") { + context("an enum") { val enum = AssertionVerb.EXPECT val result = testee.format(enum) it("returns its toString representation together with its Class.name but without System.identityHash") { @@ -109,14 +102,14 @@ object DetailedObjectFormatterSpec : Spek({ } } - on("a Throwable") { + context("a Throwable") { val result = testee.format(AssertionError("blablabla")) it("returns only its Class.name") { expect(result).toBe(AssertionError::class.java.name) } } - on("a ${Class::class.simpleName}") { + context("a ${Class::class.simpleName}") { val result = testee.format(DetailedObjectFormatterSpec::class.java) it("returns its simpleName and name in parenthesis") { val clazz = DetailedObjectFormatterSpec::class.java @@ -124,7 +117,7 @@ object DetailedObjectFormatterSpec : Spek({ } } - group("on a ${KClass::class.simpleName}") { + context("on a ${KClass::class.simpleName}") { context("java Class is the same (no special Kotlin class)") { val result = testee.format(DetailedObjectFormatterSpec::class) @@ -160,7 +153,7 @@ object DetailedObjectFormatterSpec : Spek({ java.lang.Float::class.java.simpleName to 1.0f, java.lang.Double::class.java.simpleName to 1.0 ).forEach { (typeName, value) -> - on(typeName) { + context(typeName) { val result = testee.format(value) it("returns subject's toString() $typeNameAndHash") { expect(result).toBe( @@ -171,7 +164,7 @@ object DetailedObjectFormatterSpec : Spek({ } } - on("an anonymous class") { + context("an anonymous class") { val anonymous = object : Any() { override fun toString(): String = "anonymous type" } diff --git a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextExplanatoryAssertionGroupFormatterSpec.kt b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextExplanatoryAssertionGroupFormatterSpec.kt index 291aae731..967169fa8 100644 --- a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextExplanatoryAssertionGroupFormatterSpec.kt +++ b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextExplanatoryAssertionGroupFormatterSpec.kt @@ -6,11 +6,9 @@ import ch.tutteli.atrium.assertions.ExplanatoryAssertionGroupType import ch.tutteli.atrium.reporting.AssertionFormatterController import ch.tutteli.atrium.reporting.ObjectFormatter import ch.tutteli.atrium.reporting.translating.Translator -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.include +import org.spekframework.spek2.Spek import kotlin.reflect.KClass -//TODO #116 migrate spek1 to spek2 - move to common module class TextExplanatoryAssertionGroupFormatterSpec : Spek({ include(AtriumsTextExplanatoryAssertionFormatterSpec) diff --git a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextFallbackAssertionFormatterSpec.kt b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextFallbackAssertionFormatterSpec.kt index b10e8b584..ab01b38f5 100644 --- a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextFallbackAssertionFormatterSpec.kt +++ b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextFallbackAssertionFormatterSpec.kt @@ -18,14 +18,10 @@ import ch.tutteli.atrium.specs.reporting.alwaysTrueAssertionFilter import ch.tutteli.atrium.translations.DescriptionBasic.NOT_TO_BE import ch.tutteli.atrium.translations.DescriptionBasic.TO_BE import ch.tutteli.atrium.api.verbs.internal.AssertionVerb.EXPECT -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.context -import org.jetbrains.spek.api.dsl.describe -import org.jetbrains.spek.api.dsl.it -import org.jetbrains.spek.api.include +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.describe import kotlin.reflect.KClass -//TODO #116 migrate spek1 to spek2 - move to common module class TextFallbackAssertionFormatterSpec : Spek({ include(AtriumsTextFallbackAssertionFormatterSpec) diff --git a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextFeatureAssertionGroupFormatterSpec.kt b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextFeatureAssertionGroupFormatterSpec.kt index 7918b09d0..6e1787850 100644 --- a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextFeatureAssertionGroupFormatterSpec.kt +++ b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextFeatureAssertionGroupFormatterSpec.kt @@ -6,11 +6,9 @@ import ch.tutteli.atrium.assertions.FeatureAssertionGroupType import ch.tutteli.atrium.reporting.AssertionFormatterController import ch.tutteli.atrium.reporting.ObjectFormatter import ch.tutteli.atrium.reporting.translating.Translator -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.include +import org.spekframework.spek2.Spek import kotlin.reflect.KClass -//TODO #116 migrate spek1 to spek2 - move to common module class TextFeatureAssertionGroupFormatterSpec : Spek({ include(AtriumsTextFeatureAssertionGroupFormatterSpec) diff --git a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextIndentAssertionGroupFormatterSpec.kt b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextIndentAssertionGroupFormatterSpec.kt deleted file mode 100644 index 917bff162..000000000 --- a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextIndentAssertionGroupFormatterSpec.kt +++ /dev/null @@ -1,70 +0,0 @@ -@file:Suppress("DEPRECATION" /* TODO remove with 1.0.0 */) - -package ch.tutteli.atrium.core.robstoll.lib.reporting - -import ch.tutteli.atrium.assertions.BulletPointIdentifier -import ch.tutteli.atrium.assertions.DefaultIndentAssertionGroupType -import ch.tutteli.atrium.assertions.IndentAssertionGroupType -import ch.tutteli.atrium.reporting.AssertionFormatterController -import ch.tutteli.atrium.reporting.ObjectFormatter -import ch.tutteli.atrium.reporting.translating.Translator -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.include -import kotlin.reflect.KClass - -//TODO remove with 1.0.0 -- no need to migrate to spek2 -@Deprecated("So far indentation was achieved by grouping (which is the solution to go). Will be removed with 1.0.0") -class TextIndentAssertionGroupFormatterSpec : Spek({ - - include(AtriumsTextIndentAssertionGroupFormatterSpec) - include(AtriumsEmptyNameAndSubjectAssertionGroupFormatterSpec) - include(AtriumsSingleAssertionGroupTypeFormatterSpec) - include(AtriumsAssertionFormatterSpec) - -}) { - object AtriumsTextIndentAssertionGroupFormatterSpec : - ch.tutteli.atrium.specs.reporting.TextIndentAssertionGroupFormatterSpec( - ::TextIndentAssertionGroupFormatter, "[Atrium's IndentGroup...Spec] " - ) - - object AtriumsEmptyNameAndSubjectAssertionGroupFormatterSpec : - ch.tutteli.atrium.specs.reporting.EmptyNameAndSubjectAssertionGroupFormatterSpec( - factory(), - IndentAssertionGroupType::class, - DefaultIndentAssertionGroupType, - object : IndentAssertionGroupType {}, - "[Atrium's EmptyNameAndSubject...Spec] " - ) - - object AtriumsSingleAssertionGroupTypeFormatterSpec : - ch.tutteli.atrium.specs.reporting.SingleAssertionGroupTypeFormatterSpec( - factoryWithBulletPoints(), - IndentAssertionGroupType::class, - DefaultIndentAssertionGroupType, - object : IndentAssertionGroupType {}, - "[Atrium's SingleAssertionGroupType...Spec] " - ) - - object AtriumsAssertionFormatterSpec : ch.tutteli.atrium.specs.reporting.AssertionFormatterSpec( - factoryWithBulletPoints(), "[Atrium's AssertionFormatterSpec] " - ) - - companion object { - private fun factory() = { assertionFormatterController: AssertionFormatterController -> - TextIndentAssertionGroupFormatter( - mapOf( - IndentAssertionGroupType::class to "**" - ), assertionFormatterController - ) - } - - private fun factoryWithBulletPoints() = - { _: Map, String>, assertionFormatterController: AssertionFormatterController, _: ObjectFormatter, _: Translator -> - TextIndentAssertionGroupFormatter( - mapOf( - IndentAssertionGroupType::class to "**" - ), assertionFormatterController - ) - } - } -} diff --git a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextListAssertionGroupFormatterSpec.kt b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextListAssertionGroupFormatterSpec.kt index bee1f4cae..5cca595e2 100644 --- a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextListAssertionGroupFormatterSpec.kt +++ b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextListAssertionGroupFormatterSpec.kt @@ -6,11 +6,9 @@ import ch.tutteli.atrium.assertions.ListAssertionGroupType import ch.tutteli.atrium.reporting.AssertionFormatterController import ch.tutteli.atrium.reporting.ObjectFormatter import ch.tutteli.atrium.reporting.translating.Translator -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.include +import org.spekframework.spek2.Spek import kotlin.reflect.KClass -//TODO #116 migrate spek1 to spek2 - move to common module class TextListAssertionGroupFormatterSpec : Spek({ include(AtriumsTextListAssertionFormatterSpec) diff --git a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextNextLineAssertionPairFormatterSpec.kt b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextNextLineAssertionPairFormatterSpec.kt index 9718e74be..fc48688c0 100644 --- a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextNextLineAssertionPairFormatterSpec.kt +++ b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextNextLineAssertionPairFormatterSpec.kt @@ -7,17 +7,15 @@ import ch.tutteli.atrium.domain.builders.AssertImpl import ch.tutteli.atrium.reporting.RawString import ch.tutteli.atrium.reporting.translating.Untranslatable import ch.tutteli.atrium.reporting.translating.UsingDefaultTranslator -import ch.tutteli.atrium.specs.describeFun +import ch.tutteli.atrium.specs.describeFunTemplate import ch.tutteli.atrium.specs.reporting.AssertionFormatterSpecBase import ch.tutteli.atrium.specs.reporting.ToStringObjectFormatter -import org.jetbrains.spek.api.dsl.SpecBody -import org.jetbrains.spek.api.dsl.context -import org.jetbrains.spek.api.dsl.it +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.Suite -//TODO #116 migrate spek1 to spek2 - move to common module class TextNextLineAssertionPairFormatterSpec : AssertionFormatterSpecBase({ - fun describeFun(vararg funName: String, body: SpecBody.() -> Unit) = describeFun("", funName, body = body) + fun describeFun(vararg funName: String, body: Suite.() -> Unit) = describeFunTemplate("", funName, body = body) val testee = TextNextLineAssertionPairFormatter( ToStringObjectFormatter, diff --git a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextSummaryAssertionGroupFormatterSpec.kt b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextSummaryAssertionGroupFormatterSpec.kt index 5bd4bbf47..0286f2c48 100644 --- a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextSummaryAssertionGroupFormatterSpec.kt +++ b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/TextSummaryAssertionGroupFormatterSpec.kt @@ -8,11 +8,9 @@ import ch.tutteli.atrium.reporting.ObjectFormatter import ch.tutteli.atrium.reporting.translating.Translator import ch.tutteli.atrium.reporting.translating.UsingDefaultTranslator import ch.tutteli.atrium.specs.reporting.ToStringObjectFormatter -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.include +import org.spekframework.spek2.Spek import kotlin.reflect.KClass -//TODO #116 migrate spek1 to spek2 - move to common module class TextSummaryAssertionGroupFormatterSpec : Spek({ include(AtriumsTextSummaryAssertionGroupFormatterSpec) diff --git a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/translating/ResourceBundleBasedTranslatorSpec.kt b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/translating/ResourceBundleBasedTranslatorSpec.kt index 7852d2cdc..44f01e773 100644 --- a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/translating/ResourceBundleBasedTranslatorSpec.kt +++ b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/translating/ResourceBundleBasedTranslatorSpec.kt @@ -1,8 +1,7 @@ package ch.tutteli.atrium.core.robstoll.lib.reporting.translating import ch.tutteli.atrium.domain.builders.reporting.ReporterBuilder -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.include +import org.spekframework.spek2.Spek //cannot be easily migrated to specs-common/spek2 as it depends on JVM resources => need to find a solution first object ResourceBundleBasedTranslatorSpec : Spek({ diff --git a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/translating/TranslationSupplierBasedTranslatorSpec.kt b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/translating/TranslationSupplierBasedTranslatorSpec.kt index 607b2a839..484c08459 100644 --- a/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/translating/TranslationSupplierBasedTranslatorSpec.kt +++ b/core/robstoll-lib/atrium-core-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/core/robstoll/lib/reporting/translating/TranslationSupplierBasedTranslatorSpec.kt @@ -1,10 +1,8 @@ package ch.tutteli.atrium.core.robstoll.lib.reporting.translating import ch.tutteli.atrium.core.coreFactory -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.include +import org.spekframework.spek2.Spek -//TODO #116 migrate spek1 to spek2 - move to common module object TranslationSupplierBasedTranslatorSpec : Spek({ include(AtriumsTranslationSupplierBasedTranslatorSpec) include(AtriumsTranslatorErrorCaseSpec) diff --git a/core/robstoll/atrium-core-robstoll-common/src/main/kotlin/ch/tutteli/atrium/core/robstoll/CoreFactoryCommonImpl.kt b/core/robstoll/atrium-core-robstoll-common/src/main/kotlin/ch/tutteli/atrium/core/robstoll/CoreFactoryCommonImpl.kt index e34a5ab31..f80de21b0 100644 --- a/core/robstoll/atrium-core-robstoll-common/src/main/kotlin/ch/tutteli/atrium/core/robstoll/CoreFactoryCommonImpl.kt +++ b/core/robstoll/atrium-core-robstoll-common/src/main/kotlin/ch/tutteli/atrium/core/robstoll/CoreFactoryCommonImpl.kt @@ -34,6 +34,7 @@ abstract class CoreFactoryCommonImpl : CoreFactoryCommon { final override fun newFeatureExpect( previousExpect: Expect, maybeSubject: Option, + @Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */) @UseExperimental(ExperimentalExpectConfig::class) featureConfig: FeatureExpectConfig, assertions: List diff --git a/domain/api/atrium-domain-api-common/src/main/kotlin/ch/tutteli/atrium/domain/creating/ComparableAssertions.kt b/domain/api/atrium-domain-api-common/src/main/kotlin/ch/tutteli/atrium/domain/creating/ComparableAssertions.kt index 3f0774a93..a667941bd 100644 --- a/domain/api/atrium-domain-api-common/src/main/kotlin/ch/tutteli/atrium/domain/creating/ComparableAssertions.kt +++ b/domain/api/atrium-domain-api-common/src/main/kotlin/ch/tutteli/atrium/domain/creating/ComparableAssertions.kt @@ -19,12 +19,12 @@ val comparableAssertions by lazy { loadSingleService(ComparableAssertions::class interface ComparableAssertions { fun , T2 : Any?> isLessThan(subjectProvider: SubjectProvider, expected: T2): Assertion - //TODO rename to isLessThanOrEqual with 0.1.0 + //TODO rename to isLessThanOrEqual with 1.0.0 fun , T2 : Any?> isLessOrEquals(subjectProvider: SubjectProvider, expected: T2): Assertion fun , T2 : Any?> isGreaterThan(subjectProvider: SubjectProvider, expected: T2): Assertion - //TODO rename to isGreaterThanOrEqual with 0.1.0 + //TODO rename to isGreaterThanOrEqual with 1.0.0 fun , T2 : Any?> isGreaterOrEquals( subjectProvider: SubjectProvider, expected: T2 diff --git a/domain/api/atrium-domain-api-common/src/main/kotlin/ch/tutteli/atrium/domain/creating/ThrowableAssertions.kt b/domain/api/atrium-domain-api-common/src/main/kotlin/ch/tutteli/atrium/domain/creating/ThrowableAssertions.kt index 52851d4ec..4c06e1dca 100644 --- a/domain/api/atrium-domain-api-common/src/main/kotlin/ch/tutteli/atrium/domain/creating/ThrowableAssertions.kt +++ b/domain/api/atrium-domain-api-common/src/main/kotlin/ch/tutteli/atrium/domain/creating/ThrowableAssertions.kt @@ -1,9 +1,12 @@ package ch.tutteli.atrium.domain.creating import ch.tutteli.atrium.core.polyfills.loadSingleService +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.creating.changers.ChangedSubjectPostStep import ch.tutteli.atrium.reporting.Reporter import ch.tutteli.atrium.reporting.translating.Translatable import ch.tutteli.atrium.reporting.translating.Untranslatable +import kotlin.reflect.KClass /** * The access point to an implementation of [ThrowableAssertions]. @@ -16,9 +19,13 @@ val throwableAssertions by lazy { loadSingleService(ThrowableAssertions::class) * Defines the minimum set of assertion functions and builders applicable to [Throwable], * which an implementation of the domain of Atrium has to provide. */ -//TODO remove with 1.0.0 if there aren't any non-deprecated functions added interface ThrowableAssertions { + fun cause( + expect: Expect, + expectedType: KClass + ): ChangedSubjectPostStep + /** * Turns the given [assertionVerb] into an [Untranslatable] and delegates to the other overload. */ diff --git a/domain/api/atrium-domain-api-common/src/main/kotlin/ch/tutteli/atrium/domain/creating/changers/FeatureExtractor.kt b/domain/api/atrium-domain-api-common/src/main/kotlin/ch/tutteli/atrium/domain/creating/changers/FeatureExtractor.kt index ab6c987db..0c1027791 100644 --- a/domain/api/atrium-domain-api-common/src/main/kotlin/ch/tutteli/atrium/domain/creating/changers/FeatureExtractor.kt +++ b/domain/api/atrium-domain-api-common/src/main/kotlin/ch/tutteli/atrium/domain/creating/changers/FeatureExtractor.kt @@ -50,7 +50,7 @@ interface FeatureExtractor { * if you want a different representation, then use this parameter where passing `null` still means use the * feature. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. */ fun extract( originalAssertionContainer: Expect, diff --git a/domain/api/atrium-domain-api-common/src/main/kotlin/ch/tutteli/atrium/domain/creating/changers/SubjectChanger.kt b/domain/api/atrium-domain-api-common/src/main/kotlin/ch/tutteli/atrium/domain/creating/changers/SubjectChanger.kt index ebace1334..ca2753902 100644 --- a/domain/api/atrium-domain-api-common/src/main/kotlin/ch/tutteli/atrium/domain/creating/changers/SubjectChanger.kt +++ b/domain/api/atrium-domain-api-common/src/main/kotlin/ch/tutteli/atrium/domain/creating/changers/SubjectChanger.kt @@ -44,7 +44,7 @@ interface SubjectChanger { * [Expect]) then you usually pass `this` (so the instance of [Expect]) for this parameter. * @param transformation Provides the subject. * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. */ fun unreported( originalAssertionContainer: Expect, @@ -80,7 +80,7 @@ interface SubjectChanger { * change fails since we can then already show to you (in error reporting) what you wanted to assert about * the new subject (which gives you more context to the error). * - * @return The newly created [Expect]. + * @return The newly created [Expect] for the extracted feature. */ fun reported( originalAssertionContainer: Expect, diff --git a/domain/api/atrium-domain-api-jvm/src/main/kotlin/ch/tutteli/atrium/domain/creating/PathAssertions.kt b/domain/api/atrium-domain-api-jvm/src/main/kotlin/ch/tutteli/atrium/domain/creating/PathAssertions.kt index 485f5ebf0..5e4a09e54 100644 --- a/domain/api/atrium-domain-api-jvm/src/main/kotlin/ch/tutteli/atrium/domain/creating/PathAssertions.kt +++ b/domain/api/atrium-domain-api-jvm/src/main/kotlin/ch/tutteli/atrium/domain/creating/PathAssertions.kt @@ -24,6 +24,7 @@ interface PathAssertions { fun extension(expect: Expect): ExtractedFeaturePostStep fun fileNameWithoutExtension(expect: Expect): ExtractedFeaturePostStep fun parent(expect: Expect): ExtractedFeaturePostStep + fun resolve(expect: Expect, other: String): ExtractedFeaturePostStep fun startsWith(expect: Expect, expected: Path): Assertion fun startsNotWith(expect: Expect, expected: Path): Assertion @@ -37,4 +38,5 @@ interface PathAssertions { fun isWritable(expect: Expect): Assertion fun isRegularFile(expect: Expect): Assertion fun isDirectory(expect: Expect): Assertion + } diff --git a/domain/api/extensions/kotlin_1_3/atrium-domain-api-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/domain/kotlin_1_3/creating/ResultAssertions.kt b/domain/api/extensions/kotlin_1_3/atrium-domain-api-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/domain/kotlin_1_3/creating/ResultAssertions.kt index 31e719426..82c421cfa 100644 --- a/domain/api/extensions/kotlin_1_3/atrium-domain-api-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/domain/kotlin_1_3/creating/ResultAssertions.kt +++ b/domain/api/extensions/kotlin_1_3/atrium-domain-api-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/domain/kotlin_1_3/creating/ResultAssertions.kt @@ -18,10 +18,10 @@ val resultAssertions by lazy { loadSingleService(ResultAssertions::class) } * which an implementation of the domain of Atrium has to provide. */ interface ResultAssertions { - fun > isSuccess(assertionContainer: Expect): ExtractedFeaturePostStep + fun > isSuccess(expect: Expect): ExtractedFeaturePostStep fun isFailure( - assertionContainer: Expect>, + expect: Expect>, expectedType: KClass ): ChangedSubjectPostStep } diff --git a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/ExpectImpl.kt b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/ExpectImpl.kt index b94dce233..14529fba2 100644 --- a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/ExpectImpl.kt +++ b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/ExpectImpl.kt @@ -35,8 +35,8 @@ object ExpectImpl { * into another representation (e.g. down-cast `Person` to `Student`) then you should use * [feature.extractor][NewFeatureAssertionsBuilder.extractor] instead. */ - inline fun changeSubject(originalAssertionContainer: Expect) = - SubjectChangerBuilder.create(originalAssertionContainer) + inline fun changeSubject(originalExpect: Expect) = + SubjectChangerBuilder.create(originalExpect) @Deprecated("Do no longer use Assert, use Expect instead - this method was introduced in 0.9.0 to ease the migration from Assert to Expect; will be removed with 1.0.0") @Suppress("DEPRECATION", "DeprecatedCallableAddReplaceWith") diff --git a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/NewFeatureAssertionsBuilder.kt b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/NewFeatureAssertionsBuilder.kt index 4cf5ddc9c..0ecd76652 100644 --- a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/NewFeatureAssertionsBuilder.kt +++ b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/NewFeatureAssertionsBuilder.kt @@ -80,23 +80,16 @@ object NewFeatureAssertionsBuilder : NewFeatureAssertions { description: Translatable, provider: T.() -> R ): ExtractedFeaturePostStep = - genericFeature(expect, createMetaFeature(expect, description, provider)) + genericFeature(expect, ExpectImpl.feature.meta.create(expect, description, provider)) fun genericSubjectBasedFeature( expect: Expect, provider: (T) -> MetaFeature ): ExtractedFeaturePostStep = ExpectImpl.feature.genericFeature( expect, - expect.maybeSubject.fold(this::createFeatureSubjectNotDefined) { provider(it) } + ExpectImpl.feature.meta.createSubjectBased(expect, provider) ) - private fun createFeatureSubjectNotDefined(): MetaFeature = - MetaFeature( - ErrorMessages.DEDSCRIPTION_BASED_ON_SUBJECT, - RawString.create(ErrorMessages.REPRESENTATION_BASED_ON_SUBJECT_NOT_DEFINED), - None - ) - override inline fun genericFeature( expect: Expect, metaFeature: MetaFeature @@ -107,30 +100,7 @@ object NewFeatureAssertionsBuilder : NewFeatureAssertions { description: String, provider: (T) -> R ): ExtractedFeaturePostStep = - genericFeature(expect, createMetaFeature(expect, description, provider)) - - private fun createMetaFeature( - expect: Expect, - description: String, - provider: (T) -> R - ): MetaFeature = createMetaFeature(expect, Untranslatable(description), provider) - - private fun createMetaFeature( - expect: Expect, - description: Translatable, - provider: (T) -> R - ): MetaFeature { - return expect.maybeSubject.fold({ - MetaFeature( - description, - RawString.create(ErrorMessages.REPRESENTATION_BASED_ON_SUBJECT_NOT_DEFINED), - None - ) - }) { - val prop = provider(it) - MetaFeature(description, prop, Some(prop)) - } - } + genericFeature(expect, ExpectImpl.feature.meta.create(expect, description, provider)) /** * Returns [MetaFeatureBuilder] which helps to create a [MetaFeature]. @@ -143,6 +113,7 @@ object NewFeatureAssertionsBuilder : NewFeatureAssertions { * into an overload ambiguity, then either [p] (for property) or one of the `fN` functions (e.g. [f2] for * a function which expects 2 arguments). */ +//TODO move to API, this could potentially be different per API class MetaFeatureOption(private val expect: Expect) { /** @@ -338,4 +309,43 @@ object MetaFeatureBuilder { fun f5(expect: Expect<*>, f: KFunction5, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5) = MetaFeature(coreFactory.newMethodCallFormatter().formatCall(f.name, arrayOf(a1, a2, a3, a4, a5)), f.invoke(a1, a2, a3, a4, a5)) //@formatter:on + + /** + * creates a [MetaFeature] which is entirely based on the subject (i.e. also the description). + */ + fun createSubjectBased( + expect: Expect, + provider: (T) -> MetaFeature + ): MetaFeature = expect.maybeSubject.fold(this::createFeatureSubjectNotDefined) { provider(it) } + + private fun createFeatureSubjectNotDefined(): MetaFeature = + MetaFeature( + ErrorMessages.DEDSCRIPTION_BASED_ON_SUBJECT, + RawString.create(ErrorMessages.REPRESENTATION_BASED_ON_SUBJECT_NOT_DEFINED), + None + ) + + fun create( + expect: Expect, + description: String, + provider: (T) -> R + ): MetaFeature = create(expect, Untranslatable(description), provider) + + fun create( + expect: Expect, + description: Translatable, + provider: (T) -> R + ): MetaFeature { + return expect.maybeSubject.fold({ + MetaFeature( + description, + RawString.create(ErrorMessages.REPRESENTATION_BASED_ON_SUBJECT_NOT_DEFINED), + None + ) + }) { + val feature = provider(it) + MetaFeature(description, feature, Some(feature)) + } + } + } diff --git a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/changers/FeatureExtractorBuilder.kt b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/changers/FeatureExtractorBuilder.kt index 7c7283f76..8f32d2315 100644 --- a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/changers/FeatureExtractorBuilder.kt +++ b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/changers/FeatureExtractorBuilder.kt @@ -239,31 +239,27 @@ interface FeatureExtractorBuilder { fun withDescription(description: Translatable) /** - * Wraps the given [representation] into a [RawString] and uses it as representation of the subject - * instead of the so far defined representation (which defaults to the subject as such). - */ - @Suppress("PublicApiImplicitType" /* fine withSubjectBasedRepresentation defines it */) - fun withTextRepresentation(representation: String) = withRepresentation(RawString.create(representation)) - - /** - * Uses the given [representation] as representation of the subject in case the is defined instead of - * the so far defined representation (which defaults to the subject as such). + * Wraps the given [textRepresentation] into a [RawString] and uses it as representation of the subject + * instead of the representation that has been defined so far (which defaults to the subject itself). * - * Notice, if you want to use text (e.g. a [String]) as representation, - * then use [withTextRepresentation] instead. + * In case [Expect.maybeSubject] is not defined i.e. [None], then the previous representation is used. */ - @Suppress("PublicApiImplicitType" /* fine withSubjectBasedRepresentation defines it */) - fun withRepresentation(representation: Any) = withSubjectBasedRepresentation { representation } - + fun withRepresentation(textRepresentation: String): Unit = + withRepresentation { RawString.create(textRepresentation) } /** - * Uses the given [representationProvider] which provides the representation for a given subject wrapped in - * [Option] instead of the so far defined representation (which defaults to the subject as such). + * Uses the given [representationProvider] to retrieve a representation which can be based on the current + * subject where this provided representation is used as new representation of the subject + * instead of the representation that has been defined so far (which defaults to the subject itself). * * Notice, if you want to use text (e.g. a [String]) as representation, * then wrap it into a [RawString] via [RawString.create] and pass the [RawString] instead. + * If your text does not include the current subject, then we recommend to use the other overload which expects + * a `String` and does the wrapping for you. + * + * In case [Expect.maybeSubject] is not defined i.e. [None], then the previous representation is used. */ - fun withSubjectBasedRepresentation(representationProvider: (R) -> Any) + fun withRepresentation(representationProvider: (R) -> Any) companion object { fun createAndBuild(configuration: OptionsChooser.() -> Unit): FeatureOptions = diff --git a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/changers/SubjectChangerBuilder.kt b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/changers/SubjectChangerBuilder.kt index b16be204f..3d902db27 100644 --- a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/changers/SubjectChangerBuilder.kt +++ b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/changers/SubjectChangerBuilder.kt @@ -31,7 +31,7 @@ interface SubjectChangerBuilder { /** * Entry point to use the [SubjectChangerBuilder]. */ - fun create(originalAssertionContainer: Expect): KindStep = KindStepImpl(originalAssertionContainer) + fun create(expect: Expect): KindStep = KindStepImpl(expect) @Deprecated("Do no longer use Assert, use Expect instead - this method was introduced in 0.9.0 to ease the migration from Assert to Expect; will be removed with 1.0.0") @Suppress("DEPRECATION", "DeprecatedCallableAddReplaceWith") @@ -75,7 +75,7 @@ interface SubjectChangerBuilder { /** * The previously specified assertion container to which the new [Expect] will delegate assertion checking. */ - val originalAssertionContainer: Expect + val originalExpect: Expect /** @@ -85,7 +85,7 @@ interface SubjectChangerBuilder { * @return The newly created [Expect] for the new subject. */ fun unreported(transformation: (T) -> R): Expect = - subjectChanger.unreported(originalAssertionContainer, transformation) + subjectChanger.unreported(originalExpect, transformation) /** * Entry point of the building process to not only change the subject but also report the change in reporting. @@ -107,11 +107,11 @@ interface SubjectChangerBuilder { /** * The previously specified assertion container to which the new [Expect] will delegate assertion checking. */ - val originalAssertionContainer: Expect + val originalExpect: Expect /** * Uses [DescriptionAnyAssertion.IS_A] as description of the change, - * the given [subType] as representation and tries to perform a down-cast of [originalAssertionContainer]'s + * the given [subType] as representation and tries to perform a down-cast of [originalExpect]'s * [Expect.maybeSubject] to the given type [TSub] */ //TODO once kotlin supports to have type parameters as upper bounds of another type parameter next to `: Any` we should restrict TSub : T & Any @@ -161,7 +161,7 @@ interface SubjectChangerBuilder { /** * The previously specified assertion container to which the new [Expect] will delegate assertion checking. */ - val originalAssertionContainer: Expect + val originalExpect: Expect /** * The previously specified description which describes the kind of subject change. diff --git a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/changers/impl/featureextractor/OptionsChooserImpl.kt b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/changers/impl/featureextractor/OptionsChooserImpl.kt index 268d77a3b..3b716b5d7 100644 --- a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/changers/impl/featureextractor/OptionsChooserImpl.kt +++ b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/changers/impl/featureextractor/OptionsChooserImpl.kt @@ -12,7 +12,7 @@ class OptionsChooserImpl : FeatureExtractorBuilder.OptionsChooser { this.description = description } - override fun withSubjectBasedRepresentation(representationProvider: (R) -> Any) { + override fun withRepresentation(representationProvider: (R) -> Any) { this.representationInsteadOfFeature = representationProvider } diff --git a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/changers/impl/featureextractor/defaultImpls.kt b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/changers/impl/featureextractor/defaultImpls.kt index 67f000595..c45509e06 100644 --- a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/changers/impl/featureextractor/defaultImpls.kt +++ b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/changers/impl/featureextractor/defaultImpls.kt @@ -4,6 +4,7 @@ import ch.tutteli.atrium.core.None import ch.tutteli.atrium.core.Option import ch.tutteli.atrium.core.Some import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.creating.FeatureExpect import ch.tutteli.atrium.domain.builders.creating.changers.FeatureExtractorBuilder import ch.tutteli.atrium.domain.builders.creating.changers.FeatureOptions import ch.tutteli.atrium.domain.creating.changers.ExtractedFeaturePostStep @@ -68,13 +69,13 @@ class FinalStepImpl( extractAndApply = { assertionCreator -> extractIt(this, Some(assertionCreator)) } ) - private fun extractIt(expect: Expect, subAssertions: Option.() -> Unit>) = + private fun extractIt(expect: Expect, maybeSubAssertions: Option.() -> Unit>): FeatureExpect = featureExtractor.extract( expect, featureOptions?.description ?: featureExtractionStep.description, featureExtractionStep.representationForFailure, featureExtraction, - subAssertions, + maybeSubAssertions, featureOptions?.representationInsteadOfFeature ) } diff --git a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/changers/impl/subjectchanger/defaultImpls.kt b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/changers/impl/subjectchanger/defaultImpls.kt index 81697ef87..5e54bd780 100644 --- a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/changers/impl/subjectchanger/defaultImpls.kt +++ b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/changers/impl/subjectchanger/defaultImpls.kt @@ -13,11 +13,11 @@ import ch.tutteli.atrium.reporting.RawString import ch.tutteli.atrium.reporting.translating.Translatable class KindStepImpl( - override val originalAssertionContainer: Expect + override val originalExpect: Expect ) : SubjectChangerBuilder.KindStep { override fun reportBuilder(): SubjectChangerBuilder.DescriptionRepresentationStep = - SubjectChangerBuilder.DescriptionRepresentationStep.create(originalAssertionContainer) + SubjectChangerBuilder.DescriptionRepresentationStep.create(originalExpect) } @Suppress("DEPRECATION") @@ -26,21 +26,21 @@ class DeprecatedKindStepImpl( ) : SubjectChangerBuilder.DeprecatedKindStep class DescriptionRepresentationStepImpl( - override val originalAssertionContainer: Expect + override val originalExpect: Expect ) : SubjectChangerBuilder.DescriptionRepresentationStep { override fun withDescriptionAndRepresentation( description: Translatable, representation: Any? ): SubjectChangerBuilder.TransformationStep = SubjectChangerBuilder.TransformationStep.create( - originalAssertionContainer, + originalExpect, description, representation ?: RawString.NULL ) } class TransformationStepImpl( - override val originalAssertionContainer: Expect, + override val originalExpect: Expect, override val description: Translatable, override val representation: Any ) : SubjectChangerBuilder.TransformationStep { @@ -72,7 +72,7 @@ class FinalStepImpl( ) : SubjectChangerBuilder.FinalStep { override fun build(): ChangedSubjectPostStep = - ChangedSubjectPostStep(transformationStep.originalAssertionContainer, + ChangedSubjectPostStep(transformationStep.originalExpect, transform = { transformIt(this, None) }, transformAndApply = { assertionCreator -> transformIt(this, Some(assertionCreator)) } ) diff --git a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/throwableAssertionsBuilders.kt b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/throwableAssertionsBuilders.kt index 2e278e0da..2dd9be25c 100644 --- a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/throwableAssertionsBuilders.kt +++ b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/throwableAssertionsBuilders.kt @@ -4,7 +4,10 @@ package ch.tutteli.atrium.domain.builders.creating import ch.tutteli.atrium.core.polyfills.loadSingleService import ch.tutteli.atrium.creating.AssertionPlant +import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.domain.creating.ThrowableAssertions +import ch.tutteli.atrium.domain.creating.changers.ChangedSubjectPostStep +import ch.tutteli.atrium.domain.creating.listAssertions import ch.tutteli.atrium.domain.creating.throwable.thrown.ThrowableThrown import ch.tutteli.atrium.domain.creating.throwable.thrown.creators.ThrowableThrownAssertions import ch.tutteli.atrium.domain.creating.throwable.thrown.creators.throwableThrownAssertions @@ -21,6 +24,13 @@ import kotlin.reflect.KClass */ object ThrowableAssertionsBuilder : ThrowableAssertions { + override inline fun cause( + expect: Expect, + expectedType: KClass + ): ChangedSubjectPostStep = + throwableAssertions.cause(expect, expectedType) + + @Deprecated( "Use Expect instead; will be removed with 1.0.0", ReplaceWith( diff --git a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/reporting/ExpectBuilder.kt b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/reporting/ExpectBuilder.kt index da812737a..7cf9404b8 100644 --- a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/reporting/ExpectBuilder.kt +++ b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/reporting/ExpectBuilder.kt @@ -1,5 +1,6 @@ package ch.tutteli.atrium.domain.builders.reporting +import ch.tutteli.atrium.core.None import ch.tutteli.atrium.core.Option import ch.tutteli.atrium.core.Some import ch.tutteli.atrium.creating.Expect @@ -71,13 +72,13 @@ interface ExpectBuilder { * * The function usually start with `with...` and are sometimes overloaded to ease the configuration. */ - fun withOptions(configuration: OptionsChooser.() -> Unit): FinalStep = + fun withOptions(configuration: OptionsChooser.() -> Unit): FinalStep = withOptions(ExpectOptions(configuration)) /** * Uses the given [expectOptions]. */ - fun withOptions(expectOptions: ExpectOptions): FinalStep + fun withOptions(expectOptions: ExpectOptions): FinalStep /** * States explicitly that no optional [ExpectOptions] are defined, which means, `build` will create @@ -102,7 +103,7 @@ interface ExpectBuilder { * * Calling multiple times the same method overrides the previously defined value. */ - interface OptionsChooser { + interface OptionsChooser { /** * Wraps the given [verb] into an [Untranslatable] and passes it to the overload @@ -120,29 +121,27 @@ interface ExpectBuilder { fun withVerb(verb: Translatable) /** - * Wraps the given [representation] into a [RawString] and uses it as representation of the subject - * instead of the so far defined representation (which defaults to the subject as such). + * Wraps the given [textRepresentation] into a [RawString] and uses it as representation of the subject + * instead of the representation that has been defined so far (which defaults to the subject itself). + * + * In case [Expect.maybeSubject] is not defined i.e. [None], then the previous representation is used. */ - @Suppress("PublicApiImplicitType" /* fine withRepresentation defines it */) - fun withTextRepresentation(representation: String) = withRepresentation(RawString.create(representation)) + fun withRepresentation(textRepresentation: String): Unit = + withRepresentation { RawString.create(textRepresentation) } /** - * Uses the given [representation] as representation of the subject instead of using the subject as such to - * represent itself. + * Uses the given [representationProvider] to retrieve a representation which can be based on the current + * subject where it is used as new representation of the subject + * instead of the representation that has been defined so far (which defaults to the subject itself). * * Notice, if you want to use text (e.g. a [String]) as representation, * then wrap it into a [RawString] via [RawString.create] and pass the [RawString] instead. - */ - fun withRepresentation(representation: Any) - - /** - * Use the given [representation] as custom representation for `null`. + * If your text does not include the current subject, then we recommend to use the other overload which expects + * a `String` and does the wrapping for you. * - * Notice, if you want to use text (e.g. a [String]) as representation, - * then wrap it into a [RawString] via [RawString.create] and pass the [RawString] instead. + * In case [Expect.maybeSubject] is not defined i.e. [None], then the previous representation is used. */ - //TODO #279 remove - fun withNullRepresentation(representation: Any) + fun withRepresentation(representationProvider: (T) -> Any) /** * Uses the given [reporter] instead of the default reporter. @@ -150,8 +149,8 @@ interface ExpectBuilder { fun withReporter(reporter: Reporter) companion object { - fun createAndBuild(configuration: OptionsChooser.() -> Unit): ExpectOptions = - OptionsChooserImpl().apply(configuration).build() + fun createAndBuild(configuration: OptionsChooser.() -> Unit): ExpectOptions = + OptionsChooserImpl().apply(configuration).build() } } @@ -174,7 +173,7 @@ interface ExpectBuilder { /** * Either the previously specified [ExpectOptions] or `null`. */ - val options: ExpectOptions? + val options: ExpectOptions? /** * Creates a new [Expect] based on the previously defined maybeOptions. @@ -185,7 +184,7 @@ interface ExpectBuilder { fun create( maybeSubject: Option, assertionVerb: Translatable, - options: ExpectOptions? + options: ExpectOptions? ): FinalStep = FinalStepImpl(maybeSubject, assertionVerb, options) } } @@ -195,29 +194,30 @@ interface ExpectBuilder { * Additional (non-mandatory) options for the [ExpectBuilder] to create an [Expect]. * * @property assertionVerb Defines a custom assertion verb if not null. - * @property representation Defines a custom representation for the subject if not null. + * @property representationInsteadOfSubject Defines a custom representation based on a present subject if not null. * @property reporter Defines a custom reporter if not null. */ -data class ExpectOptions( +data class ExpectOptions( val assertionVerb: Translatable? = null, - val representation: Any? = null, + val representationInsteadOfSubject: ((T) -> Any)? = null, val reporter: Reporter? = null ) { /** * Merges the given [options] with this object creating a new [ExpectOptions] * where defined properties in [options] will have precedence over properties defined in this instance. * - * For instance, this object has defined [representation] (meaning it is [Some]) and the given [options] as well, - * then the resulting [ExpectOptions] will have the [representation] of [options]. + * For instance, this object has defined [representationInsteadOfSubject] (meaning it is not `null`) and + * the given [options] as well, then the resulting [ExpectOptions] will have the + * [representationInsteadOfSubject] of [options]. */ - fun merge(options: ExpectOptions): ExpectOptions = + fun merge(options: ExpectOptions): ExpectOptions = ExpectOptions( options.assertionVerb ?: assertionVerb, - options.representation ?: representation, + options.representationInsteadOfSubject ?: representationInsteadOfSubject, options.reporter ?: reporter ) } @Suppress("FunctionName") -fun ExpectOptions(configuration: ExpectBuilder.OptionsChooser.() -> Unit): ExpectOptions = +fun ExpectOptions(configuration: ExpectBuilder.OptionsChooser.() -> Unit): ExpectOptions = ExpectBuilder.OptionsChooser.createAndBuild(configuration) diff --git a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/reporting/impl/verb/OptionsChooserImpl.kt b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/reporting/impl/verb/OptionsChooserImpl.kt index cac8af1dc..9789d677d 100644 --- a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/reporting/impl/verb/OptionsChooserImpl.kt +++ b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/reporting/impl/verb/OptionsChooserImpl.kt @@ -5,28 +5,23 @@ import ch.tutteli.atrium.domain.builders.reporting.ExpectOptions import ch.tutteli.atrium.reporting.Reporter import ch.tutteli.atrium.reporting.translating.Translatable -class OptionsChooserImpl : ExpectBuilder.OptionsChooser { +class OptionsChooserImpl : ExpectBuilder.OptionsChooser { private var description: Translatable? = null - private var representation: Any? = null - private var nullRepresentation: Any? = null + private var representationInsteadOfSubject: ((T) -> Any)? = null private var reporter: Reporter? = null override fun withVerb(verb: Translatable) { this.description = verb } - override fun withRepresentation(representation: Any) { - this.representation = representation - } - - override fun withNullRepresentation(representation: Any) { - this.nullRepresentation = representation + override fun withRepresentation(representationProvider: (T) -> Any) { + this.representationInsteadOfSubject = representationProvider } override fun withReporter(reporter: Reporter) { this.reporter = reporter } - fun build(): ExpectOptions = ExpectOptions(description, representation, reporter) + fun build(): ExpectOptions = ExpectOptions(description, representationInsteadOfSubject, reporter) } diff --git a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/reporting/impl/verb/defaultImpls.kt b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/reporting/impl/verb/defaultImpls.kt index 8182c142d..66c73f681 100644 --- a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/reporting/impl/verb/defaultImpls.kt +++ b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/reporting/impl/verb/defaultImpls.kt @@ -22,17 +22,17 @@ class OptionsStepImpl( override val assertionVerb: Translatable ) : ExpectBuilder.OptionsStep { - override fun withOptions(expectOptions: ExpectOptions): ExpectBuilder.FinalStep = toFinalStep(expectOptions) + override fun withOptions(expectOptions: ExpectOptions): ExpectBuilder.FinalStep = toFinalStep(expectOptions) override fun withoutOptions(): ExpectBuilder.FinalStep = toFinalStep(null) - private fun toFinalStep(expectOptions: ExpectOptions?) = + private fun toFinalStep(expectOptions: ExpectOptions?) = ExpectBuilder.FinalStep.create(maybeSubject, assertionVerb, expectOptions) } class FinalStepImpl( override val maybeSubject: Option, override val assertionVerb: Translatable, - override val options: ExpectOptions? + override val options: ExpectOptions? ) : ExpectBuilder.FinalStep { override fun build(): RootExpect = @@ -40,7 +40,10 @@ class FinalStepImpl( ReportingAssertionContainer.AssertionCheckerDecorator.create( options?.assertionVerb ?: assertionVerb, maybeSubject, - options?.representation ?: maybeSubject.getOrElse { + options?.representationInsteadOfSubject?.let { provider -> + this.maybeSubject.fold({ null }) { provider(it) } + } ?: maybeSubject.getOrElse { + // a RootExpect without a defined subject is almost certain a bug RawString.create(SHOULD_NOT_BE_SHOWN_TO_THE_USER_BUG) }, coreFactory.newThrowingAssertionChecker(options?.reporter ?: reporter) diff --git a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/utils/VarArgHelper.kt b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/utils/VarArgHelper.kt index a73e9c06c..8a37d7fd8 100644 --- a/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/utils/VarArgHelper.kt +++ b/domain/builders/atrium-domain-builders-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/utils/VarArgHelper.kt @@ -11,6 +11,7 @@ interface VarArgHelper { * The first argument in the argument list `T, vararg T` */ val expected: T + /** * The second argument in the argument list `T, vararg T` */ @@ -19,10 +20,21 @@ interface VarArgHelper { /** * Creates an [ArgumentMapperBuilder] which allows to map [expected] and [otherExpected]. */ - val mapArguments get() = ArgumentMapperBuilder(expected, otherExpected) + val mapArguments: ArgumentMapperBuilder get() = ArgumentMapperBuilder(expected, otherExpected) /** * Returns the arguments as [List]. */ fun toList(): List = expected glue otherExpected } + +/** + * Transforms the given [iterable] to `Pair>` with the intend that it can be easily used for a function + * requiring `T, vararg T` + * + * @throws IllegalArgumentException in case the iterable is empty. + */ +inline fun toVarArg(iterable: Iterable): Pair> { + require(iterable.iterator().hasNext()) { "Iterable without elements are not allowed for this function." } + return iterable.first() to iterable.drop(1).toTypedArray() +} diff --git a/domain/builders/atrium-domain-builders-jvm/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/PathAssertionsBuilder.kt b/domain/builders/atrium-domain-builders-jvm/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/PathAssertionsBuilder.kt index 6a092915b..d4cf5188c 100644 --- a/domain/builders/atrium-domain-builders-jvm/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/PathAssertionsBuilder.kt +++ b/domain/builders/atrium-domain-builders-jvm/src/main/kotlin/ch/tutteli/atrium/domain/builders/creating/PathAssertionsBuilder.kt @@ -48,6 +48,9 @@ object PathAssertionsBuilder : PathAssertions { override inline fun parent(expect: Expect) = pathAssertions.parent(expect) + override inline fun resolve(expect: Expect, other: String) = + pathAssertions.resolve(expect, other) + override inline fun isReadable(expect: Expect) = pathAssertions.isReadable(expect) diff --git a/domain/builders/extensions/kotlin_1_3/atrium-domain-builders-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/kotlin_1_3/creating/ResultAssertionsBuilder.kt b/domain/builders/extensions/kotlin_1_3/atrium-domain-builders-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/kotlin_1_3/creating/ResultAssertionsBuilder.kt index 86deda1c8..11cc08716 100644 --- a/domain/builders/extensions/kotlin_1_3/atrium-domain-builders-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/kotlin_1_3/creating/ResultAssertionsBuilder.kt +++ b/domain/builders/extensions/kotlin_1_3/atrium-domain-builders-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/domain/builders/kotlin_1_3/creating/ResultAssertionsBuilder.kt @@ -16,12 +16,9 @@ import kotlin.reflect.KClass */ object ResultAssertionsBuilder : ResultAssertions { - override inline fun > isSuccess( - assertionContainer: Expect - ): ExtractedFeaturePostStep = resultAssertions.isSuccess(assertionContainer) + override inline fun > isSuccess(expect: Expect): ExtractedFeaturePostStep = + resultAssertions.isSuccess(expect) - override fun isFailure( - assertionContainer: Expect>, - expectedType: KClass - ) = resultAssertions.isFailure(assertionContainer, expectedType) + override fun isFailure(expect: Expect>, expectedType: KClass) = + resultAssertions.isFailure(expect, expectedType) } diff --git a/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/changers/extractFeature.kt b/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/changers/extractFeature.kt index 2f02637c5..6e4a2569e 100644 --- a/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/changers/extractFeature.kt +++ b/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/changers/extractFeature.kt @@ -14,6 +14,7 @@ import ch.tutteli.atrium.domain.builders.ExpectImpl import ch.tutteli.atrium.domain.builders.creating.collectors.collectAssertions import ch.tutteli.atrium.reporting.translating.Translatable +@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */) @UseExperimental(ExperimentalExpectConfig::class) fun _extractFeature( originalAssertionContainer: Expect, diff --git a/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/featureAssertions.kt b/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/featureAssertions.kt index 34f9f16c9..fb9f76289 100644 --- a/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/featureAssertions.kt +++ b/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/featureAssertions.kt @@ -12,6 +12,6 @@ fun _genericFeature(expect: Expect, metaFeature: MetaFeature): Extr .withDescription(metaFeature.description) .withRepresentationForFailure(representation) .withFeatureExtraction { metaFeature.maybeSubject } - .withOptions { withRepresentation(representation) } + .withOptions { withRepresentation { representation } } .build() } diff --git a/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/fun0Assertions.kt b/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/fun0Assertions.kt index 1904ff008..e2d5e9113 100644 --- a/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/fun0Assertions.kt +++ b/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/fun0Assertions.kt @@ -1,7 +1,7 @@ package ch.tutteli.atrium.domain.robstoll.lib.creating import ch.tutteli.atrium.api.fluent.en_GB.ExperimentalWithOptions -import ch.tutteli.atrium.api.fluent.en_GB.withOptions +import ch.tutteli.atrium.api.fluent.en_GB.withRepresentation import ch.tutteli.atrium.core.Either import ch.tutteli.atrium.core.Left import ch.tutteli.atrium.core.Right @@ -14,6 +14,7 @@ import ch.tutteli.atrium.reporting.reporter import ch.tutteli.atrium.translations.DescriptionFunLikeAssertion.* import kotlin.reflect.KClass +@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */) @UseExperimental(ExperimentalWithOptions::class) fun _isThrowing( expect: Expect Any?>, @@ -30,7 +31,7 @@ fun _isThrowing( ) } .getExpectOfFeature() - .withOptions { withSubjectBasedRepresentation { it ?: RawString.create(NO_EXCEPTION_OCCURRED) } } + .withRepresentation { it ?: RawString.create(NO_EXCEPTION_OCCURRED) } .let { ExpectImpl.changeSubject(it).reportBuilder() .downCastTo(expectedType) diff --git a/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/throwableAssertions.kt b/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/throwableAssertions.kt new file mode 100644 index 000000000..731c4e842 --- /dev/null +++ b/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/throwableAssertions.kt @@ -0,0 +1,27 @@ +package ch.tutteli.atrium.domain.robstoll.lib.creating + +import ch.tutteli.atrium.api.fluent.en_GB.ExperimentalWithOptions +import ch.tutteli.atrium.api.fluent.en_GB.withRepresentation +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.domain.builders.ExpectImpl +import ch.tutteli.atrium.domain.creating.changers.ChangedSubjectPostStep +import ch.tutteli.atrium.domain.robstoll.lib.creating.throwable.thrown.creators.ThrowableThrownFailureHandler +import ch.tutteli.atrium.reporting.RawString +import ch.tutteli.atrium.translations.DescriptionThrowableAssertion +import kotlin.reflect.KClass + +@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */) +@UseExperimental(ExperimentalWithOptions::class) +fun _cause( + expect: Expect, + expectedType: KClass +): ChangedSubjectPostStep = + ExpectImpl.feature.manualFeature(expect, DescriptionThrowableAssertion.OCCURRED_EXCEPTION_CAUSE) { cause } + .getExpectOfFeature() + .withRepresentation { it ?: RawString.create(DescriptionThrowableAssertion.NOT_CAUSED) } + .let { + ExpectImpl.changeSubject(it).reportBuilder() + .downCastTo(expectedType) + .withFailureHandler(ThrowableThrownFailureHandler(maxStackTrace = 7)) + .build() + } diff --git a/domain/robstoll-lib/atrium-domain-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/assertions/LazyThreadUnsafeAssertionGroupSpec.kt b/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/test/kotlin/ch/tutteli/assertions/LazyThreadUnsafeAssertionGroupSpec.kt similarity index 71% rename from domain/robstoll-lib/atrium-domain-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/assertions/LazyThreadUnsafeAssertionGroupSpec.kt rename to domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/test/kotlin/ch/tutteli/assertions/LazyThreadUnsafeAssertionGroupSpec.kt index f8170c4f6..f38d14642 100644 --- a/domain/robstoll-lib/atrium-domain-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/assertions/LazyThreadUnsafeAssertionGroupSpec.kt +++ b/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/test/kotlin/ch/tutteli/assertions/LazyThreadUnsafeAssertionGroupSpec.kt @@ -5,10 +5,8 @@ import ch.tutteli.atrium.api.fluent.en_GB.toBe import ch.tutteli.atrium.api.verbs.internal.expect import ch.tutteli.atrium.domain.builders.AssertImpl import ch.tutteli.atrium.domain.robstoll.lib.assertions.LazyThreadUnsafeAssertionGroup -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.describe -import org.jetbrains.spek.api.dsl.it -import org.jetbrains.spek.api.dsl.on +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.describe object LazyThreadUnsafeAssertionGroupSpec : Spek({ @@ -26,15 +24,19 @@ object LazyThreadUnsafeAssertionGroupSpec : Spek({ .withAssertion(assertion) .build() } - test("does not evaluate anything") { + it("does not evaluate anything") { expect(callingCount).toBe(0) } - test("adding it to a list does not evaluate anything") { + it("adding it to a list does not evaluate anything") { listOf(testee) expect(callingCount).toBe(0) } - on("invoking ${testee::holds.name}") { - val resultHolds = testee.holds() + context("invoking ${testee::holds.name}") { + var resultHolds = true + + it("execute it") { + resultHolds = testee.holds() + } it("evaluates it") { expect(callingCount).toBe(1) @@ -45,9 +47,12 @@ object LazyThreadUnsafeAssertionGroupSpec : Spek({ } } - on("invoking ${testee::holds.name} and then ${testee::assertions.name}") { - val resultHolds = testee.holds() - val resultAssertions = testee.assertions + context("invoking ${testee::holds.name} and then ${testee::assertions.name}") { + var resultHolds = true + + it("execute it") { + resultHolds = testee.holds() + } it("evaluates it only once") { expect(callingCount).toBe(1) @@ -58,7 +63,7 @@ object LazyThreadUnsafeAssertionGroupSpec : Spek({ } it("returns the ${AssertionGroup::assertions.name} of the underlying ${AssertionGroup::class.simpleName}") { - expect(resultAssertions).containsExactly(assertion) + expect(testee.assertions).containsExactly(assertion) } } } diff --git a/domain/robstoll-lib/atrium-domain-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/assertions/LazyThreadUnsafeBasicAssertionSpec.kt b/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/test/kotlin/ch/tutteli/assertions/LazyThreadUnsafeBasicAssertionSpec.kt similarity index 68% rename from domain/robstoll-lib/atrium-domain-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/assertions/LazyThreadUnsafeBasicAssertionSpec.kt rename to domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/test/kotlin/ch/tutteli/assertions/LazyThreadUnsafeBasicAssertionSpec.kt index 859b9f220..3bfe78a14 100644 --- a/domain/robstoll-lib/atrium-domain-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/assertions/LazyThreadUnsafeBasicAssertionSpec.kt +++ b/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/test/kotlin/ch/tutteli/assertions/LazyThreadUnsafeBasicAssertionSpec.kt @@ -4,10 +4,8 @@ import ch.tutteli.atrium.api.fluent.en_GB.toBe import ch.tutteli.atrium.api.verbs.internal.expect import ch.tutteli.atrium.domain.builders.AssertImpl import ch.tutteli.atrium.domain.robstoll.lib.assertions.LazyThreadUnsafeBasicAssertion -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.describe -import org.jetbrains.spek.api.dsl.it -import org.jetbrains.spek.api.dsl.on +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.describe object LazyThreadUnsafeBasicAssertionSpec : Spek({ @@ -17,15 +15,18 @@ object LazyThreadUnsafeBasicAssertionSpec : Spek({ ++callingCount AssertImpl.builder.descriptive.failing.withDescriptionAndRepresentation("a", 2).build() } - test("does not evaluate anything") { + it("does not evaluate anything") { expect(callingCount).toBe(0) } - test("adding it to a list does not evaluate anything") { + it("adding it to a list does not evaluate anything") { listOf(testee) expect(callingCount).toBe(0) } - on("invoking ${testee::holds.name}") { - val resultHolds = testee.holds() + context("invoking ${testee::holds.name}") { + var resultHolds = true + it("execute it") { + resultHolds = testee.holds() + } it("evaluates it") { expect(callingCount).toBe(1) @@ -36,9 +37,12 @@ object LazyThreadUnsafeBasicAssertionSpec : Spek({ } } - on("invoking ${testee::holds.name} and then ${testee::representation.name}") { - val resultHolds = testee.holds() - val resultExpected = testee.representation + context("invoking ${testee::holds.name} and then ${testee::representation.name}") { + var resultHolds = true + + it("execute it") { + resultHolds = testee.holds() + } it("evaluates it only once") { expect(callingCount).toBe(1) @@ -49,7 +53,7 @@ object LazyThreadUnsafeBasicAssertionSpec : Spek({ } it("returns ${DescriptiveAssertion::representation.name} of the underlying ${DescriptiveAssertion::class.simpleName}") { - expect(resultExpected).toBe(2) + expect(testee.representation).toBe(2) } } } diff --git a/domain/robstoll-lib/atrium-domain-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/creating/charsequence/contains/searchers/CharSequenceContainsIndexSearcherSpec.kt b/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/test/kotlin/ch/tutteli/atrium/creating/charsequence/contains/searchers/CharSequenceContainsIndexSearcherSpec.kt similarity index 66% rename from domain/robstoll-lib/atrium-domain-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/creating/charsequence/contains/searchers/CharSequenceContainsIndexSearcherSpec.kt rename to domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/test/kotlin/ch/tutteli/atrium/creating/charsequence/contains/searchers/CharSequenceContainsIndexSearcherSpec.kt index 2f659f031..f1e77adb0 100644 --- a/domain/robstoll-lib/atrium-domain-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/creating/charsequence/contains/searchers/CharSequenceContainsIndexSearcherSpec.kt +++ b/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/test/kotlin/ch/tutteli/atrium/creating/charsequence/contains/searchers/CharSequenceContainsIndexSearcherSpec.kt @@ -4,13 +4,13 @@ import ch.tutteli.atrium.api.fluent.en_GB.contains import ch.tutteli.atrium.api.fluent.en_GB.exactly import ch.tutteli.atrium.api.fluent.en_GB.value import ch.tutteli.atrium.api.verbs.internal.expect -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.context +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.describe object CharSequenceContainsIndexSearcherSpec : Spek({ - context("text 'aaaa'") { - test("search for 'aa' finds 3 hits since we want non disjoint matches") { + describe("text 'aaaa'") { + it("search for 'aa' finds 3 hits since we want non disjoint matches") { expect("aaaa").contains.exactly(3).value("aa") } } diff --git a/domain/robstoll-lib/atrium-domain-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/creating/charsequence/contains/searchers/CharSequenceContainsRegexSearcherSpec.kt b/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/test/kotlin/ch/tutteli/atrium/creating/charsequence/contains/searchers/CharSequenceContainsRegexSearcherSpec.kt similarity index 62% rename from domain/robstoll-lib/atrium-domain-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/creating/charsequence/contains/searchers/CharSequenceContainsRegexSearcherSpec.kt rename to domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/test/kotlin/ch/tutteli/atrium/creating/charsequence/contains/searchers/CharSequenceContainsRegexSearcherSpec.kt index f4931d388..45b1d2e5c 100644 --- a/domain/robstoll-lib/atrium-domain-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/creating/charsequence/contains/searchers/CharSequenceContainsRegexSearcherSpec.kt +++ b/domain/robstoll-lib/atrium-domain-robstoll-lib-common/src/test/kotlin/ch/tutteli/atrium/creating/charsequence/contains/searchers/CharSequenceContainsRegexSearcherSpec.kt @@ -4,16 +4,16 @@ import ch.tutteli.atrium.api.fluent.en_GB.contains import ch.tutteli.atrium.api.fluent.en_GB.exactly import ch.tutteli.atrium.api.fluent.en_GB.regex import ch.tutteli.atrium.api.verbs.internal.expect -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.context +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.describe object CharSequenceContainsRegexSearcherSpec : Spek({ - context("text 'aaaa'") { - test("search for 'aa' finds 3 hits since we want non disjoint matches") { + describe("text 'aaaa'") { + it("search for 'aa' finds 3 hits since we want non disjoint matches") { expect("aaaa").contains.exactly(3).regex("aa") } - test("search for 'aa?' finds 4 hits since we want non disjoint matches") { + it("search for 'aa?' finds 4 hits since we want non disjoint matches") { expect("aaaa").contains.exactly(4).regex("aa?") } } diff --git a/domain/robstoll-lib/atrium-domain-robstoll-lib-js/build.gradle b/domain/robstoll-lib/atrium-domain-robstoll-lib-js/build.gradle index cd7fa2123..336efd556 100644 --- a/domain/robstoll-lib/atrium-domain-robstoll-lib-js/build.gradle +++ b/domain/robstoll-lib/atrium-domain-robstoll-lib-js/build.gradle @@ -14,5 +14,5 @@ dependencies { // TODO remove with 1.0.0 implementation prefixedProject('api-cc-en_GB-js') - testImplementation prefixedProject('verbs-internal-js') + testImplementation prefixedProject('specs-js') } diff --git a/domain/robstoll-lib/atrium-domain-robstoll-lib-jvm/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/pathAssertions.kt b/domain/robstoll-lib/atrium-domain-robstoll-lib-jvm/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/pathAssertions.kt index 0b63f5670..7522a8e53 100644 --- a/domain/robstoll-lib/atrium-domain-robstoll-lib-jvm/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/pathAssertions.kt +++ b/domain/robstoll-lib/atrium-domain-robstoll-lib-jvm/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/lib/creating/pathAssertions.kt @@ -395,5 +395,8 @@ fun _parent(expect: Expect): ExtractedFeaturePostStep = .withoutOptions() .build() +fun _resolve(expect: Expect, other: String): ExtractedFeaturePostStep = + ExpectImpl.feature.f1(expect, Path::resolve, other) + fun _extension(expect: Expect): ExtractedFeaturePostStep = ExpectImpl.feature.manualFeature(expect, EXTENSION) { extension } diff --git a/domain/robstoll-lib/extensions/kotlin_1_3/atrium-domain-robstoll-lib-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/domain.robstoll.lib.kotlin_1_3/creating/resultAssertions.kt b/domain/robstoll-lib/extensions/kotlin_1_3/atrium-domain-robstoll-lib-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/domain.robstoll.lib.kotlin_1_3/creating/resultAssertions.kt index 0d0ac745d..21c72c5fb 100644 --- a/domain/robstoll-lib/extensions/kotlin_1_3/atrium-domain-robstoll-lib-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/domain.robstoll.lib.kotlin_1_3/creating/resultAssertions.kt +++ b/domain/robstoll-lib/extensions/kotlin_1_3/atrium-domain-robstoll-lib-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/domain.robstoll.lib.kotlin_1_3/creating/resultAssertions.kt @@ -1,7 +1,7 @@ package ch.tutteli.atrium.domain.robstoll.lib.kotlin_1_3.creating import ch.tutteli.atrium.api.fluent.en_GB.ExperimentalWithOptions -import ch.tutteli.atrium.api.fluent.en_GB.withOptions +import ch.tutteli.atrium.api.fluent.en_GB.withRepresentation import ch.tutteli.atrium.core.Option import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.domain.builders.ExpectImpl @@ -24,16 +24,17 @@ fun > _isSuccess(expect: Expect): ExtractedFeaturePostStep _isFailure( - assertionContainer: Expect>, + expect: Expect>, expectedType: KClass ): ChangedSubjectPostStep { val throwableExpect = ExpectImpl.feature - .manualFeature(assertionContainer, EXCEPTION) { exceptionOrNull() } + .manualFeature(expect, EXCEPTION) { exceptionOrNull() } .getExpectOfFeature() - .withOptions { withSubjectBasedRepresentation { it ?: RawString.create(IS_NOT_FAILURE) } } + .withRepresentation { it ?: RawString.create(IS_NOT_FAILURE) } return ExpectImpl.changeSubject(throwableExpect).reportBuilder() .downCastTo(expectedType) diff --git a/domain/robstoll/atrium-domain-robstoll-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/creating/ThrowableAssertionsImpl.kt b/domain/robstoll/atrium-domain-robstoll-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/creating/ThrowableAssertionsImpl.kt index e27ef97d7..f22ced9ec 100644 --- a/domain/robstoll/atrium-domain-robstoll-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/creating/ThrowableAssertionsImpl.kt +++ b/domain/robstoll/atrium-domain-robstoll-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/creating/ThrowableAssertionsImpl.kt @@ -1,12 +1,22 @@ package ch.tutteli.atrium.domain.robstoll.creating +import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.domain.creating.ThrowableAssertions +import ch.tutteli.atrium.domain.creating.changers.ChangedSubjectPostStep +import ch.tutteli.atrium.domain.robstoll.lib.creating._cause import ch.tutteli.atrium.reporting.Reporter import ch.tutteli.atrium.reporting.translating.Translatable +import kotlin.reflect.KClass -//TODO remove with 1.0.0 if there aren't any non-deprecated functions added class ThrowableAssertionsImpl : ThrowableAssertions { + override fun cause( + expect: Expect, + expectedType: KClass + ): ChangedSubjectPostStep = + _cause(expect, expectedType) + + @Suppress("OverridingDeprecatedMember", "DEPRECATION") override fun thrownBuilder( assertionVerb: Translatable, diff --git a/domain/robstoll/atrium-domain-robstoll-jvm/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/creating/PathAssertionsImpl.kt b/domain/robstoll/atrium-domain-robstoll-jvm/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/creating/PathAssertionsImpl.kt index 5c4009279..6cbb9bcc0 100644 --- a/domain/robstoll/atrium-domain-robstoll-jvm/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/creating/PathAssertionsImpl.kt +++ b/domain/robstoll/atrium-domain-robstoll-jvm/src/main/kotlin/ch/tutteli/atrium/domain/robstoll/creating/PathAssertionsImpl.kt @@ -30,6 +30,7 @@ class PathAssertionsImpl : PathAssertions { _fileNameWithoutExtension(expect) override fun parent(expect: Expect) = _parent(expect) + override fun resolve(expect: Expect, other: String) = _resolve(expect, other) override fun isReadable(expect: Expect) = _isReadable(expect) override fun isWritable(expect: Expect) = _isWritable(expect) diff --git a/domain/robstoll/extensions/kotlin_1_3/atrium-domain-robstoll-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll.kotlin_1_3/creating/ResultAssertionsImpl.kt b/domain/robstoll/extensions/kotlin_1_3/atrium-domain-robstoll-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll.kotlin_1_3/creating/ResultAssertionsImpl.kt index ad2892552..e1a79f578 100644 --- a/domain/robstoll/extensions/kotlin_1_3/atrium-domain-robstoll-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll.kotlin_1_3/creating/ResultAssertionsImpl.kt +++ b/domain/robstoll/extensions/kotlin_1_3/atrium-domain-robstoll-kotlin_1_3-common/src/main/kotlin/ch/tutteli/atrium/domain/robstoll.kotlin_1_3/creating/ResultAssertionsImpl.kt @@ -1,17 +1,15 @@ package ch.tutteli.atrium.domain.robstoll.kotlin_1_3.creating import ch.tutteli.atrium.creating.Expect -import ch.tutteli.atrium.domain.creating.changers.ChangedSubjectPostStep import ch.tutteli.atrium.domain.kotlin_1_3.creating.ResultAssertions import ch.tutteli.atrium.domain.robstoll.lib.kotlin_1_3.creating._isFailure import ch.tutteli.atrium.domain.robstoll.lib.kotlin_1_3.creating._isSuccess import kotlin.reflect.KClass class ResultAssertionsImpl : ResultAssertions { - override fun > isSuccess(assertionContainer: Expect) = _isSuccess(assertionContainer) + override fun > isSuccess(expect: Expect) = + _isSuccess(expect) - override fun isFailure( - assertionContainer: Expect>, - expectedType: KClass - ) = _isFailure(assertionContainer, expectedType) + override fun isFailure(expect: Expect>, expectedType: KClass) = + _isFailure(expect, expectedType) } diff --git a/gradle/package-lock.json b/gradle/package-lock.json index d50014913..84b93db0c 100644 --- a/gradle/package-lock.json +++ b/gradle/package-lock.json @@ -2,12 +2,58 @@ "requires": true, "lockfileVersion": 1, "dependencies": { + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, + "binary-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "dev": true + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -18,16 +64,117 @@ "concat-map": "0.0.1" } }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "chokidar": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", + "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, "concat-map": { @@ -37,12 +184,27 @@ "dev": true }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" } }, "diff": { @@ -51,22 +213,105 @@ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "flat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", + "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "dev": true, + "requires": { + "is-buffer": "~2.0.3" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "fsevents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -77,22 +322,46 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, "inflight": { @@ -111,6 +380,84 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-buffer": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", + "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", + "dev": true + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, "jasmine": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.5.0.tgz", @@ -143,6 +490,41 @@ "integrity": "sha512-nCeAiw37MIMA9w9IXso7bRaLl+c/ef3wnxsoSAlYrzS+Ot0zTG6nU8G/cIfGkqpkjX2wNaIW9RFG0TwIFnG6bA==", "dev": true }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "log-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2" + } + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -168,30 +550,87 @@ } }, "mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.1.0.tgz", + "integrity": "sha512-MymHK8UkU0K15Q/zX7uflZgVoRWiTjy0fXE/QjKts6mowUvGxOdPhZ2qj3b0iZdUrNZlW9LAIMFHB4IW+2b3EQ==", "dev": true, "requires": { + "ansi-colors": "3.2.3", "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", + "chokidar": "3.3.0", + "debug": "3.2.6", "diff": "3.5.0", "escape-string-regexp": "1.0.5", - "glob": "7.1.2", + "find-up": "3.0.0", + "glob": "7.1.3", "growl": "1.10.5", - "he": "1.1.1", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "3.0.0", "minimatch": "3.0.4", "mkdirp": "0.5.1", - "supports-color": "5.4.0" + "ms": "2.1.1", + "node-environment-flags": "1.0.6", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.0", + "yargs-parser": "13.1.1", + "yargs-unparser": "1.6.0" } }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, + "node-environment-flags": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", + "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -201,26 +640,271 @@ "wrappy": "1" } }, + "p-limit": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "picomatch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz", + "integrity": "sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==", + "dev": true + }, + "readdirp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", + "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "dev": true, + "requires": { + "picomatch": "^2.0.4" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", "dev": true, "requires": { "has-flag": "^3.0.0" } }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yargs-unparser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "dev": true, + "requires": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" + } } } } diff --git a/gradle/package.json b/gradle/package.json index 9eebdbe35..8b649334e 100644 --- a/gradle/package.json +++ b/gradle/package.json @@ -4,6 +4,6 @@ "repository": "https://github.com/robstoll/atrium", "devDependencies": { "jasmine": "^3.5.0", - "mocha": "^5.2.0" + "mocha": "^7.1.0" } } diff --git a/misc/maven/example-pom.xml b/misc/maven/example-pom.xml index bff9e0ae4..80d1f8658 100644 --- a/misc/maven/example-pom.xml +++ b/misc/maven/example-pom.xml @@ -5,7 +5,7 @@ com.example.artifactId - v0.9.0 + 0.10.0 diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/SpekExtensions.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/SpekExtensions.kt index b6c647b3e..b5ae7e78f 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/SpekExtensions.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/SpekExtensions.kt @@ -35,21 +35,7 @@ fun GroupBody.prefixedDescribeTemplate( body: Suite.() -> Unit ): Unit = describe("${prefix}describe$suffix $description", body = body) -fun Suite.checkNarrowingAssertion( - description: String, - act: (Expect.() -> Unit) -> Unit, - lazy: (Expect.() -> Unit), - vararg otherMethods: Pair.() -> Unit)> -) { - checkGenericNarrowingAssertion(description, act, lazy, *otherMethods) -} -fun Suite.checkGenericNarrowingAssertion( - description: String, - act: (T.() -> Unit) -> Unit, - lazy: (T.() -> Unit), - vararg otherMethods: Pair Unit)> -): Unit = checkGenericNarrowingAssertion(description, act, "lazy" to lazy, *otherMethods) fun Suite.checkGenericNarrowingAssertion( description: String, act: (T.() -> Unit) -> Unit, vararg methods: Pair Unit)> diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/checking/ThrowingAssertionCheckerSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/checking/ThrowingAssertionCheckerSpec.kt similarity index 71% rename from misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/checking/ThrowingAssertionCheckerSpec.kt rename to misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/checking/ThrowingAssertionCheckerSpec.kt index 8e038733e..aee74db1c 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/checking/ThrowingAssertionCheckerSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/checking/ThrowingAssertionCheckerSpec.kt @@ -9,30 +9,28 @@ import ch.tutteli.atrium.checking.AssertionChecker import ch.tutteli.atrium.core.coreFactory import ch.tutteli.atrium.reporting.Reporter import ch.tutteli.atrium.specs.AssertionVerb -import ch.tutteli.atrium.specs.describeFun -import com.nhaarman.mockitokotlin2.any -import com.nhaarman.mockitokotlin2.mock -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.SpecBody -import org.jetbrains.spek.api.dsl.it +import ch.tutteli.atrium.specs.describeFunTemplate +import io.mockk.* +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.Suite -//TODO #116 migrate spek1 to spek2 - move to specs-common abstract class ThrowingAssertionCheckerSpec( testeeFactory: (Reporter) -> AssertionChecker, describePrefix: String = "[Atrium] " ) : Spek({ - fun describeFun(vararg funName: String, body: SpecBody.() -> Unit) = - describeFun(describePrefix, funName, body = body) + fun describeFun(vararg funName: String, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, funName, body = body) val assertionVerb = AssertionVerb.VERB val reporterResponse = "hello" - //TODO #116 use mockk instead of mockito-kotlin - val reporter = mock { - on { format(any(), @Suppress("RemoveExplicitTypeArguments") any()) }.thenAnswer { - (it.arguments[1] as StringBuilder).append(reporterResponse) + val strbldSlot = slot() + + val reporter = mockk { + every { format(any(), @Suppress("RemoveExplicitTypeArguments") capture(strbldSlot)) } answers { + (strbldSlot.captured).append(reporterResponse) } - on { atriumErrorAdjuster }.thenReturn(coreFactory.newNoOpAtriumErrorAdjuster()) + every { atriumErrorAdjuster } returns (coreFactory.newNoOpAtriumErrorAdjuster()) } val testee = testeeFactory(reporter) val assertionWhichHolds = object : Assertion { diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceContainsContainsNotAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceContainsContainsNotAssertionsSpec.kt index 92189eb8a..244b86b0a 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceContainsContainsNotAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceContainsContainsNotAssertionsSpec.kt @@ -8,8 +8,8 @@ import ch.tutteli.atrium.translations.DescriptionCharSequenceAssertion.CONTAINS_ import org.spekframework.spek2.style.specification.Suite abstract class CharSequenceContainsContainsNotAssertionsSpec( - contains: Fun2>, - containsNot: Fun2>, + contains: Fun2>, + containsNot: Fun2>, rootBulletPoint: String, listBulletPoint: String, featureArrow: String, diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceContainsRegexAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceContainsRegexAssertionsSpec.kt index aa00b115c..37273873f 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceContainsRegexAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceContainsRegexAssertionsSpec.kt @@ -66,55 +66,55 @@ abstract class CharSequenceContainsRegexAssertionsSpec( describeFun(containsRegex) { context("throws an ${IllegalArgumentException::class.simpleName}") { - it("if an erroneous pattern is passed to `$containsAtLeast` as first argument") { + it("if an erroneous pattern is passed to `${containsAtLeast.name}` as first argument") { expect { expect("a" as CharSequence).containsAtLeastFun(1, "notA(validPattern") }.toThrow() } - it("if an erroneous pattern is passed to `$containsAtLeast` as second argument") { + it("if an erroneous pattern is passed to `${containsAtLeast.name}` as second argument") { expect { expect("a" as CharSequence).containsAtLeastFun(1, "h(a|e)llo", "notA(validPattern") }.toThrow() } - it("if an erroneous pattern is passed to `$containsAtLeastIgnoringCase` as first argument") { + it("if an erroneous pattern is passed to `${containsAtLeastIgnoringCase.name}` as first argument") { expect { expect("a" as CharSequence).containsAtLeastIgnoringCaseFun(1, "notA(validPattern") }.toThrow() } - it("if an erroneous pattern is passed to `$containsAtLeastIgnoringCase` as second argument") { + it("if an erroneous pattern is passed to `${containsAtLeastIgnoringCase.name}` as second argument") { expect { expect("a" as CharSequence).containsAtLeastIgnoringCaseFun(1, "h(a|e)llo", "notA(validPattern") }.toThrow() } - it("if an erroneous pattern is passed to `$containsShortcut` as first argument") { + it("if an erroneous pattern is passed to `${containsShortcut.name}` as first argument") { expect { expect("a" as CharSequence).containsShortcutFun("notA(validPattern") }.toThrow() } - it("if an erroneous pattern is passed to `$containsShortcut` as second argument") { + it("if an erroneous pattern is passed to `${containsShortcut.name}` as second argument") { expect { expect("a" as CharSequence).containsShortcutFun("h(a|e)llo", "notA(validPattern") }.toThrow() } - it("if an erroneous pattern is passed to `$containsAtMost` as first argument") { + it("if an erroneous pattern is passed to `${containsAtMost.name}` as first argument") { expect { expect("a" as CharSequence).containsAtMostFun(2, "notA(validPattern") }.toThrow() } - it("if an erroneous pattern is passed to `$containsAtMost` as second argument") { + it("if an erroneous pattern is passed to `${containsAtMost.name}` as second argument") { expect { expect("a" as CharSequence).containsAtMostFun(2, "h(a|e)llo", "notA(validPattern") }.toThrow() } - it("if an erroneous pattern is passed to `$containsAtMostIgnoringCase` as first argument") { + it("if an erroneous pattern is passed to `${containsAtMostIgnoringCase.name}` as first argument") { expect { expect("a" as CharSequence).containsAtMostIgnoringCaseFun(2, "notA(validPattern") }.toThrow() } - it("if an erroneous pattern is passed to `$containsAtMostIgnoringCase` as second argument") { + it("if an erroneous pattern is passed to `${containsAtMostIgnoringCase.name}` as second argument") { expect { expect("a" as CharSequence).containsAtMostIgnoringCaseFun(2, "h(a|e)llo", "notA(validPattern") }.toThrow() diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/Fun0AssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/Fun0AssertionsSpec.kt index 9730d3e72..863704843 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/Fun0AssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/Fun0AssertionsSpec.kt @@ -6,6 +6,7 @@ import ch.tutteli.atrium.core.polyfills.fullName import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.specs.* import ch.tutteli.atrium.translations.DescriptionAnyAssertion +import ch.tutteli.atrium.translations.DescriptionBasic import ch.tutteli.atrium.translations.DescriptionFunLikeAssertion import ch.tutteli.atrium.translations.DescriptionThrowableAssertion import org.spekframework.spek2.Spek @@ -21,7 +22,14 @@ abstract class Fun0AssertionsSpec( describePrefix: String = "[Atrium] " ) : Spek({ - include(object : SubjectLessSpec<() -> Any?>(describePrefix, + @Suppress("NAME_SHADOWING") + val toThrow = toThrow.adjustName { it.substringBefore(" (feature)") } + + @Suppress("NAME_SHADOWING") + val notToThrow = notToThrow.adjustName { it.substringBefore(" (feature)") } + + include(object : SubjectLessSpec<() -> Any?>( + "$describePrefix[toThrow] ", toThrowFeature.forSubjectLess().adjustName { "$it feature" }, toThrow.forSubjectLess { messageContains("bla") } ) {}) @@ -32,7 +40,7 @@ abstract class Fun0AssertionsSpec( ) {}) include(object : AssertionCreatorSpec<() -> Any?>( - describePrefix, { throw IllegalArgumentException("bla") }, + "$describePrefix[toThrow] ", { throw IllegalArgumentException("bla") }, assertionCreatorSpecTriple( toThrow.name, "bla", @@ -51,32 +59,9 @@ abstract class Fun0AssertionsSpec( ) ) {}) - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) + fun describeFun(vararg pairs: SpecPair<*>, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, pairs.map { it.name }.toTypedArray(), body = body) - fun Suite.checkToThrow( - description: String, - act: (Expect Any?>.() -> Unit) -> Unit, - lazy: (Expect Any?>.() -> Unit), - immediate: (Expect Any?>.() -> Unit) - ) { - checkGenericNarrowingAssertion(description, act, lazy, "immediate" to immediate) - } - - fun expectThrowsAssertionErrorAndMessageContainsRegex( - toThrowFun: Expect<() -> R>.() -> Unit, - throwable: Throwable, - pattern: String, vararg otherPatterns: String - ) { - expect { - val act: () -> R = { throw throwable } - expect(act).toThrowFun() - }.toThrow { - message { containsRegex(pattern, *otherPatterns) } - } - } - - val isADescr = DescriptionAnyAssertion.IS_A.getDefault() val messageDescr = DescriptionThrowableAssertion.OCCURRED_EXCEPTION_MESSAGE.getDefault() val stackTraceDescr = DescriptionThrowableAssertion.OCCURRED_EXCEPTION_STACKTRACE.getDefault() val causeDescr = DescriptionThrowableAssertion.OCCURRED_EXCEPTION_CAUSE.getDefault() @@ -88,179 +73,179 @@ abstract class Fun0AssertionsSpec( "\\s+\\Q$explanationBulletPoint\\E$stackTraceDescr: $separator" + "\\s+\\Q$listBulletPoint\\E${Fun0AssertionsSpec::class.fullName}" - describeFun("${toThrowFeature.name} feature and ${toThrow.name}") { - val toThrowFeatureFun = toThrowFeature.lambda - val toThrowFun = toThrow.lambda + describeFun(toThrowFeature, toThrow, notToThrowFeature, notToThrow) { + val toThrowFunctions = unifySignatures(toThrowFeature, toThrow) + val notToThrowFunctions = unifySignatures(notToThrowFeature, notToThrow) - checkToThrow("it throws an AssertionError when no exception occurs", { doToThrow -> - expect { - expect { /* no exception occurs */ 1 }.doToThrow() - }.toThrow { - message { - contains.exactly(1).regex( - "${DescriptionFunLikeAssertion.THROWN_EXCEPTION_WHEN_CALLED.getDefault()}: " + - DescriptionFunLikeAssertion.NO_EXCEPTION_OCCURRED.getDefault(), - "$isADescr: ${IllegalArgumentException::class.simpleName}" - ) + context("no exception occurs") { + toThrowFunctions.forEach { (name, toThrowFun, hasExtraHint) -> + it("$name - throws an AssertionError" + showsSubAssertionIf(hasExtraHint)) { + expect { + expect<() -> Any?> { /* no exception occurs */ 1 }.toThrowFun { toBe(IllegalArgumentException("what")) } + }.toThrow { + message { + contains.exactly(1).regex( + "${DescriptionFunLikeAssertion.THROWN_EXCEPTION_WHEN_CALLED.getDefault()}: " + + DescriptionFunLikeAssertion.NO_EXCEPTION_OCCURRED.getDefault(), + "$isADescr: ${IllegalArgumentException::class.simpleName}" + ) + if (hasExtraHint) contains("$toBeDescr: ${IllegalArgumentException::class.fullName}") + } + } } } - }, { toThrowFun { toBe(IllegalArgumentException("what")) } }, { toThrowFeatureFun() }) + notToThrowFunctions.forEach { (name, notToThrowFun, _) -> + it("$name - does not throw, allows to make a sub assertion") { + expect { 1 }.notToThrowFun { toBe(1) } + } + } + } - checkToThrow( - "it allows to define assertions for the Throwable if the correct exception is thrown", - { toThrowWithCheck -> - expect { - throw IllegalArgumentException("hello") - }.toThrowWithCheck() - }, - { toThrowFun { message { toBe("hello") } } }, { toThrowFeatureFun().message.toBe("hello") }) + context("exception is thrown") { - context("wrong exception") { + val wrongException = UnsupportedOperationException(errMessage) - checkToThrow("it throws an AssertionError and shows message and stacktrace as extra hint", { doToThrow -> - expectThrowsAssertionErrorAndMessageContainsRegex( - doToThrow, - UnsupportedOperationException(errMessage), - "$isADescr:.+" + IllegalArgumentException::class.fullName, - UnsupportedOperationException::class.simpleName + separator + messageAndStackTrace(errMessage) - ) - }, { toThrowFun { message { toBe("hello") } } }, { toThrowFeatureFun().message.toBe("hello") }) + toThrowFunctions.forEach { (name, toThrowFun, hasExtraHint) -> + it("$name - allows to define assertions for the Throwable if the correct exception is thrown") { + expect<() -> Any?> { + throw IllegalArgumentException("hello") + }.toThrowFun { message.toBe("hello") } + } + + it( + "$name - throws an AssertionError in case of a wrong exception and shows message and stacktrace as extra hint" + + showsSubAssertionIf(hasExtraHint) + ) { + expect { + expect<() -> Any?> { + throw wrongException + }.toThrowFun { message.toBe("hello") } + }.toThrow { + message { + containsRegex( + "$isADescr:.+" + IllegalArgumentException::class.fullName, + UnsupportedOperationException::class.simpleName + separator + + messageAndStackTrace(errMessage) + ) + if (hasExtraHint) contains("$toBeDescr: \"hello\"") + } + } + } + } + + notToThrowFunctions.forEach { (name, notToThrowFun, hasExtraHint) -> + it( + "$name - throws an AssertionError and shows message and stacktrace as extra hint" + + showsSubAssertionIf(hasExtraHint) + ) { + expect { + expect<() -> Int> { + throw wrongException + }.notToThrowFun { toBe(2) } + }.toThrow { + message { + containsRegex( + "${DescriptionFunLikeAssertion.IS_NOT_THROWING_1.getDefault()}: "+ + DescriptionFunLikeAssertion.IS_NOT_THROWING_2.getDefault(), + UnsupportedOperationException::class.simpleName + separator + + messageAndStackTrace(errMessage) + ) + if (hasExtraHint) contains("$toBeDescr: 2") + } + } + } + } context("with a cause") { - checkToThrow("shows cause as extra hint", { doToThrow -> - expectThrowsAssertionErrorAndMessageContainsRegex( - doToThrow, - UnsupportedOperationException("not supported", IllegalStateException(errMessage)), - UnsupportedOperationException::class.simpleName + separator + - messageAndStackTrace("not supported"), - "\\s+\\Q$explanationBulletPoint\\E$causeDescr: ${IllegalStateException::class.fullName}" + - messageAndStackTrace(errMessage) - ) - }, { toThrowFun { message { toBe("hello") } } }, { toThrowFeatureFun() }) + val exceptionWithCause = + UnsupportedOperationException("not supported", IllegalStateException(errMessage)) - checkToThrow( - "with nested cause, shows both causes as extra hint", - { doToThrow -> - expectThrowsAssertionErrorAndMessageContainsRegex( - doToThrow, - UnsupportedOperationException( - "not supported", - RuntimeException("io", IllegalStateException(errMessage)) - ), + fun Expect.expectCauseInReporting() = + message { + containsRegex( UnsupportedOperationException::class.simpleName + separator + messageAndStackTrace("not supported"), - "\\s+\\Q$explanationBulletPoint\\E$causeDescr: ${RuntimeException::class.fullName}" + - messageAndStackTrace("io"), "\\s+\\Q$explanationBulletPoint\\E$causeDescr: ${IllegalStateException::class.fullName}" + messageAndStackTrace(errMessage) ) - }, - { toThrowFun { message { toBe("hello") } } }, - { toThrowFeatureFun().message.toBe("hello") }) - } - } - } - describeFun("${notToThrowFeature.name} feature") { - val notToThrowFeatureFun = notToThrowFeature.lambda + } - context("no exception occurs") { - it("does not throw, allows to make a sub assertion") { - expect { 1 }.notToThrowFeatureFun().toBe(1) - } - } - context("exception is thrown") { - val notThrown: Expect<() -> Int>.() -> Unit = { notToThrowFeatureFun().toBe(1) } - - it("throws an AssertionError and shows message and stackTrace as well as intended sub assertion") { - expectThrowsAssertionErrorAndMessageContainsRegex( - notThrown, - UnsupportedOperationException(errMessage), - UnsupportedOperationException::class.simpleName + separator + messageAndStackTrace(errMessage), - "..." - ) - } - - context("with a cause") { - it("shows cause as extra hint") { - expectThrowsAssertionErrorAndMessageContainsRegex( - notThrown, - UnsupportedOperationException("not supported", IllegalStateException(errMessage)), - UnsupportedOperationException::class.simpleName + separator + - messageAndStackTrace("not supported"), - "\\s+\\Q$explanationBulletPoint\\E$causeDescr: ${IllegalStateException::class.fullName}" + - messageAndStackTrace(errMessage) - ) + toThrowFunctions.forEach { (name, toThrowFun, hasExtraHint) -> + it( + "$name - shows cause as extra hint in case of a wrong exception" + + showsSubAssertionIf(hasExtraHint) + ) { + expect { + expect<() -> Any?> { + throw exceptionWithCause + }.toThrowFun { message.toBe("hello") } + }.toThrow { + expectCauseInReporting() + if (hasExtraHint) messageContains("$toBeDescr: \"hello\"") + } + } } - it("with nested cause, shows both causes as extra hint") { - expectThrowsAssertionErrorAndMessageContainsRegex( - notThrown, - UnsupportedOperationException( - "not supported", - RuntimeException("io", IllegalStateException(errMessage)) - ), - UnsupportedOperationException::class.simpleName + separator + - messageAndStackTrace("not supported"), - "\\s+\\Q$explanationBulletPoint\\E$causeDescr: ${RuntimeException::class.fullName}" + - messageAndStackTrace("io"), - "\\s+\\Q$explanationBulletPoint\\E$causeDescr: ${IllegalStateException::class.fullName}" + - messageAndStackTrace(errMessage) - ) - } - } - } - } - - describeFun(notToThrow.name) { - val notToThrowFun = notToThrow.lambda - - context("no exception occurs") { - it("does not throw, allows to make a sub assertion") { - expect { 1 }.notToThrowFun { toBe(1) } - } - } - context("exception is thrown") { - val notThrown: Expect<() -> Int>.() -> Unit = { notToThrowFun { toBe(1) } } - - it("throws an AssertionError and shows message and stackTrace as well as intended sub assertion") { - expectThrowsAssertionErrorAndMessageContainsRegex( - notThrown, - UnsupportedOperationException(errMessage), - UnsupportedOperationException::class.simpleName + separator + messageAndStackTrace(errMessage), - "...", - "$toBeDescr: 1" - ) - } - - context("with a cause") { - it("shows cause as extra hint") { - expectThrowsAssertionErrorAndMessageContainsRegex( - notThrown, - UnsupportedOperationException("not supported", IllegalStateException(errMessage)), - UnsupportedOperationException::class.simpleName + separator + - messageAndStackTrace("not supported"), - "\\s+\\Q$explanationBulletPoint\\E$causeDescr: ${IllegalStateException::class.fullName}" + - messageAndStackTrace(errMessage) - ) + notToThrowFunctions.forEach { (name, notToThrowFun, hasExtraHint) -> + it("$name - shows cause as extra hint" + showsSubAssertionIf(hasExtraHint)) { + expect { + expect<() -> Int> { + throw exceptionWithCause + }.notToThrowFun { toBe(2) } + }.toThrow { + expectCauseInReporting() + if (hasExtraHint) messageContains("$toBeDescr: 2") + } + } } - it("with nested cause, shows both causes as extra hint") { - expectThrowsAssertionErrorAndMessageContainsRegex( - notThrown, - UnsupportedOperationException( - "not supported", - RuntimeException("io", IllegalStateException(errMessage)) - ), - UnsupportedOperationException::class.simpleName + separator + - messageAndStackTrace("not supported"), - "\\s+\\Q$explanationBulletPoint\\E$causeDescr: ${RuntimeException::class.fullName}" + - messageAndStackTrace("io"), - "\\s+\\Q$explanationBulletPoint\\E$causeDescr: ${IllegalStateException::class.fullName}" + - messageAndStackTrace(errMessage) + context("with nested cause") { + val exceptionWithNestedCause = UnsupportedOperationException( + "not supported", + RuntimeException("io", IllegalStateException(errMessage)) ) + + fun Expect.expectCauseAndNestedInReporting() = + message { + containsRegex( + UnsupportedOperationException::class.simpleName + separator + + messageAndStackTrace("not supported"), + "\\s+\\Q$explanationBulletPoint\\E$causeDescr: ${RuntimeException::class.fullName}" + + messageAndStackTrace("io"), + "\\s+\\Q$explanationBulletPoint\\E$causeDescr: ${IllegalStateException::class.fullName}" + + messageAndStackTrace(errMessage) + ) + } + + + toThrowFunctions.forEach { (name, toThrowFun, hasExtraHint) -> + it("$name - shows both causes as extra hint" + showsSubAssertionIf(hasExtraHint)) { + expect { + expect<() -> Any?> { + throw exceptionWithNestedCause + }.toThrowFun { message.toBe("hello") } + }.toThrow { + expectCauseAndNestedInReporting() + if (hasExtraHint) messageContains("$toBeDescr: \"hello\"") + } + } + } + + notToThrowFunctions.forEach { (name, notToThrowFun, hasExtraHint) -> + it("$name - shows both causes as extra hint" + showsSubAssertionIf(hasExtraHint)) { + expect { + expect<() -> Int> { + throw exceptionWithNestedCause + }.notToThrowFun { toBe(2) } + }.toThrow { + expectCauseAndNestedInReporting() + if (hasExtraHint) messageContains("$toBeDescr: 2") + } + } + } } } } diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableAllAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableAllAssertionsSpec.kt index 823295acf..24b17101d 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableAllAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableAllAssertionsSpec.kt @@ -16,7 +16,7 @@ abstract class IterableAllAssertionsSpec( featureArrow: String, featureBulletPoint: String, describePrefix: String = "[Atrium] " -) : IterablePredicateSpecBase({ +) : IterableContainsEntriesSpecBase({ include(object : SubjectLessSpec>(describePrefix, all.first to expectLambda { all.second(this) { toBe(2.5) } } @@ -52,9 +52,9 @@ abstract class IterableAllAssertionsSpec( ) { allFun -> context("empty collection") { - it("$isLessThanFun(1.0) throws AssertionError") { + it("throws AssertionError as there needs to be at least one element") { expect { - fluentEmpty.allFun { isLessThan(1.0) } + expect(fluentEmpty()).allFun { isLessThan(1.0) } }.toThrow { messageContains( "$rootBulletPoint$featureArrow$hasElement: false$separator" + @@ -95,7 +95,7 @@ abstract class IterableAllAssertionsSpec( nullableCases(describePrefix) { - describeFun("${allNullable.name} for nullable") { + describeFun(allNullable) { val allNullableFun = allNullable.lambda val iterableOfNulls = { sequenceOf(null, null).constrainOnce().asIterable() } diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableAnyAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableAnyAssertionsSpec.kt index cb16dfdb3..eb07fbcb2 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableAnyAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableAnyAssertionsSpec.kt @@ -8,6 +8,7 @@ import ch.tutteli.atrium.domain.builders.migration.asAssert import ch.tutteli.atrium.domain.builders.migration.asExpect import ch.tutteli.atrium.specs.* import ch.tutteli.atrium.translations.DescriptionComparableAssertion +import ch.tutteli.atrium.translations.DescriptionIterableAssertion import ch.tutteli.atrium.translations.ErrorMessages abstract class IterableAnyAssertionsSpec( @@ -15,7 +16,7 @@ abstract class IterableAnyAssertionsSpec( anyNullable: Fun1, (Expect.() -> Unit)?>, rootBulletPoint: String, describePrefix: String = "[Atrium] " -) : IterablePredicateSpecBase({ +) : IterableContainsEntriesSpecBase({ val isGreaterThanDescr = DescriptionComparableAssertion.IS_GREATER_THAN.getDefault() @@ -43,9 +44,9 @@ abstract class IterableAnyAssertionsSpec( ) { anyFun -> context("empty collection") { - it("$isLessThanFun(1.0) throws AssertionError") { + it("throws AssertionError as there needs to be at least one element") { expect { - fluentEmpty.anyFun { isLessThan(1.0) } + expect(fluentEmpty()).anyFun { isLessThan(1.0) } }.toThrow { messageContains( "$rootBulletPoint$containsInAnyOrder: $separator", @@ -54,12 +55,13 @@ abstract class IterableAnyAssertionsSpec( "$numberOfOccurrences: 0", "$atLeast: 1" ) + } } //TODO remove with 1.0.0 it("$returnValueOfFun(...) states warning that subject is not set") { expect { - fluentEmpty.anyFun { + expect(fluentEmpty()).anyFun { @Suppress("DEPRECATION") asAssert().returnValueOf(subject::dec).asExpect().toBe(1.0) } @@ -98,7 +100,7 @@ abstract class IterableAnyAssertionsSpec( nullableCases(describePrefix) { - describeFun("${anyNullable.name} for nullable") { + describeFun(anyNullable) { val anyNullableFun = anyNullable.lambda context("iterable ${oneToSevenNullable().toList()}") { diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableAssertionsSpec.kt index 716e51eee..f86a8912c 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableAssertionsSpec.kt @@ -3,12 +3,7 @@ package ch.tutteli.atrium.specs.integration import ch.tutteli.atrium.api.fluent.en_GB.messageContains import ch.tutteli.atrium.api.fluent.en_GB.toThrow import ch.tutteli.atrium.api.verbs.internal.expect -import ch.tutteli.atrium.specs.Fun0 -import ch.tutteli.atrium.specs.SubjectLessSpec -import ch.tutteli.atrium.specs.describeFunTemplate -import ch.tutteli.atrium.specs.forSubjectLess -import ch.tutteli.atrium.specs.lambda -import ch.tutteli.atrium.specs.name +import ch.tutteli.atrium.specs.* import ch.tutteli.atrium.translations.DescriptionBasic import ch.tutteli.atrium.translations.DescriptionIterableAssertion import org.spekframework.spek2.Spek @@ -25,15 +20,14 @@ abstract class IterableAssertionsSpec( hasNext.forSubjectLess() ) {}) - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) - + fun describeFun(vararg pairs: SpecPair<*>, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, pairs.map { it.name }.toTypedArray(), body = body) val hasDescriptionBasic = DescriptionBasic.HAS.getDefault() val hasNotDescriptionBasic = DescriptionBasic.HAS_NOT.getDefault() val nextElement = DescriptionIterableAssertion.NEXT_ELEMENT.getDefault() - describeFun(hasNext.name) { + describeFun(hasNext) { val hasNextFun = hasNext.lambda it("does not throw if an iterable has next") { @@ -47,7 +41,7 @@ abstract class IterableAssertionsSpec( } } - describeFun(hasNotNext.name) { + describeFun(hasNotNext) { val hasNotNextFun = hasNotNext.lambda it("does not throw if an iterable has not next") { diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsEntriesSpecBase.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsEntriesSpecBase.kt index 2f9d17731..0f71210f5 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsEntriesSpecBase.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsEntriesSpecBase.kt @@ -1,22 +1,14 @@ package ch.tutteli.atrium.specs.integration -import ch.tutteli.atrium.api.cc.en_GB.returnValueOf import ch.tutteli.atrium.api.fluent.en_GB.isGreaterThan import ch.tutteli.atrium.api.fluent.en_GB.isLessThan import ch.tutteli.atrium.api.fluent.en_GB.toBe -import ch.tutteli.atrium.api.verbs.internal.expect -import ch.tutteli.atrium.creating.Assert import ch.tutteli.atrium.creating.Expect -import ch.tutteli.atrium.domain.builders.migration.asAssert import ch.tutteli.atrium.specs.fun1 import ch.tutteli.atrium.specs.name import ch.tutteli.atrium.translations.DescriptionComparableAssertion import ch.tutteli.atrium.translations.DescriptionIterableAssertion import org.spekframework.spek2.dsl.Root -import org.spekframework.spek2.style.specification.Suite -import org.spekframework.spek2.style.specification.describe -import kotlin.reflect.KFunction -import kotlin.reflect.KFunction0 abstract class IterableContainsEntriesSpecBase( spec: Root.() -> Unit @@ -26,8 +18,7 @@ abstract class IterableContainsEntriesSpecBase( isGreaterThanFun = Expect::isGreaterThan.name toBeFun = fun1(Expect::toBe).name //TODO remove with 1.0.0 - @Suppress("DEPRECATION") val f: (KFunction0) -> Assert = expect(1).asAssert()::returnValueOf - returnValueOfFun = (f as KFunction<*>).name + returnValueOfFun = "returnValueOf" } companion object { @@ -38,26 +29,5 @@ abstract class IterableContainsEntriesSpecBase( val anEntryWhich = DescriptionIterableAssertion.AN_ENTRY_WHICH.getDefault() val isLessThanDescr = DescriptionComparableAssertion.IS_LESS_THAN.getDefault() val isGreaterThanDescr = DescriptionComparableAssertion.IS_GREATER_THAN.getDefault() - - fun Root.nonNullableCases( - describePrefix: String, - containsPair: Pair>.(Expect.() -> Unit, Array.() -> Unit>) -> Expect>>, - containsNullablePair: Pair>.((Expect.() -> Unit)?, Array.() -> Unit)?>) -> Expect>>, - action: Suite.(Expect>.(Expect.() -> Unit, Array.() -> Unit>) -> Any) -> Unit - ) { - describe("$describePrefix describe non-nullable cases") { - mapOf>.(Expect.() -> Unit, Array.() -> Unit>) -> Any>( - containsPair.first to { a, aX -> containsPair.second(this, a, aX) }, - containsNullablePair.first to { a, aX -> - @Suppress("UNCHECKED_CAST") - containsNullablePair.second(this as Expect>, a, aX) - } - ).forEach { (describe, containsEntriesFunArr) -> - describeFun(describe) { - action(containsEntriesFunArr) - } - } - } - } } } diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderAtLeast1EntriesAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderAtLeast1EntriesAssertionsSpec.kt index 0e319c462..92c181ce8 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderAtLeast1EntriesAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderAtLeast1EntriesAssertionsSpec.kt @@ -60,7 +60,7 @@ abstract class IterableContainsInAnyOrderAtLeast1EntriesAssertionsSpec( context("empty collection") { it("$isLessThanFun(1.0) throws AssertionError") { expect { - fluentEmpty.containsEntriesFun({ isLessThan(1.0) }) + expect(fluentEmpty()).containsEntriesFun({ isLessThan(1.0) }) }.toThrow { message { contains.exactly(1).values( @@ -75,7 +75,7 @@ abstract class IterableContainsInAnyOrderAtLeast1EntriesAssertionsSpec( } it("$isLessThanFun(1.0) and $isGreaterThanFun(2.0) throws AssertionError") { expect { - fluentEmpty.containsEntriesFun({ isLessThan(1.0) }, { isGreaterThan(2.0) }) + expect(fluentEmpty()).containsEntriesFun({ isLessThan(1.0) }, { isGreaterThan(2.0) }) }.toThrow { message { contains.exactly(2).values( @@ -94,7 +94,7 @@ abstract class IterableContainsInAnyOrderAtLeast1EntriesAssertionsSpec( //TODO remove with 1.0.0 it("$returnValueOfFun(...) states warning that subject is not set") { expect { - fluentEmpty.containsEntriesFun({ + expect(fluentEmpty()).containsEntriesFun({ @Suppress("DEPRECATION") asAssert().returnValueOf(subject::dec).asExpect().toBe(1.0) }) @@ -143,7 +143,7 @@ abstract class IterableContainsInAnyOrderAtLeast1EntriesAssertionsSpec( nullableCases(describePrefix) { - describeFun("${containsInAnyOrderNullableEntries.name} for nullable") { + describeFun(containsInAnyOrderNullableEntries) { context("iterable ${oneToSevenNullable().toList()}") { context("happy cases (do not throw)") { diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec.kt index 7c7321eca..e422d08f3 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec.kt @@ -37,7 +37,7 @@ abstract class IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec( context("empty collection") { it("1.0 throws AssertionError") { expect { - fluentEmpty.containsFun(1.0) + expect(fluentEmpty()).containsFun(1.0) }.toThrow { messageContains( "$rootBulletPoint$containsInAnyOrder: $separator", @@ -113,7 +113,7 @@ abstract class IterableContainsInAnyOrderAtLeast1ValuesAssertionsSpec( nullableCases(describePrefix) { - describeFun("${containsInAnyOrderNullableValues.name} for nullable") { + describeFun(containsInAnyOrderNullableValues) { context("iterable ${oneToSevenNullable().toList()}") { listOf( diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderAtLeastValuesAssertionSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderAtLeastValuesAssertionSpec.kt index edc5566eb..f4363eb0e 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderAtLeastValuesAssertionSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderAtLeastValuesAssertionSpec.kt @@ -25,8 +25,8 @@ abstract class IterableContainsInAnyOrderAtLeastValuesAssertionSpec( containsAtLeastButAtMost.forSubjectLess(1, 2, 2.3, arrayOf()) ) {}) - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) + fun describeFun(vararg pairs: SpecPair<*>, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, pairs.map { it.name }.toTypedArray(), body = body) fun Expect>.containsAtLeastFun(atLeast: Int, a: Double, vararg aX: Double) = containsAtLeast(this, atLeast, a, aX.toTypedArray()) @@ -37,7 +37,7 @@ abstract class IterableContainsInAnyOrderAtLeastValuesAssertionSpec( val (containsNot, errorMsgContainsNot) = containsNotPair val (exactly, errorMsgExactly) = exactlyPair - describeFun(containsAtLeast.name, containsAtLeastButAtMost.name) { + describeFun(containsAtLeast, containsAtLeastButAtMost) { context("throws an $illegalArgumentException") { it("for at least -1 -- only positive numbers") { expect { diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderAtMostValuesAssertionSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderAtMostValuesAssertionSpec.kt index ed3c654fd..3a6310df2 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderAtMostValuesAssertionSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderAtMostValuesAssertionSpec.kt @@ -21,8 +21,8 @@ abstract class IterableContainsInAnyOrderAtMostValuesAssertionSpec( containsAtMost.forSubjectLess(2, 2.3, arrayOf()) ) {}) - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) + fun describeFun(vararg pairs: SpecPair<*>, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, pairs.map { it.name }.toTypedArray(), body = body) fun Expect>.containsAtMostFun(atLeast: Int, a: Double, vararg aX: Double) = containsAtMost(this, atLeast, a, aX.toTypedArray()) @@ -30,7 +30,7 @@ abstract class IterableContainsInAnyOrderAtMostValuesAssertionSpec( val (containsNot, errorMsgContainsNot) = containsNotPair val (exactly, errorMsgExactly) = exactlyPair - describeFun(containsAtMost.name) { + describeFun(containsAtMost) { context("throws an $illegalArgumentException") { it("for at most -1 -- only positive numbers") { diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderExactlyValuesAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderExactlyValuesAssertionsSpec.kt index 0fcecfffd..dd63b67c3 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderExactlyValuesAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderExactlyValuesAssertionsSpec.kt @@ -21,8 +21,8 @@ abstract class IterableContainsInAnyOrderExactlyValuesAssertionsSpec( containsExactly.forSubjectLess(2, 2.3, arrayOf()) ) {}) - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) + fun describeFun(vararg pairs: SpecPair<*>, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, pairs.map { it.name }.toTypedArray(), body = body) fun Expect>.containsExactlyFun(atLeast: Int, a: Double, vararg aX: Double) = containsExactly.invoke(this, atLeast, a, aX.toTypedArray()) @@ -31,7 +31,7 @@ abstract class IterableContainsInAnyOrderExactlyValuesAssertionsSpec( val exactly = EXACTLY.getDefault() - describeFun(containsExactly.name) { + describeFun(containsExactly) { context("throws an $illegalArgumentException") { it("for exactly -1 -- only positive numbers") { expect { diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderNotOrAtMostValuesAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderNotOrAtMostValuesAssertionsSpec.kt index 85f21e798..79ba56907 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderNotOrAtMostValuesAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderNotOrAtMostValuesAssertionsSpec.kt @@ -20,15 +20,15 @@ abstract class IterableContainsInAnyOrderNotOrAtMostValuesAssertionsSpec( containsNotOrAtMost.forSubjectLess(2, 2.3, arrayOf()) ) {}) - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) + fun describeFun(vararg pairs: SpecPair<*>, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, pairs.map { it.name }.toTypedArray(), body = body) fun Expect>.containsNotOrAtMostFun(atLeast: Int, a: Double, vararg aX: Double) = containsNotOrAtMost(this, atLeast, a, aX.toTypedArray()) val (containsNot, errorMsgContainsNot) = containsNotPair - describeFun(containsNotOrAtMost.name) { + describeFun(containsNotOrAtMost) { context("throws an $illegalArgumentException") { it("for not at all or at most -1 -- only positive numbers") { diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderOnlyEntriesAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderOnlyEntriesAssertionsSpec.kt index b488eecf0..61ca4afc6 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderOnlyEntriesAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderOnlyEntriesAssertionsSpec.kt @@ -73,7 +73,7 @@ abstract class IterableContainsInAnyOrderOnlyEntriesAssertionsSpec( context("empty collection") { it("$isLessThanFun(1.0) throws AssertionError") { expect { - fluentEmpty.containsEntriesFun({ isLessThan(1.0) }) + expect(fluentEmpty()).containsEntriesFun({ isLessThan(1.0) }) }.toThrow { message { contains( @@ -87,7 +87,7 @@ abstract class IterableContainsInAnyOrderOnlyEntriesAssertionsSpec( } it("$isLessThanFun(1.0) and $isGreaterThanFun(4.0) throws AssertionError") { expect { - fluentEmpty.containsEntriesFun({ isLessThan(1.0) }, { isGreaterThan(4.0) }) + expect(fluentEmpty()).containsEntriesFun({ isLessThan(1.0) }, { isGreaterThan(4.0) }) }.toThrow { message { contains.exactly(1).values( @@ -104,7 +104,7 @@ abstract class IterableContainsInAnyOrderOnlyEntriesAssertionsSpec( //TODO remove with 1.0.0 it("$returnValueOfFun(...) states warning that subject is not set") { expect { - fluentEmpty.containsEntriesFun({ + expect(fluentEmpty()).containsEntriesFun({ @Suppress("DEPRECATION") asAssert().returnValueOf(subject::dec).asExpect().toBe(1.0) }) @@ -292,7 +292,7 @@ abstract class IterableContainsInAnyOrderOnlyEntriesAssertionsSpec( nullableCases(describePrefix) { - describeFun("${containsInAnyOrderOnlyNullableEntries.name} for nullable") { + describeFun(containsInAnyOrderOnlyNullableEntries) { val null1null3 = { sequenceOf(null, 1.0, null, 3.0).constrainOnce().asIterable() } context("iterable ${null1null3().toList()}") { diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderOnlyValuesAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderOnlyValuesAssertionsSpec.kt index e195957db..68bcbf64e 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderOnlyValuesAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInAnyOrderOnlyValuesAssertionsSpec.kt @@ -6,6 +6,7 @@ import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.specs.Fun2 import ch.tutteli.atrium.specs.SubjectLessSpec import ch.tutteli.atrium.specs.forSubjectLess +import ch.tutteli.atrium.specs.invoke abstract class IterableContainsInAnyOrderOnlyValuesAssertionsSpec( containsInAnyOrderOnlyValues: Fun2, Double, Array>, @@ -28,9 +29,8 @@ abstract class IterableContainsInAnyOrderOnlyValuesAssertionsSpec( containsInAnyOrderOnlyNullableValues.forSubjectLess(2.5, arrayOf()) ) {}) - val (containsInOrderNullableValues, containsInOrderNullableValuesFunArr) = containsInAnyOrderOnlyNullableValues - fun Expect>.containsInOrderNullableValuesFun(t: Double?, vararg tX: Double?) = - containsInOrderNullableValuesFunArr(t, tX) + fun Expect>.containsInAnyOrderNullableValuesFun(t: Double?, vararg tX: Double?) = + containsInAnyOrderOnlyNullableValues(this, t, tX) nonNullableCases( describePrefix, @@ -44,7 +44,7 @@ abstract class IterableContainsInAnyOrderOnlyValuesAssertionsSpec( context("empty collection") { it("1.0 throws AssertionError") { expect { - fluentEmpty.containsFun(1.0) + expect(fluentEmpty()).containsFun(1.0) }.toThrow { message { contains( @@ -58,7 +58,7 @@ abstract class IterableContainsInAnyOrderOnlyValuesAssertionsSpec( } it("1.0 and 4.0 throws AssertionError") { expect { - fluentEmpty.containsFun(1.0, 4.0) + expect(fluentEmpty()).containsFun(1.0, 4.0) }.toThrow { message { contains.exactly(1).values( @@ -200,30 +200,30 @@ abstract class IterableContainsInAnyOrderOnlyValuesAssertionsSpec( nullableCases(describePrefix) { - describeFun("$containsInOrderNullableValues for nullable") { + describeFun(containsInAnyOrderOnlyValues) { val null1null3 = { sequenceOf(null, 1.0, null, 3.0).constrainOnce().asIterable() } context("iterable ${null1null3().toList()}") { context("happy cases (do not throw)") { it("null, 1.0, null, 3.0") { - expect(null1null3()).containsInOrderNullableValuesFun(null, 1.0, null, 3.0) + expect(null1null3()).containsInAnyOrderNullableValuesFun(null, 1.0, null, 3.0) } it("1.0, null, null, 3.0") { - expect(null1null3()).containsInOrderNullableValuesFun(1.0, null, null, 3.0) + expect(null1null3()).containsInAnyOrderNullableValuesFun(1.0, null, null, 3.0) } it("1.0, null, 3.0, null") { - expect(null1null3()).containsInOrderNullableValuesFun(1.0, null, 3.0, null) + expect(null1null3()).containsInAnyOrderNullableValuesFun(1.0, null, 3.0, null) } it("1.0, 3.0, null, null") { - expect(null1null3()).containsInOrderNullableValuesFun(1.0, 3.0, null, null) + expect(null1null3()).containsInAnyOrderNullableValuesFun(1.0, 3.0, null, null) } } context("failing cases") { it("null, 1.0, 3.0 -- null was missing") { expect { - expect(null1null3()).containsInOrderNullableValuesFun(null, 1.0, 3.0) + expect(null1null3()).containsInAnyOrderNullableValuesFun(null, 1.0, 3.0) }.toThrow { message { contains.exactly(1).values( diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInOrderOnlyEntriesAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInOrderOnlyEntriesAssertionsSpec.kt index 1129bc145..d1805e1fb 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInOrderOnlyEntriesAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInOrderOnlyEntriesAssertionsSpec.kt @@ -49,9 +49,6 @@ abstract class IterableContainsInOrderOnlyEntriesAssertionsSpec( ) ) {}) - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) - fun Expect>.containsInOrderOnlyNullableEntriesFun( t: (Expect.() -> Unit)?, vararg tX: (Expect.() -> Unit)? @@ -103,7 +100,7 @@ abstract class IterableContainsInOrderOnlyEntriesAssertionsSpec( context("empty collection") { it("$isLessThanFun(1.0) throws AssertionError") { expect { - fluentEmpty.containsEntriesFun({ isLessThan(1.0) }) + expect(fluentEmpty()).containsEntriesFun({ isLessThan(1.0) }) }.toThrow { message { contains("$rootBulletPoint$containsInOrderOnly:") @@ -115,7 +112,7 @@ abstract class IterableContainsInOrderOnlyEntriesAssertionsSpec( } it("$isLessThanFun(1.0) and $isGreaterThanFun(4.0) throws AssertionError") { expect { - fluentEmpty.containsEntriesFun({ isLessThan(1.0) }, { isGreaterThan(4.0) }) + expect(fluentEmpty()).containsEntriesFun({ isLessThan(1.0) }, { isGreaterThan(4.0) }) }.toThrow { message { contains.exactly(1).value("$rootBulletPoint$containsInOrderOnly:") @@ -129,7 +126,7 @@ abstract class IterableContainsInOrderOnlyEntriesAssertionsSpec( //TODO remove with 1.0.0 it("$returnValueOfFun(...) states warning that subject is not set") { expect { - fluentEmpty.containsEntriesFun({ + expect(fluentEmpty()).containsEntriesFun({ @Suppress("DEPRECATION") asAssert().returnValueOf(subject::dec).asExpect().toBe(1.0) }) @@ -271,7 +268,7 @@ abstract class IterableContainsInOrderOnlyEntriesAssertionsSpec( nullableCases(describePrefix) { - describeFun("${containsInOrderOnlyNullableEntries.name} for nullable") { + describeFun(containsInOrderOnlyNullableEntries) { val null1null3 = { sequenceOf(null, 1.0, null, 3.0).constrainOnce().asIterable() } diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInOrderOnlyGroupedValuesAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInOrderOnlyGroupedValuesAssertionsSpec.kt index 4a403e17e..cbea341d2 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInOrderOnlyGroupedValuesAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInOrderOnlyGroupedValuesAssertionsSpec.kt @@ -8,7 +8,6 @@ import ch.tutteli.atrium.specs.* import ch.tutteli.atrium.translations.DescriptionBasic.TO_BE import ch.tutteli.atrium.translations.DescriptionIterableAssertion import org.spekframework.spek2.style.specification.Suite -import org.spekframework.spek2.style.specification.describe abstract class IterableContainsInOrderOnlyGroupedValuesAssertionsSpec( containsInOrderOnlyGroupedValues: Fun3, Group, Group, Array>>, @@ -37,9 +36,6 @@ abstract class IterableContainsInOrderOnlyGroupedValuesAssertionsSpec( containsInOrderOnlyGroupedNullableValues.forSubjectLess(nullableGroup(2.5), nullableGroup(4.1), arrayOf()) ) {}) - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) - fun Expect>.containsInOrderOnlyGroupedNullableValuesFun( t1: Group, t2: Group, @@ -137,187 +133,167 @@ abstract class IterableContainsInOrderOnlyGroupedValuesAssertionsSpec( ) } - fun groupToNullableGroup(group: Group) = nullableGroup(*group.toList().toTypedArray()) + nonNullableCases( + describePrefix, + containsInOrderOnlyGroupedValues, + containsInOrderOnlyGroupedNullableValues + ) { containsFunArr -> - describe("$describePrefix describe non-nullable cases") { - mapOf>.(Group, Group, Array>) -> Any>( - containsInOrderOnlyGroupedValues.name to { g1, g2, gX -> - containsInOrderOnlyGroupedValues( - this, - g1, - g2, - gX - ) - }, - "$containsInOrderOnlyGroupedNullableValues for nullable" to { g1, g2, gX -> - @Suppress("UNCHECKED_CAST") - containsInOrderOnlyGroupedNullableValues( - this as Expect>, - groupToNullableGroup(g1), - groupToNullableGroup(g2), - gX.map { groupToNullableGroup(it) }.toTypedArray() - ) + fun Expect>.containsFun(t1: Group, t2: Group, vararg tX: Group) = + containsFunArr(t1, t2, tX) + + context("throws an $illegalArgumentException") { + it("if an empty group is given as first parameter") { + expect { + expect(oneToFour()).containsFun(context(), context(-1.2)) + }.toThrow { messageContains("a group of values cannot be empty") } } - ).forEach { (describe, containsFunArr) -> + it("if an empty group is given as second parameter") { + expect { + expect(oneToFour()).containsFun(context(1.2), context()) + }.toThrow { messageContains("a group of values cannot be empty") } + } + it("if an empty group is given as third parameter") { + expect { + expect(oneToFour()).containsFun(context(1.2), context(4.3), context()) + }.toThrow { messageContains("a group of values cannot be empty") } + } + it("if an empty group is given as fourth parameter") { + expect { + expect(oneToFour()).containsFun(context(1.2), context(4.3), context(5.7), context()) + }.toThrow { messageContains("a group of values cannot be empty") } + } + } - fun Expect>.containsFun(t1: Group, t2: Group, vararg tX: Group) = - containsFunArr(t1, t2, tX) - - describeFun(describe) { - context("throws an $illegalArgumentException") { - it("if an empty group is given as first parameter") { - expect { - expect(oneToFour()).containsFun(context(), context(-1.2)) - }.toThrow { messageContains("a group of values cannot be empty") } - } - it("if an empty group is given as second parameter") { - expect { - expect(oneToFour()).containsFun(context(1.2), context()) - }.toThrow { messageContains("a group of values cannot be empty") } - } - it("if an empty group is given as third parameter") { - expect { - expect(oneToFour()).containsFun(context(1.2), context(4.3), context()) - }.toThrow { messageContains("a group of values cannot be empty") } - } - it("if an empty group is given as fourth parameter") { - expect { - expect(oneToFour()).containsFun(context(1.2), context(4.3), context(5.7), context()) - }.toThrow { messageContains("a group of values cannot be empty") } + context("empty collection") { + it("(1.0), (1.2) throws AssertionError") { + expect { + expect(fluentEmpty()).containsFun(context(1.0), context(1.2)) + }.toThrow { + message { + contains.exactly(1).value("$rootBulletPoint$containsInOrderOnlyGrouped:") + indexFail(0, sizeExceeded, 1.0) + indexFail(1, sizeExceeded, 1.2) + containsNot(additionalEntries) + containsSize(0, 2) } } + } + } - context("empty collection") { - it("(1.0), (1.2) throws AssertionError") { - expect { - fluentEmpty.containsFun(context(1.0), context(1.2)) - }.toThrow { - message { - contains.exactly(1).value("$rootBulletPoint$containsInOrderOnlyGrouped:") - indexFail(0, sizeExceeded, 1.0) - indexFail(1, sizeExceeded, 1.2) - containsNot(additionalEntries) - containsSize(0, 2) - } + context("iterable ${oneToFour().toList()}") { + + context("happy case") { + it("(1.0), (2.0, 3.0), (4.0, 4.0)") { + expect(oneToFour()).containsFun(context(1.0), context(2.0, 3.0), context(4.0, 4.0)) + } + it("(2.0, 1.0), (4.0, 3.0), (4.0)") { + expect(oneToFour()).containsFun(context(2.0, 1.0), context(4.0, 3.0), context(4.0)) + } + it("(2.0, 3.0, 1.0), (4.0), (4.0)") { + expect(oneToFour()).containsFun(context(2.0, 3.0, 1.0), context(4.0), context(4.0)) + } + it("(1.0, 2.0), (4.0, 3.0, 4.0)") { + expect(oneToFour()).containsFun(context(1.0, 2.0), context(4.0, 3.0, 4.0)) + } + } + + context("error cases (throws AssertionError)") { + + it("(4.0, 1.0), (2.0, 3.0, 4.0) -- wrong order") { + expect { + expect(oneToFour()).containsFun(context(4.0, 1.0), context(2.0, 3.0, 4.0)) + }.toThrow { + message { + contains.exactly(1).value("$rootBulletPoint$containsInOrderOnlyGrouped:") + indexFail( + 0, 1, listOf(1.0, 2.0), + failAfterFail(4.0), + successAfterFail(1.0), + successSizeAfterFail(2), + mismatchesAfterFail(2.0) + ) + indexFail( + 2, 4, listOf(3.0, 4.0, 4.0), + failAfterFail(2.0), + successAfterFail(3.0), + successAfterFail(4.0), + successSizeAfterFail(3), + mismatchesAfterFail(4.0) + ) + containsRegex(size(indentBulletPoint, successfulBulletPoint, 5, 5)) } } } - context("iterable ${oneToFour().toList()}") { - - context("happy case") { - it("(1.0), (2.0, 3.0), (4.0, 4.0)") { - expect(oneToFour()).containsFun(context(1.0), context(2.0, 3.0), context(4.0, 4.0)) - } - it("(2.0, 1.0), (4.0, 3.0), (4.0)") { - expect(oneToFour()).containsFun(context(2.0, 1.0), context(4.0, 3.0), context(4.0)) - } - it("(2.0, 3.0, 1.0), (4.0), (4.0)") { - expect(oneToFour()).containsFun(context(2.0, 3.0, 1.0), context(4.0), context(4.0)) - } - it("(1.0, 2.0), (4.0, 3.0, 4.0)") { - expect(oneToFour()).containsFun(context(1.0, 2.0), context(4.0, 3.0, 4.0)) + it("(1.0), (4.0, 3.0, 2.0) -- 4.0 was missing") { + expect { + expect(oneToFour()).containsFun(context(1.0), context(4.0, 2.0, 3.0)) + }.toThrow { + message { + contains.exactly(1).value("$rootBulletPoint$containsInOrderOnlyGrouped:") + indexSuccess(0, 1.0) + indexSuccess( + 1, 3, listOf(2.0, 3.0, 4.0), + successAfterSuccess(4.0, 2.0, 3.0), + successSizeAfterSuccess(3) + ) + containsRegex(size(indentBulletPoint, failingBulletPoint, 5, 4)) + containsRegex(additional(4 to 4.0)) } } + } - context("error cases (throws AssertionError)") { - - it("(4.0, 1.0), (2.0, 3.0, 4.0) -- wrong order") { - expect { - expect(oneToFour()).containsFun(context(4.0, 1.0), context(2.0, 3.0, 4.0)) - }.toThrow { - message { - contains.exactly(1).value("$rootBulletPoint$containsInOrderOnlyGrouped:") - indexFail( - 0, 1, listOf(1.0, 2.0), - failAfterFail(4.0), - successAfterFail(1.0), - successSizeAfterFail(2), - mismatchesAfterFail(2.0) - ) - indexFail( - 2, 4, listOf(3.0, 4.0, 4.0), - failAfterFail(2.0), - successAfterFail(3.0), - successAfterFail(4.0), - successSizeAfterFail(3), - mismatchesAfterFail(4.0) - ) - containsRegex(size(indentBulletPoint, successfulBulletPoint, 5, 5)) - } - } + it("(1.0), (4.0) -- 2.0, 3.0 and 4.0 was missing") { + expect { + expect(oneToFour()).containsFun(context(1.0), context(4.0)) + }.toThrow { + message { + contains.exactly(1).value("$rootBulletPoint$containsInOrderOnlyGrouped:") + indexSuccess(0, 1.0) + indexFail(1, 2.0, 4.0) + containsRegex(size(indentBulletPoint, failingBulletPoint, 5, 2)) + containsRegex(additional(2 to 3.0, 3 to 4.0, 4 to 4.0)) } - - it("(1.0), (4.0, 3.0, 2.0) -- 4.0 was missing") { - expect { - expect(oneToFour()).containsFun(context(1.0), context(4.0, 2.0, 3.0)) - }.toThrow { - message { - contains.exactly(1).value("$rootBulletPoint$containsInOrderOnlyGrouped:") - indexSuccess(0, 1.0) - indexSuccess( - 1, 3, listOf(2.0, 3.0, 4.0), - successAfterSuccess(4.0, 2.0, 3.0), - successSizeAfterSuccess(3) - ) - containsRegex(size(indentBulletPoint, failingBulletPoint, 5, 4)) - containsRegex(additional(4 to 4.0)) - } - } + } + } + it("(1.0, 3.0), (5.0) -- 5.0 is wrong and 4.0 and 4.0 are missing") { + expect { + expect(oneToFour()).containsFun(context(1.0, 3.0), context(5.0)) + }.toThrow { + message { + contains.exactly(1).value("$rootBulletPoint$containsInOrderOnlyGrouped:") + indexFail( + 0, 1, listOf(1.0, 2.0), + successAfterFail(1.0), + failAfterFail(3.0), + successSizeAfterFail(2), + mismatchesAfterFail(2.0) + ) + indexFail(2, 3.0, 5.0) + containsRegex(size(indentBulletPoint, failingBulletPoint, 5, 3)) + containsRegex(additional(3 to 4.0, 4 to 4.0)) } - - it("(1.0), (4.0) -- 2.0, 3.0 and 4.0 was missing") { - expect { - expect(oneToFour()).containsFun(context(1.0), context(4.0)) - }.toThrow { - message { - contains.exactly(1).value("$rootBulletPoint$containsInOrderOnlyGrouped:") - indexSuccess(0, 1.0) - indexFail(1, 2.0, 4.0) - containsRegex(size(indentBulletPoint, failingBulletPoint, 5, 2)) - containsRegex(additional(2 to 3.0, 3 to 4.0, 4 to 4.0)) - } - } - } - it("(1.0, 3.0), (5.0) -- 5.0 is wrong and 4.0 and 4.0 are missing") { - expect { - expect(oneToFour()).containsFun(context(1.0, 3.0), context(5.0)) - }.toThrow { - message { - contains.exactly(1).value("$rootBulletPoint$containsInOrderOnlyGrouped:") - indexFail( - 0, 1, listOf(1.0, 2.0), - successAfterFail(1.0), - failAfterFail(3.0), - successSizeAfterFail(2), - mismatchesAfterFail(2.0) - ) - indexFail(2, 3.0, 5.0) - containsRegex(size(indentBulletPoint, failingBulletPoint, 5, 3)) - containsRegex(additional(3 to 4.0, 4 to 4.0)) - } - } - } - it("( 4.0, 1.0, 3.0, 2.0), (5.0, 4.0) -- 5.0 too much") { - expect { - expect(oneToFour()).containsFun(context(4.0, 1.0, 3.0, 2.0), context(5.0, 4.0)) - }.toThrow { - message { - contains.exactly(1).value("$rootBulletPoint$containsInOrderOnlyGrouped:") - indexSuccess( - 0, 3, listOf(1.0, 2.0, 3.0, 4.0), - successAfterSuccess(4.0, 1.0, 3.0, 2.0), - successSizeAfterSuccess(4) - ) - indexFail( - 4, 5, listOf(4.0), - failAfterFail(5.0), - successAfterFail(4.0), - failSizeAfterFail(1, 2) - ) - containsRegex(size(indentBulletPoint, failingBulletPoint, 5, 6)) - } - } + } + } + it("( 4.0, 1.0, 3.0, 2.0), (5.0, 4.0) -- 5.0 too much") { + expect { + expect(oneToFour()).containsFun(context(4.0, 1.0, 3.0, 2.0), context(5.0, 4.0)) + }.toThrow { + message { + contains.exactly(1).value("$rootBulletPoint$containsInOrderOnlyGrouped:") + indexSuccess( + 0, 3, listOf(1.0, 2.0, 3.0, 4.0), + successAfterSuccess(4.0, 1.0, 3.0, 2.0), + successSizeAfterSuccess(4) + ) + indexFail( + 4, 5, listOf(4.0), + failAfterFail(5.0), + successAfterFail(4.0), + failSizeAfterFail(1, 2) + ) + containsRegex(size(indentBulletPoint, failingBulletPoint, 5, 6)) } } } @@ -327,7 +303,7 @@ abstract class IterableContainsInOrderOnlyGroupedValuesAssertionsSpec( nullableCases(describePrefix) { - describeFun("$containsInOrderOnlyGroupedNullableValues for nullable") { + describeFun(containsInOrderOnlyGroupedNullableValues) { val null1null3 = { sequenceOf(null, 1.0, null, 3.0).constrainOnce().asIterable() } context("iterable ${null1null3().toList()}") { diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInOrderOnlyValuesAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInOrderOnlyValuesAssertionsSpec.kt index 2338a56a0..4a7f77be8 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInOrderOnlyValuesAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsInOrderOnlyValuesAssertionsSpec.kt @@ -71,7 +71,7 @@ abstract class IterableContainsInOrderOnlyValuesAssertionsSpec( context("empty collection") { it("1.0 throws AssertionError") { expect { - fluentEmpty.containsFun(1.0) + expect(fluentEmpty()).containsFun(1.0) }.toThrow { message { contains("$rootBulletPoint$containsInOrderOnly:") @@ -83,7 +83,7 @@ abstract class IterableContainsInOrderOnlyValuesAssertionsSpec( } it("1.0 and 4.0 throws AssertionError") { expect { - fluentEmpty.containsFun(1.0, 4.0) + expect(fluentEmpty()).containsFun(1.0, 4.0) }.toThrow { message { contains("$rootBulletPoint$containsInOrderOnly:") @@ -199,7 +199,7 @@ abstract class IterableContainsInOrderOnlyValuesAssertionsSpec( nullableCases(describePrefix) { - describeFun("${containsInOrderOnlyNullableValues.name} for nullable") { + describeFun(containsInOrderOnlyNullableValues) { val null1null3 = { sequenceOf(null, 1.0, null, 3.0).constrainOnce().asIterable() } context("iterable ${null1null3().toList()}") { diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsNotEntriesAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsNotEntriesAssertionsSpec.kt index 7b8285425..97257e0d1 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsNotEntriesAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsNotEntriesAssertionsSpec.kt @@ -47,10 +47,6 @@ abstract class IterableContainsNotEntriesAssertionsSpec( ) ) {}) - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) - - fun Expect>.containsNotNullableFun( a: (Expect.() -> Unit)?, vararg aX: (Expect.() -> Unit)? @@ -177,7 +173,7 @@ abstract class IterableContainsNotEntriesAssertionsSpec( } nullableCases(describePrefix) { - describeFun("${containsNotNullableEntries.name} for nullable") { + describeFun(containsNotNullableEntries) { context("iterable ${oneToSeven().toList()}") { it("null does not throw") { expect(oneToSeven() as Iterable).containsNotNullableFun(null) diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsNotValuesAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsNotValuesAssertionsSpec.kt index 6ca3ab444..b13a1b059 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsNotValuesAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsNotValuesAssertionsSpec.kt @@ -31,10 +31,6 @@ abstract class IterableContainsNotValuesAssertionsSpec( containsNotNullableValues.forSubjectLess(2.3, arrayOf()) ) {}) - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) - - fun Expect>.containsNotNullableFun(a: Double?, vararg aX: Double?) = containsNotNullableValues(this, a, aX) @@ -69,7 +65,7 @@ abstract class IterableContainsNotValuesAssertionsSpec( it("4.0 throws AssertionError") { expect { - fluentEmpty.containsNotFun(4.0) + expect(fluentEmpty()).containsNotFun(4.0) }.toThrow { message { containsRegex( @@ -164,7 +160,7 @@ abstract class IterableContainsNotValuesAssertionsSpec( } nullableCases(describePrefix) { - describeFun("${containsNotNullableValues.name} for nullable") { + describeFun(containsNotNullableValues) { context("iterable ${oneToSeven().toList()}") { it("null does not throw") { expect(oneToSeven() as Iterable).containsNotNullableFun(null) diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsSpecBase.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsSpecBase.kt index b618ed894..3c8fed80b 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsSpecBase.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableContainsSpecBase.kt @@ -3,10 +3,8 @@ package ch.tutteli.atrium.specs.integration import ch.tutteli.atrium.api.fluent.en_GB.contains import ch.tutteli.atrium.api.fluent.en_GB.exactly import ch.tutteli.atrium.api.fluent.en_GB.regex -import ch.tutteli.atrium.api.verbs.internal.expect import ch.tutteli.atrium.creating.Expect -import ch.tutteli.atrium.specs.format -import ch.tutteli.atrium.specs.lineSeperator +import ch.tutteli.atrium.specs.* import ch.tutteli.atrium.translations.DescriptionIterableAssertion import org.spekframework.spek2.Spek import org.spekframework.spek2.dsl.Root @@ -48,35 +46,31 @@ abstract class IterableContainsSpecBase(spec: Root.() -> Unit) : Spek(spec) { val atLeast = DescriptionIterableAssertion.AT_LEAST.getDefault() val atMost = DescriptionIterableAssertion.AT_MOST.getDefault() - val fluentEmpty = expect(setOf() as Iterable) + val fluentEmpty = { sequenceOf().constrainOnce().asIterable() } val illegalArgumentException = IllegalArgumentException::class.simpleName val separator = lineSeperator fun Expect.containsSize(actual: Int, expected: Int) = contains.exactly(1).regex("size: $actual[^:]+: $expected") - fun Suite.describeFun(funName: String, body: Suite.() -> Unit) = context("fun `$funName`", body = body) + fun Suite.describeFun(spec: SpecPair<*>, body: Suite.() -> Unit) = describeFun(spec.name, body) + private fun Suite.describeFun(funName: String, body: Suite.() -> Unit) = context("fun `$funName`", body = body) fun Root.nullableCases(describePrefix: String, body: Suite.() -> Unit) { - describe("$describePrefix describe nullable cases", body = body) + describe("$describePrefix nullable cases", body = body) } - fun Root.nonNullableCases( + fun Root.nonNullableCases( describePrefix: String, - containsPair: Pair>.(Double, Array) -> Expect>>, - containsNullablePair: Pair>.(Double?, Array) -> Expect>>, - action: Suite.(Expect>.(Double, Array) -> Any) -> Unit + nonNullableFun: SpecPair, + nullableFun: Any, + action: Suite.(F) -> Unit ) { - describe("$describePrefix describe non-nullable cases") { - mapOf>.(Double, Array) -> Any>( - containsPair.first to { a, aX -> containsPair.second(this, a, aX) }, - containsNullablePair.first to { a, aX -> - @Suppress("UNCHECKED_CAST") - containsNullablePair.second(this as Expect>, a, aX) - } - ).forEach { (describe, containsEntriesFunArr) -> - describeFun(describe) { - action(containsEntriesFunArr) + describe("$describePrefix non-nullable cases") { + val functions = uncheckedToNonNullable(nonNullableFun, nullableFun) + functions.forEach { (name, funArr) -> + describeFun(name) { + action(funArr) } } } diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableFeatureAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableFeatureAssertionsSpec.kt index ef5a10bcf..ca0053c10 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableFeatureAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableFeatureAssertionsSpec.kt @@ -7,17 +7,7 @@ import ch.tutteli.atrium.api.fluent.en_GB.toBe import ch.tutteli.atrium.api.fluent.en_GB.toThrow import ch.tutteli.atrium.api.verbs.internal.expect import ch.tutteli.atrium.creating.Expect -import ch.tutteli.atrium.specs.AssertionCreatorSpec -import ch.tutteli.atrium.specs.Feature0 -import ch.tutteli.atrium.specs.Fun1 -import ch.tutteli.atrium.specs.SubjectLessSpec -import ch.tutteli.atrium.specs.adjustName -import ch.tutteli.atrium.specs.describeFunTemplate -import ch.tutteli.atrium.specs.forAssertionCreatorSpec -import ch.tutteli.atrium.specs.forSubjectLess -import ch.tutteli.atrium.specs.lambda -import ch.tutteli.atrium.specs.name -import ch.tutteli.atrium.specs.toBeDescr +import ch.tutteli.atrium.specs.* import ch.tutteli.atrium.translations.DescriptionIterableAssertion import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.Suite @@ -31,9 +21,9 @@ abstract class IterableFeatureAssertionsSpec( ) : Spek({ include(object : SubjectLessSpec>(describePrefix, - minFeature.forSubjectLess().adjustName { "$it feature" }, + minFeature.forSubjectLess(), min.forSubjectLess { isGreaterThan(-100) }, - maxFeature.forSubjectLess().adjustName { "$it feature" }, + maxFeature.forSubjectLess(), max.forSubjectLess { toBe(1) } ) {}) @@ -43,93 +33,63 @@ abstract class IterableFeatureAssertionsSpec( max.forAssertionCreatorSpec("$toBeDescr: 20") { toBe(20) } ) {}) - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) + fun describeFun(vararg pairs: SpecPair<*>, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, pairs.map { it.name }.toTypedArray(), body = body) - val fluent = expect(listOf(4, 3) as Iterable) - val empty = expect (emptyList() as Iterable) - - describeFun("val ${minFeature.name}") { - val minVal = minFeature.lambda + describeFun(minFeature, min, maxFeature, max) { + val minFunctions = unifySignatures(minFeature, min) + val maxFunctions = unifySignatures(maxFeature, max) context("list with 4 and 3") { - it("toBe(3) holds") { - fluent.minVal().toBe(3) + val fluent = expect(listOf(4, 3) as Iterable) + minFunctions.forEach { (name, minFun, _) -> + it("$name - is greater than 2 holds") { + fluent.minFun { isGreaterThan(2) } + } + it("$name - is less than 2 fails") { + expect { + fluent.minFun { isLessThan(2) } + }.toThrow { + messageContains("min(): 3") + } + } } - it("toBe(5) fails") { - expect { - fluent.minVal().toBe(5) - }.toThrow { - messageContains("min(): 3") + maxFunctions.forEach { (name, maxFun, _) -> + it("$name - toBe(4) holds") { + fluent.maxFun { toBe(4) } + } + it("$name - toBe(3) fails") { + expect { + fluent.maxFun { toBe(3) } + }.toThrow { + messageContains("max(): 4") + } } } } context("empty list") { - it("toBe(3) fails") { - expect { - empty.minVal().toBe(3) - }.toThrow { - messageContains(DescriptionIterableAssertion.NO_ELEMENTS.getDefault()) + val emptyIterable = expect(emptyList() as Iterable) + val noElementsDescr = DescriptionIterableAssertion.NO_ELEMENTS.getDefault() + + minFunctions.forEach { (name, minFun, _) -> + it("$name - fails warning about empty iterable") { + expect { + emptyIterable.minFun { toBe(1) } + }.toThrow { + messageContains(noElementsDescr) + } + } + } + maxFunctions.forEach { (name, maxFun, _) -> + it("$name - fails warning about empty iterable") { + expect { + emptyIterable.maxFun { toBe(1) } + }.toThrow { + messageContains(noElementsDescr) + } } } } } - - describeFun("fun ${min.name}") { - val minFun = min.lambda - - context("list with two entries") { - it("is greater than 2 holds") { - fluent.minFun { isGreaterThan(2) } - } - it("is less than 2 fails") { - expect { - fluent.minFun { isLessThan(2) } - }.toThrow { - messageContains("min(): 3") - } - } - } - } - - describeFun("val ${maxFeature.name}") { - val maxVal = max.lambda - checkMax { assertion -> maxVal(assertion) } - } - - describeFun("fun ${max.name}") { - val maxFun = maxFeature.lambda - checkMax { assert -> maxFun().assert() } - } }) - - -private fun Suite.checkMax(testMax: Expect>.(Expect.() -> Unit) -> Unit) { - val emptyIterable = expect(emptyList() as Iterable) - - val filledIterable = expect(listOf(1, 2) as Iterable) - - context("list with 1 and 2") { - it("toBe(2) holds") { - filledIterable.testMax { toBe(2) } - } - it("toBe(1) fails") { - expect { - filledIterable.testMax { toBe(1) } - }.toThrow { - messageContains("max(): 2") - } - } - } - - context("empty list") { - it("fails warning about empty iterable") { - expect { - emptyIterable.testMax { toBe(1) } - }.toThrow { - messageContains(DescriptionIterableAssertion.NO_ELEMENTS.getDefault()) - } - } - } -} diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableNoneAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableNoneAssertionsSpec.kt index 0e04479f4..a2f828069 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableNoneAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableNoneAssertionsSpec.kt @@ -5,7 +5,6 @@ import ch.tutteli.atrium.api.verbs.internal.expect import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.specs.* import ch.tutteli.atrium.translations.DescriptionIterableAssertion -import org.spekframework.spek2.style.specification.Suite abstract class IterableNoneAssertionsSpec( none: Fun1, Expect.() -> Unit>, @@ -18,7 +17,7 @@ abstract class IterableNoneAssertionsSpec( featureArrow: String, featureBulletPoint: String, describePrefix: String = "[Atrium] " -) : IterablePredicateSpecBase({ +) : IterableContainsEntriesSpecBase({ include(object : SubjectLessSpec>(describePrefix, none.forSubjectLess { toBe(2.3) } @@ -36,10 +35,6 @@ abstract class IterableNoneAssertionsSpec( noneNullable.forAssertionCreatorSpec("$isGreaterThanDescr: 10.0") { isGreaterThan(10.0) } ) {}) - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) - - val containsNotDescr = DescriptionIterableAssertion.CONTAINS_NOT.getDefault() val hasElement = DescriptionIterableAssertion.HAS_ELEMENT.getDefault() @@ -63,6 +58,16 @@ abstract class IterableNoneAssertionsSpec( noneNullable ) { noneFun -> + context("empty collection") { + it("throws AssertionError as there needs to be at least one element") { + expect { + expect(fluentEmpty()).noneFun { isLessThan(1.0) } + }.toThrow { + messageContains("$featureArrow$hasElement: false") + } + } + } + context("iterable ${oneToSeven().toList()}") { context("happy case") { listOf(1.1, 2.2, 3.3).forEach { @@ -93,9 +98,8 @@ abstract class IterableNoneAssertionsSpec( } } } - nullableCases(describePrefix) { - describeFun("${noneNullable.name} for nullable") { + describeFun(noneNullable) { val noneFun = noneNullable.lambda context("iterable ${oneToSeven().toList()}") { diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterablePredicateSpecBase.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterablePredicateSpecBase.kt deleted file mode 100644 index 9d2e77cab..000000000 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterablePredicateSpecBase.kt +++ /dev/null @@ -1,33 +0,0 @@ -package ch.tutteli.atrium.specs.integration - -import ch.tutteli.atrium.creating.Expect -import org.spekframework.spek2.dsl.Root -import org.spekframework.spek2.style.specification.Suite -import org.spekframework.spek2.style.specification.describe - -abstract class IterablePredicateSpecBase(spec: Root.() -> Unit) : - IterableContainsEntriesSpecBase(spec) { - companion object { - - fun Root.nonNullableCases( - describePrefix: String, - containsPair: Pair>.(Expect.() -> Unit) -> Expect>>, - containsNullablePair: Pair>.((Expect.() -> Unit)?) -> Expect>>, - action: Suite.(Expect>.(Expect.() -> Unit) -> Any) -> Unit - ) { - describe("$describePrefix describe non-nullable cases") { - mapOf>.(Expect.() -> Unit) -> Any>( - containsPair.first to { a -> containsPair.second(this, a) }, - "${containsNullablePair.first} for nullable" to { a -> - @Suppress("UNCHECKED_CAST") - containsNullablePair.second(this as Expect>, a) - } - ).forEach { (describe, containsEntriesFunArr) -> - describeFun(describe) { - action(containsEntriesFunArr) - } - } - } - } - } -} diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/KeyValueLikeFeatureAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/KeyValueLikeFeatureAssertionsSpec.kt index 9485338c3..13be4d739 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/KeyValueLikeFeatureAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/KeyValueLikeFeatureAssertionsSpec.kt @@ -4,7 +4,8 @@ import ch.tutteli.atrium.api.fluent.en_GB.* import ch.tutteli.atrium.api.verbs.internal.expect import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.specs.* -import ch.tutteli.atrium.translations.DescriptionBasic.TO_BE +import ch.tutteli.atrium.translations.DescriptionCharSequenceAssertion +import ch.tutteli.atrium.translations.DescriptionComparableAssertion import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.Suite @@ -17,27 +18,28 @@ abstract class KeyValueLikeFeatureAssertionsSpec( key: Fun1.() -> Unit>, valueFeature: Feature0, value: Fun1.() -> Unit>, - nullableKeyFeature: Feature0, - nullableKey: Fun1.() -> Unit>, - nullableValueFeature: Feature0, - nullableValue: Fun1.() -> Unit>, + keyFeatureNullable: Feature0, + keyNullable: Fun1.() -> Unit>, + valueFeatureNullable: Feature0, + valueNullable: Fun1.() -> Unit>, describePrefix: String = "[Atrium] " ) : Spek({ val mapEntry = creator("hello", 1) val nullMapEntry = creatorNullable(null, null) - val toBeDescr = TO_BE.getDefault() include(object : SubjectLessSpec(describePrefix, - keyFeature.forSubjectLess().adjustName { "$it feature" }, + keyFeature.forSubjectLess(), key.forSubjectLess { endsWith("a") }, - valueFeature.forSubjectLess().adjustName { "$it feature" }, + valueFeature.forSubjectLess(), value.forSubjectLess { isGreaterThan(2) } ) {}) include(object : SubjectLessSpec( "$describePrefix[nullable] ", - nullableKeyFeature.forSubjectLess().adjustName { "$it feature" }, - nullableValueFeature.forSubjectLess().adjustName { "$it feature" } + keyFeatureNullable.forSubjectLess(), + keyNullable.forSubjectLess { toBe(null) }, + valueFeatureNullable.forSubjectLess(), + valueNullable.forSubjectLess { toBe(null) } ) {}) include(object : AssertionCreatorSpec( @@ -46,13 +48,13 @@ abstract class KeyValueLikeFeatureAssertionsSpec( value.forAssertionCreatorSpec("$toBeDescr: 1") { toBe(1) } ) {}) include(object : AssertionCreatorSpec( - describePrefix, nullMapEntry, - nullableKey.forAssertionCreatorSpec("$toBeDescr: null") { toBe(null) }, - nullableValue.forAssertionCreatorSpec("$toBeDescr: null") { toBe(null) } + "$describePrefix[nullable]", nullMapEntry, + keyNullable.forAssertionCreatorSpec("$toBeDescr: null") { toBe(null) }, + valueNullable.forAssertionCreatorSpec("$toBeDescr: null") { toBe(null) } ) {}) - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) + fun describeFun(vararg pairs: SpecPair<*>, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, pairs.map { it.name }.toTypedArray(), body = body) val nullableMapEntry = creatorNullable("hello", 1) @@ -60,187 +62,102 @@ abstract class KeyValueLikeFeatureAssertionsSpec( val nullableFluent = expect(nullableMapEntry) val nullFluent = expect(nullMapEntry) - describeFun("${keyFeature.name} feature") { - val keyVal = keyFeature.lambda + describeFun(keyFeature, key, keyFeatureNullable, keyNullable, valueFeature, value, valueFeature, valueNullable) { + val keyFunctions = uncheckedToNonNullable( + unifySignatures(keyFeature, key), + unifySignatures(keyFeatureNullable, keyNullable) + ) + val valueFunctions = unifySignatures(valueFeature, value) context("$mapEntry") { - it("startsWith(h) holds") { - fluent.keyVal().startsWith("h") - } - it("endsWith(h) fails") { - expect { - fluent.keyVal().endsWith("h") - }.toThrow { - messageContains("$keyName: \"hello\"") + keyFunctions.forEach { (name, keyFun, _) -> + it("$name - startsWith(h) holds") { + fluent.keyFun { startsWith("h") } + } + it("$name - endsWith(h) fails") { + expect { + fluent.keyFun { endsWith('h') } + }.toThrow { + messageContains( + "$keyName: \"hello\"", + DescriptionCharSequenceAssertion.ENDS_WITH.getDefault() + ": \"h\"" + ) + } } } - } - } - describeFun(key.name) { - val keyFun = key.lambda - - context("$mapEntry") { - it("startsWith(h) holds") { - fluent.keyFun { startsWith("h") } - } - it("endsWith(h) fails") { - expect { - fluent.keyFun { endsWith("h") } - }.toThrow { - messageContains("$keyName: \"hello\"") + valueFunctions.forEach { (name, valueFun, _) -> + it("$name - isGreaterThan(0) holds") { + fluent.valueFun { isGreaterThan(0) } + } + it("$name - isGreaterThan(1) fails") { + expect { + fluent.valueFun { isGreaterThan(1) } + }.toThrow { + messageContains( + "$valueName: 1", + DescriptionComparableAssertion.IS_GREATER_THAN.getDefault() + ": 1" + ) + } } } } } - describeFun("${valueFeature.name} feature") { - val valueVal = valueFeature.lambda - - context("$mapEntry") { - it("isGreaterThan(0) holds") { - fluent.valueVal().isGreaterThan(0) - } - it("isGreaterThan(1) fails") { - expect { - fluent.valueVal().isGreaterThan(1) - }.toThrow { - messageContains("$valueName: 1") - } - } - } - } - - describeFun(value.name) { - val valueFun = value.lambda - - context("$mapEntry") { - it("isGreaterThan(0) holds") { - fluent.valueFun { isGreaterThan(0) } - } - it("isGreaterThan(1) fails") { - expect { - fluent.valueFun { isGreaterThan(1) } - }.toThrow { - messageContains("$valueName: 1") - } - } - } - } - - describeFun("${nullableKeyFeature.name} nullable feature") { - val nullableKeyFun = nullableKeyFeature.lambda + describeFun(keyFeatureNullable, keyNullable, valueFeatureNullable, valueNullable) { + val keyFunctions = unifySignatures(keyFeatureNullable, keyNullable) + val valueFunctions = unifySignatures(valueFeatureNullable, valueNullable) context("$nullableMapEntry") { - it("toBe(hello)") { - nullableFluent.nullableKeyFun().toBe("hello") + keyFunctions.forEach { (name, nullableKeyFun, _) -> + it("$name - toBe(hello) holds") { + nullableFluent.nullableKeyFun { toBe("hello") } + } + it("$name - toBe(null) throws AssertionError") { + expect { + nullableFluent.nullableKeyFun { toBe(null) } + }.toThrow { + messageContains("$keyName: \"hello\"") + } + } } - it("toBe(null) fails") { - expect { - nullableFluent.nullableKeyFun().toBe(null) - }.toThrow { - messageContains("$keyName: \"hello\"") + valueFunctions.forEach { (name, nullableValueFun, _) -> + it("$name - isGreaterThan(0) holds") { + nullableFluent.nullableValueFun { notToBeNull { isGreaterThan(0) } } + } + it("$name - toBe(null) throws AssertionError") { + expect { + nullableFluent.nullableValueFun { toBe(null) } + }.toThrow { + messageContains("$valueName: 1") + } } } } context("$nullMapEntry") { - it("toBe(null)") { - nullFluent.nullableKeyFun().toBe(null) - } - it("toBe(hello) fails") { - expect { - nullFluent.nullableKeyFun().toBe("hello") - }.toThrow { - messageContains("$keyName: null") + keyFunctions.forEach { (name, nullableKeyFun, _) -> + it("$name - toBe(null) holds") { + nullFluent.nullableKeyFun { toBe(null) } + } + it("$name - toBe(hello) throws AssertionError") { + expect { + nullFluent.nullableKeyFun { toBe("hello") } + }.toThrow { + messageContains("$keyName: null", "$toBeDescr: \"hello\"") + } } } - } - } - - describeFun("${nullableKey.name} nullable") { - val nullableKeyFun = nullableKey.lambda - - context("$nullableMapEntry") { - it("toBe(hello)") { - nullableFluent.nullableKeyFun { toBe("hello") } - } - it("toBe(null) fails") { - expect { - nullableFluent.nullableKeyFun { toBe(null) } - }.toThrow { - messageContains("$keyName: \"hello\"") + valueFunctions.forEach { (name, nullableValueFun, _) -> + it("$name - toBe(null) holds") { + nullFluent.nullableValueFun { toBe(null) } } - } - } - context("$nullMapEntry") { - it("toBe(null)") { - nullFluent.nullableKeyFun { toBe(null) } - } - it("toBe(hello) fails") { - expect { - nullFluent.nullableKeyFun { toBe("hello") } - }.toThrow { - messageContains("$keyName: null") - } - } - } - } - - - describeFun("${nullableValueFeature.name} nullable feature") { - val nullableValueFun = nullableValueFeature.lambda - - context("$nullableMapEntry") { - it("isGreaterThan(0) holds") { - nullableFluent.nullableValueFun().notToBeNull { isGreaterThan(0) } - } - it("toBe(null) fails") { - expect { - nullableFluent.nullableValueFun().toBe(null) - }.toThrow { - messageContains("$valueName: 1") - } - } - } - context("$nullMapEntry") { - it("toBe(null)") { - nullFluent.nullableValueFun().toBe(null) - } - it("toBe(1) fails") { - expect { - nullFluent.nullableValueFun().toBe(1) - }.toThrow { - messageContains("$valueName: null") - } - } - } - } - - describeFun("${nullableValue.name} nullable") { - val nullableValueFun = nullableValue.lambda - - context("$nullableMapEntry") { - it("isGreaterThan(0) holds") { - nullableFluent.nullableValueFun { notToBeNull { isGreaterThan(0) } } - } - it("toBe(null) fails") { - expect { - nullableFluent.nullableValueFun { toBe(null) } - }.toThrow { - messageContains("$valueName: 1") - } - } - } - context("$nullMapEntry") { - it("toBe(null)") { - nullFluent.nullableValueFun { toBe(null) } - } - it("toBe(1) fails") { - expect { - nullFluent.nullableValueFun { toBe(1) } - }.toThrow { - messageContains("$valueName: null") + it("$name - toBe(1) throws AssertionError") { + expect { + nullFluent.nullableValueFun { toBe(1) } + }.toThrow { + messageContains("$valueName: null") + } } } } diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/ListFeatureAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/ListFeatureAssertionsSpec.kt index 8f46c20d6..fe9c4743e 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/ListFeatureAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/ListFeatureAssertionsSpec.kt @@ -13,7 +13,7 @@ import org.spekframework.spek2.style.specification.Suite abstract class ListFeatureAssertionsSpec( getFeature: Feature1, Int, Int>, get: Fun2, Int, Expect.() -> Unit>, - getNullableFeature: Feature1, Int, Int?>, + getFeatureNullable: Feature1, Int, Int?>, getNullable: Fun2, Int, Expect.() -> Unit>, describePrefix: String = "[Atrium] " ) : Spek({ @@ -21,11 +21,11 @@ abstract class ListFeatureAssertionsSpec( val list = listOf(1, 2, 3, 4) include(object : SubjectLessSpec>(describePrefix, - getFeature.forSubjectLess(1).adjustName { "$it feature" }, + getFeature.forSubjectLess(1), get.forSubjectLess(1) { toBe(1) } ) {}) include(object : SubjectLessSpec>("$describePrefix[nullable Element] ", - getNullableFeature.forSubjectLess(1).adjustName { "$it feature" }, + getFeatureNullable.forSubjectLess(1), getNullable.forSubjectLess(1) { toBe(null) } ) {}) @@ -38,9 +38,8 @@ abstract class ListFeatureAssertionsSpec( getNullable.forAssertionCreatorSpec("$toBeDescr: 2", 1) { toBe(2) } ) {}) - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) - + fun describeFun(vararg pairs: SpecPair<*>, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, pairs.map { it.name }.toTypedArray(), body = body) val fluent = expect(list) val listNullable = listOf(1, null, 3, 4) @@ -48,73 +47,37 @@ abstract class ListFeatureAssertionsSpec( val indexOutOfBounds = DescriptionListAssertion.INDEX_OUT_OF_BOUNDS.getDefault() - describeFun("${getFeature.name} feature") { - val getFun = getFeature.lambda + describeFun(getFeature, get, getFeatureNullable, getNullable) { + val getFunctions = uncheckedToNonNullable( + unifySignatures(getFeature, get), + unifySignatures(getFeatureNullable, getNullable) + ) + context("list $list") { - it("can perform sub-assertion on existing index") { - fluent.getFun(0).toBe(1) - } - it("non-existing index throws") { - expect { - fluent.getFun(4).toBe(1) - }.toThrow { - messageContains("get(4): $indexOutOfBounds") + getFunctions.forEach { (name, getFun, hasExtraHint) -> + it("$name - can perform sub-assertion on existing index") { + fluent.getFun(0) { toBe(1) } + } + it("$name - non-existing index throws" + showsSubAssertionIf(hasExtraHint)) { + expect { + fluent.getFun(4) { toBe(3) } + }.toThrow { + messageContains("get(4): $indexOutOfBounds") + if (hasExtraHint) messageContains("$toBeDescr: 3") + } } } + + } } - describeFun(get.name) { - val getFun = get.lambda - context("list $list") { - it("can perform sub-assertion on existing index") { - fluent.getFun(0) { toBe(1) } - } - it("non-existing index throws but shows intended sub-assertion") { - expect { - fluent.getFun(4) { toBe(3) } - }.toThrow { - messageContains("get(4): $indexOutOfBounds", "$toBeDescr: 3") - } - } - } - } - - describeFun("${getNullableFeature.name} nullable feature") { - val getFun = getNullableFeature.lambda + describeFun(getFeatureNullable, getNullable) { + val getFunctions = unifySignatures(getFeatureNullable, getNullable) context("list $listNullable") { - it("can perform sub-assertion on existing key") { - fluentNullable.getFun(0).toBe(1) - } - it("can perform sub-assertion on existing key with value null") { - fluentNullable.getFun(1).toBe(null) - } - - it("non-existing key throws") { - expect { - fluentNullable.getFun(4).toBe(null) - }.toThrow { - messageContains("get(4): $indexOutOfBounds") - } - } - } - } - - describeFun("${getNullable.name} nullable") { - val getFun = getNullable.lambda - context("list $listNullable") { - it("can perform sub-assertion on existing key") { - fluentNullable.getFun(0) { toBe(1) } - } - it("can perform sub-assertion on existing key with value null") { - fluentNullable.getFun(1) { toBe(null) } - } - - it("non-existing key throws but shows intended sub-assertion") { - expect { - fluentNullable.getFun(4) { toBe(null) } - }.toThrow { - messageContains("get(4): $indexOutOfBounds", "$toBeDescr: null") + getFunctions.forEach { (name, getFun, _) -> + it("$name - can perform sub-assertion on existing index with value null") { + fluentNullable.getFun(1) { toBe(null) } } } } diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/MapAsEntriesAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/MapAsEntriesAssertionsSpec.kt index 20c867cf3..4d22ea6a6 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/MapAsEntriesAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/MapAsEntriesAssertionsSpec.kt @@ -15,32 +15,27 @@ abstract class MapAsEntriesAssertionsSpec( include(object : SubjectLessSpec>( describePrefix, - asEntriesFeature.forSubjectLess().adjustName { "$it feature" }, + asEntriesFeature.forSubjectLess(), asEntries.forSubjectLess { contains("a" to 1) } ) {}) - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) + fun describeFun(vararg pairs: SpecPair<*>, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, pairs.map { it.name }.toTypedArray(), body = body) - describeFun(asEntriesFeature.name + " feature") { - it("transformation can be applied and an assertion made") { - expect(mapOf("a" to 1, "b" to 2)).(asEntriesFeature.lambda)().contains.inAnyOrder.only.entries( - { isKeyValue("b", 2) }, - { key { startsWith("a") }.and.value.isGreaterThanOrEqual(1) } - ) - } - } + describeFun(asEntriesFeature, asEntries) { + val asEntriesFunctions = unifySignatures(asEntriesFeature, asEntries) - describeFun(asEntries.name) { - it("transformation can be applied and an assertion made") { - expect(mapOf("a" to 1, "b" to 2)).(asEntries.lambda){ - contains.inAnyOrder.only.entries( - { isKeyValue("b", 2) }, - { - key { startsWith("a") } - value.isGreaterThanOrEqual(1) - } - ) + asEntriesFunctions.forEach{ (name, asEntriesFun, _) -> + it("$name - transformation can be applied and an assertion made") { + expect(mapOf("a" to 1, "b" to 2)).asEntriesFun { + contains.inAnyOrder.only.entries( + { isKeyValue("b", 2) }, + { + key { startsWith("a") } + value.isGreaterThanOrEqual(1) + } + ) + } } } } diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/MapAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/MapAssertionsSpec.kt index 774df8141..5f81787ca 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/MapAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/MapAssertionsSpec.kt @@ -9,16 +9,24 @@ import ch.tutteli.atrium.translations.DescriptionComparableAssertion import ch.tutteli.atrium.translations.DescriptionMapAssertion import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.Suite +import kotlin.reflect.KFunction3 + +typealias MFun2 = Fun2, Pair, Array>> + +fun mfun2( + f: KFunction3>, Pair, Array>, Expect>> +) = fun2(f) + abstract class MapAssertionsSpec( - contains: Fun2, Pair, Array>>, - containsNullable: Fun2, Pair, Array>>, - containsKeyWithValueAssertions: Fun2, Pair.() -> Unit>, Array.() -> Unit>>>, - containsKeyWithNullableValueAssertions: Fun2, Pair.() -> Unit)?>, Array.() -> Unit)?>>>, + contains: MFun2, + containsNullable: MFun2, + containsKeyWithValueAssertions: MFun2.() -> Unit>, + containsKeyWithNullableValueAssertions: MFun2.() -> Unit)?>, containsKey: Fun1, String>, - containsNullableKey: Fun1, String?>, + containsKeyNullable: Fun1, String?>, containsNotKey: Fun1, String>, - containsNotNullableKey: Fun1, String?>, + containsNotKeyNullable: Fun1, String?>, isEmpty: Fun0>, isNotEmpty: Fun0>, describePrefix: String = "[Atrium] " @@ -55,8 +63,8 @@ abstract class MapAssertionsSpec( keyNullableValue(null) { toBe(1) }, arrayOf(keyNullableValue("a", null)) ), - containsNullableKey.forSubjectLess(null).unchecked1(), - containsNotNullableKey.forSubjectLess(null).unchecked1() + containsKeyNullable.forSubjectLess(null).unchecked1(), + containsNotKeyNullable.forSubjectLess(null).unchecked1() ) {}) include(object : AssertionCreatorSpec>( @@ -75,8 +83,9 @@ abstract class MapAssertionsSpec( ) {}) - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) + fun describeFun(vararg pairs: SpecPair<*>, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, pairs.map { it.name }.toTypedArray(), body = body) + val map: Map = mapOf("a" to 1, "b" to 2) val fluent = expect(map) @@ -93,43 +102,46 @@ abstract class MapAssertionsSpec( fun entry(key: String, value: Any): String = entry(key) + ": " + value - describeFun(contains.name) { - val containsFun = contains.lambda + describeFun(contains, containsNullable) { + val containsFunctions = uncheckedToNonNullable(contains, containsNullable) + context("map $map") { - listOf( - listOf("a" to 1), - listOf("b" to 2), - listOf("a" to 1, "b" to 2), - listOf("b" to 2, "a" to 1) - ).forEach { - it("$it does not throw") { - fluent.containsFun(it.first(), it.drop(1).toTypedArray()) + containsFunctions.forEach { (name, containsFun) -> + listOf( + listOf("a" to 1), + listOf("b" to 2), + listOf("a" to 1, "b" to 2), + listOf("b" to 2, "a" to 1) + ).forEach { + it("$name - $it does not throw") { + fluent.containsFun(it.first(), it.drop(1).toTypedArray()) + } } - } - it("a to 1 and a to 1 does not throw (no unique match)") { - fluent.containsFun("a" to 1, arrayOf("a" to 1)) - } + it("$name - a to 1 and a to 1 does not throw (no unique match)") { + fluent.containsFun("a" to 1, arrayOf("a" to 1)) + } - it("{a to 1, b to 3, c to 4} throws AssertionError, reports b and c") { - expect { - fluent.containsFun("a" to 1, arrayOf("b" to 3, "c" to 4)) - }.toThrow { - message { - contains( - entry("b", 2), - "$toBeDescr: 3", - entry("c", keyDoesNotExist), - "$toBeDescr: 4" - ) - containsNot(entry("a")) + it("$name - {a to 1, b to 3, c to 4} throws AssertionError, reports b and c") { + expect { + fluent.containsFun("a" to 1, arrayOf("b" to 3, "c" to 4)) + }.toThrow { + message { + contains( + entry("b", 2), + "$toBeDescr: 3", + entry("c", keyDoesNotExist), + "$toBeDescr: 4" + ) + containsNot(entry("a")) + } } } } } } - describeFun("${containsNullable.name} for nullable") { + describeFun(containsNullable) { val containsNullableFun = containsNullable.lambda context("map $nullableMap") { listOf( @@ -169,49 +181,55 @@ abstract class MapAssertionsSpec( } } - describeFun(containsKeyWithValueAssertions.name) { - val containsKeyWithValueAssertionsFun = containsKeyWithValueAssertions.lambda + describeFun(containsKeyWithValueAssertions, containsKeyWithNullableValueAssertions) { + val containsKeyWithValueAssertionsFunctions = uncheckedToNonNullable( + containsKeyWithValueAssertions, + containsKeyWithNullableValueAssertions + ) + context("map $map") { - listOf( - "a { toBe(1) }" to listOf(keyValue("a") { toBe(1) }), - "b { toBe(2) }" to listOf(keyValue("b") { toBe(2) }), - "a { toBe(1) }, b { toBe(2) }" to listOf(keyValue("a") { toBe(1) }, keyValue("b") { toBe(2) }), - "b { toBe(2) }, a { toBe(1) }" to listOf(keyValue("b") { toBe(2) }, keyValue("a") { toBe(1) }) - ).forEach { (description, keyValues) -> - it("$description does not throw") { - fluent.containsKeyWithValueAssertionsFun(keyValues.first(), keyValues.drop(1).toTypedArray()) + containsKeyWithValueAssertionsFunctions.forEach { (name, containsKeyWithValueAssertionsFun) -> + listOf( + "a { toBe(1) }" to listOf(keyValue("a") { toBe(1) }), + "b { toBe(2) }" to listOf(keyValue("b") { toBe(2) }), + "a { toBe(1) }, b { toBe(2) }" to listOf(keyValue("a") { toBe(1) }, keyValue("b") { toBe(2) }), + "b { toBe(2) }, a { toBe(1) }" to listOf(keyValue("b") { toBe(2) }, keyValue("a") { toBe(1) }) + ).forEach { (description, keyValues) -> + it("$name - $description does not throw") { + fluent.containsKeyWithValueAssertionsFun(keyValues.first(), keyValues.drop(1).toTypedArray()) + } } - } - it("a { isLessThan(2) } and a { isGreaterThan(0) } does not throw (no unique match)") { - fluent.containsKeyWithValueAssertionsFun( - keyValue("a") { isLessThan(2) }, - arrayOf(keyValue("a") { isGreaterThan(0) }) - ) - } - - it("a { isLessThan(3) }, b { isLessThan(2) }, c { isLessThan(1) }} throws AssertionError, reports b and c") { - expect { + it("$name - a { isLessThan(2) } and a { isGreaterThan(0) } does not throw (no unique match)") { fluent.containsKeyWithValueAssertionsFun( - keyValue("a") { isLessThan(3) }, - arrayOf(keyValue("b") { isLessThan(2) }, keyValue("c") { isLessThan(1) }) + keyValue("a") { isLessThan(2) }, + arrayOf(keyValue("a") { isGreaterThan(0) }) ) - }.toThrow { - message { - contains( - entry("b", 2), - "$lessThanDescr: 2", - entry("c", keyDoesNotExist), - "$lessThanDescr: 1" + } + + it("$name - a { isLessThan(3) }, b { isLessThan(2) }, c { isLessThan(1) }} throws AssertionError, reports b and c") { + expect { + fluent.containsKeyWithValueAssertionsFun( + keyValue("a") { isLessThan(3) }, + arrayOf(keyValue("b") { isLessThan(2) }, keyValue("c") { isLessThan(1) }) ) - containsNot(entry("a")) + }.toThrow { + message { + contains( + entry("b", 2), + "$lessThanDescr: 2", + entry("c", keyDoesNotExist), + "$lessThanDescr: 1" + ) + containsNot(entry("a")) + } } } } } } - describeFun("${containsKeyWithNullableValueAssertions.name} for nullable") { + describeFun(containsKeyWithNullableValueAssertions) { val containsKeyWithNullableValueAssertionsFun = containsKeyWithNullableValueAssertions.lambda context("map $nullableMap") { listOf( @@ -247,13 +265,6 @@ abstract class MapAssertionsSpec( } } - it("b { isLessThan(3) } and b { isGreaterThan(0) } does not throw (no unique match)") { - nullableFluent.containsKeyWithNullableValueAssertionsFun( - keyNullableValue("b") { isLessThan(3) }, - arrayOf(keyNullableValue("b") { isGreaterThan(0) }) - ) - } - it("(a, null), b { isLessThan(2) }, c { isLessThan(1) }} throws AssertionError, reports b and c") { expect { nullableFluent.containsKeyWithNullableValueAssertionsFun( @@ -277,99 +288,99 @@ abstract class MapAssertionsSpec( } } - describeFun(containsKey.name) { - val containsKeyFun = containsKey.lambda + describeFun(containsKey, containsKeyNullable, containsNotKey, containsNotKeyNullable) { + val containsKeyFunctions = uncheckedToNonNullable(containsKey, containsKeyNullable) + val containsNotKeyFunctions = uncheckedToNonNullable(containsNotKey, containsNotKeyNullable) + val fluent2 = expect(map as Map) - it("does not throw if the map contains the key") { - fluent2.containsKeyFun("a") - } + context("$map") { + containsKeyFunctions.forEach { (name, containsKeyFun) -> + it("$name - does not throw if the map contains the key") { + fluent2.containsKeyFun("a") + } - it("throws an AssertionError if the map does not contain the key") { - expect { - fluent2.containsKeyFun("c") - }.toThrow { messageContains("$containsKeyDescr: \"c\"") } - } + it("$name - throws an AssertionError if the map does not contain the key") { + expect { + fluent2.containsKeyFun("c") + }.toThrow { messageContains("$containsKeyDescr: \"c\"") } + } - it("does not throw if null is passed and the map contains null as key") { - fluent2.containsKeyFun("a") + it("$name - does not throw if null is passed and the map contains null as key") { + fluent2.containsKeyFun("a") + } + } + + containsNotKeyFunctions.forEach { (name, containsNotKeyFun) -> + it("$name - does not throw if the map does not contain the key") { + fluent2.containsNotKeyFun("c") + } + + it("$name - throws an AssertionError if the map contains the key") { + expect { + fluent2.containsNotKeyFun("a") + }.toThrow { messageContains("$containsNotKeyDescr: \"a\"") } + } + } } } - describeFun("$containsNullableKey for nullable key type") { - val containsNullableKeyFun = containsNullableKey.lambda - it("does not throw if the map contains the key") { - val map2: Map = mapOf("a" to 1, null to 2) - expect(map2).containsNullableKeyFun(null) - } + describeFun(containsKeyNullable, containsNotKeyNullable) { + val containsNullableKeyFun = containsKeyNullable.lambda + val containsNotNullableKeyFun = containsNotKeyNullable.lambda - it("throws an AssertionError if the map does not contain the key") { - expect { - val map2: Map = mapOf("a" to 1, "b" to 2) + val map2: Map = mapOf("a" to 1, null to 2) + context("$map2") { + it("${containsKeyNullable.name} - does not throw if the map contains the key") { expect(map2).containsNullableKeyFun(null) - }.toThrow { messageContains("$containsKeyDescr: null") } + } + + it("${containsNotKeyNullable.name} - throws an AssertionError if the map contains the key") { + expect { + expect(map2).containsNotNullableKeyFun(null) + }.toThrow { messageContains("$containsNotKeyDescr: null") } + } + } + + val map3: Map = mapOf("a" to 1, "b" to 2) + context("$map3") { + it("${containsKeyNullable.name} - throws an AssertionError if the map does not contain the key") { + expect { + expect(map3).containsNullableKeyFun(null) + }.toThrow { messageContains("$containsKeyDescr: null") } + } + + it("${containsNotKeyNullable.name} - does not throw if the map does not contain the key") { + expect(map3).containsNotNullableKeyFun(null) + } } } - describeFun(containsNotKey.name) { - val containsNotKeyFun = containsNotKey.lambda - val fluent2 = expect(map as Map) - - it("does not throw if the map does not contain the key") { - fluent2.containsNotKeyFun("c") - } - - it("throws an AssertionError if the map contains the key") { - expect { - fluent2.containsNotKeyFun("a") - }.toThrow { messageContains("$containsNotKeyDescr: \"a\"") } - } - } - - describeFun("${containsNotNullableKey.name} for nullable key type") { - val containsNotNullableKeyFun = containsNotNullableKey.lambda - - it("does not throw if the map does not contain the key") { - val map2: Map = mapOf("a" to 1, "b" to 2) - expect(map2).containsNotNullableKeyFun(null) - } - - it("throws an AssertionError if the map contains the key") { - expect { - val map2: Map = mapOf("a" to 1, null to 2) - expect(map2).containsNotNullableKeyFun(null) - }.toThrow { messageContains("$containsNotKeyDescr: null") } - } - } - - - describeFun(isEmpty.name) { + describeFun(isEmpty, isNotEmpty) { val isEmptyFun = isEmpty.lambda - - it("does not throw if a map is empty") { - val map2: Map<*, *> = mapOf() - expect(map2).isEmptyFun() - } - - it("throws an AssertionError if a map is not empty") { - expect { - expect(map as Map<*, *>).isEmptyFun() - }.toThrow { messageContains("$isDescr: $empty") } - } - } - - describeFun(isNotEmpty.name) { val isNotEmptyFun = isNotEmpty.lambda - it("does not throw if a map is not empty") { - expect(map as Map<*, *>).isNotEmptyFun() - } + val map2: Map<*, *> = mapOf() + context("empty Map") { + it("${isEmpty.name} - does not throw") { + expect(map2).isEmptyFun() + } - it("throws an AssertionError if a map is empty") { - expect { - val map2: Map<*, *> = mapOf() - expect(map2).isNotEmptyFun() - }.toThrow { messageContains("$isNotDescr: $empty") } + it("${isNotEmpty.name} - throws an AssertionError") { + expect { + expect(map2).isNotEmptyFun() + }.toThrow { messageContains("$isNotDescr: $empty") } + } + } + context("$map") { + it("${isEmpty.name} - throws an AssertionError") { + expect { + expect(map as Map<*, *>).isEmptyFun() + }.toThrow { messageContains("$isDescr: $empty") } + } + it("${isNotEmpty.name} - does not throw") { + expect(map as Map<*, *>).isNotEmptyFun() + } } } }) diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/MapEntryAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/MapEntryAssertionsSpec.kt index 7e69d23ec..a56e88029 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/MapEntryAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/MapEntryAssertionsSpec.kt @@ -1,9 +1,6 @@ package ch.tutteli.atrium.specs.integration -import ch.tutteli.atrium.api.fluent.en_GB.contains -import ch.tutteli.atrium.api.fluent.en_GB.containsNot -import ch.tutteli.atrium.api.fluent.en_GB.message -import ch.tutteli.atrium.api.fluent.en_GB.toThrow +import ch.tutteli.atrium.api.fluent.en_GB.* import ch.tutteli.atrium.api.verbs.internal.expect import ch.tutteli.atrium.specs.* import org.spekframework.spek2.Spek @@ -24,83 +21,58 @@ abstract class MapEntryAssertionsSpec( isKeyValueNullable.forSubjectLess("key", 1) ) {}) - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) + fun describeFun(vararg pairs: SpecPair<*>, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, pairs.map { it.name }.toTypedArray(), body = body) val mapEntry = mapEntry("a", 1) val fluent = expect(mapEntry) - val mapEntryNullable = mapEntry("a" as String?, 1 as Int?) - val fluentNullable = expect(mapEntryNullable) - describeFun(isKeyValue.name) { - val isKeyValueFun = isKeyValue.lambda + describeFun(isKeyValue, isKeyValueNullable) { + val isKeyValueFunctions = uncheckedToNonNullable(isKeyValue, isKeyValueNullable) + context("map $mapEntry") { - it("a to 1 does not throw") { - fluent.isKeyValueFun("a", 1) - } + isKeyValueFunctions.forEach { (name, isKeyValueFun) -> + it("$name - a to 1 does not throw") { + fluent.isKeyValueFun("a", 1) + } - it("a to 2 throws AssertionError") { - expect { - fluent.isKeyValueFun("a", 2) - }.toThrow { - message { - contains("value: 1", "$toBeDescr: 2") - containsNot("key") + it("$name - a to 2 throws AssertionError") { + expect { + fluent.isKeyValueFun("a", 2) + }.toThrow { + message { + contains("value: 1", "$toBeDescr: 2") + containsNot("key") + } } } - } - it("b to 1 throws AssertionError") { - expect { - fluent.isKeyValueFun("b", 1) - }.toThrow { - message { - contains("key: \"a\"", "$toBeDescr: \"b\"") - containsNot("value") + it("$name - b to 1 throws AssertionError") { + expect { + fluent.isKeyValueFun("b", 1) + }.toThrow { + message { + contains("key: \"a\"", "$toBeDescr: \"b\"") + containsNot("value") + } } } } } } - describeFun("${isKeyValueNullable.name} nullable") { + describeFun(isKeyValueNullable) { val isKeyValueFun = isKeyValueNullable.lambda - context("map $mapEntryNullable") { - it("a to 1 does not throw") { - fluentNullable.isKeyValueFun("a", 1) - } - - it("a to 2 throws AssertionError") { - expect { - fluentNullable.isKeyValueFun("a", 2) - }.toThrow { - message { - contains("value: 1", "$toBeDescr: 2") - containsNot("key") - } - } - } - it("b to 1 throws AssertionError") { - expect { - fluentNullable.isKeyValueFun("b", 1) - }.toThrow { - message { - contains("key: \"a\"", "$toBeDescr: \"b\"") - containsNot("value") - } - } - } - } val mapEntryNullable2 = mapEntry(null as String?, null as Int?) - val fluentNullable2 = expect(mapEntryNullable2) + val fluentNullable = expect(mapEntryNullable2) context("map $mapEntryNullable2") { it("null to null does not throw") { - fluentNullable2.isKeyValueFun(null, null) + fluentNullable.isKeyValueFun(null, null) } it("null to 2 throws AssertionError") { expect { - fluentNullable2.isKeyValueFun(null, 2) + fluentNullable.isKeyValueFun(null, 2) }.toThrow { message { contains("value: null", "$toBeDescr: 2") @@ -110,7 +82,7 @@ abstract class MapEntryAssertionsSpec( } it("b to null throws AssertionError") { expect { - fluentNullable2.isKeyValueFun("b", null) + fluentNullable.isKeyValueFun("b", null) }.toThrow { message { contains("key: null", "$toBeDescr: \"b\"") diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/MapFeatureAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/MapFeatureAssertionsSpec.kt index 9c5fe4e9f..189116557 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/MapFeatureAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/MapFeatureAssertionsSpec.kt @@ -24,14 +24,14 @@ abstract class MapFeatureAssertionsSpec( val mapNullable = mapOf("a" to 1, "b" to null, null to 3) include(object : SubjectLessSpec>(describePrefix, - keysFeature.forSubjectLess().adjustName { "$it feature" }, + keysFeature.forSubjectLess(), keys.forSubjectLess { isEmpty() }, - valuesFeature.forSubjectLess().adjustName { "$it feature" }, + valuesFeature.forSubjectLess(), values.forSubjectLess { isEmpty() }, getExistingFeature.forSubjectLess("a"), getExisting.forSubjectLess("a") { isGreaterThan(1) } ) {}) - include(object : SubjectLessSpec>("$describePrefix[nullable Key] ", + include(object : SubjectLessSpec>("$describePrefix[nullable] ", getExistingNullableFeature.forSubjectLess("a"), getExistingNullable.forSubjectLess("a") { toBe(null) } ) {}) @@ -43,161 +43,91 @@ abstract class MapFeatureAssertionsSpec( getExisting.forAssertionCreatorSpec("$toBeDescr: 2", "b") { toBe(2) } ) {}) include(object : AssertionCreatorSpec>( - "$describePrefix[nullable Element] ", mapNullable, + "$describePrefix[nullable] ", mapNullable, getExistingNullable.forAssertionCreatorSpec("$toBeDescr: 2", "b") { toBe(null) } ) {}) - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) + fun describeFun(vararg pairs: SpecPair<*>, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, pairs.map { it.name }.toTypedArray(), body = body) val fluent = expect(map) val fluentNullable = expect(mapNullable) val keyDoesNotExist = DescriptionMapAssertion.KEY_DOES_NOT_EXIST.getDefault() - describeFun("${keysFeature.name} feature") { - val keysVal = keysFeature.lambda + describeFun(keysFeature, keys, valuesFeature, values) { + val keysFunctions = unifySignatures(keysFeature, keys) + val valuesFunctions = unifySignatures(valuesFeature, values) context("map with two entries") { - it("hasSize(2) holds") { - fluent.keysVal().hasSize(2) + keysFunctions.forEach { (name, keysFun, _) -> + it("$name - hasSize(2) holds") { + fluent.keysFun { hasSize(2) } + } + it("$name - hasSize(1) throws AssertionError") { + expect { + fluent.keysFun { hasSize(1) } + }.toThrow { + messageContains("keys: [a, b]") + } + } } - it("hasSize(1) fails") { - expect { - fluent.keysVal().hasSize(1) - }.toThrow { - messageContains("keys: [a, b]") + valuesFunctions.forEach { (name, valuesFun, _) -> + it("$name - hasSize(2) holds") { + fluent.valuesFun { hasSize(2) } + } + it("$name - hasSize(1) throws AssertionError") { + expect { + fluent.valuesFun { hasSize(1) } + }.toThrow { + messageContains("values: [1, 2]") + } } } } } - describeFun(keys.name) { - val keysFun = keys.lambda - - context("map with two entries") { - it("hasSize(2) holds") { - fluent.keysFun { hasSize(2) } - } - it("hasSize(1) fails") { - expect { - fluent.keysFun { hasSize(1) } - }.toThrow { - messageContains("keys: [a, b]") - } - } - } - } - - - describeFun("${valuesFeature.name} feature") { - val valuesVal = valuesFeature.lambda - - context("map with two entries") { - it("hasSize(2) holds") { - fluent.valuesVal().hasSize(2) - } - it("hasSize(1) fails") { - expect { - fluent.valuesVal().hasSize(1) - }.toThrow { - messageContains("values: [1, 2]") - } - } - } - } - - describeFun(values.name) { - val valuesFun = values.lambda - - context("map with two entries") { - it("hasSize(2) holds") { - fluent.valuesFun { hasSize(2) } - } - it("hasSize(1) fails") { - expect { - fluent.valuesFun { hasSize(1) } - }.toThrow { - messageContains("values: [1, 2]") - } - } - } - } - - describeFun("${getExistingFeature.name} feature") { - val getExistingFun = getExistingFeature.lambda - context("map $map") { - it("can perform sub-assertion on existing key") { - fluent.getExistingFun("a").toBe(1) - } - it("non-existing key throws") { - expect { - fluent.getExistingFun("c").toBe(1) - }.toThrow { - messageContains("get(\"c\"): $keyDoesNotExist") - } - } - } - } - - describeFun(getExisting.name) { - val getExistingFun = getExisting.lambda + describeFun(getExistingFeature, getExisting) { + val getExistingFunctions = unifySignatures(getExistingFeature, getExisting) context("map $map") { - it("can perform sub-assertion on existing key") { - fluent.getExistingFun("a") { toBe(1) } - } - it("non-existing key throws but shows intended sub-assertion") { - expect { - fluent.getExistingFun("c") { toBe(3) } - }.toThrow { - messageContains("get(\"c\"): $keyDoesNotExist", "$toBeDescr: 3") + getExistingFunctions.forEach { (name, getExistingFun, hasExtraHint) -> + it("$name - can perform sub-assertion on existing key") { + fluent.getExistingFun("a") { toBe(1) } + } + it("$name - non-existing key throws" + showsSubAssertionIf(hasExtraHint)) { + expect { + fluent.getExistingFun("c") { toBe(3) } + }.toThrow { + messageContains("get(\"c\"): $keyDoesNotExist") + if (hasExtraHint) messageContains("$toBeDescr: 3") + } } } } } - describeFun("${getExistingNullableFeature.name} nullable feature") { - val getExistingNullableFun = getExistingNullableFeature.lambda + describeFun(getExistingNullableFeature, getExistingNullable) { + val getExistingFunctions = unifySignatures(getExistingNullableFeature, getExistingNullable) context("map $mapNullable") { - it("can perform sub-assertion on existing key") { - fluentNullable.getExistingNullableFun("a").toBe(1) - } - it("can perform sub-assertion on existing key which is null") { - fluentNullable.getExistingNullableFun(null).toBe(3) - } - it("can perform sub-assertion on existing key whose value is null") { - fluentNullable.getExistingNullableFun("b").toBe(null) - } - it("non-existing key throws") { - expect { - fluentNullable.getExistingNullableFun("c").toBe(null) - }.toThrow { - messageContains("get(\"c\"): $keyDoesNotExist") + getExistingFunctions.forEach { (name, getExistingFun, hasExtraHint) -> + it("$name - can perform sub-assertion on existing key") { + fluentNullable.getExistingFun("a") { toBe(1) } } - } - } - } - - describeFun("$getExistingNullable for nullable") { - val getExistingNullableFun = getExistingNullable.lambda - - context("map $mapNullable") { - it("can perform sub-assertion on existing key") { - fluentNullable.getExistingNullableFun("a") { toBe(1) } - } - it("can perform sub-assertion on existing key which is null") { - fluentNullable.getExistingNullableFun(null) { toBe(3) } - } - it("can perform sub-assertion on existing key whose value is null") { - fluentNullable.getExistingNullableFun("b") { toBe(null) } - } - it("non-existing key throws but shows intended sub-assertion") { - expect { - fluentNullable.getExistingNullableFun("c") { toBe(null) } - }.toThrow { - messageContains("get(\"c\"): $keyDoesNotExist", "$toBeDescr: null") + it("$name - can perform sub-assertion on existing key which is null") { + fluentNullable.getExistingFun(null) { toBe(3) } + } + it("$name - can perform sub-assertion on existing key whose value is null") { + fluentNullable.getExistingFun("b") { toBe(null) } + } + it("$name - non-existing key throws" + showsSubAssertionIf(hasExtraHint)) { + expect { + fluentNullable.getExistingFun("c") { toBe(null) } + }.toThrow { + messageContains("get(\"c\"): $keyDoesNotExist") + if (hasExtraHint) messageContains("$toBeDescr: null") + } } } } diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/ResultFeatureAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/ResultFeatureAssertionsSpec.kt index 3851acedc..028cdb0e7 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/ResultFeatureAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/ResultFeatureAssertionsSpec.kt @@ -17,7 +17,7 @@ import org.spekframework.spek2.style.specification.Suite abstract class ResultFeatureAssertionsSpec( isSuccessFeature: Feature0, Int>, isSuccess: Fun1, Expect.() -> Unit>, - isSuccessNullableFeature: Feature0, Int?>, + isSuccessFeatureNullable: Feature0, Int?>, isSuccessNullable: Fun1, Expect.() -> Unit>, isFailureFeature: Feature0, IllegalArgumentException>, isFailure: Feature1, Expect.() -> Unit, IllegalArgumentException>, @@ -26,14 +26,14 @@ abstract class ResultFeatureAssertionsSpec( include(object : SubjectLessSpec>( describePrefix, - isSuccessFeature.forSubjectLess().adjustName { "$it feature" }, + isSuccessFeature.forSubjectLess(), isSuccess.forSubjectLess { toBe(1) }, - isFailureFeature.forSubjectLess().adjustName { "$it feature" }, + isFailureFeature.forSubjectLess(), isFailure.forSubjectLess { messageContains("message") } ) {}) include(object : SubjectLessSpec>( - describePrefix, - isSuccessNullableFeature.forSubjectLess().adjustName { "$it feature" }, + "$describePrefix[nullable] ", + isSuccessFeatureNullable.forSubjectLess(), isSuccessNullable.forSubjectLess { toBe(1) } ) {}) @@ -42,11 +42,12 @@ abstract class ResultFeatureAssertionsSpec( isSuccess.forAssertionCreatorSpec("$toBeDescr: 2") { toBe(2) } ) {}) include(object : AssertionCreatorSpec>( - describePrefix, Result.success(2), + "$describePrefix[nullable] ", Result.success(2), isSuccessNullable.forAssertionCreatorSpec("$toBeDescr: 2") { toBe(2) } ) {}) + include(object : AssertionCreatorSpec>( - describePrefix, Result.failure(IllegalArgumentException("oh no...")), + "$describePrefix[failure] ", Result.failure(IllegalArgumentException("oh no...")), assertionCreatorSpecTriple( isFailure.name, "${VALUE.getDefault()}: \"oh no...\"", @@ -55,199 +56,114 @@ abstract class ResultFeatureAssertionsSpec( ) ) {}) - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) + fun describeFun(vararg pairs: SpecPair<*>, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, pairs.map { it.name }.toTypedArray(), body = body) val resultSuccess = Result.success(1) val resultFailure = Result.failure(IllegalArgumentException("oh no...")) - val resultNullableSuccess = Result.success(1 as Int?) val resultNullSuccess = Result.success(null as Int?) val resultNullableFailure = Result.failure(IllegalArgumentException("oh no...")) val isNotSuccessDescr = DescriptionResultAssertion.IS_NOT_SUCCESS.getDefault() val isNotFailureDescr = DescriptionResultAssertion.IS_NOT_FAILURE.getDefault() val exceptionDescr = DescriptionResultAssertion.EXCEPTION.getDefault() - val isADescr = DescriptionAnyAssertion.IS_A.getDefault() - describeFun("${isSuccessFeature.name} feature", "${isFailureFeature.name} feature") { - val isSuccessFun = isSuccessFeature.lambda - val isFailureFun = isFailureFeature.lambda + describeFun(isSuccessFeature, isSuccess, isSuccessFeatureNullable, isSuccessNullable, isFailureFeature, isFailure) { + val successFunctions = uncheckedToNonNullable( + unifySignatures(isSuccessFeature, isSuccess), + unifySignatures(isSuccessFeatureNullable, isSuccessNullable) + ) + val failureFunctions = unifySignatures(isFailureFeature, isFailure) - context("$resultSuccess") { - it("${isSuccessFeature.name} - can perform sub-assertion which holds") { - expect(resultSuccess).isSuccessFun().toBe(1) - } - it("${isSuccessFeature.name} - can perform sub-assertion which fails, throws AssertionError") { - expect { - expect(resultSuccess).isSuccessFun().toBe(2) - }.toThrow { - messageContains("value: 1", "$toBeDescr: 2") + context("subject is $resultSuccess") { + successFunctions.forEach { (name, isSuccessFun, _) -> + it("$name - can perform sub-assertion which holds") { + expect(resultSuccess).isSuccessFun { toBe(1) } + } + it("$name - can perform sub-assertion which fails, throws AssertionError") { + expect { + expect(resultSuccess).isSuccessFun { toBe(2) } + }.toThrow { + messageContains("value: 1", "$toBeDescr: 2") + } } } - it("${isFailureFeature.name} - throws AssertionError showing the expected type") { - expect { - expect(resultSuccess).isFailureFun() - }.toThrow { - messageContains( - "exception: $isNotFailureDescr", - "$isADescr: ${IllegalArgumentException::class.simpleName}" - ) + + failureFunctions.forEach { (name, isFailureFun, hasExtraHint) -> + it("$name - throws AssertionError showing the expected type" + if (hasExtraHint) " and the expected message" else "") { + expect { + expect(resultSuccess).isFailureFun { messageContains("oh yes...") } + }.toThrow { + messageContains( + "exception: $isNotFailureDescr", + "$isADescr: ${IllegalArgumentException::class.simpleName}" + ) + if (hasExtraHint) { + messageContains( + CONTAINS.getDefault(), + "${VALUE.getDefault()}: \"oh yes...\"" + ) + } + } } } } - context("$resultFailure") { - it("${isSuccessFeature.name} - throws AssertionError") { - expect { - expect(resultFailure).isSuccessFun().toBe(1) - }.toThrow { - messageContains("value: $isNotSuccessDescr") + context("subject is $resultFailure") { + successFunctions.forEach { (name, isSuccessFun, hasExtraHint) -> + it("$name throws AssertionError" + showsSubAssertionIf(hasExtraHint)) { + expect { + expect(resultFailure).isSuccessFun { toBe(1) } + }.toThrow { + messageContains("value: $isNotSuccessDescr") + if (hasExtraHint) messageContains("$toBeDescr: 1") + } } } - it("${isFailureFeature.name} - does not throw AssertionError") { - expect(resultFailure).isFailureFun() - } - it("${isFailureFeature.name} - can perform sub-assertion which holds") { - expect(resultFailure).isFailureFun().messageContains("oh no...") - } - it("${isFailureFeature.name} - can perform sub-assertion which fails, throws AssertionError") { - expect { - expect(resultFailure).isFailureFun().messageContains("oh yes...") - }.toThrow { - messageContains( - "$exceptionDescr: ${IllegalArgumentException::class.fullName}", - CONTAINS.getDefault(), "${VALUE.getDefault()}: \"oh yes...\"" - ) + + failureFunctions.forEach { (name, isFailureFun, _) -> + it("$name - can perform sub-assertion which holds") { + expect(resultFailure).isFailureFun { messageContains("oh no...") } + } + it("$name - can perform sub-assertion which fails, throws AssertionError") { + expect { + expect(resultFailure).isFailureFun { messageContains("oh yes...") } + }.toThrow { + messageContains( + "$exceptionDescr: ${IllegalArgumentException::class.fullName}", + CONTAINS.getDefault(), "${VALUE.getDefault()}: \"oh yes...\"" + ) + } } } } } - describeFun(isSuccess.name, isFailure.name) { - val isSuccessFun = isSuccess.lambda - val isFailureFun = isFailure.lambda + describeFun(isSuccessFeatureNullable, isSuccessNullable) { + val successFunctions = unifySignatures(isSuccessFeatureNullable, isSuccessNullable) - context("$resultSuccess") { - it("${isSuccessFeature.name} - can perform sub-assertion which holds") { - expect(resultSuccess).isSuccessFun { toBe(1) } - } - it("${isSuccessFeature.name} - can perform sub-assertion which fails, throws AssertionError") { - expect { - expect(resultSuccess).isSuccessFun { toBe(2) } - }.toThrow { - messageContains("value: 1", "$toBeDescr: 2") + successFunctions.forEach { (name, isSuccessFun, hasExtraHint) -> + context("subject is $resultNullSuccess") { + it("$name - can perform sub-assertion which holds") { + expect(resultNullSuccess).isSuccessFun { toBe(null) } + } + it("$name - can perform sub-assertion which fails, throws AssertionError") { + expect { + expect(resultNullSuccess).isSuccessFun { toBe(2) } + }.toThrow { + messageContains("value: null", "$toBeDescr: 2") + } } } - it("${isFailureFeature.name} - throws AssertionError showing the expected type and the expected message") { - expect { - expect(resultSuccess).isFailureFun { messageContains("oh yes...") } - }.toThrow { - messageContains( - "exception: $isNotFailureDescr", - "$isADescr: ${IllegalArgumentException::class.simpleName}", - CONTAINS.getDefault(), "${VALUE.getDefault()}: \"oh yes...\"" - ) - } - } - } - context("$resultFailure") { - it("${isSuccessFeature.name} throws AssertionError but shows intended sub-assertion") { - expect { - expect(resultFailure).isSuccessFun { toBe(1) } - }.toThrow { - messageContains("value: $isNotSuccessDescr", "$toBeDescr: 1") - } - } - it("${isFailure.name} - can perform sub-assertion which holds") { - expect(resultFailure).isFailureFun { messageContains("oh no...") } - } - it("${isFailure.name} - can perform sub-assertion which fails, throws AssertionError") { - expect { - expect(resultFailure).isFailureFun { messageContains("oh yes...") } - }.toThrow { - messageContains( - "$exceptionDescr: ${IllegalArgumentException::class.fullName}", - CONTAINS.getDefault(), "${VALUE.getDefault()}: \"oh yes...\"" - ) - } - } - } - } - - describeFun("${isSuccessNullableFeature.name} nullable feature") { - val isSuccessFun = isSuccessNullableFeature.lambda - - context("$resultNullableSuccess") { - it("${isSuccessFeature.name} - can perform sub-assertion which holds") { - expect(resultNullableSuccess).isSuccessFun().toBe(1) - } - it("${isSuccessFeature.name} - can perform sub-assertion which fails, throws AssertionError") { - expect { - expect(resultNullableSuccess).isSuccessFun().toBe(2) - }.toThrow { - messageContains("value: 1", "$toBeDescr: 2") - } - } - } - context("$resultNullSuccess") { - it("${isSuccessFeature.name} - can perform sub-assertion which holds") { - expect(resultNullSuccess).isSuccessFun().toBe(null) - } - it("${isSuccessFeature.name} - can perform sub-assertion which fails, throws AssertionError") { - expect { - expect(resultNullSuccess).isSuccessFun().toBe(2) - }.toThrow { - messageContains("value: null", "$toBeDescr: 2") - } - } - } - - context("$resultNullableFailure") { - it("${isSuccessFeature.name} throws AssertionError") { - expect { - expect(resultNullableFailure).isSuccessFun().toBe(1) - }.toThrow { - messageContains("value: $isNotSuccessDescr") - } - } - } - } - - describeFun("${isSuccessNullable.name} nullable") { - val isSuccessFun = isSuccessNullable.lambda - - context("$resultNullableSuccess") { - it("${isSuccessFeature.name} - can perform sub-assertion which holds") { - expect(resultNullableSuccess).isSuccessFun { toBe(1) } - } - it("${isSuccessFeature.name} - can perform sub-assertion which fails, throws AssertionError") { - expect { - expect(resultNullableSuccess).isSuccessFun { toBe(2) } - }.toThrow { - messageContains("value: 1", "$toBeDescr: 2") - } - } - } - context("$resultNullSuccess") { - it("${isSuccessFeature.name} - can perform sub-assertion which holds") { - expect(resultNullSuccess).isSuccessFun { toBe(null) } - } - it("${isSuccessFeature.name} - can perform sub-assertion which fails, throws AssertionError") { - expect { - expect(resultNullSuccess).isSuccessFun { toBe(2) } - }.toThrow { - messageContains("value: null", "$toBeDescr: 2") - } - } - } - - context("$resultNullableFailure") { - it("${isSuccessFeature.name} throws AssertionError but shows intended sub-assertion") { - expect { - expect(resultNullableFailure).isSuccessFun { toBe(1) } - }.toThrow { - messageContains("value: $isNotSuccessDescr", "$toBeDescr: 1") + context("subject is $resultNullableFailure") { + it("${isSuccessFeature.name} throws AssertionError" + showsSubAssertionIf(hasExtraHint)) { + expect { + expect(resultNullableFailure).isSuccessFun { toBe(1) } + }.toThrow { + messageContains("value: $isNotSuccessDescr") + if (hasExtraHint) messageContains("$toBeDescr: 1") + } } } } diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/ThrowableAssertionsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/ThrowableAssertionsSpec.kt index f833c1b16..49d73e156 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/ThrowableAssertionsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/ThrowableAssertionsSpec.kt @@ -2,15 +2,15 @@ package ch.tutteli.atrium.specs.integration -import ch.tutteli.atrium.api.fluent.en_GB.contains -import ch.tutteli.atrium.api.fluent.en_GB.messageContains -import ch.tutteli.atrium.api.fluent.en_GB.toBe -import ch.tutteli.atrium.api.fluent.en_GB.toThrow +import ch.tutteli.atrium.api.fluent.en_GB.* import ch.tutteli.atrium.api.verbs.internal.expect import ch.tutteli.atrium.core.polyfills.fullName import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.specs.* import ch.tutteli.atrium.translations.DescriptionAnyAssertion +import ch.tutteli.atrium.translations.DescriptionCharSequenceAssertion.CONTAINS +import ch.tutteli.atrium.translations.DescriptionCharSequenceAssertion.VALUE +import ch.tutteli.atrium.translations.DescriptionThrowableAssertion import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.Suite @@ -18,11 +18,15 @@ abstract class ThrowableAssertionsSpec( messageFeature: Feature0, message: Fun1.() -> Unit>, messageContains: Fun2>, + + causeFeature: Feature0, + cause: Feature1.() -> Unit, IllegalArgumentException>, + describePrefix: String = "[Atrium] " ) : Spek({ include(object : SubjectLessSpec( - "$describePrefix[nullable Key] ", + describePrefix, messageFeature.forSubjectLess(), message.forSubjectLess { toBe("hello") }, messageContains.forSubjectLess("hello", arrayOf()) @@ -33,129 +37,188 @@ abstract class ThrowableAssertionsSpec( message.forAssertionCreatorSpec("$toBeDescr: hello") { toBe("hello") } ) {}) - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) + fun describeFun(vararg pairs: SpecPair<*>, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, pairs.map { it.name }.toTypedArray(), body = body) + + describeFun(messageFeature, message, messageContains) { + val messageFunctions = unifySignatures(messageFeature, message) + val messageContainsFun = messageContains.lambda + + context("Throwable.message is null") { + val throwable: Throwable = IllegalArgumentException() + + messageFunctions.forEach { (name, messageFun, hasExtraHint) -> + it("$name - throws an AssertionError" + showsSubAssertionIf(hasExtraHint)) { + expect { + expect(throwable).messageFun { toBe("hello") } + }.toThrow { + messageContains( + DescriptionAnyAssertion.IS_A.getDefault(), + String::class.fullName + ) + if (hasExtraHint) messageContains("$toBeDescr: \"hello\"") + } + } + } + + it("${messageContains.name} - throws an AssertionError which shows intended sub assertion") { - describeFun("${messageFeature.name} feature") { - val messageFun = messageFeature.lambda - checkNarrowingAssertion( - "it throws an AssertionError if the ${Throwable::message.name} is null", - { message -> - val throwable: Throwable = IllegalArgumentException() expect { - expect(throwable).message() + expect(throwable).messageContainsFun(1, arrayOf(2.3, 'z', "hello")) }.toThrow { messageContains( - DescriptionAnyAssertion.IS_A.getDefault(), - String::class.fullName + DescriptionAnyAssertion.IS_A.getDefault(), String::class.fullName, + CONTAINS.getDefault(), + VALUE.getDefault() + ": 1", + VALUE.getDefault() + ": 2.3", + VALUE.getDefault() + ": 'z'", + VALUE.getDefault() + ": \"hello\"" ) } - }, - { messageFun().toBe("hello") } - ) + } + } - context("it allows to define an assertion for the ${Throwable::message.name} if it is not null") { - val throwable: Throwable = IllegalArgumentException("oh no") - checkNarrowingAssertion( - "it throws an AssertionError if the assertion does not hold", - { messageWithCheck -> + context("Throwable.message is empty") { + val throwable: Throwable = IllegalArgumentException("") + messageFunctions.forEach { (name, messageFun, _) -> + it("$name - throws an AssertionError if the assertion does not hold") { expect { - expect(throwable).messageWithCheck() - }.toThrow() - }, - { messageFun().contains("hello") } - ) + expect(throwable).messageFun { toBe("hello") } + }.toThrow { messageContains("$toBeDescr: \"hello\"") } + } - checkNarrowingAssertion( - "it does not throw an exception if the assertion holds", - { messageWithCheck -> expect(throwable).messageWithCheck() }, { messageFun().contains("oh") } - ) + it("$name - does not throw if the assertion holds") { + expect(throwable).messageFun { isEmpty() } + } + } + it("${messageContains.name} - throws an AssertionError if the assertion does not hold") { + expect { + expect(throwable).messageContainsFun("nada", arrayOf()) + }.toThrow { messageContains(VALUE.getDefault() + ": \"nada\"") } + } + it("${messageContains.name} - throws IllegalArgumentException if empty string is passed") { + expect { + expect(throwable).messageContainsFun("", arrayOf()) + }.toThrow() + } + } + + context("Throwable.message is blank") { + val throwable: Throwable = IllegalArgumentException(" ") + messageFunctions.forEach { (name, messageFun, _) -> + it("$name - throws an AssertionError if the assertion does not hold") { + expect { + expect(throwable).messageFun { toBe("hello") } + }.toThrow { messageContains("$toBeDescr: \"hello\"") } + } + + it("$name - does not throw if the assertion holds") { + expect(throwable).messageFun { toBe(" ") } + } + } + it("${messageContains.name} - throws an AssertionError if the assertion does not hold") { + expect { + expect(throwable).messageContainsFun("nada", arrayOf()) + }.toThrow { messageContains(VALUE.getDefault() + ": \"nada\"") } + } + it("${messageContains.name} - does not throw if the assertion holds") { + expect(throwable).messageContainsFun(" ", arrayOf()) + } + } + + context("Throwable.message is not empty/blank") { + val throwable: Throwable = IllegalArgumentException("1 and 2.3 with extra z results in hello") + + messageFunctions.forEach { (name, messageFun, _) -> + it("$name - throws an AssertionError if the assertion does not hold") { + expect { + expect(throwable).messageFun { toBe("hello") } + }.toThrow { messageContains("$toBeDescr: \"hello\"") } + } + + it("$name - does not throw if the assertion holds") { + expect(throwable).messageFun { contains("hello") } + } + } + + it("${messageContains.name} - throws an AssertionError if the assertion does not hold") { + expect { + expect(throwable).messageContainsFun("nada", arrayOf()) + }.toThrow { messageContains(VALUE.getDefault() + ": \"nada\"") } + } + it("${messageContains.name} - does not throw if the assertion holds") { + expect(throwable).messageContainsFun(1, arrayOf(2.3, 'z', "hello")) + } + } + + it("${messageContains.name} - throws an IllegalArgumentException if an object is passed") { + val throwable: Throwable = IndexOutOfBoundsException() + expect { + expect(throwable).messageContainsFun(Pair(1, 2), arrayOf()) + }.toThrow() } } - describeFun(message.name) { - val messageFun = message.lambda - checkNarrowingAssertion( - "it throws an AssertionError if the ${Throwable::message.name} is null", - { message -> - val throwable: Throwable = IllegalArgumentException() - expect { - expect(throwable).message() - }.toThrow { - messageContains( - DescriptionAnyAssertion.IS_A.getDefault(), - String::class.fullName - ) + describeFun(causeFeature, cause) { + val causeFunctions = unifySignatures(causeFeature, cause) + + context("Throwable.cause is not null") { + val exceptionCause = IllegalArgumentException("Hello from the Clause") + val throwable: Throwable = + RuntimeException("Outer exception message", exceptionCause) + + causeFunctions.forEach { (name, causeFun) -> + it("$name - does not throw if the assertion holds") { + expect(throwable).causeFun { toBe(exceptionCause) } } - }, - { messageFun { toBe("hello") } } - ) - context("it allows to define an assertion for the ${Throwable::message.name} if it is not null") { - val throwable: Throwable = IllegalArgumentException("oh no") - checkNarrowingAssertion( - "it throws an AssertionError if the assertion does not hold", - { messageWithCheck -> + it("$name - throws an AssertionError") { expect { - expect(throwable).messageWithCheck() - }.toThrow() - }, - { messageFun { contains("hello") } } - ) - - checkNarrowingAssertion( - "it does not throw an exception if the assertion holds", - { messageWithCheck -> expect(throwable).messageWithCheck() }, - { messageFun { contains("oh") } } - ) - } - } - - describeFun(messageContains.name) { - - checkNarrowingAssertion( - "it throws an AssertionError if the ${Throwable::message.name} is null", - { messageContainsFun -> - val throwable: Throwable = IllegalArgumentException() - expect { - expect(throwable).messageContainsFun() - }.toThrow { - messageContains(DescriptionAnyAssertion.IS_A.getDefault(), String::class.fullName) + expect(throwable).causeFun { messageContains("WRONG message") } + }.toThrow { + messageContains( + DescriptionThrowableAssertion.OCCURRED_EXCEPTION_CAUSE.getDefault() + ": java.lang.IllegalArgumentException", + VALUE.getDefault() + ": \"WRONG message\"" + ) + } } - }, - { (messageContains.lambda)(1, arrayOf(2.3, 'z', "hello")) }) - - context("it allows to define an assertion for the ${Throwable::message.name} if it is not null") { - val throwable: Throwable = IllegalArgumentException("1 2.3 z hello") - checkNarrowingAssertion( - "it throws an AssertionError if the assertion does not hold", - { messageContains -> + it("$name - throws if wrong type is expected") { + val throwableWithDifferentCauseType: Throwable = + RuntimeException( + "Outer exception message", + UnsupportedOperationException("Cause exception: UNSUPPORTED OPERATION") + ) expect { - expect(throwable).messageContains() - }.toThrow() - }, - { (messageContains.lambda)("nada", arrayOf()) } - ) + expect(throwableWithDifferentCauseType).causeFun { messageContains("Cause exception") } + }.toThrow { + messageContains( + String.format( + DescriptionThrowableAssertion.OCCURRED_EXCEPTION_PROPERTIES.getDefault(), + UnsupportedOperationException::class.simpleName!! + ) + ) + } + } + } - checkNarrowingAssertion( - "it does not throw an exception if the assertion holds", - { messageWithCheck -> - expect(throwable).messageWithCheck() - }, - { (messageContains.lambda)(1, arrayOf(2.3, 'z', "hello")) } - ) - - - checkNarrowingAssertion( - "it throws an IllegalArgumentException if an object is passed", - { messageContains -> - expect { - expect(throwable).messageContains() - }.toThrow() - }, - { (messageContains.lambda)(Pair(1, 2), arrayOf()) } - ) } + + context("Throwable.cause is null") { + val throwable: Throwable = RuntimeException("Outer exception message") + causeFunctions.forEach { (name, causeFun) -> + it("$name - throws an AssertionError") { + expect { + expect(throwable).causeFun { messageContains("Hello") } + }.toThrow { + messageContains( + DescriptionThrowableAssertion.NOT_CAUSED.getDefault(), + IllegalArgumentException::class.fullName + ) + } + } + } + } + } }) diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/EmptyNameAndSubjectAssertionGroupFormatterSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/reporting/EmptyNameAndSubjectAssertionGroupFormatterSpec.kt similarity index 88% rename from misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/EmptyNameAndSubjectAssertionGroupFormatterSpec.kt rename to misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/reporting/EmptyNameAndSubjectAssertionGroupFormatterSpec.kt index c75641ec1..179850f65 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/EmptyNameAndSubjectAssertionGroupFormatterSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/reporting/EmptyNameAndSubjectAssertionGroupFormatterSpec.kt @@ -11,14 +11,11 @@ import ch.tutteli.atrium.reporting.AssertionFormatter import ch.tutteli.atrium.reporting.AssertionFormatterController import ch.tutteli.atrium.reporting.AssertionFormatterParameterObject import ch.tutteli.atrium.reporting.translating.StringBasedTranslatable -import ch.tutteli.atrium.specs.describeFun -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.SpecBody -import org.jetbrains.spek.api.dsl.context -import org.jetbrains.spek.api.dsl.it +import ch.tutteli.atrium.specs.describeFunTemplate +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.Suite import kotlin.reflect.KClass -//TODO #116 migrate spek1 to spek2 - move to specs-common abstract class EmptyNameAndSubjectAssertionGroupFormatterSpec( testeeFactory: (AssertionFormatterController) -> AssertionFormatter, assertionGroupClass: KClass, @@ -27,8 +24,8 @@ abstract class EmptyNameAndSubjectAssertionGroupFormatterSpec Unit) = - describeFun(describePrefix, funName, body = body) + fun describeFun(vararg funName: String, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, funName, body = body) val testee = testeeFactory(coreFactory.newAssertionFormatterController()) diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/ObjectFormatterSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/reporting/ObjectFormatterSpec.kt similarity index 73% rename from misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/ObjectFormatterSpec.kt rename to misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/reporting/ObjectFormatterSpec.kt index 3ab506e15..f633786c7 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/ObjectFormatterSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/reporting/ObjectFormatterSpec.kt @@ -9,28 +9,23 @@ import ch.tutteli.atrium.reporting.StringBasedRawString import ch.tutteli.atrium.reporting.translating.TranslatableBasedRawString import ch.tutteli.atrium.reporting.translating.Translator import ch.tutteli.atrium.specs.AssertionVerb -import ch.tutteli.atrium.specs.describeFun -import com.nhaarman.mockitokotlin2.any -import com.nhaarman.mockitokotlin2.doReturn -import com.nhaarman.mockitokotlin2.mock -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.SpecBody -import org.jetbrains.spek.api.dsl.context -import org.jetbrains.spek.api.dsl.it +import ch.tutteli.atrium.specs.describeFunTemplate +import io.mockk.* +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.Suite -//TODO #116 migrate spek1 to spek2 - move to specs-common abstract class ObjectFormatterSpec( testeeFactory: (Translator) -> ObjectFormatter, describePrefix: String = "[Atrium] " ) : Spek({ - fun describeFun(vararg funName: String, body: SpecBody.() -> Unit) = - describeFun(describePrefix, funName, body = body) + fun describeFun(vararg funName: String, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, funName, body = body) val translatable = AssertionVerb.ASSERT val translatedText = "es gilt" - val translator = mock { - on { translate(any()) } doReturn (translatedText) + val translator = mockk { + every { translate(any()) } returns (translatedText) } val testee = testeeFactory(translator) diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/OnlyFailureReporterSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/reporting/OnlyFailureReporterSpec.kt similarity index 81% rename from misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/OnlyFailureReporterSpec.kt rename to misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/reporting/OnlyFailureReporterSpec.kt index 8c38244f8..166fc2814 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/OnlyFailureReporterSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/reporting/OnlyFailureReporterSpec.kt @@ -14,25 +14,19 @@ import ch.tutteli.atrium.reporting.AtriumErrorAdjuster import ch.tutteli.atrium.reporting.Reporter import ch.tutteli.atrium.reporting.translating.UsingDefaultTranslator import ch.tutteli.atrium.specs.AssertionVerb -import ch.tutteli.atrium.specs.describeFun +import ch.tutteli.atrium.specs.describeFunTemplate import ch.tutteli.atrium.translations.DescriptionBasic.TO_BE -import com.nhaarman.mockitokotlin2.any -import com.nhaarman.mockitokotlin2.eq -import com.nhaarman.mockitokotlin2.mock -import com.nhaarman.mockitokotlin2.verify -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.SpecBody -import org.jetbrains.spek.api.dsl.context -import org.jetbrains.spek.api.dsl.it +import io.mockk.* +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.Suite -//TODO #116 migrate spek1 to spek2 - move to specs-common abstract class OnlyFailureReporterSpec( testeeFactory: (AssertionFormatterFacade, AtriumErrorAdjuster) -> Reporter, describePrefix: String = "[Atrium] " ) : Spek({ - fun describeFun(vararg funName: String, body: SpecBody.() -> Unit) = - describeFun(describePrefix, funName, body = body) + fun describeFun(vararg funName: String, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, funName, body = body) val translator = UsingDefaultTranslator() val facade = coreFactory.newAssertionFormatterFacade(coreFactory.newAssertionFormatterController()) @@ -82,14 +76,16 @@ abstract class OnlyFailureReporterSpec( } context("dependencies") { - val assertionFormatterFacade = mock() + val assertionFormatterFacade = mockk() + every { assertionFormatterFacade.format(any(), any(), any()) } just Runs + val testeeWithMockedFacade = testeeFactory( assertionFormatterFacade, coreFactory.newNoOpAtriumErrorAdjuster() ) - it("delegates to ${assertionFormatterFacade::class.java.simpleName}") { + it("delegates to ${assertionFormatterFacade::class.simpleName}") { testeeWithMockedFacade.format(basicAssertion, sb) - verify(assertionFormatterFacade).format(eq(basicAssertion), eq(sb), any()) + verify { assertionFormatterFacade.format(eq(basicAssertion), eq(sb), any()) } } } } diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextMethodCallFormatterSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextMethodCallFormatterSpec.kt similarity index 90% rename from misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextMethodCallFormatterSpec.kt rename to misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextMethodCallFormatterSpec.kt index 234de912b..d4c761017 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextMethodCallFormatterSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextMethodCallFormatterSpec.kt @@ -3,21 +3,18 @@ package ch.tutteli.atrium.specs.reporting import ch.tutteli.atrium.api.fluent.en_GB.toBe import ch.tutteli.atrium.api.verbs.internal.expect import ch.tutteli.atrium.reporting.MethodCallFormatter -import ch.tutteli.atrium.specs.describeFun -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.SpecBody -import org.jetbrains.spek.api.dsl.context -import org.jetbrains.spek.api.dsl.it +import ch.tutteli.atrium.specs.describeFunTemplate +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.Suite -//TODO #116 migrate spek1 to spek2 - move to specs-common @Suppress("UNUSED_PARAMETER") abstract class TextMethodCallFormatterSpec( testeeFactory: () -> MethodCallFormatter, describePrefix: String = "[Atrium] " ) : Spek({ - fun describeFun(vararg funName: String, body: SpecBody.() -> Unit) = - describeFun(describePrefix, funName, body = body) + fun describeFun(vararg funName: String, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, funName, body = body) val testee = testeeFactory() diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/LocaleOrderDeciderSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/LocaleOrderDeciderSpec.kt similarity index 92% rename from misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/LocaleOrderDeciderSpec.kt rename to misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/LocaleOrderDeciderSpec.kt index ea7f2ef47..c7c1cfb0a 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/LocaleOrderDeciderSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/LocaleOrderDeciderSpec.kt @@ -4,22 +4,18 @@ import ch.tutteli.atrium.api.fluent.en_GB.containsExactly import ch.tutteli.atrium.api.verbs.internal.expect import ch.tutteli.atrium.reporting.translating.Locale import ch.tutteli.atrium.reporting.translating.LocaleOrderDecider -import ch.tutteli.atrium.specs.prefixedDescribe +import ch.tutteli.atrium.specs.prefixedDescribeTemplate import ch.tutteli.kbox.joinToString -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.SpecBody -import org.jetbrains.spek.api.dsl.context -import org.jetbrains.spek.api.dsl.describe -import org.jetbrains.spek.api.dsl.it +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.Suite -//TODO #116 migrate spek1 to spek2 - move to specs-common abstract class LocaleOrderDeciderSpec( testeeFactory: () -> LocaleOrderDecider, describePrefix: String = "[Atrium] " ) : Spek({ - fun prefixedDescribe(description: String, body: SpecBody.() -> Unit) = - prefixedDescribe(describePrefix, description, body) + fun prefixedDescribe(description: String, body: Suite.() -> Unit) = + prefixedDescribeTemplate(describePrefix, description, body) val testee = testeeFactory() diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/TranslationSupplierBasedTranslatorSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/TranslationSupplierBasedTranslatorSpec.kt similarity index 86% rename from misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/TranslationSupplierBasedTranslatorSpec.kt rename to misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/TranslationSupplierBasedTranslatorSpec.kt index 191e58a5e..e56a86cfd 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/TranslationSupplierBasedTranslatorSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/TranslationSupplierBasedTranslatorSpec.kt @@ -4,30 +4,26 @@ import ch.tutteli.atrium.api.fluent.en_GB.toBe import ch.tutteli.atrium.api.verbs.internal.expect import ch.tutteli.atrium.core.coreFactory import ch.tutteli.atrium.reporting.translating.* -import ch.tutteli.atrium.specs.describeFun -import com.nhaarman.mockitokotlin2.doReturn -import com.nhaarman.mockitokotlin2.mock -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.SpecBody -import org.jetbrains.spek.api.dsl.context -import org.jetbrains.spek.api.dsl.describe -import org.jetbrains.spek.api.dsl.it +import ch.tutteli.atrium.specs.describeFunTemplate +import io.mockk.* +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.Suite -//TODO #116 migrate spek1 to spek2 - move to specs-common abstract class TranslationSupplierBasedTranslatorSpec( testeeFactory: (translationSupplier: TranslationSupplier, localeOrderDecider: LocaleOrderDecider, locale: Locale, fallbackLocals: List) -> Translator, describePrefix: String = "[Atrium] " ) : Spek({ - fun describeFun(vararg funName: String, body: SpecBody.() -> Unit) = - describeFun(describePrefix, funName, body = body) + fun describeFun(vararg funName: String, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, funName, body = body) fun testeeFactory(translationSupplier: TranslationSupplier, locale: Locale, vararg fallbackLocals: Locale) = testeeFactory(translationSupplier, coreFactory.newLocaleOrderDecider(), locale, fallbackLocals.toList()) - fun mockTranslationProvider(locale: Locale, translatable: Translatable, translation: String): TranslationSupplier { - return mock { - on { get(translatable, locale) }.doReturn(translation) + fun mockTranslationProvider(locale: Locale, translatable: Translatable, translation: String?): TranslationSupplier { + return mockk { + every { get(any(), any()) } returns null + every { get(translatable, locale) } returns translation } } @@ -46,7 +42,7 @@ abstract class TranslationSupplierBasedTranslatorSpec( } @Suppress("unused") - fun SpecBody.checkUsesDefaultOfTranslatable(testee: Translator) { + fun Suite.checkUsesDefaultOfTranslatable(testee: Translator) { it("uses ${Translatable::class.simpleName}'s ${Translatable::getDefault.name}") { val result = testee.translate(translatableHello) expect(result).toBe(translatableHello.value) @@ -54,19 +50,19 @@ abstract class TranslationSupplierBasedTranslatorSpec( } @Suppress("unused") - fun SpecBody.checkTranslationSuccessfulForDesiredTranslatable( + fun Suite.checkTranslationSuccessfulForDesiredTranslatable( testee: Translator, translation: String, locale: Locale ) { - context("but for the wrong ${Translatable::class.simpleName}") { + describe("but for the wrong ${Translatable::class.simpleName}") { it("uses ${Translatable::class.simpleName}'s ${Translatable::getDefault.name}") { val result = testee.translate(translatableTest) expect(result).toBe(translatableTest.value) } } - context("for the desired ${Translatable::class.simpleName}") { + describe("for the desired ${Translatable::class.simpleName}") { it("uses the translation of Locale $locale") { val result = testee.translate(translatableHello) expect(result).toBe(translation) @@ -91,7 +87,9 @@ abstract class TranslationSupplierBasedTranslatorSpec( describe("translating a ${Translatable::class.simpleName} to $greatBritain without fallbacks") { context("no translations provided at all") { - val testee = testeeFactory(mock(), greatBritain) + val testee = testeeFactory(mockk { + every { get(any(), any()) } returns null + }, greatBritain) checkUsesDefaultOfTranslatable(testee) } diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/TranslatorErrorCaseSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/TranslatorErrorCaseSpec.kt similarity index 91% rename from misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/TranslatorErrorCaseSpec.kt rename to misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/TranslatorErrorCaseSpec.kt index 140c243e2..cd7f3c33f 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/TranslatorErrorCaseSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/TranslatorErrorCaseSpec.kt @@ -5,21 +5,17 @@ import ch.tutteli.atrium.api.fluent.en_GB.toThrow import ch.tutteli.atrium.api.verbs.internal.expect import ch.tutteli.atrium.reporting.translating.Locale import ch.tutteli.atrium.reporting.translating.Translator -import ch.tutteli.atrium.specs.describeFun -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.SpecBody -import org.jetbrains.spek.api.dsl.context -import org.jetbrains.spek.api.dsl.describe -import org.jetbrains.spek.api.dsl.it +import ch.tutteli.atrium.specs.describeFunTemplate +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.Suite -//TODO #116 migrate spek1 to spek2 - move to specs-common abstract class TranslatorErrorCaseSpec( testeeFactory: (locale: Locale, fallbackLocals: List) -> Translator, describePrefix: String = "[Atrium] " ) : Spek({ - fun describeFun(vararg funName: String, body: SpecBody.() -> Unit) = - describeFun(describePrefix, funName, body = body) + fun describeFun(vararg funName: String, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, funName, body = body) fun testeeFactory(locale: Locale, vararg fallbackLocals: Locale) = testeeFactory(locale, fallbackLocals.toList()) diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/testUtils.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/testUtils.kt index 48d0f2102..c98239986 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/testUtils.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/testUtils.kt @@ -5,23 +5,27 @@ package ch.tutteli.atrium.specs import ch.tutteli.atrium.core.polyfills.format import ch.tutteli.atrium.creating.Expect import ch.tutteli.atrium.domain.builders.utils.subExpect +import ch.tutteli.atrium.translations.DescriptionAnyAssertion import ch.tutteli.atrium.translations.DescriptionBasic +import kotlin.jvm.JvmName import kotlin.reflect.KFunction1 import kotlin.reflect.KFunction2 import kotlin.reflect.KFunction3 import kotlin.reflect.KProperty1 -typealias Fun = Pair +typealias SpecPair = Pair -inline val Fun.name get(): String = this.first -inline val Fun.lambda get(): T = this.second -inline fun Fun.adjustName(f: (String) -> String): Fun = f(name) to lambda +inline val SpecPair.name get(): String = this.first +inline val SpecPair.lambda get(): T = this.second +inline fun SpecPair.withFeatureSuffix(): SpecPair = "$name (feature)" to lambda +inline fun SpecPair.withNullableSuffix(): SpecPair = "$name nullable" to lambda +inline fun SpecPair.adjustName(f: (String) -> String): SpecPair = f(name) to lambda -typealias Feature0 = Fun.() -> Expect> -typealias Feature1 = Fun.(A1) -> Expect> -typealias Feature2 = Fun.(A1, A2) -> Expect> -typealias Feature3 = Fun.(A1, A2, A3) -> Expect> -typealias Feature4 = Fun.(A1, A2, A3, A4) -> Expect> +typealias Feature0 = SpecPair.() -> Expect> +typealias Feature1 = SpecPair.(A1) -> Expect> +typealias Feature2 = SpecPair.(A1, A2) -> Expect> +typealias Feature3 = SpecPair.(A1, A2, A3) -> Expect> +typealias Feature4 = SpecPair.(A1, A2, A3, A4) -> Expect> typealias Fun0 = Feature0 typealias Fun1 = Feature1 @@ -105,16 +109,98 @@ inline fun Fun2.() -> Unit, Array.() -> Unit>> ) ) +fun unifySignatures( + f0: Feature0, + f1: Fun1.() -> Unit> +): List.(Expect.() -> Unit) -> Expect, Boolean>> = + listOf( + Triple(f0.name, f0.withSubAssertion(), false), + Triple(f1.name, f1.lambda, true) + ) + +@JvmName("unifySignatures1") +fun unifySignatures( + f0: Feature1, + f1: Fun2.() -> Unit> +): List.(A1, Expect.() -> Unit) -> Expect, Boolean>> = + listOf( + Triple(f0.name, f0.withSubAssertion(), false), + Triple(f1.name, f1.lambda, true) + ) + +@JvmName("unifySignatures2") +fun unifySignatures( + f0: Feature2, + f1: Fun3.() -> Unit> +): List.(A1, A2, Expect.() -> Unit) -> Expect, Boolean>> = + listOf( + Triple(f0.name, f0.withSubAssertion(), false), + Triple(f1.name, f1.lambda, true) + ) + +@JvmName("unifySignatures0Feature") +fun unifySignatures( + f0: Feature0, + f1: Feature1.() -> Unit, R> +): List.(Expect.() -> Unit) -> Expect, Boolean>> { + val f0WithSubAssertion: Expect.(Expect.() -> Unit) -> Expect = + { f: Expect.() -> Unit -> (f0.lambda)().apply(f) } + return listOf( + Triple(f0.name, f0WithSubAssertion, false), + Triple(f1.name, f1.lambda, true) + ) +} + +@JvmName("unifySignatures1Feature") +fun unifySignatures( + f0: Feature1, + f1: Feature2.() -> Unit, R> +): List.(A1, Expect.() -> Unit) -> Expect, Boolean>> { + val f0WithSubAssertion: Expect.(A1, Expect.() -> Unit) -> Expect = + { a1, f: Expect.() -> Unit -> (f0.lambda)(a1).apply(f) } + return listOf( + Triple(f0.name, f0WithSubAssertion, false), + Triple(f1.name, f1.lambda, true) + ) +} + +@Suppress("UNCHECKED_CAST") +fun uncheckedToNonNullable(f: List, fNullable: List): List = f + (fNullable as List) + +@Suppress("UNCHECKED_CAST") +fun uncheckedToNonNullable(f: F, fNullable: Any): List = listOf(f, fNullable as F) + + +internal inline fun Feature0.withSubAssertion(): Expect.(Expect.() -> Unit) -> Expect = + { f: Expect.() -> Unit -> apply { (lambda)().f() } } + +@JvmName("withSubAssertion1") +internal inline fun Feature1.withSubAssertion() + : Expect.(A1, Expect.() -> Unit) -> Expect = + { a1, f: Expect.() -> Unit -> apply { (lambda)(a1).f() } } + +@JvmName("withSubAssertion2") +internal inline fun Feature2.withSubAssertion(): + Expect.(A1, A2, Expect.() -> Unit) -> Expect = + { a1, a2, f: Expect.() -> Unit -> apply { (lambda)(a1, a2).f() } } + +@JvmName("withSubAssertion3") +internal inline fun Feature3.withSubAssertion(): + Expect.(A1, A2, A3, Expect.() -> Unit) -> Expect = + { a1, a2, a3, f: Expect.() -> Unit -> apply { (lambda)(a1, a2, a3).f() } } //@formatter:off -inline fun property(f: KProperty1, Expect>, suffix: String = ""): Feature0 = f.name + suffix to f -inline fun feature0(f: KFunction1, Expect>, suffix: String = ""): Feature0 = f.name + suffix to f -inline fun feature1(f: KFunction2, A1, Expect>, suffix: String = ""): Feature1 = f.name + suffix to f -inline fun feature2(f: KFunction3, A1, A2, Expect>, suffix: String = ""): Feature2 = f.name + suffix to f +inline fun property(f: KProperty1, Expect>): Feature0 = (f.name to f).withFeatureSuffix() +//TODO simplify further instead of adjustName { "$it nullable" } once https://youtrack.jetbrains.com/issue/KT-35992 is fixed +//@JvmName("feature0Nullable") +//inline fun feature0(f: KFunction1, Expect>): Feature0 = "${f.name} (nullable feature)" to f +inline fun feature0(f: KFunction1, Expect>): Feature0 = (f.name to f).withFeatureSuffix() +inline fun feature1(f: KFunction2, A1, Expect>): Feature1 = (f.name to f).withFeatureSuffix() +inline fun feature2(f: KFunction3, A1, A2, Expect>): Feature2 = (f.name to f).withFeatureSuffix() -inline fun fun0(f: KFunction1, Expect>, suffix: String = ""): Fun0 = f.name + suffix to f -inline fun fun1(f: KFunction2, A1, Expect>, suffix: String = ""): Fun1 = f.name + suffix to f -inline fun fun2(f: KFunction3, A1, A2, Expect>, suffix: String = ""): Fun2 = f.name + suffix to f +inline fun fun0(f: KFunction1, Expect>): Fun0 = f.name to f +inline fun fun1(f: KFunction2, A1, Expect>): Fun1 = f.name to f +inline fun fun2(f: KFunction3, A1, A2, Expect>): Fun2 = f.name to f //@formatter:on fun notImplemented(): T = throw NotImplementedError() @@ -125,5 +211,8 @@ fun String.Companion.format(string: String, arg: Any, vararg otherArgs: Any): St val toBeDescr = DescriptionBasic.TO_BE.getDefault() val isDescr = DescriptionBasic.IS.getDefault() val isNotDescr = DescriptionBasic.IS_NOT.getDefault() +val isADescr = DescriptionAnyAssertion.IS_A.getDefault() expect val lineSeperator: String + +fun showsSubAssertionIf(hasExtraHint: Boolean): String = if (hasExtraHint) "; shows intended sub assertion" else "" diff --git a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/testutils/AsciiBulletPointReporterFactory.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/testutils/AsciiBulletPointReporterFactory.kt similarity index 94% rename from apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/testutils/AsciiBulletPointReporterFactory.kt rename to misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/testutils/AsciiBulletPointReporterFactory.kt index bfd58bc0a..1a5d3fec3 100644 --- a/apis/infix-en_GB/atrium-api-infix-en_GB-common/src/test/kotlin/ch/tutteli/atrium/api/infix/en_GB/testutils/AsciiBulletPointReporterFactory.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/testutils/AsciiBulletPointReporterFactory.kt @@ -1,4 +1,4 @@ -package ch.tutteli.atrium.api.infix.en_GB.testutils +package ch.tutteli.atrium.specs.testutils import ch.tutteli.atrium.assertions.* import ch.tutteli.atrium.domain.builders.reporting.ReporterBuilder @@ -6,7 +6,7 @@ import ch.tutteli.atrium.reporting.Reporter import ch.tutteli.atrium.reporting.ReporterFactory class AsciiBulletPointReporterFactory : ReporterFactory { - override val id = "ascii" + override val id: String = "ascii" override fun create(): Reporter { return ReporterBuilder.create() diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/SpecBodyExtensions.kt b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/SpecBodyExtensions.kt deleted file mode 100644 index 0843ba3e5..000000000 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/SpecBodyExtensions.kt +++ /dev/null @@ -1,26 +0,0 @@ -//TODO remove file as soon as all specs have been transformed to spek2 -package ch.tutteli.atrium.specs - -import ch.tutteli.kbox.joinToString -import org.jetbrains.spek.api.dsl.SpecBody - -//TODO #116 remove once there aren't any spek1 specs anymore -fun SpecBody.describeFun( - describePrefix: String, - funNames: Array, - funNamePrefix: String = "`", - funNameSuffix: String = "`", - body: SpecBody.() -> Unit -) = prefixedDescribe(describePrefix, " fun ", giveWrappedNames(funNames, funNamePrefix, funNameSuffix), body) - -private fun giveWrappedNames(names: Array, prefix: String, postfix: String): String { - return names.joinToString(", ", " and ") { it, sb -> - sb.append(prefix).append(it).append(postfix) - } -} - -fun SpecBody.prefixedDescribe(prefix: String, description: String, body: SpecBody.() -> Unit) = - prefixedDescribe(prefix, "", description, body) - -fun SpecBody.prefixedDescribe(prefix: String, suffix: String, description: String, body: SpecBody.() -> Unit) = - group("${prefix}describe$suffix $description", body = body) diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/integration/Fun0AssertionsJvmSpec.kt b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/integration/Fun0AssertionsJvmSpec.kt index aa2ea1746..be7fcd168 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/integration/Fun0AssertionsJvmSpec.kt +++ b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/integration/Fun0AssertionsJvmSpec.kt @@ -2,10 +2,7 @@ package ch.tutteli.atrium.specs.integration -import ch.tutteli.atrium.api.fluent.en_GB.containsRegex -import ch.tutteli.atrium.api.fluent.en_GB.message -import ch.tutteli.atrium.api.fluent.en_GB.toBe -import ch.tutteli.atrium.api.fluent.en_GB.toThrow +import ch.tutteli.atrium.api.fluent.en_GB.* import ch.tutteli.atrium.api.verbs.internal.expect import ch.tutteli.atrium.core.polyfills.fullName import ch.tutteli.atrium.creating.Expect @@ -25,30 +22,14 @@ abstract class Fun0AssertionsJvmSpec( describePrefix: String = "[Atrium] " ) : Spek({ - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) + @Suppress("NAME_SHADOWING") + val toThrow = toThrow.adjustName { it.substringBefore(" (feature)") } - fun Suite.checkToThrow( - description: String, - act: (Expect Any?>.() -> Unit) -> Unit, - lazy: (Expect Any?>.() -> Unit), - immediate: (Expect Any?>.() -> Unit) - ) { - checkGenericNarrowingAssertion(description, act, lazy, "immediate" to immediate) - } + @Suppress("NAME_SHADOWING") + val notToThrow = notToThrow.adjustName { it.substringBefore(" (feature)") } - fun expectThrowsAssertionErrorAndMessageContainsRegex( - toThrowFun: Expect<() -> R>.() -> Unit, - throwable: Throwable, - pattern: String, vararg otherPatterns: String - ) { - expect { - val act: () -> R = { throw throwable } - expect(act).toThrowFun() - }.toThrow { - message { containsRegex(pattern, *otherPatterns) } - } - } + fun describeFun(vararg pairs: SpecPair<*>, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, pairs.map { it.name }.toTypedArray(), body = body) val messageDescr = DescriptionThrowableAssertion.OCCURRED_EXCEPTION_MESSAGE.getDefault() val stackTraceDescr = DescriptionThrowableAssertion.OCCURRED_EXCEPTION_STACKTRACE.getDefault() @@ -63,97 +44,96 @@ abstract class Fun0AssertionsJvmSpec( "\\s+\\Q$explanationBulletPoint\\E$stackTraceDescr: $separator" + "\\s+\\Q$listBulletPoint\\E${Fun0AssertionsJvmSpec::class.fullName}" - describeFun("${toThrowFeature.name} feature and ${toThrow.name}") { - val toThrowFeatureFun = toThrowFeature.lambda - val toThrowFun = toThrow.lambda + describeFun(toThrowFeature, toThrow, notToThrowFeature, notToThrow) { + val toThrowFunctions = unifySignatures(toThrowFeature, toThrow) + val notToThrowFunctions = unifySignatures(notToThrowFeature, notToThrow) context("wrong exception with suppressed") { + val exceptionWithSuppressed = UnsupportedOperationException("not supported") + exceptionWithSuppressed.addSuppressed(IllegalStateException("not good")) + exceptionWithSuppressed.addSuppressed(IllegalArgumentException(errMessage)) - checkToThrow("shows all suppressed as extra hint", { doToThrow -> - val ex = UnsupportedOperationException("not supported") - ex.addSuppressed(IllegalStateException("not good")) - ex.addSuppressed(IllegalArgumentException(errMessage)) - expectThrowsAssertionErrorAndMessageContainsRegex( - doToThrow, - ex, - UnsupportedOperationException::class.simpleName + separator + messageAndStackTrace("not supported"), - "\\s+\\Q$explanationBulletPoint\\E$supressedDescr: ${IllegalStateException::class.fullName}" + - messageAndStackTrace("not good"), - "\\s+\\Q$explanationBulletPoint\\E$supressedDescr: ${IllegalArgumentException::class.fullName}" + - messageAndStackTrace(errMessage) - ) - }, { toThrowFun { message { toBe("hello") } } }, { toThrowFeatureFun() }) - } - } + fun Expect.expectSuppressedInReporting() = + message { + containsRegex( + UnsupportedOperationException::class.simpleName + separator + messageAndStackTrace("not supported"), + "\\s+\\Q$explanationBulletPoint\\E$supressedDescr: ${IllegalStateException::class.fullName}" + + messageAndStackTrace("not good"), + "\\s+\\Q$explanationBulletPoint\\E$supressedDescr: ${IllegalArgumentException::class.fullName}" + + messageAndStackTrace(errMessage) + ) + } - describeFun("${notToThrowFeature.name} feature") { - val notToThrowFeatureFun = notToThrowFeature.lambda + toThrowFunctions.forEach { (name, toThrowFun, hasExtraHint) -> + it("$name - shows all suppressed as extra hint" + showsSubAssertionIf(hasExtraHint)) { - context("exception is thrown with suppressed") { - val notThrown: Expect<() -> Int>.() -> Unit = { notToThrowFeatureFun().toBe(1) } - - it("shows all suppressed as extra hint") { - val ex = UnsupportedOperationException("not supported") - ex.addSuppressed(IllegalStateException("not good")) - ex.addSuppressed(IllegalArgumentException(errMessage)) - expectThrowsAssertionErrorAndMessageContainsRegex( - notThrown, - ex, - UnsupportedOperationException::class.simpleName + separator + messageAndStackTrace("not supported"), - "\\s+\\Q$explanationBulletPoint\\E$supressedDescr: ${IllegalStateException::class.fullName}" + - messageAndStackTrace("not good"), - "\\s+\\Q$explanationBulletPoint\\E$supressedDescr: ${IllegalArgumentException::class.fullName}" + - messageAndStackTrace(errMessage) - ) + expect { + expect<() -> Any?> { + throw exceptionWithSuppressed + }.toThrowFun { message.toBe("hello") } + }.toThrow { + expectSuppressedInReporting() + if (hasExtraHint) messageContains("$toBeDescr: \"hello\"") + } + } } - it("with nested cause, shows both causes as extra hint") { - val ex = UnsupportedOperationException("not supported") - ex.addSuppressed(IOException("io", IllegalStateException(errMessage))) - expectThrowsAssertionErrorAndMessageContainsRegex( - notThrown, - ex, - UnsupportedOperationException::class.simpleName + separator + messageAndStackTrace("not supported"), - "\\s+\\Q$explanationBulletPoint\\E$supressedDescr: ${IOException::class.fullName}" + - messageAndStackTrace("io"), - "\\s+\\Q$explanationBulletPoint\\E$causeDescr: ${IllegalStateException::class.fullName}" + - messageAndStackTrace(errMessage) - ) + + notToThrowFunctions.forEach { (name, notToThrowFun, hasExtraHint) -> + it("$name - shows all suppressed as extra hint" + showsSubAssertionIf(hasExtraHint)) { + expect { + expect<() -> Int> { + throw exceptionWithSuppressed + }.notToThrowFun { toBe(2) } + }.toThrow { + expectSuppressedInReporting() + if (hasExtraHint) messageContains("$toBeDescr: 2") + } + } } - } - } - describeFun(notToThrow.name) { - val notToThrowFun = notToThrow.lambda - context("exception is thrown with suppressed") { - val notThrown: Expect<() -> Int>.() -> Unit = { notToThrowFun { toBe(1) } } + context("with nested cause") { + val exceptionWithSuppressedWhichHasCause = UnsupportedOperationException("not supported") + exceptionWithSuppressedWhichHasCause.addSuppressed(IOException("io", IllegalStateException(errMessage))) - it("shows all suppressed as extra hint") { - val ex = UnsupportedOperationException("not supported") - ex.addSuppressed(IllegalStateException("not good")) - ex.addSuppressed(IllegalArgumentException(errMessage)) - expectThrowsAssertionErrorAndMessageContainsRegex( - notThrown, - ex, - UnsupportedOperationException::class.simpleName + separator + messageAndStackTrace("not supported"), - "\\s+\\Q$explanationBulletPoint\\E$supressedDescr: ${IllegalStateException::class.fullName}" + - messageAndStackTrace("not good"), - "\\s+\\Q$explanationBulletPoint\\E$supressedDescr: ${IllegalArgumentException::class.fullName}" + - messageAndStackTrace(errMessage) - ) - } - it("with nested cause, shows both causes as extra hint") { - val ex = UnsupportedOperationException("not supported") - ex.addSuppressed(IOException("io", IllegalStateException(errMessage))) - expectThrowsAssertionErrorAndMessageContainsRegex( - notThrown, - ex, - UnsupportedOperationException::class.simpleName + separator + messageAndStackTrace("not supported"), - "\\s+\\Q$explanationBulletPoint\\E$supressedDescr: ${IOException::class.fullName}" + - messageAndStackTrace("io"), - "\\s+\\Q$explanationBulletPoint\\E$causeDescr: ${IllegalStateException::class.fullName}" + - messageAndStackTrace(errMessage) - ) + fun Expect.expectSuppressedAndCauseInReporting() = + message { + containsRegex( + UnsupportedOperationException::class.simpleName + separator + messageAndStackTrace("not supported"), + "\\s+\\Q$explanationBulletPoint\\E$supressedDescr: ${IOException::class.fullName}" + + messageAndStackTrace("io"), + "\\s+\\Q$explanationBulletPoint\\E$causeDescr: ${IllegalStateException::class.fullName}" + + messageAndStackTrace(errMessage) + ) + + } + + toThrowFunctions.forEach { (name, toThrowFun, hasExtraHint) -> + it("$name -shows suppressed including cause as extra hint" + showsSubAssertionIf(hasExtraHint)) { + + expect { + expect<() -> Any?> { + throw exceptionWithSuppressedWhichHasCause + }.toThrowFun { message.toBe("hello") } + }.toThrow { + expectSuppressedAndCauseInReporting() + if (hasExtraHint) messageContains("$toBeDescr: \"hello\"") + } + } + } + + notToThrowFunctions.forEach { (name, notToThrowFun, hasExtraHint) -> + it("$name - shows suppressed including cause as extra hint" + showsSubAssertionIf(hasExtraHint)) { + expect { + expect<() -> Int> { + throw exceptionWithSuppressedWhichHasCause + }.notToThrowFun { toBe(2) } + }.toThrow { + expectSuppressedAndCauseInReporting() + if (hasExtraHint) messageContains("$toBeDescr: 2") + } + } + } } } } diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/integration/OptionalAssertionsSpec.kt b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/integration/OptionalAssertionsSpec.kt index 008a784a3..0ad4484ca 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/integration/OptionalAssertionsSpec.kt +++ b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/integration/OptionalAssertionsSpec.kt @@ -9,8 +9,7 @@ import ch.tutteli.atrium.specs.* import ch.tutteli.atrium.translations.DescriptionOptionalAssertion import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.Suite -import java.lang.AssertionError -import java.util.Optional +import java.util.* abstract class OptionalAssertionsSpec( isEmpty: Fun0>, @@ -30,32 +29,33 @@ abstract class OptionalAssertionsSpec( isPresent.forAssertionCreatorSpec("$toBeDescr: 2") { toBe(2) } ) {}) - fun describeFun(vararg funName: String, body: Suite.() -> Unit) = - describeFunTemplate(describePrefix, funName, body = body) - describeFun(isEmpty.name, isPresent.name) { + fun describeFun(vararg pairs: SpecPair<*>, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, pairs.map { it.name }.toTypedArray(), body = body) + + describeFun(isEmpty, isPresentFeature, isPresent) { val isEmptyFun = isEmpty.lambda - val isPresentFun = isPresentFeature.lambda + val isPresentFunctions = unifySignatures(isPresentFeature, isPresent) val emptyValue = Optional.empty() context("$emptyValue") { it("${isEmpty.name} - does not throw") { expect(emptyValue).isEmptyFun() } - it("${isPresent.name} - throws an AssertionError") { - expect { - expect(emptyValue).isPresentFun() - }.toThrow { - messageContains(DescriptionOptionalAssertion.IS_NOT_PRESENT.getDefault()) + isPresentFunctions.forEach { (name, isPresentFun, hasExtraHint) -> + it("$name - throws an AssertionError" + showsSubAssertionIf(hasExtraHint)) { + expect { + expect(emptyValue).isPresentFun { toBe(2) } + }.toThrow { + messageContains(DescriptionOptionalAssertion.IS_NOT_PRESENT.getDefault()) + if (hasExtraHint) messageContains("$toBeDescr: 2") + } } } } val presentValue: Optional = Optional.of(2) context("$presentValue") { - it("${isPresent.name} - can perform sub-assertion which holds") { - expect(presentValue).isPresentFun() - } it("${isEmpty.name} - throws an AssertionError") { expect { expect(presentValue).isEmptyFun() @@ -63,6 +63,12 @@ abstract class OptionalAssertionsSpec( messageContains("$isDescr: ${DescriptionOptionalAssertion.EMPTY.getDefault()}") } } + + isPresentFunctions.forEach { (name, isPresentFun, hasExtraHint) -> + it("$name - can perform sub-assertion which holds") { + expect(presentValue).isPresentFun { toBe(2) } + } + } } } }) diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/integration/PathFeatureAssertionsSpec.kt b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/integration/PathFeatureAssertionsSpec.kt index b3ab36942..5b60c07ee 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/integration/PathFeatureAssertionsSpec.kt +++ b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/integration/PathFeatureAssertionsSpec.kt @@ -16,6 +16,8 @@ import java.nio.file.Paths abstract class PathFeatureAssertionsSpec( parentFeature: Feature0, parent: Fun1.() -> Unit>, + resolveFeature: Feature1, + resolve: Fun2.() -> Unit>, fileNameFeature: Feature0, fileName: Fun1.() -> Unit>, fileNameWithoutExtensionFeature: Feature0, @@ -30,6 +32,8 @@ abstract class PathFeatureAssertionsSpec( include(object : SubjectLessSpec(describePrefix, parentFeature.forSubjectLess().adjustName { "$it feature" }, parent.forSubjectLess { }, + resolveFeature.forSubjectLess("test").adjustName { "$it feature" }, + resolve.forSubjectLess("test") { toBe(Paths.get("a/my.txt")) }, fileNameFeature.forSubjectLess().adjustName { "$it feature" }, fileName.forSubjectLess { }, fileNameWithoutExtensionFeature.forSubjectLess().adjustName { "$it feature" }, @@ -105,6 +109,49 @@ abstract class PathFeatureAssertionsSpec( } } + describeFun("val ${resolveFeature.name}") { + val resolveVal = resolveFeature.lambda + + context("Folder resolved from root") { + it("toBe(folder.resolve) holds") { + val resolvedFolder = tempFolder.newDirectory("resolve") + val rootFolder = resolvedFolder.parent + expect(rootFolder).resolveVal("resolve").toBe(resolvedFolder) + } + it("toBe(folder) fails") { + expect { + val resolvedFolder = tempFolder.newDirectory("resolve") + val rootFolder = resolvedFolder.parent + expect(rootFolder).resolveVal("notResolved").toBe(resolvedFolder) + }.toThrow { + messageContains("notResolved") + } + } + } + } + + describeFun("fun ${resolve.name}") { + val resolveFun = resolve.lambda + + context("Folder resolved from root") { + it("toBe(folder.resolve) holds") { + val resolvedFolder = tempFolder.newDirectory("resolve") + val rootFolder = resolvedFolder.parent + expect(rootFolder).resolveFun("resolve") { toBe(resolvedFolder) } + } + it("toBe(folder) fails") { + expect { + val resolvedFolder = tempFolder.newDirectory("resolve") + val rootFolder = resolvedFolder.parent + expect(rootFolder).resolveFun("notResolved"){ toBe(resolvedFolder) } + }.toThrow { + messageContains("notResolved") + } + } + } + } + + describeFun("val ${fileNameFeature.name}") { val fileNameVal = fileNameFeature.lambda diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/AssertionFormatterControllerSpec.kt b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/AssertionFormatterControllerSpec.kt index a097925eb..7865b9531 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/AssertionFormatterControllerSpec.kt +++ b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/AssertionFormatterControllerSpec.kt @@ -14,21 +14,18 @@ import ch.tutteli.atrium.reporting.RawString import ch.tutteli.atrium.reporting.translating.Untranslatable import ch.tutteli.atrium.reporting.translating.UsingDefaultTranslator import ch.tutteli.atrium.specs.AssertionVerb -import ch.tutteli.atrium.specs.describeFun +import ch.tutteli.atrium.specs.describeFunTemplate import ch.tutteli.atrium.translations.DescriptionComparableAssertion.* -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.SpecBody -import org.jetbrains.spek.api.dsl.context -import org.jetbrains.spek.api.dsl.it +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.Suite -//TODO #116 migrate spek1 to spek2 - move to specs-common abstract class AssertionFormatterControllerSpec( testeeFactory: () -> AssertionFormatterController, describePrefix: String = "[Atrium] " ) : Spek({ - fun describeFun(vararg funName: String, body: SpecBody.() -> Unit) = - describeFun(describePrefix, funName, body = body) + fun describeFun(vararg funName: String, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, funName, body = body) val testee = testeeFactory() val arrow = " >>" diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/AssertionFormatterSpec.kt b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/AssertionFormatterSpec.kt index e991b9c1c..54002d400 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/AssertionFormatterSpec.kt +++ b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/AssertionFormatterSpec.kt @@ -16,23 +16,21 @@ import ch.tutteli.atrium.reporting.ObjectFormatter import ch.tutteli.atrium.reporting.translating.Translator import ch.tutteli.atrium.reporting.translating.Untranslatable import ch.tutteli.atrium.reporting.translating.UsingDefaultTranslator -import ch.tutteli.atrium.specs.describeFun -import com.nhaarman.mockitokotlin2.mock -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.SpecBody -import org.jetbrains.spek.api.dsl.it +import ch.tutteli.atrium.specs.describeFunTemplate +import io.mockk.*; +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.Suite import kotlin.reflect.KClass -//TODO #116 migrate spek1 to spek2 - move to specs-common abstract class AssertionFormatterSpec( testeeFactory: (Map, String>, AssertionFormatterController, ObjectFormatter, Translator) -> AssertionFormatter, describePrefix: String = "[Atrium] " ) : Spek({ - fun describeFun(vararg funName: String, body: SpecBody.() -> Unit) = - describeFun(describePrefix, funName, body = body) + fun describeFun(vararg funName: String, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, funName, body = body) - val controller = mock() + val controller = mockk() val testee = testeeFactory( mapOf(), controller, ToStringObjectFormatter, UsingDefaultTranslator() diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/AssertionFormatterSpecBase.kt b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/AssertionFormatterSpecBase.kt index cf657a707..a50575f98 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/AssertionFormatterSpecBase.kt +++ b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/AssertionFormatterSpecBase.kt @@ -5,14 +5,12 @@ import ch.tutteli.atrium.core.coreFactory import ch.tutteli.atrium.reporting.* import ch.tutteli.atrium.reporting.translating.Translator import ch.tutteli.atrium.reporting.translating.UsingDefaultTranslator -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.Spec -import org.jetbrains.spek.api.include +import org.spekframework.spek2.Spek +import org.spekframework.spek2.dsl.Root import kotlin.reflect.KClass -//TODO #116 migrate spek1 to spek2 - move to specs-common -abstract class AssertionFormatterSpecBase(spec: Spec.() -> Unit) : Spek({ - include(wrap(spec)) +abstract class AssertionFormatterSpecBase(spec: Root.() -> Unit) : Spek({ + include(object: Spek(spec) {}) afterEachTest { sb = StringBuilder() diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/SingleAssertionGroupTypeFormatterSpec.kt b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/SingleAssertionGroupTypeFormatterSpec.kt index 9ecfa7f3f..620373d84 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/SingleAssertionGroupTypeFormatterSpec.kt +++ b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/SingleAssertionGroupTypeFormatterSpec.kt @@ -18,13 +18,11 @@ import ch.tutteli.atrium.reporting.ObjectFormatter import ch.tutteli.atrium.reporting.translating.Translator import ch.tutteli.atrium.reporting.translating.Untranslatable import ch.tutteli.atrium.reporting.translating.UsingDefaultTranslator -import ch.tutteli.atrium.specs.describeFun -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.SpecBody -import org.jetbrains.spek.api.dsl.it +import ch.tutteli.atrium.specs.describeFunTemplate +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.Suite import kotlin.reflect.KClass -//TODO #116 migrate spek1 to spek2 - move to specs-common abstract class SingleAssertionGroupTypeFormatterSpec( testeeFactory: (Map, String>, AssertionFormatterController, ObjectFormatter, Translator) -> AssertionFormatter, supportedAssertionGroupTypeClass: KClass, @@ -33,8 +31,8 @@ abstract class SingleAssertionGroupTypeFormatterSpec describePrefix: String = "[Atrium] " ) : Spek({ - fun describeFun(vararg funName: String, body: SpecBody.() -> Unit) = - describeFun(describePrefix, funName, body = body) + fun describeFun(vararg funName: String, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, funName, body = body) val testee = testeeFactory( mapOf(), coreFactory.newAssertionFormatterController(), diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextExplanatoryAssertionGroupFormatterSpec.kt b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextExplanatoryAssertionGroupFormatterSpec.kt index 4fdce7ca5..98a4cb814 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextExplanatoryAssertionGroupFormatterSpec.kt +++ b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextExplanatoryAssertionGroupFormatterSpec.kt @@ -7,7 +7,6 @@ import ch.tutteli.atrium.reporting.AssertionFormatter import ch.tutteli.atrium.reporting.AssertionFormatterController import kotlin.reflect.KClass -//TODO #116 migrate spek1 to spek2 - move to specs-common abstract class TextExplanatoryAssertionGroupFormatterSpec( testeeFactory: (Map, String>, AssertionFormatterController) -> AssertionFormatter, describePrefix: String = "[Atrium] " @@ -16,5 +15,4 @@ abstract class TextExplanatoryAssertionGroupFormatterSpec( ExplanatoryAssertionGroupType::class, object : ExplanatoryAssertionGroupType {}, { ExpectImpl.builder.explanatoryGroup.withDefaultType.withAssertions(it).build() }, - describePrefix -) + describePrefix) diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextExplanatoryBasedAssertionGroupFormatterSpec.kt b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextExplanatoryBasedAssertionGroupFormatterSpec.kt index af50de140..ed0fb433e 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextExplanatoryBasedAssertionGroupFormatterSpec.kt +++ b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextExplanatoryBasedAssertionGroupFormatterSpec.kt @@ -6,11 +6,9 @@ import ch.tutteli.atrium.assertions.BulletPointIdentifier import ch.tutteli.atrium.assertions.ExplanatoryAssertionGroupType import ch.tutteli.atrium.reporting.AssertionFormatter import ch.tutteli.atrium.reporting.AssertionFormatterController -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.include +import org.spekframework.spek2.Spek import kotlin.reflect.KClass -//TODO #116 migrate spek1 to spek2 - move to specs-common abstract class TextExplanatoryBasedAssertionGroupFormatterSpec( testeeFactory: (Map, String>, AssertionFormatterController) -> AssertionFormatter, assertionGroupTypeClass: KClass, diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextFallbackAssertionFormatterSpec.kt b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextFallbackAssertionFormatterSpec.kt index 431be308b..2e0419ed3 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextFallbackAssertionFormatterSpec.kt +++ b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextFallbackAssertionFormatterSpec.kt @@ -5,6 +5,7 @@ import ch.tutteli.atrium.api.fluent.en_GB.toBe import ch.tutteli.atrium.api.verbs.internal.expect import ch.tutteli.atrium.assertions.* import ch.tutteli.atrium.core.coreFactory +import ch.tutteli.atrium.core.polyfills.fullName import ch.tutteli.atrium.domain.builders.ExpectImpl import ch.tutteli.atrium.reporting.AssertionFormatter import ch.tutteli.atrium.reporting.AssertionFormatterController @@ -12,22 +13,19 @@ import ch.tutteli.atrium.reporting.ObjectFormatter import ch.tutteli.atrium.reporting.translating.Translator import ch.tutteli.atrium.reporting.translating.Untranslatable import ch.tutteli.atrium.reporting.translating.UsingDefaultTranslator -import ch.tutteli.atrium.specs.describeFun +import ch.tutteli.atrium.specs.describeFunTemplate import ch.tutteli.atrium.translations.DescriptionAnyAssertion.IS_SAME import ch.tutteli.atrium.translations.DescriptionBasic.TO_BE -import org.jetbrains.spek.api.dsl.SpecBody -import org.jetbrains.spek.api.dsl.context -import org.jetbrains.spek.api.dsl.it +import org.spekframework.spek2.style.specification.Suite import kotlin.reflect.KClass -//TODO #116 migrate spek1 to spek2 - move to specs-common abstract class TextFallbackAssertionFormatterSpec( testeeFactory: (Map, String>, AssertionFormatterController, ObjectFormatter, Translator) -> AssertionFormatter, describePrefix: String = "[Atrium] " ) : AssertionFormatterSpecBase({ - fun describeFun(vararg funName: String, body: SpecBody.() -> Unit) = - describeFun(describePrefix, funName, body = body) + fun describeFun(vararg funName: String, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, funName, body = body) val testee = testeeFactory( bulletPoints, coreFactory.newAssertionFormatterController(), @@ -39,7 +37,7 @@ abstract class TextFallbackAssertionFormatterSpec( } describeFun(testee::canFormat.name) { - group("check that it always returns true even for...") { + context("check that it always returns true even for...") { it("... an anonymous class of ${Assertion::class.simpleName}") { testee.canFormat(unsupportedAssertion) } @@ -62,7 +60,7 @@ abstract class TextFallbackAssertionFormatterSpec( testee.formatNonGroup(unsupportedAssertion, parameterObject) expect(sb) { contains("false") - contains("Unsupported type ${unsupportedAssertion::class.java.name}") + contains("Unsupported type ${unsupportedAssertion::class.fullName}") } } } @@ -153,7 +151,7 @@ abstract class TextFallbackAssertionFormatterSpec( "$bulletPoint inner group: subject of inner group$separator" + "$indentBulletPoint$bulletPoint ${IS_SAME.getDefault()}: b$separator" + "$indentBulletPoint$bulletPoint ${TO_BE.getDefault()}: d", - "$bulletPoint Unsupported type ${unsupportedAssertion::class.java.name}" + "$bulletPoint Unsupported type ${unsupportedAssertion::class.fullName}" ) } } diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextFeatureAssertionGroupFormatterSpec.kt b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextFeatureAssertionGroupFormatterSpec.kt index 9df729d82..77f9e0e5c 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextFeatureAssertionGroupFormatterSpec.kt +++ b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextFeatureAssertionGroupFormatterSpec.kt @@ -15,21 +15,18 @@ import ch.tutteli.atrium.reporting.translating.Translator import ch.tutteli.atrium.reporting.translating.Untranslatable import ch.tutteli.atrium.reporting.translating.UsingDefaultTranslator import ch.tutteli.atrium.specs.AssertionVerb -import ch.tutteli.atrium.specs.describeFun +import ch.tutteli.atrium.specs.describeFunTemplate import ch.tutteli.atrium.specs.reporting.translating.TranslatorIntSpec -import org.jetbrains.spek.api.dsl.SpecBody -import org.jetbrains.spek.api.dsl.context -import org.jetbrains.spek.api.dsl.it +import org.spekframework.spek2.style.specification.Suite import kotlin.reflect.KClass -//TODO #116 migrate spek1 to spek2 - move to specs-common abstract class TextFeatureAssertionGroupFormatterSpec( testeeFactory: (Map, String>, AssertionFormatterController, ObjectFormatter, Translator) -> AssertionFormatter, describePrefix: String = "[Atrium] " ) : AssertionFormatterSpecBase({ - fun describeFun(vararg funName: String, body: SpecBody.() -> Unit) = - describeFun(describePrefix, funName, body = body) + fun describeFun(vararg funName: String, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, funName, body = body) val assertions = listOf( ExpectImpl.builder.descriptive.holding.withDescriptionAndRepresentation(AssertionVerb.ASSERT, 1).build(), diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextIndentAssertionGroupFormatterSpec.kt b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextIndentAssertionGroupFormatterSpec.kt index b4f867bbe..662ada2e1 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextIndentAssertionGroupFormatterSpec.kt +++ b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextIndentAssertionGroupFormatterSpec.kt @@ -1,5 +1,3 @@ -@file:Suppress("DEPRECATION" /* TODO remove with 1.0.0 */) - package ch.tutteli.atrium.specs.reporting import ch.tutteli.atrium.assertions.BulletPointIdentifier @@ -10,8 +8,6 @@ import ch.tutteli.atrium.reporting.AssertionFormatter import ch.tutteli.atrium.reporting.AssertionFormatterController import kotlin.reflect.KClass -//TODO remove with 1.0.0 - no need to migrate to spek2 -@Deprecated("So far indentation was achieved by grouping (which is the solution to go). Will be removed with 1.0.0") abstract class TextIndentAssertionGroupFormatterSpec( testeeFactory: (Map, String>, AssertionFormatterController) -> AssertionFormatter, describePrefix: String = "[Atrium] " diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextIndentBasedAssertionGroupFormatterSpec.kt b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextIndentBasedAssertionGroupFormatterSpec.kt index d7f847f85..81e39a9e5 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextIndentBasedAssertionGroupFormatterSpec.kt +++ b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextIndentBasedAssertionGroupFormatterSpec.kt @@ -9,14 +9,11 @@ import ch.tutteli.atrium.reporting.AssertionFormatter import ch.tutteli.atrium.reporting.AssertionFormatterController import ch.tutteli.atrium.reporting.translating.Untranslatable import ch.tutteli.atrium.specs.AssertionVerb -import ch.tutteli.atrium.specs.describeFun -import org.jetbrains.spek.api.dsl.SpecBody -import org.jetbrains.spek.api.dsl.context -import org.jetbrains.spek.api.dsl.it +import ch.tutteli.atrium.specs.describeFunTemplate +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.Suite import kotlin.reflect.KClass -//TODO remove with 1.0.0 - no need to migrate to spek2 -@Deprecated("So far indentation was achieved by grouping (which is the solution to go). Will be removed with 1.0.0") abstract class TextIndentBasedAssertionGroupFormatterSpec( testeeFactory: (Map, String>, AssertionFormatterController) -> AssertionFormatter, assertionGroupTypeClass: KClass, @@ -25,8 +22,8 @@ abstract class TextIndentBasedAssertionGroupFormatterSpec Unit) = - describeFun(describePrefix, funName, body = body) + fun describeFun(vararg funName: String, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, funName, body = body) val indentBulletPoint = " +" val indentIndentBulletPoint = " ".repeat(indentBulletPoint.length + 1) diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextListAssertionGroupFormatterSpec.kt b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextListAssertionGroupFormatterSpec.kt index 0fbd564e6..48ba39e16 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextListAssertionGroupFormatterSpec.kt +++ b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextListAssertionGroupFormatterSpec.kt @@ -9,7 +9,6 @@ import ch.tutteli.atrium.reporting.ObjectFormatter import ch.tutteli.atrium.reporting.translating.Translator import kotlin.reflect.KClass -//TODO #116 migrate spek1 to spek2 - move to specs-common abstract class TextListAssertionGroupFormatterSpec( testeeFactory: (Map, String>, AssertionFormatterController, ObjectFormatter, Translator) -> AssertionFormatter, describePrefix: String = "[Atrium] " diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextListBasedAssertionGroupFormatterSpec.kt b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextListBasedAssertionGroupFormatterSpec.kt index 851933268..58158457e 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextListBasedAssertionGroupFormatterSpec.kt +++ b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextListBasedAssertionGroupFormatterSpec.kt @@ -12,14 +12,11 @@ import ch.tutteli.atrium.reporting.translating.Translator import ch.tutteli.atrium.reporting.translating.Untranslatable import ch.tutteli.atrium.reporting.translating.UsingDefaultTranslator import ch.tutteli.atrium.specs.AssertionVerb -import ch.tutteli.atrium.specs.describeFun +import ch.tutteli.atrium.specs.describeFunTemplate import ch.tutteli.atrium.specs.reporting.translating.TranslatorIntSpec -import org.jetbrains.spek.api.dsl.SpecBody -import org.jetbrains.spek.api.dsl.context -import org.jetbrains.spek.api.dsl.it +import org.spekframework.spek2.style.specification.Suite import kotlin.reflect.KClass -//TODO #116 migrate spek1 to spek2 - move to specs-common abstract class TextListBasedAssertionGroupFormatterSpec( testeeFactory: (Map, String>, AssertionFormatterController, ObjectFormatter, Translator) -> AssertionFormatter, assertionGroupClass: Class, @@ -28,8 +25,8 @@ abstract class TextListBasedAssertionGroupFormatterSpec( describePrefix: String = "[Atrium] " ) : AssertionFormatterSpecBase({ - fun describeFun(vararg funName: String, body: SpecBody.() -> Unit) = - describeFun(describePrefix, funName, body = body) + fun describeFun(vararg funName: String, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, funName, body = body) val assertions = listOf( ExpectImpl.builder.descriptive.holding.withDescriptionAndRepresentation(AssertionVerb.ASSERT, 1).build(), diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextSummaryAssertionGroupFormatterSpec.kt b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextSummaryAssertionGroupFormatterSpec.kt index 1294a0208..40eb27774 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextSummaryAssertionGroupFormatterSpec.kt +++ b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextSummaryAssertionGroupFormatterSpec.kt @@ -10,20 +10,18 @@ import ch.tutteli.atrium.reporting.AssertionFormatter import ch.tutteli.atrium.reporting.AssertionFormatterController import ch.tutteli.atrium.reporting.translating.Untranslatable import ch.tutteli.atrium.specs.AssertionVerb -import ch.tutteli.atrium.specs.describeFun -import org.jetbrains.spek.api.dsl.SpecBody -import org.jetbrains.spek.api.dsl.context -import org.jetbrains.spek.api.dsl.it +import ch.tutteli.atrium.specs.describeFunTemplate +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.Suite import kotlin.reflect.KClass -//TODO #116 migrate spek1 to spek2 - move to specs-common abstract class TextSummaryAssertionGroupFormatterSpec( testeeFactory: (Map, String>, AssertionFormatterController) -> AssertionFormatter, describePrefix: String = "[Atrium] " ) : AssertionFormatterSpecBase({ - fun describeFun(vararg funName: String, body: SpecBody.() -> Unit) = - describeFun(describePrefix, funName, body = body) + fun describeFun(vararg funName: String, body: Suite.() -> Unit) = + describeFunTemplate(describePrefix, funName, body = body) val successBulletPoint = "(/)" val indentSuccessBulletPoint = " ".repeat(successBulletPoint.length + 1) @@ -220,7 +218,7 @@ abstract class TextSummaryAssertionGroupFormatterSpec( } } context("${AssertionGroup::class.simpleName} of ${DefaultSummaryAssertionGroupType::class.simpleName} and group holds") { - test("The group is not formatted since it is filtered out") { + it("The group is not formatted since it is filtered out") { val assertions = listOf( ExpectImpl.builder.descriptive.holding.withDescriptionAndRepresentation( AssertionVerb.ASSERT, diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextWarningAssertionGroupFormatterSpec.kt b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextWarningAssertionGroupFormatterSpec.kt index a63d8fd56..d8bb41d45 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextWarningAssertionGroupFormatterSpec.kt +++ b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/TextWarningAssertionGroupFormatterSpec.kt @@ -7,7 +7,6 @@ import ch.tutteli.atrium.reporting.AssertionFormatter import ch.tutteli.atrium.reporting.AssertionFormatterController import kotlin.reflect.KClass -//TODO #116 migrate spek1 to spek2 - move to specs-common abstract class TextWarningAssertionGroupFormatterSpec( testeeFactory: (Map, String>, AssertionFormatterController) -> AssertionFormatter, describePrefix: String = "[Atrium] " diff --git a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/TranslatorIntSpec.kt b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/TranslatorIntSpec.kt index 118f2b416..9092e15db 100644 --- a/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/TranslatorIntSpec.kt +++ b/misc/specs/atrium-specs-jvm/src/main/kotlin/ch/tutteli/atrium/specs/reporting/translating/TranslatorIntSpec.kt @@ -8,16 +8,13 @@ import ch.tutteli.atrium.reporting.Reporter import ch.tutteli.atrium.reporting.translating.Locale import ch.tutteli.atrium.reporting.translating.StringBasedTranslatable import ch.tutteli.atrium.reporting.translating.TranslatableWithArgs -import ch.tutteli.atrium.specs.AssertionVerb -import ch.tutteli.atrium.specs.prefixedDescribe +import ch.tutteli.atrium.specs.* import ch.tutteli.atrium.translations.DescriptionAnyAssertion import ch.tutteli.atrium.translations.DescriptionBasic import ch.tutteli.atrium.translations.DescriptionComparableAssertion -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.SpecBody -import org.jetbrains.spek.api.dsl.context -import org.jetbrains.spek.api.dsl.describe -import org.jetbrains.spek.api.dsl.it +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.describe +import org.spekframework.spek2.style.specification.Suite import java.text.SimpleDateFormat /** @@ -97,7 +94,6 @@ import java.text.SimpleDateFormat * ch.tutteli.atrium.translations.DescriptionAnyAssertion-IS_NOT_SAME=IS_NOT_SAME zh * ch.tutteli.atrium.translations.DescriptionAnyAssertion-IS_SAME=IS_SAME zh */ -//TODO #116 migrate spek1 to spek2 - move to specs-common abstract class TranslatorIntSpec( reporterFactory: (Locale, Array) -> Reporter, //TODO Remove as soon as https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8193496 is fixed in JDK8 @@ -105,9 +101,8 @@ abstract class TranslatorIntSpec( describePrefix: String = "[Atrium] " ) : Spek({ - fun prefixedDescribe(description: String, body: SpecBody.() -> Unit) { - prefixedDescribe(describePrefix, description, body) - } + fun prefixedDescribe(description: String, body: Suite.() -> Unit) = + prefixedDescribeTemplate(describePrefix, description, body) val reporterDeChFallbackFr = reporterFactory(Locale("de", "CH"), arrayOf(Locale("fr"))) fun assertWithDeCh_Fr(subject: T) = @@ -138,7 +133,7 @@ abstract class TranslatorIntSpec( context("properties file for $descriptionAnyAssertion is provided for 'de_CH'") { describe("translation for $descriptionAnyAssertion.$toBe is provided for 'de_CH'") { - test("a failing assertion contains 'ist' instead of 'to be' in the error message") { + it("a failing assertion contains 'ist' instead of 'to be' in the error message") { expect { assertWithDeCh_Fr(1).toBe(2) }.toThrow { messageContains("ist: 2") } @@ -147,7 +142,7 @@ abstract class TranslatorIntSpec( describe("translation for $descriptionAnyAssertion.$notToBe is provided for 'de'") { val text = "ist nicht" - test("a failing assertion contains '$text' instead of 'not to be' in the error message") { + it("a failing assertion contains '$text' instead of 'not to be' in the error message") { expect { assertWithDeCh_Fr(1).notToBe(1) }.toThrow { messageContains("$text: 1") } @@ -156,7 +151,7 @@ abstract class TranslatorIntSpec( describe("translation for $descriptionAnyAssertion.$isNotSame is provided 'fr'") { val text = "n'est pas la même instance que" - test("a failing assertion contains '$text' instead of 'assert' in the error message") { + it("a failing assertion contains '$text' instead of 'assert' in the error message") { expect { assertWithDeCh_Fr(1).isNotSameAs(1) }.toThrow { messageContains("$text: 1") } @@ -167,7 +162,7 @@ abstract class TranslatorIntSpec( context("properties file for ${AssertionVerb::class.simpleName} is not provided for 'de_CH' nor one of its parents") { describe("translation for ${AssertionVerb::class.simpleName}.${AssertionVerb.ASSERT} is provided for 'fr'") { val text = "il applique que" - test("a failing assertion contains '$text' instead of 'assert' in the error message") { + it("a failing assertion contains '$text' instead of 'assert' in the error message") { expect { assertWithDeCh_Fr(1).toBe(2) }.toThrow { messageContains("$text: 1") } @@ -284,14 +279,14 @@ abstract class TranslatorIntSpec( prefixedDescribe("primary locale is 'zh_$country' and no fallback defined") { if (withSpecialCases) { describe("translation for $descriptionAnyAssertion.$toBe is provided for 'zh_$country' and for ${zhWithScript}_$country") { - test("a failing assertion contains '$toBe ${zhWithScript}_$country' instead of 'to be' in the error message") { + it("a failing assertion contains '$toBe ${zhWithScript}_$country' instead of 'to be' in the error message") { expect { assert.toBe(2) }.toThrow { messageContains("$toBe ${zhWithScript}_$country: 2") } } } describe("translation for $descriptionAnyAssertion.$notToBe is provided for 'zh_$country' and for $zhWithScript") { - test("a failing assertion contains '$notToBe $zhWithScript' instead of 'to be' in the error message") { + it("a failing assertion contains '$notToBe $zhWithScript' instead of 'to be' in the error message") { expect { assert.notToBe(1) }.toThrow { messageContains("$notToBe $zhWithScript: 1") } @@ -299,14 +294,14 @@ abstract class TranslatorIntSpec( } } describe("translation for $descriptionAnyAssertion.$isNotSame is provided for 'zh_$country' and zh") { - test("a failing assertion contains '$isNotSame zh_$country' instead of 'to be' in the error message") { + it("a failing assertion contains '$isNotSame zh_$country' instead of 'to be' in the error message") { expect { assert.isNotSameAs(1) }.toThrow { messageContains("$isNotSame zh_$country: 1") } } } describe("translation for $descriptionAnyAssertion.$isSame is not provided for 'zh_$country' but for zh") { - test("a failing assertion contains '$isSame zh' instead of 'to be' in the error message") { + it("a failing assertion contains '$isSame zh' instead of 'to be' in the error message") { expect { assert.isSameAs(2) }.toThrow { messageContains("$isSame zh: 2") } diff --git a/misc/tools/atrium-bc-test/build.gradle b/misc/tools/atrium-bc-test/build.gradle index a20870938..b39bc485c 100644 --- a/misc/tools/atrium-bc-test/build.gradle +++ b/misc/tools/atrium-bc-test/build.gradle @@ -369,7 +369,11 @@ createBcAndBbcTasksForApis('0.8.0', ')', 'cc-de_CH', 'cc-en_GB', 'cc-infix-en_GB' ) -createBcAndBbcTasksForApis('0.9.0', +createBcAndBbcTasksForApis('0.9.2', + 'forgive=^$', + 'fluent-en_GB' +) +createBcAndBbcTasksForApis('0.10.0', 'forgive=^$', 'fluent-en_GB' ) diff --git a/misc/tools/atrium-bc-test/src/main/kotlin/ch/tutteil/atrium/bctest/DeprecationSpek2ExecutionListener.kt b/misc/tools/atrium-bc-test/src/main/kotlin/ch/tutteil/atrium/bctest/DeprecationSpek2ExecutionListener.kt index d1dee6c8e..eb7ab2b60 100644 --- a/misc/tools/atrium-bc-test/src/main/kotlin/ch/tutteil/atrium/bctest/DeprecationSpek2ExecutionListener.kt +++ b/misc/tools/atrium-bc-test/src/main/kotlin/ch/tutteil/atrium/bctest/DeprecationSpek2ExecutionListener.kt @@ -18,8 +18,8 @@ class DeprecationSpek2ExecutionListener( } private fun handleFailure(result: ExecutionResult.Failure, test: TestScopeImpl) { - if (forgiveRegex.matches(test.id.name)) { - println("forgiving $test") + if (forgiveRegex.matches(test.path.toString())) { + println("forgiving ${test.path}") listener.testExecutionFinish(test, ExecutionResult.Success) } else { listener.testExecutionFinish(test, result) diff --git a/misc/verbs/atrium-verbs-common/src/main/kotlin/ch/tutteli/atrium/api.verbs/assert.kt b/misc/verbs/atrium-verbs-common/src/main/kotlin/ch/tutteli/atrium/api.verbs/assert.kt index 9b4669ebe..982bb5269 100644 --- a/misc/verbs/atrium-verbs-common/src/main/kotlin/ch/tutteli/atrium/api.verbs/assert.kt +++ b/misc/verbs/atrium-verbs-common/src/main/kotlin/ch/tutteli/atrium/api.verbs/assert.kt @@ -3,6 +3,8 @@ package ch.tutteli.atrium.api.verbs import ch.tutteli.atrium.api.verbs.AssertionVerb.ASSERT import ch.tutteli.atrium.assertions.Assertion import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.creating.FeatureExpect +import ch.tutteli.atrium.creating.RootExpect import ch.tutteli.atrium.domain.builders.ExpectImpl import ch.tutteli.atrium.domain.builders.reporting.ExpectBuilder import ch.tutteli.atrium.domain.builders.reporting.ExpectOptions @@ -15,7 +17,7 @@ import ch.tutteli.atrium.domain.builders.reporting.ExpectOptions * @return The newly created assertion container. * @throws AssertionError in case an assertion does not hold. */ -fun assert(subject: T): Expect = +fun assert(subject: T): RootExpect = ExpectBuilder.forSubject(subject) .withVerb(ASSERT) .withoutOptions() @@ -41,5 +43,5 @@ fun assert(subject: T, assertionCreator: Expect.() -> Unit): Expect = "ch.tutteli.atrium.api.fluent.en_GB.feature" ) ) -fun Expect.assert(newSubject: R): Expect = +fun Expect.assert(newSubject: R): FeatureExpect = ExpectImpl.feature.manualFeature(this, ASSERT) { newSubject }.getExpectOfFeature() diff --git a/misc/verbs/atrium-verbs-common/src/main/kotlin/ch/tutteli/atrium/api.verbs/assertThat.kt b/misc/verbs/atrium-verbs-common/src/main/kotlin/ch/tutteli/atrium/api.verbs/assertThat.kt index 75ff304a5..db5462c90 100644 --- a/misc/verbs/atrium-verbs-common/src/main/kotlin/ch/tutteli/atrium/api.verbs/assertThat.kt +++ b/misc/verbs/atrium-verbs-common/src/main/kotlin/ch/tutteli/atrium/api.verbs/assertThat.kt @@ -3,6 +3,8 @@ package ch.tutteli.atrium.api.verbs import ch.tutteli.atrium.api.verbs.AssertionVerb.ASSERT_THAT import ch.tutteli.atrium.assertions.Assertion import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.creating.FeatureExpect +import ch.tutteli.atrium.creating.RootExpect import ch.tutteli.atrium.domain.builders.ExpectImpl import ch.tutteli.atrium.domain.builders.reporting.ExpectBuilder import ch.tutteli.atrium.domain.builders.reporting.ExpectOptions @@ -15,7 +17,7 @@ import ch.tutteli.atrium.domain.builders.reporting.ExpectOptions * @return The newly created assertion container. * @throws AssertionError in case an assertion does not hold. */ -fun assertThat(subject: T): Expect = +fun assertThat(subject: T): RootExpect = ExpectBuilder.forSubject(subject) .withVerb(ASSERT_THAT) .withoutOptions() @@ -41,5 +43,5 @@ fun assertThat(subject: T, assertionCreator: Expect.() -> Unit): Expect Expect.assertThat(newSubject: R): Expect = +fun Expect.assertThat(newSubject: R): FeatureExpect = ExpectImpl.feature.manualFeature(this, ASSERT_THAT) { newSubject }.getExpectOfFeature() diff --git a/misc/verbs/atrium-verbs-common/src/main/kotlin/ch/tutteli/atrium/api.verbs/expect.kt b/misc/verbs/atrium-verbs-common/src/main/kotlin/ch/tutteli/atrium/api.verbs/expect.kt index b1bf56063..82af9c080 100644 --- a/misc/verbs/atrium-verbs-common/src/main/kotlin/ch/tutteli/atrium/api.verbs/expect.kt +++ b/misc/verbs/atrium-verbs-common/src/main/kotlin/ch/tutteli/atrium/api.verbs/expect.kt @@ -3,6 +3,8 @@ package ch.tutteli.atrium.api.verbs import ch.tutteli.atrium.api.verbs.AssertionVerb.EXPECT import ch.tutteli.atrium.assertions.Assertion import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.creating.FeatureExpect +import ch.tutteli.atrium.creating.RootExpect import ch.tutteli.atrium.domain.builders.ExpectImpl import ch.tutteli.atrium.domain.builders.reporting.ExpectBuilder import ch.tutteli.atrium.domain.builders.reporting.ExpectOptions @@ -15,7 +17,7 @@ import ch.tutteli.atrium.domain.builders.reporting.ExpectOptions * @return The newly created assertion container. * @throws AssertionError in case an assertion does not hold. */ -fun expect(subject: T): Expect = +fun expect(subject: T): RootExpect = ExpectBuilder.forSubject(subject) .withVerb(EXPECT) .withoutOptions() @@ -41,5 +43,5 @@ fun expect(subject: T, assertionCreator: Expect.() -> Unit): Expect = "ch.tutteli.atrium.api.fluent.en_GB.feature" ) ) -fun Expect.expect(newSubject: R): Expect = +fun Expect.expect(newSubject: R): FeatureExpect = ExpectImpl.feature.manualFeature(this, EXPECT) { newSubject }.getExpectOfFeature() diff --git a/samples/js/jasmine/build.gradle b/samples/js/jasmine/build.gradle index d18f3d406..4250c751b 100644 --- a/samples/js/jasmine/build.gradle +++ b/samples/js/jasmine/build.gradle @@ -2,7 +2,7 @@ buildscript { ext { atrium_api = 'atrium-fluent-en_GB-js' - atrium_version = '0.9.0' + atrium_version = '0.10.0' } repositories { maven { url "https://plugins.gradle.org/m2/" } @@ -18,7 +18,6 @@ apply plugin: 'com.github.node-gradle.node' repositories { jcenter() - mavenLocal() // either use jcenter or the repository on the next line // maven { url "https://dl.bintray.com/robstoll/tutteli-jars" } } diff --git a/samples/js/jasmine/src/test/kotlin/ch/tutteli/SampleJsTest.kt b/samples/js/jasmine/src/test/kotlin/ch/tutteli/SampleJsTest.kt new file mode 100644 index 000000000..e648735f6 --- /dev/null +++ b/samples/js/jasmine/src/test/kotlin/ch/tutteli/SampleJsTest.kt @@ -0,0 +1,44 @@ +package ch.tutteli + +import ch.tutteli.atrium.api.fluent.en_GB.messageContains +import ch.tutteli.atrium.api.fluent.en_GB.toBe +import ch.tutteli.atrium.api.fluent.en_GB.toThrow +import ch.tutteli.atrium.api.verbs.assertThat +import ch.tutteli.atrium.api.verbs.expect +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.reporting.RawString +import ch.tutteli.atrium.translations.DescriptionBasic +import kotlin.test.Test + +class SampleJsTest { + @Test + fun toBe() { + expect(1).toBe(1) + } + + @Test + fun assertAnExceptionOccurred() { + expect { + throw IllegalArgumentException() + }.toThrow() + } + + + @Test + fun assertAnExceptionWithAMessageOccurred() { + expect { + throw IllegalArgumentException("oho... hello btw") + }.toThrow { + messageContains("hello") + } + } + + @Test + fun useOwnFunction() { + // isEven is defined in the common module + assertThat(2).isEven() + } +} + +fun Expect.isEven() = + createAndAddAssertion(DescriptionBasic.IS, RawString.create("an even number")) { it % 2 == 0 } diff --git a/samples/js/mocha/build.gradle b/samples/js/mocha/build.gradle index 4830e5b7d..91978c185 100644 --- a/samples/js/mocha/build.gradle +++ b/samples/js/mocha/build.gradle @@ -2,7 +2,7 @@ buildscript { ext { atrium_api = 'atrium-fluent-en_GB-js' - atrium_version = '0.9.0' + atrium_version = '0.10.0' } repositories { maven { url "https://plugins.gradle.org/m2/" } @@ -18,7 +18,6 @@ apply plugin: 'com.github.node-gradle.node' repositories { jcenter() - mavenLocal() // either use jcenter or the repository on the next line // maven { url "https://dl.bintray.com/robstoll/tutteli-jars" } } diff --git a/samples/js/mocha/src/test/kotlin/ch/tutteli/SampleJsTest.kt b/samples/js/mocha/src/test/kotlin/ch/tutteli/SampleJsTest.kt new file mode 100644 index 000000000..e648735f6 --- /dev/null +++ b/samples/js/mocha/src/test/kotlin/ch/tutteli/SampleJsTest.kt @@ -0,0 +1,44 @@ +package ch.tutteli + +import ch.tutteli.atrium.api.fluent.en_GB.messageContains +import ch.tutteli.atrium.api.fluent.en_GB.toBe +import ch.tutteli.atrium.api.fluent.en_GB.toThrow +import ch.tutteli.atrium.api.verbs.assertThat +import ch.tutteli.atrium.api.verbs.expect +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.reporting.RawString +import ch.tutteli.atrium.translations.DescriptionBasic +import kotlin.test.Test + +class SampleJsTest { + @Test + fun toBe() { + expect(1).toBe(1) + } + + @Test + fun assertAnExceptionOccurred() { + expect { + throw IllegalArgumentException() + }.toThrow() + } + + + @Test + fun assertAnExceptionWithAMessageOccurred() { + expect { + throw IllegalArgumentException("oho... hello btw") + }.toThrow { + messageContains("hello") + } + } + + @Test + fun useOwnFunction() { + // isEven is defined in the common module + assertThat(2).isEven() + } +} + +fun Expect.isEven() = + createAndAddAssertion(DescriptionBasic.IS, RawString.create("an even number")) { it % 2 == 0 } diff --git a/samples/js/mocha/src/test/kotlin/ch/tutteli/SmokeTest.kt b/samples/js/mocha/src/test/kotlin/ch/tutteli/SmokeTest.kt deleted file mode 100644 index 623a166fb..000000000 --- a/samples/js/mocha/src/test/kotlin/ch/tutteli/SmokeTest.kt +++ /dev/null @@ -1,68 +0,0 @@ -package ch.tutteli - -import ch.tutteli.atrium.api.fluent.en_GB.isLessThan -import ch.tutteli.atrium.api.fluent.en_GB.messageContains -import ch.tutteli.atrium.api.fluent.en_GB.notToThrow -import ch.tutteli.atrium.api.fluent.en_GB.toThrow -import ch.tutteli.atrium.api.verbs.assertThat -import ch.tutteli.atrium.assertions.Assertion -import ch.tutteli.atrium.creating.Expect -import ch.tutteli.atrium.domain.builders.AssertImpl -import ch.tutteli.atrium.reporting.RawString -import ch.tutteli.atrium.reporting.translating.StringBasedTranslatable -import ch.tutteli.atrium.translations.DescriptionBasic -import kotlin.test.Test - -class SmokeTest { - @Test - fun toBe_canBeUsed() { - assertThat(1).isLessThan(2) - } - - @Test - fun assertionFunctionWithoutI18nCanBeUsed() { - assertThat(2).isEven() - } - - @Test - fun assertionFunctionWithI18nCanBeUsed() { - assertThat(4).isMultipleOf(2) - } - - @Test - fun assertAnExceptionOccurred() { - assertThat { - throw IllegalArgumentException() - }.toThrow() - } - - @Test - fun assertAnExceptionWithAMessageOccurred() { - assertThat { - throw IllegalArgumentException("oho... hello btw") - }.toThrow{ - messageContains("hello") - } - } - - @Test - fun assertNotToThrow() { - assertThat { - - }.notToThrow() - } -} - -fun Expect.isEven() = - createAndAddAssertion(DescriptionBasic.IS, RawString.create("an even number")) { it % 2 == 0 } - -fun Expect.isMultipleOf(base: Int) = addAssertion(_isMultipleOf(this, base)) - -fun _isMultipleOf(expect: Expect, base: Int): Assertion = - AssertImpl.builder.createDescriptive(expect, DescriptionIntAssertions.IS_MULTIPLE_OF, base) { - it % base == 0 - } - -enum class DescriptionIntAssertions(override val value: String) : StringBasedTranslatable { - IS_MULTIPLE_OF("is multiple of") -} diff --git a/samples/jvm/junit5/build.gradle b/samples/jvm/junit5/build.gradle index e9622e9a9..089d07c83 100644 --- a/samples/jvm/junit5/build.gradle +++ b/samples/jvm/junit5/build.gradle @@ -2,7 +2,7 @@ buildscript { ext { kotlin_version= '1.3.41' atrium_api= 'atrium-fluent-en_GB' - atrium_version='0.9.0' + atrium_version='0.10.0' junit_version= '5.3.1' } diff --git a/samples/jvm/junit5/src/test/kotlin/ch/tutteli/SampleJvmTest.kt b/samples/jvm/junit5/src/test/kotlin/ch/tutteli/SampleJvmTest.kt new file mode 100644 index 000000000..348631ee2 --- /dev/null +++ b/samples/jvm/junit5/src/test/kotlin/ch/tutteli/SampleJvmTest.kt @@ -0,0 +1,45 @@ +package ch.tutteli + +import ch.tutteli.atrium.api.fluent.en_GB.messageContains +import ch.tutteli.atrium.api.fluent.en_GB.toBe +import ch.tutteli.atrium.api.fluent.en_GB.toThrow +import ch.tutteli.atrium.api.verbs.assertThat +import ch.tutteli.atrium.api.verbs.expect +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.reporting.RawString +import ch.tutteli.atrium.translations.DescriptionBasic +import org.junit.jupiter.api.Test + +class SampleJvmTest { + @Test + fun toBe() { + expect(1).toBe(1) + } + + @Test + fun assertAnExceptionOccurred() { + expect { + throw IllegalArgumentException() + }.toThrow() + } + + + @Test + fun assertAnExceptionWithAMessageOccurred() { + expect { + throw IllegalArgumentException("oho... hello btw") + }.toThrow { + messageContains("hello") + } + } + + @Test + fun useOwnFunction() { + // isEven is defined in the common module + assertThat(2).isEven() + } +} + +fun Expect.isEven() = + createAndAddAssertion(DescriptionBasic.IS, RawString.create("an even number")) { it % 2 == 0 } + diff --git a/samples/jvm/junit5/src/test/kotlin/ch/tutteli/SmokeTest.kt b/samples/jvm/junit5/src/test/kotlin/ch/tutteli/SmokeTest.kt deleted file mode 100644 index 9313e380d..000000000 --- a/samples/jvm/junit5/src/test/kotlin/ch/tutteli/SmokeTest.kt +++ /dev/null @@ -1,66 +0,0 @@ -package ch.tutteli - -import org.junit.jupiter.api.*; - -import ch.tutteli.atrium.api.fluent.en_GB.* -import ch.tutteli.atrium.api.verbs.assertThat -import ch.tutteli.atrium.assertions.Assertion -import ch.tutteli.atrium.creating.Expect -import ch.tutteli.atrium.domain.builders.AssertImpl -import ch.tutteli.atrium.reporting.RawString -import ch.tutteli.atrium.reporting.translating.StringBasedTranslatable -import ch.tutteli.atrium.translations.DescriptionBasic - -class SmokeTest { - @Test - fun toBe_canBeUsed() { - assertThat(1).isLessThan(2) - } - - @Test - fun assertionFunctionWithoutI18nCanBeUsed() { - assertThat(2).isEven() - } - - @Test - fun assertionFunctionWithI18nCanBeUsed() { - assertThat(4).isMultipleOf(2) - } - - @Test - fun assertAnExceptionOccurred() { - assertThat { - throw IllegalArgumentException() - }.toThrow() - } - - @Test - fun assertAnExceptionWithAMessageOccurred() { - assertThat { - throw IllegalArgumentException("oho... hello btw") - }.toThrow{ - messageContains("hello") - } - } - - @Test - fun assertNotToThrow() { - assertThat { - - }.notToThrow() - } -} - -fun Expect.isEven() = - createAndAddAssertion(DescriptionBasic.IS, RawString.create("an even number")) { it % 2 == 0 } - -fun Expect.isMultipleOf(base: Int) = addAssertion(_isMultipleOf(this, base)) - -fun _isMultipleOf(expect: Expect, base: Int): Assertion = - AssertImpl.builder.createDescriptive(expect, DescriptionIntAssertions.IS_MULTIPLE_OF, base) { - it % base == 0 - } - -enum class DescriptionIntAssertions(override val value: String) : StringBasedTranslatable { - IS_MULTIPLE_OF("is multiple of") -} diff --git a/samples/jvm/spek/build.gradle b/samples/jvm/spek/build.gradle index a6244603c..5efb4a008 100644 --- a/samples/jvm/spek/build.gradle +++ b/samples/jvm/spek/build.gradle @@ -2,7 +2,7 @@ buildscript { ext { kotlin_version = '1.3.41' spek_version = '2.0.0' - atrium_version='0.9.0' + atrium_version='0.10.0' } repositories { @@ -26,9 +26,6 @@ apply plugin: 'kotlin' repositories { // atrium jvm installation: more info here -> https://github.com/robstoll/atrium#jvm jcenter() - - // dependencies for spek - mavenLocal() } // setup the test task diff --git a/samples/multiplatform/.gitattributes b/samples/multiplatform/.gitattributes new file mode 100644 index 000000000..00a51aff5 --- /dev/null +++ b/samples/multiplatform/.gitattributes @@ -0,0 +1,6 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# These are explicitly windows files and should use crlf +*.bat text eol=crlf + diff --git a/samples/multiplatform/.gitignore b/samples/multiplatform/.gitignore new file mode 100644 index 000000000..2156c08d8 --- /dev/null +++ b/samples/multiplatform/.gitignore @@ -0,0 +1,10 @@ +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build + +#ignore .idea stuff +.idea +out +*.iml diff --git a/samples/multiplatform/build.gradle b/samples/multiplatform/build.gradle new file mode 100644 index 000000000..ba0777a94 --- /dev/null +++ b/samples/multiplatform/build.gradle @@ -0,0 +1,42 @@ +plugins { + id 'org.jetbrains.kotlin.multiplatform' version '1.3.61' +} +repositories { + mavenCentral() + jcenter() +} +group 'com.atrium' +version '0.0.1' + +apply plugin: 'maven-publish' + +kotlin { + def atrium_version = '0.10.0' + jvm() + js { + nodejs {} + } + sourceSets { + commonTest { + dependencies { + implementation kotlin('test-common') + implementation kotlin('test-annotations-common') + implementation "ch.tutteli.atrium:atrium-fluent-en_GB-common:$atrium_version" + } + } + jvmTest { + dependencies { + implementation kotlin('test') + implementation kotlin('test-junit') + implementation "org.junit.jupiter:junit-jupiter-api:5.3.1" + implementation "ch.tutteli.atrium:atrium-fluent-en_GB:$atrium_version" + } + } + jsTest { + dependencies { + implementation kotlin('test-js') + implementation "ch.tutteli.atrium:atrium-fluent-en_GB-js:$atrium_version" + } + } + } +} diff --git a/samples/multiplatform/gradle.properties b/samples/multiplatform/gradle.properties new file mode 100644 index 000000000..a3293d9a8 --- /dev/null +++ b/samples/multiplatform/gradle.properties @@ -0,0 +1,2 @@ +kotlin.code.style=official + diff --git a/samples/multiplatform/gradle/wrapper/gradle-wrapper.jar b/samples/multiplatform/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..cc4fdc293 Binary files /dev/null and b/samples/multiplatform/gradle/wrapper/gradle-wrapper.jar differ diff --git a/samples/multiplatform/gradle/wrapper/gradle-wrapper.properties b/samples/multiplatform/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..94920145f --- /dev/null +++ b/samples/multiplatform/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/samples/multiplatform/gradlew b/samples/multiplatform/gradlew new file mode 100755 index 000000000..2fe81a7d9 --- /dev/null +++ b/samples/multiplatform/gradlew @@ -0,0 +1,183 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/samples/multiplatform/gradlew.bat b/samples/multiplatform/gradlew.bat new file mode 100644 index 000000000..9618d8d96 --- /dev/null +++ b/samples/multiplatform/gradlew.bat @@ -0,0 +1,100 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/samples/multiplatform/settings.gradle b/samples/multiplatform/settings.gradle new file mode 100644 index 000000000..4c283e3c5 --- /dev/null +++ b/samples/multiplatform/settings.gradle @@ -0,0 +1,10 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user manual at https://docs.gradle.org/6.0.1/userguide/multi_project_builds.html + */ + +rootProject.name = 'multiplatform' diff --git a/samples/multiplatform/src/commonTest/kotlin/SampleTest.kt b/samples/multiplatform/src/commonTest/kotlin/SampleTest.kt new file mode 100644 index 000000000..bf825cee6 --- /dev/null +++ b/samples/multiplatform/src/commonTest/kotlin/SampleTest.kt @@ -0,0 +1,42 @@ +import ch.tutteli.atrium.api.fluent.en_GB.messageContains +import ch.tutteli.atrium.api.fluent.en_GB.toBe +import ch.tutteli.atrium.api.fluent.en_GB.toThrow +import ch.tutteli.atrium.api.verbs.assertThat +import ch.tutteli.atrium.api.verbs.expect +import ch.tutteli.atrium.creating.Expect +import ch.tutteli.atrium.reporting.RawString +import ch.tutteli.atrium.translations.DescriptionBasic.IS +import kotlin.test.Test + +class SampleTest { + + @Test + fun toBe() { + expect(1).toBe(1) + } + + @Test + fun assertAnExceptionOccurred() { + expect { + throw IllegalArgumentException() + }.toThrow() + } + + + @Test + fun assertAnExceptionWithAMessageOccurred() { + expect { + throw IllegalArgumentException("oho... hello btw") + }.toThrow { + messageContains("hello") + } + } + + @Test + fun useOwnFunction() { + assertThat(2).isEven() + } +} + + +fun Expect.isEven() = createAndAddAssertion(IS, RawString.create("an even number")) { it % 2 == 0 } diff --git a/samples/multiplatform/src/jsTest/kotlin/ch/tutteli/SampleJsTest.kt b/samples/multiplatform/src/jsTest/kotlin/ch/tutteli/SampleJsTest.kt new file mode 100644 index 000000000..c20325605 --- /dev/null +++ b/samples/multiplatform/src/jsTest/kotlin/ch/tutteli/SampleJsTest.kt @@ -0,0 +1,39 @@ +package ch.tutteli + +import ch.tutteli.atrium.api.fluent.en_GB.messageContains +import ch.tutteli.atrium.api.fluent.en_GB.toBe +import ch.tutteli.atrium.api.fluent.en_GB.toThrow +import ch.tutteli.atrium.api.verbs.assertThat +import ch.tutteli.atrium.api.verbs.expect +import isEven +import kotlin.test.Test + +class SampleJsTest { + @Test + fun toBe() { + expect(1).toBe(1) + } + + @Test + fun assertAnExceptionOccurred() { + expect { + throw IllegalArgumentException() + }.toThrow() + } + + + @Test + fun assertAnExceptionWithAMessageOccurred() { + expect { + throw IllegalArgumentException("oho... hello btw") + }.toThrow { + messageContains("hello") + } + } + + @Test + fun useOwnFunction() { + // isEven is defined in the common module + assertThat(2).isEven() + } +} diff --git a/samples/multiplatform/src/jsTest/kotlin/testSetup.kt b/samples/multiplatform/src/jsTest/kotlin/testSetup.kt new file mode 100644 index 000000000..deb1129d0 --- /dev/null +++ b/samples/multiplatform/src/jsTest/kotlin/testSetup.kt @@ -0,0 +1,4 @@ + import ch.tutteli.atrium.fluent.en_GB.dependOnAtrium + + @Suppress("unused") + private val establishDependencyToAtrium = dependOnAtrium() diff --git a/samples/multiplatform/src/jvmTest/kotlin/ch/tutteli/SampleJvmTest.kt b/samples/multiplatform/src/jvmTest/kotlin/ch/tutteli/SampleJvmTest.kt new file mode 100644 index 000000000..c6ad03c88 --- /dev/null +++ b/samples/multiplatform/src/jvmTest/kotlin/ch/tutteli/SampleJvmTest.kt @@ -0,0 +1,39 @@ +package ch.tutteli + +import ch.tutteli.atrium.api.fluent.en_GB.messageContains +import ch.tutteli.atrium.api.fluent.en_GB.toBe +import ch.tutteli.atrium.api.fluent.en_GB.toThrow +import ch.tutteli.atrium.api.verbs.assertThat +import ch.tutteli.atrium.api.verbs.expect +import isEven +import kotlin.test.Test + +class SampleJvmTest { + @Test + fun toBe() { + expect(1).toBe(1) + } + + @Test + fun assertAnExceptionOccurred() { + expect { + throw IllegalArgumentException() + }.toThrow() + } + + + @Test + fun assertAnExceptionWithAMessageOccurred() { + expect { + throw IllegalArgumentException("oho... hello btw") + }.toThrow { + messageContains("hello") + } + } + + @Test + fun useOwnFunction() { + // isEven is defined in the common module + assertThat(2).isEven() + } +} diff --git a/settings.gradle b/settings.gradle index 3c2e71196..32c138d70 100644 --- a/settings.gradle +++ b/settings.gradle @@ -58,6 +58,7 @@ include { bundles { bundleWithExtensionsAndSmokeTest(delegate, 'fluent-en_GB') + bundleWithExtensionsAndSmokeTest(delegate, 'infix-en_GB') } apis('api-') { diff --git a/translations/de_CH/atrium-translations-de_CH-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionThrowableAssertion.kt b/translations/de_CH/atrium-translations-de_CH-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionThrowableAssertion.kt index fb841ada8..ad22ed228 100644 --- a/translations/de_CH/atrium-translations-de_CH-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionThrowableAssertion.kt +++ b/translations/de_CH/atrium-translations-de_CH-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionThrowableAssertion.kt @@ -12,7 +12,12 @@ enum class DescriptionThrowableAssertion(override val value: String) : StringBas ReplaceWith("ch.tutteli.atrium.translations.DescriptionAnyAssertion.IS_A") ) IS_A("ist eine"), + @Deprecated("Will be removed with 1.0.0", + ReplaceWith("ch.tutteli.atrium.translations.DescriptionFunLikeAssertion.NO_EXCEPTION_OCCURRED") + ) NO_EXCEPTION_OCCURRED("keine Exception wurde geworfen"), + NOT_CAUSED("❗❗ nicht durch eine andere Exception verursacht"), + //TODO rename to CAUSE with 1.0.0 OCCURRED_EXCEPTION_CAUSE("cause"), OCCURRED_EXCEPTION_PROPERTIES("Eigenschaften der unerwarteten %s"), OCCURRED_EXCEPTION_MESSAGE("message"), diff --git a/translations/en_GB/atrium-translations-en_GB-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionThrowableAssertion.kt b/translations/en_GB/atrium-translations-en_GB-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionThrowableAssertion.kt index 61d74203f..8fd76dc79 100644 --- a/translations/en_GB/atrium-translations-en_GB-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionThrowableAssertion.kt +++ b/translations/en_GB/atrium-translations-en_GB-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionThrowableAssertion.kt @@ -12,7 +12,13 @@ enum class DescriptionThrowableAssertion(override val value: String) : StringBas ReplaceWith("ch.tutteli.atrium.translations.DescriptionAnyAssertion.IS_A") ) IS_A("is a"), + @Deprecated( + "Will be removed with 1.0.0", + ReplaceWith("ch.tutteli.atrium.translations.DescriptionFunLikeAssertion.NO_EXCEPTION_OCCURRED") + ) NO_EXCEPTION_OCCURRED("no exception occurred"), + NOT_CAUSED("❗❗ not caused by another exception"), + //TODO rename to CAUSE with 1.0.0 OCCURRED_EXCEPTION_CAUSE("cause"), OCCURRED_EXCEPTION_PROPERTIES("Properties of the unexpected %s"), OCCURRED_EXCEPTION_MESSAGE("message"),