remove deprecated modules, ReportFactory, ExpectBuilder and dependOnMe

moreover:
- adjust packages.md, also remove deprecaed modules there and remove
  documentation which is no longer used
- remove createRegisterJsServicesTask in build.gradle
- adjust bbc/bc due to breaking changes (removal of different types).
  in the same go we have to forgive bc for infix as we no longer have
  ReporterFactory and since we don't use ascii bullet points in infix
  tests any more since 0.16.0 - we have established own tests for this
  aspect
- rename RealTranslatorIntSpec to TranslatorIntSpec and remove the
  existing TranslatorIntSpec which was intended for ReporterFactory
  based implementations.
This commit is contained in:
Robert Stoll
2021-04-01 22:57:33 +02:00
parent b138a7bb3a
commit 2519afb254
249 changed files with 302 additions and 7276 deletions

View File

@@ -2335,16 +2335,12 @@ Unfortunately we do not have the time to cover all cases, so let us know if you
## Own Sophisticated Assertion Builders
Do you want to write an own sophisticated assertion builder (or extend a current with more options) instead of an assertion function?
Great, we do not provide documentation yet (had only one question about it so far).
Therefore, please have a look at the implementation, for instance how the sophisticated assertion builders for `Iterable<T>` are defined:
[ch.tutteli.atrium.creating.iterable.contains](https://github.com/robstoll/atrium/tree/master/domain/api/atrium-domain-api-common/src/main/kotlin/ch/tutteli/atrium/domain/creating/iterable/contains).
Notice that the implementation supports [Internationalization](#internationalization-1).
Great, we do not provide documentation yet (had only one question about it since 2017).
We are willing to provide more documentation if you need it (please open an issue).
In the meantime we might help you via slack, please post your questions in the [atrium Slack channel](https://kotlinlang.slack.com/messages/C887ZKGCQ)
([Invite yourself](https://slack.kotlinlang.org/) in case you do not have an account yet).
# Use own Assertion Verbs
Atrium offers three assertion verbs out of the box: `expect`, `assert` and `assertThat`.

View File

@@ -7,12 +7,10 @@ Atrium provides so called bundle-modules which merely bundle dependencies (they
These modules bundle:
- an API module
- a translation module (the language used in reporting)
- an implementation of the domain of Atrium
- an implementation of the core of Atrium
- predefined expectation verbs.
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.
The links point to the KDoc of their included API where you find an overview of all available expectation functions of the API.
- [atrium-fluent-en_GB](https://docs.atriumlib.org/latest#/doc/ch.tutteli.atrium.api.fluent.en_-g-b/index.html)
- [atrium-infix-en_GB](https://docs.atriumlib.org/latest#/doc/ch.tutteli.atrium.api.infix.en_-g-b/index.html)
@@ -39,7 +37,7 @@ If you forget to dit it, then the compiler will complain that you have the same
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<T>.toBe`:
For instance, the expectation function `Expect<T>.toBe`:
*atrium-api-fluent-en_GB*
```kotlin
@@ -60,7 +58,7 @@ is toit similar, we will not list it here (ok, we did now but I guess you get th
- [in any order](#iterable-contains-in-any-order)
- [in order](#iterable-contains-in-order)
- [Iterable contains not](#iterable-contains-not)
- [Iterable predicate-like assertions](#iterable-predicate-like-assertions)
- [Iterable predicate-like expectations](#iterable-predicate-like-expectations)
- [List get](#list-get)
- [Map getExisting](#map-getexisting)
- [Map contains](#map-contains)
@@ -111,7 +109,7 @@ expect(x).contains.ignoringCase.notOrAtMost(1).elementsOf(anIterable)
```
Notice that the final steps
`value`, `values` and `regex`
in the sophisticated assertion building process
in the sophisticated expectation 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).
@@ -128,7 +126,7 @@ expect(x) contains o ignoring case notOrAtMost 1 elementsOf anIterable
```
Notice that the final steps
`value`, `values(...)`, `regex` and `regexPatterns(..)`
in the sophisticated assertion building process
in the sophisticated expectation 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).
@@ -154,7 +152,7 @@ expect(x).contains.inAnyOrder.only.entries({ toBe(3) }, { isLessThan(2) })
```
Notice that the final steps
`value`, `values`, `entry` and `entries`
in the sophisticated assertion building process
in the sophisticated expectation building process
are applicable to all shown examples
(e.g. `butAtMost(2).value(3.2)` could have been finished with `entries(...)` as well)
@@ -178,7 +176,7 @@ Note that `o` is a filler object which is only there so that we can turn extensi
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,
in the sophisticated expectation building process,
are applicable to all shown examples
(e.g. `butAtMost 2 value 3.2` could have been finished with `entries(...)` as well)
@@ -257,8 +255,8 @@ 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`
# Iterable predicate-like expectations
For more sophisticated expectations such as "there should be two matches", use the sophisticated expectation builder `contains.inAnyOrder`
-&gt; see [Iterable contains in any order](#iterable-contains-in-any-order) for more information
*atrium-api-fluent-en_GB*

View File

@@ -1,13 +0,0 @@
//TODO remove file with 1.0.0
@file:Suppress("DEPRECATION")
import ch.tutteli.atrium.core.robstoll.dependOn_atrium_core_robstoll
import ch.tutteli.atrium.domain.robstoll.dependOn_atrium_domain_robstoll
fun dependOnAtrium() {
dependOn_atrium_core_robstoll()
dependOn_atrium_domain_robstoll()
}
@Suppress("unused")
private val establishDependencyToAtrium = dependOnAtrium()

View File

@@ -4,13 +4,6 @@ ext.jacoco_additional = [
prefixedProject('translations-en_GB-jvm'),
prefixedProject('logic-jvm'),
prefixedProject('core-api-jvm'),
//TODO remove with 0.17.0
prefixedProject('domain-builders-jvm'),
prefixedProject('domain-robstoll-jvm'),
prefixedProject('domain-robstoll-lib-jvm'),
prefixedProject('domain-api-jvm'),
prefixedProject('core-robstoll-jvm'),
prefixedProject('core-robstoll-lib-jvm'),
]
dependencies {
@@ -18,12 +11,3 @@ dependencies {
testImplementation prefixedProject('specs-jvm')
}
//TODO 0.17.0 or 0.18.0 should not be necessary https://youtrack.jetbrains.com/issue/KT-28124
compileTestKotlin.dependsOn(
prefixedProject('core-robstoll-jvm').compileKotlin,
prefixedProject('core-robstoll-jvm').processResources,
prefixedProject('domain-robstoll-jvm').compileKotlin,
prefixedProject('domain-robstoll-jvm').processResources
)

View File

@@ -1,11 +1,7 @@
description = 'Kotlin 1.3 specific assertion functions and builders for fluent-en_GB -- will be merged into fluent-en_GB with 1.0.0'
ext.jacoco_additional = [
prefixedProject('domain-builders-jvm'),
prefixedProject('domain-robstoll-jvm'),
prefixedProject('domain-robstoll-lib-jvm'),
prefixedProject('core-robstoll-jvm'),
prefixedProject('core-robstoll-lib-jvm'),
prefixedProject('logic-kotlin_1_3-jvm'),
]
dependencies {
@@ -14,12 +10,3 @@ dependencies {
testImplementation prefixedProject('specs-jvm')
}
//TODO 0.17.0 or 0.18.0 should not be necessary https://youtrack.jetbrains.com/issue/KT-28124
compileTestKotlin.dependsOn(
prefixedProject('core-robstoll-jvm').compileKotlin,
prefixedProject('core-robstoll-jvm').processResources,
prefixedProject('domain-robstoll-jvm').compileKotlin,
prefixedProject('domain-robstoll-jvm').processResources
)

View File

@@ -1,13 +0,0 @@
//TODO remove file with 1.0.0
@file:Suppress("DEPRECATION")
import ch.tutteli.atrium.core.robstoll.dependOn_atrium_core_robstoll
import ch.tutteli.atrium.domain.robstoll.dependOn_atrium_domain_robstoll
fun dependOnAtrium() {
dependOn_atrium_core_robstoll()
dependOn_atrium_domain_robstoll()
}
@Suppress("unused")
private val establishDependencyToAtrium = dependOnAtrium()

View File

@@ -4,13 +4,6 @@ ext.jacoco_additional = [
prefixedProject('translations-de_CH-jvm'),
prefixedProject('logic-jvm'),
prefixedProject('core-api-jvm'),
//TODO remove with 0.17.0
prefixedProject('domain-builders-jvm'),
prefixedProject('domain-robstoll-jvm'),
prefixedProject('domain-robstoll-lib-jvm'),
prefixedProject('domain-api-jvm'),
prefixedProject('core-robstoll-jvm'),
prefixedProject('core-robstoll-lib-jvm'),
]
dependencies {
@@ -21,12 +14,3 @@ dependencies {
}
testImplementation prefixedProject('translations-de_CH-jvm')
}
//TODO 0.17.0 or 0.18.0 should not be necessary https://youtrack.jetbrains.com/issue/KT-28124
compileTestKotlin.dependsOn(
prefixedProject('core-robstoll-jvm').compileKotlin,
prefixedProject('core-robstoll-jvm').processResources,
prefixedProject('domain-robstoll-jvm').compileKotlin,
prefixedProject('domain-robstoll-jvm').processResources
)

View File

@@ -1,11 +1,7 @@
description = 'Kotlin 1.3 specific assertion functions and builders for infix-en_GB -- will be merged into infix-en_GB with 1.0.0'
ext.jacoco_additional = [
prefixedProject('domain-builders-jvm'),
prefixedProject('domain-robstoll-jvm'),
prefixedProject('domain-robstoll-lib-jvm'),
prefixedProject('core-robstoll-jvm'),
prefixedProject('core-robstoll-lib-jvm'),
prefixedProject('logic-kotlin_1_3-jvm'),
]
dependencies {
@@ -14,12 +10,3 @@ dependencies {
testImplementation prefixedProject('specs-jvm')
}
//TODO 0.17.0 or 0.18.0 should not be necessary https://youtrack.jetbrains.com/issue/KT-28124
compileTestKotlin.dependsOn(
prefixedProject('core-robstoll-jvm').compileKotlin,
prefixedProject('core-robstoll-jvm').processResources,
prefixedProject('domain-robstoll-jvm').compileKotlin,
prefixedProject('domain-robstoll-jvm').processResources
)

View File

@@ -80,12 +80,7 @@ buildscript {
!(it.projectDir.path.contains("/translations/") || it.projectDir.path.contains("\\translations\\")) &&
!it.name.endsWith("-common") &&
!it.name.endsWith("-js") &&
it.name != "${rootProject.name}-domain-api-jvm" &&
it.name != "${rootProject.name}-core-robstoll-jvm" &&
!it.name.startsWith("${rootProject.name}-specs") &&
//TODO remove with 0.17.0
it.name != "${rootProject.name}-domain-robstoll-jvm" &&
it.name != "${rootProject.name}-domain-builders-jvm"
!it.name.startsWith("${rootProject.name}-specs")
}
]
}
@@ -319,67 +314,8 @@ configure(bundleSmokeTests) {
import java.nio.file.Files
import java.nio.file.Paths
import java.util.function.Function
import java.util.stream.Collectors
def createRegisterJsServicesTask(String projectName, String packageName, Function<String, Boolean> filter) {
Project project = prefixedProject(projectName)
configure(project) {
def registerJsServices = project.tasks.create(name: 'generateJsRegisterServices', group: 'build') {
def jvm = "${getProjectNameWithoutSuffix(project)}-jvm"
def servicesDir = project.file("../$jvm/src/main/resources/META-INF/services/")
def services = project.file("$srcKotlin/${packageName.replace('.', '/')}/registerServices.kt")
inputs.dir servicesDir
outputs.file services
doLast {
services.write("""\
@file:Suppress("DEPRECATION")
package $packageName
import ch.tutteli.atrium.core.polyfills.registerService
@Suppress("unused" /* here in order that the code is executed when module is loaded */)
private val register = run {
""".stripIndent())
def sortedMap = new TreeMap<String, String>()
servicesDir.traverse {
if (it.isFile() && filter.apply(it.name)) {
sortedMap.put(it.name, it.withReader { it.readLine() })
}
}
sortedMap.each { entry ->
services.append("\n registerService<")
services.append(entry.key)
services.append("> { ")
services.append(entry.value)
services.append("() }")
}
services.append("\n}\n")
}
}
compileKotlin2Js.dependsOn registerJsServices
}
}
//TODO remove with 0.17.0
createRegisterJsServicesTask('core-robstoll-js', 'ch.tutteli.atrium.core.robstoll') { true }
createRegisterJsServicesTask('domain-builders-js', 'ch.tutteli.atrium.domain.builders') { true }
createRegisterJsServicesTask('domain-robstoll-js', 'ch.tutteli.atrium.domain.robstoll') {
!(it in [
'ch.tutteli.atrium.domain.creating.BigDecimalAssertions',
'ch.tutteli.atrium.domain.creating.OptionalAssertions',
'ch.tutteli.atrium.domain.creating.PathAssertions',
'ch.tutteli.atrium.domain.creating.LocalDateAssertions',
'ch.tutteli.atrium.domain.creating.LocalDateTimeAssertions',
'ch.tutteli.atrium.domain.creating.ZonedDateTimeAssertions',
'ch.tutteli.atrium.domain.creating.ChronoLocalDateAssertions',
'ch.tutteli.atrium.domain.creating.ChronoLocalDateTimeAssertions',
'ch.tutteli.atrium.domain.creating.ChronoZonedDateTimeAssertions'
])
}
List<Project> projectNamesToProject(String[] names) {
names.collect { projectName -> prefixedProject(projectName) }
}
@@ -430,10 +366,10 @@ def createJsTestTask(String... subprojectNames) {
createJsTestTask(
'core-api-js',
'core-robstoll-lib-js',
'api-fluent-en_GB-js',
'api-infix-en_GB-js',
'fluent-en_GB-js'
'fluent-en_GB-js',
'infix-en_GB-js'
)
def useJupiter(String... projectNames) {

View File

@@ -4,10 +4,4 @@ dependencies {
api prefixedProject('verbs-common')
api prefixedProject('api-fluent-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')
}

View File

@@ -4,10 +4,4 @@ dependencies {
api prefixedProject('verbs-js')
api prefixedProject('api-fluent-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')
}

View File

@@ -1,17 +0,0 @@
//TODO remove file with 1.0.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.fluent.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-fluent-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()
}

View File

@@ -1,4 +0,0 @@
import ch.tutteli.atrium.fluent.en_GB.dependOnAtrium
@Suppress("unused")
private val establishDependencyToAtrium = dependOnAtrium()

View File

@@ -5,23 +5,10 @@ ext.jacoco_additional = [
prefixedProject('translations-en_GB-jvm'),
prefixedProject('logic-jvm'),
prefixedProject('core-api-jvm'),
//TODO remove with 0.17.0
prefixedProject('domain-builders-jvm'),
prefixedProject('domain-robstoll-jvm'),
prefixedProject('domain-robstoll-lib-jvm'),
prefixedProject('domain-api-jvm'),
prefixedProject('core-robstoll-jvm'),
prefixedProject('core-robstoll-lib-jvm'),
]
dependencies {
api prefixedProject('verbs-jvm')
api prefixedProject('api-fluent-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')
}

View File

@@ -1,7 +1,6 @@
module ch.tutteli.atrium.fluent.en_GB {
requires transitive ch.tutteli.atrium.verbs;
requires transitive ch.tutteli.atrium.api.fluent.en_GB;
requires transitive ch.tutteli.atrium.domain.builders;
requires transitive ch.tutteli.atrium.translations.en_GB;
requires kotlin.stdlib;
}

View File

@@ -4,10 +4,5 @@ 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')
}

View File

@@ -4,10 +4,5 @@ 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')
}

View File

@@ -1,18 +0,0 @@
//TODO remove file with 1.0.0
@file:Suppress("DEPRECATION")
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()
}

View File

@@ -1,4 +0,0 @@
import ch.tutteli.atrium.infix.en_GB.dependOnAtrium
@Suppress("unused")
private val establishDependencyToAtrium = dependOnAtrium()

View File

@@ -5,24 +5,11 @@ ext.jacoco_additional = [
prefixedProject('translations-en_GB-jvm'),
prefixedProject('logic-jvm'),
prefixedProject('core-api-jvm'),
//TODO remove with 0.17.0
prefixedProject('domain-builders-jvm'),
prefixedProject('domain-robstoll-jvm'),
prefixedProject('domain-robstoll-lib-jvm'),
prefixedProject('domain-api-jvm'),
prefixedProject('core-robstoll-jvm'),
prefixedProject('core-robstoll-lib-jvm'),
]
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')
}

View File

@@ -1,7 +1,6 @@
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;
}

View File

@@ -19,6 +19,7 @@ annotation class ExperimentalNewExpectTypes
*
* It loads the implementation lazily via [loadSingleService].
*/
//TODO 0.17.0 deprecate
val coreFactory by lazy { loadSingleService(CoreFactory::class) }
/**
@@ -30,6 +31,7 @@ val coreFactory by lazy { loadSingleService(CoreFactory::class) }
* Notice, the platform specific types have to define the default methods for `newReportingPlantNullable`
* (otherwise we are not binary backward compatible) -> will be moved to CoreFactoryCommon with 1.0.0
*/
//TODO 0.17.0 deprecate
expect interface CoreFactory : CoreFactoryCommon
/**
@@ -50,6 +52,7 @@ expect interface CoreFactory : CoreFactoryCommon
* - [Reporter]
* - [AtriumErrorAdjuster]
*/
//TODO 0.17.0 deprecate
interface CoreFactoryCommon {
/**

View File

@@ -11,6 +11,7 @@ import kotlin.reflect.KClass
* @throws NoSuchElementException in case there is no service found for [kClass].
* @throws IllegalStateException in case there is more than one service found for [kClass].
*/
//TODO 0.17.0 deprecate
expect fun <T : Any> loadSingleService(kClass: KClass<T>): T
/**
@@ -18,6 +19,7 @@ expect fun <T : Any> loadSingleService(kClass: KClass<T>): T
*
* @return The loaded services as a [Sequence].
*/
//TODO 0.17.0 deprecate
expect fun <T : Any> loadServices(kClass: KClass<T>): Sequence<T>
/**
@@ -26,6 +28,7 @@ expect fun <T : Any> loadServices(kClass: KClass<T>): Sequence<T>
* @throws NoSuchElementException in case there is no service found for [kClass].
* @throws IllegalStateException in case there is more than one service found for [kClass].
*/
//TODO 0.17.0 deprecate
fun <T : Any> useSingleService(kClass: KClass<T>, itr: Iterator<T>): T {
if (!itr.hasNext()) throw NoSuchElementException("Could not find any implementation for ${kClass.fullName}")

View File

@@ -1,15 +0,0 @@
package ch.tutteli.atrium.core.polyfills
/**
* Returns the specified value for the property with the given [key] or `null` in case it is not defined.
*
* @return The value of the property with the specified [key] or `null` in case it is not defined.
*/
@Deprecated("Will be removed with 0.17.0 without replacement - note, a Reporter should now be be retrieved via ComponentFactoryContainer")
expect fun getAtriumProperty(key: String): String?
/**
* Sets the property with the given [key] to the given [newValue].
*/
@Deprecated("Will be removed with 0.17.0 without replacement - note, a Reporter should now be be retrieved via ComponentFactoryContainer")
expect fun setAtriumProperty(key: String, newValue: String)

View File

@@ -1,93 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.reporting
import ch.tutteli.atrium.core.polyfills.getAtriumProperty
import ch.tutteli.atrium.core.polyfills.loadServices
import ch.tutteli.atrium.core.polyfills.setAtriumProperty
/**
* The access point to an implementation of [Reporter].
*
* It loads implementations of [ReporterFactory] lazily via [loadServices] and searches for the id specified via
* Atrium's property with key [ReporterFactory.ATRIUM_PROPERTY_KEY] (which is
* `ch.tutteli.atrium.reporting.reporterFactory`) or uses `default` in case the property is not specified.
*
* Use [ReporterFactory.specifyFactory] or [ReporterFactory.specifyFactoryIfNotYetSet] to define another value for the
* property.
*
* Notice, that searching for a [ReporterFactory] is only done once and the result is cached afterwards.
* Please [open an issue](https://github.com/robstoll/atrium/issues/new?template=feature_request.md&title=[Feature]%20change%20Reporter%20during%20test%20run)
* if you want to able to change the [Reporter] during a test-run.
*/
@Deprecated("A Reporter should now be be retrieved via ComponentFactoryContainer where the different components of a reporter should also be defined via ComponentFactoryContainer. This property will be removed with 0.17.0")
val reporter: Reporter by lazy {
val id = getAtriumProperty(ReporterFactory.ATRIUM_PROPERTY_KEY) ?: "default"
val factory = loadServices(ReporterFactory::class)
.firstOrNull { it.id == id }
?: throw IllegalStateException("Could not find a ${ReporterFactory::class.simpleName} with id $id")
factory.create()
}
/**
* Responsible to create a [Reporter].
*
* It identify itself via its [id]. This id can be used by a user to specify that this [ReporterFactory] shall be used.
* In order to do that, the user has to define the system property `ch.tutteli.atrium.reporting.reporterFactory`
*/
@Deprecated("A Reporter should now be be retrieved via ComponentFactoryContainer where the different components of a reporter should also be defined via ComponentFactoryContainer. This class will be removed with 0.17.0")
interface ReporterFactory {
/**
* Identification of the supplier
*/
val id: String
/**
* Creates a new [Reporter].
*/
fun create(): Reporter
/**
* Provides utility functions to specify a [ReporterFactory].
*/
@Suppress("DeprecatedCallableAddReplaceWith")
companion object {
/**
* The key of Atrium's property which is used to define which [ReporterFactory] shall be used.
* You can use [ReporterFactory.specifyFactory] or [ReporterFactory.specifyFactoryIfNotYetSet]
*/
@Deprecated("A Reporter should now be be retrieved via ComponentFactoryContainer where the different components of a reporter should also be defined via ComponentFactoryContainer. ReporterFactory will be removed with 0.17.0")
const val ATRIUM_PROPERTY_KEY = "ch.tutteli.atrium.reporting.reporterFactory"
/**
* Sets Atrium's property with key [ATRIUM_PROPERTY_KEY] (which is
* `ch.tutteli.atrium.reporting.reporterFactory`) to the given [reporterFactoryId]
* regardless if another id was specified before.
*
* Use [specifyFactoryIfNotYetSet] if you only want to set a default value but not overwrite an existing
* specification.
*/
@Deprecated("A Reporter should now be be retrieved via ComponentFactoryContainer where the different components of a reporter should also be defined via ComponentFactoryContainer. ReporterFactory will be removed with 0.17.0")
fun specifyFactory(reporterFactoryId: String) {
setAtriumProperty(ATRIUM_PROPERTY_KEY, reporterFactoryId)
}
/**
* Sets Atrium's property with key [ATRIUM_PROPERTY_KEY] (which is
* `ch.tutteli.atrium.reporting.reporterFactory`) to the given [reporterFactoryId]
* if another id was not *yet* specified before.
*
* Use [specifyFactory] if you do not care if another id was specified before or in other words, if you want to
* overwrite a potentially previously defined id.
*/
@Deprecated("A Reporter should now be be retrieved via ComponentFactoryContainer where the different components of a reporter should also be defined via ComponentFactoryContainer. ReporterFactory will be removed with 0.17.0")
fun specifyFactoryIfNotYetSet(reporterFactoryId: String) {
if (getAtriumProperty(ATRIUM_PROPERTY_KEY) == null) {
specifyFactory(reporterFactoryId)
}
}
}
}

View File

@@ -1,42 +0,0 @@
//TODO remove with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.polyfills
import ch.tutteli.atrium.api.infix.en_GB.*
import ch.tutteli.atrium.api.verbs.internal.expect
import kotlin.test.Test
class AtriumPropertyTest {
@Test
fun get_undefined_returnsNull() {
expect(getAtriumProperty("notYetDefined")) toBe null
}
@Test
fun get_defined_returnsDefinedValue() {
//arrange
setAtriumProperty("a", "b")
//act & assert
expect(getAtriumProperty("a")) toBe "b"
}
@Test
fun set_undefined_definedAfterwards() {
//act
setAtriumProperty("a", "b")
//assert
expect(getAtriumProperty("a")) toBe "b"
}
@Test
fun set_defined_overwrites() {
//arrange
setAtriumProperty("a", "b")
//act
setAtriumProperty("a", "c")
//assert
expect(getAtriumProperty("a")) toBe "c"
}
}

View File

@@ -1,37 +0,0 @@
//TODO remove with 0.17.0
package ch.tutteli.atrium.core.polyfills
import ch.tutteli.atrium.api.infix.en_GB.*
import ch.tutteli.atrium.api.verbs.internal.expect
import kotlin.test.Test
class LoadServicesTest {
@Test
fun noServiceFound_EmptySequence() {
expect(loadServices(LoadServicesTest::class).toList()) toBe empty
}
@Test
fun oneServiceFound_ReturnsTheService() {
expect(loadServices(InterfaceWithOneImplementation::class)).asIterable {
it containsExactly { isA<SingleService>() }
}
}
@Test
fun twoServicesFound_ThrowsIllegalStateException() {
expect(loadServices(InterfaceWithTwoImplementation::class)) asIterable o contains o inAny order but only the entries(
{ isA<Service1>() },
{ isA<Service2>() }
)
expect {
loadSingleService(InterfaceWithTwoImplementation::class)
}.toThrow<IllegalStateException> {
this messageContains values(
"Found more than one implementation ",
Service1::class.fullName,
Service2::class.fullName
)
}
}
}

View File

@@ -1,36 +0,0 @@
//TODO remove with 0.17.0
package ch.tutteli.atrium.core.polyfills
import ch.tutteli.atrium.api.infix.en_GB.*
import ch.tutteli.atrium.api.verbs.internal.expect
import kotlin.test.Test
class LoadSingleServiceTest {
@Test
fun noServiceFound_ThrowsNoSuchElementException() {
expect {
loadSingleService(LoadSingleServiceTest::class)
}.toThrow<NoSuchElementException> {
it messageContains values("Could not find any implementation", LoadSingleServiceTest::class.fullName)
}
}
@Test
fun oneServiceFound_ReturnsTheService() {
val service = loadSingleService(InterfaceWithOneImplementation::class)
expect(service).isA<SingleService>()
}
@Test
fun twoServicesFound_ThrowsIllegalStateException() {
expect {
loadSingleService(InterfaceWithTwoImplementation::class)
}.toThrow<IllegalStateException> {
its messageContains values(
"Found more than one implementation ",
Service1::class.fullName,
Service2::class.fullName
)
}
}
}

View File

@@ -1,40 +0,0 @@
//TODO remove with 0.17.0
package ch.tutteli.atrium.core.polyfills
import ch.tutteli.atrium.api.infix.en_GB.*
import ch.tutteli.atrium.api.verbs.internal.expect
import kotlin.test.Test
class UseSingleServiceTest {
@Test
fun emptyIterator_ThrowsNoSuchElementException() {
expect {
useSingleService(InterfaceWithOneImplementation::class, listOf<InterfaceWithOneImplementation>().iterator())
}.toThrow<NoSuchElementException> {
its messageContains values(
"Could not find any implementation",
InterfaceWithOneImplementation::class.fullName
)
}
}
@Test
fun oneServiceFound_ReturnsTheService() {
val service = useSingleService(InterfaceWithOneImplementation::class, listOf(SingleService()).iterator())
expect(service).isA<SingleService>()
}
@Test
fun twoServiceFound_ReturnsTheService() {
expect {
useSingleService(InterfaceWithTwoImplementation::class, listOf(Service1(), Service2()).iterator())
}.toThrow<IllegalStateException> {
its messageContains values(
"Found more than one implementation ",
Service1::class.fullName,
Service2::class.fullName
)
}
}
}

View File

@@ -1,9 +0,0 @@
//TODO remove with 0.17.0
package ch.tutteli.atrium.core.polyfills
interface InterfaceWithOneImplementation
class SingleService : InterfaceWithOneImplementation
interface InterfaceWithTwoImplementation
class Service1 : InterfaceWithTwoImplementation
class Service2 : InterfaceWithTwoImplementation

View File

@@ -1,11 +0,0 @@
package ch.tutteli.atrium.core.polyfills
private val properties = mutableMapOf<String, String>()
@Deprecated("Will be removed with 0.17.0 without replacement")
actual fun getAtriumProperty(key: String): String? = properties[key]
@Deprecated("Will be removed with 0.17.0 without replacement")
actual fun setAtriumProperty(key: String, newValue: String) {
properties[key] = newValue
}

View File

@@ -1,14 +0,0 @@
//TODO remove file with 1.0.0
@file:Suppress("DEPRECATION")
import ch.tutteli.atrium.core.polyfills.*
import ch.tutteli.atrium.core.robstoll.dependOn_atrium_core_robstoll
import ch.tutteli.atrium.domain.robstoll.dependOn_atrium_domain_robstoll
private val currentSetupWorkaround = dep()
private fun dep() {
dependOn_atrium_domain_robstoll()
dependOn_atrium_core_robstoll()
registerService<InterfaceWithOneImplementation> { SingleService() }
registerService<InterfaceWithTwoImplementation> { Service1() }
registerService<InterfaceWithTwoImplementation> { Service2() }
}

View File

@@ -11,6 +11,7 @@ import ch.tutteli.atrium.reporting.translating.Locale
import ch.tutteli.atrium.reporting.translating.TranslationSupplier
import java.util.*
//TODO 0.17.0 deprecate
actual interface CoreFactory : CoreFactoryCommon {
/**

View File

@@ -1,8 +0,0 @@
package ch.tutteli.atrium.core.polyfills
@Deprecated("Will be removed with 0.17.0 without replacement")
actual fun getAtriumProperty(key: String): String? = System.getProperty(key)
@Deprecated("Will be removed with 0.17.0 without replacement")
actual fun setAtriumProperty(key: String, newValue: String) {
System.setProperty(key, newValue)
}

View File

@@ -19,6 +19,5 @@ module ch.tutteli.atrium.core.api {
// TODO 0.17.0 or 0.18.0 remove once DefaultComponentFactoryContainer is internal
exports ch.tutteli.atrium.creating.impl to
ch.tutteli.atrium.logic,
ch.tutteli.atrium.domain.robstoll.lib,
ch.tutteli.atrium.api.infix.en_GB;
}

View File

@@ -13,8 +13,6 @@ import ch.tutteli.atrium.logic._logic
import ch.tutteli.atrium.logic.creating.RootExpectBuilder
import ch.tutteli.atrium.logic.utils.expectLambda
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
import ch.tutteli.atrium.reporting.Reporter
import ch.tutteli.atrium.reporting.reporter
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe

View File

@@ -3,10 +3,10 @@ package ch.tutteli.atrium.reporting.translating
import ch.tutteli.atrium.creating.ExperimentalComponentFactoryContainer
import ch.tutteli.atrium.creating.build
import ch.tutteli.atrium.reporting.translating.impl.TranslationSupplierBasedTranslator
import ch.tutteli.atrium.specs.reporting.translating.RealTranslatorIntSpec
import ch.tutteli.atrium.specs.reporting.translating.TranslatorIntSpec
@ExperimentalComponentFactoryContainer
object PropertiesPerEntityAndLocaleTranslationSupplierSpec : RealTranslatorIntSpec(
object PropertiesPerEntityAndLocaleTranslationSupplierSpec : TranslatorIntSpec(
{ optionsChooser, primaryLocale, fallbackLocales ->
optionsChooser.apply {
withSingletonComponent(TranslationSupplier::class){

View File

@@ -5,7 +5,7 @@ import ch.tutteli.atrium.creating.build
import ch.tutteli.atrium.reporting.translating.impl.TranslationSupplierBasedTranslator
@ExperimentalComponentFactoryContainer
object PropertiesPerLocaleTranslationSupplierSpec : ch.tutteli.atrium.specs.reporting.translating.RealTranslatorIntSpec(
object PropertiesPerLocaleTranslationSupplierSpec : ch.tutteli.atrium.specs.reporting.translating.TranslatorIntSpec(
{ optionsChooser, primaryLocale, fallbackLocales ->
optionsChooser.apply {
withSingletonComponent(TranslationSupplier::class){

View File

@@ -13,7 +13,7 @@ object ResourceBundleBasedTranslatorSpec : Spek({
)
object AtriumsTranslatorIntSpec : ch.tutteli.atrium.specs.reporting.translating.RealTranslatorIntSpec(
object AtriumsTranslatorIntSpec : ch.tutteli.atrium.specs.reporting.translating.TranslatorIntSpec(
{ options, primaryLocale, fallbackLocales ->
options.apply {
withSingletonComponent(Translator::class) {

View File

@@ -1,2 +0,0 @@
# TODO remove with 1.0.0
ch.tutteli.atrium.core.polyfills.SingleService

View File

@@ -1,3 +0,0 @@
# TODO remove with 1.0.0
ch.tutteli.atrium.core.polyfills.Service1
ch.tutteli.atrium.core.polyfills.Service2

View File

@@ -2,8 +2,5 @@ ch.tutteli.atrium.translations.DescriptionAnyAssertion-TO_BE=est
ch.tutteli.atrium.translations.DescriptionAnyAssertion-NOT_TO_BE=n'est pas
ch.tutteli.atrium.translations.DescriptionAnyAssertion-IS_NOT_SAME=n'est pas la m\u00EAme instance que
ch.tutteli.atrium.specs.AssertionVerb-ASSERT=il applique que
ch.tutteli.atrium.specs.reporting.translating.RealTranslatorIntSpec.TestTranslatable-DATE_KNOWN=%tD \u00E9tait %tA!!
ch.tutteli.atrium.specs.reporting.translating.RealTranslatorIntSpec.TestTranslatable-PLACEHOLDER=Caract\u00E8re de remplacement %s
# TODO remove with 0.17.0
ch.tutteli.atrium.specs.reporting.translating.TranslatorIntSpec.TestTranslatable-DATE_KNOWN=%tD \u00E9tait %tA!!
ch.tutteli.atrium.specs.reporting.translating.TranslatorIntSpec.TestTranslatable-PLACEHOLDER=Caract\u00E8re de remplacement %s

View File

@@ -1,5 +1,2 @@
ch.tutteli.atrium.specs.reporting.translating.RealTranslatorIntSpec.TestTranslatable-DATE_KNOWN=solo %tA!!
ch.tutteli.atrium.specs.reporting.translating.RealTranslatorIntSpec.TestTranslatable-DATE_UNKNOWN=solo %tA!!
# TODO remove with 0.17.0
ch.tutteli.atrium.specs.reporting.translating.TranslatorIntSpec.TestTranslatable-DATE_KNOWN=solo %tA!!
ch.tutteli.atrium.specs.reporting.translating.TranslatorIntSpec.TestTranslatable-DATE_UNKNOWN=solo %tA!!

View File

@@ -1,15 +0,0 @@
description = 'Contains the bits and pieces behind robstoll\'s <rstoll@tutteli.ch> implementation ' +
'of Atrium as common module. You should only depend on this module if you are ' +
'providing an implementation as well and want to reuse certain artifacts. If you are a consumer of ' +
'Atrium, then you should depend on atrium-core-robstoll-common instead.'
dependencies {
implementation "ch.tutteli.kbox:kbox-common:$kbox_version", excludeKotlin
api prefixedProject('core-api-common')
// it is up to the consumer of atrium-core-robstoll-lib which atrium-translations module is used at runtime
compileOnly prefixedProject('translations-en_GB-common')
testImplementation prefixedProject('api-fluent-en_GB-common')
testImplementation prefixedProject('specs-common')
}

View File

@@ -1,28 +0,0 @@
//TODO remove with 0.17.0
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.reporting.AssertionFormatter
import ch.tutteli.atrium.reporting.AssertionFormatterController
import ch.tutteli.atrium.reporting.AssertionFormatterFacade
import ch.tutteli.atrium.reporting.AssertionFormatterParameterObject
/**
* Responsible to call an appropriate [AssertionFormatter] which supports [format]ing a given [Assertion] -- it does
* so by delegating this responsibility to the specified [assertionFormatterController].
*
* @constructor Responsible to call an appropriate [AssertionFormatter] which supports [format]ing a given [Assertion] -- it does
* so by delegating this responsibility to the given [assertionFormatterController].
* @param assertionFormatterController The controller used to control the flow of formatting.
*/
@Deprecated("Use the implementation of atrium-core; will be removed with 0.17.0")
class AssertionFormatterControllerBasedFacade(private val assertionFormatterController: AssertionFormatterController) :
AssertionFormatterFacade {
override fun format(assertion: Assertion, sb: StringBuilder, assertionFilter: (Assertion) -> Boolean) =
assertionFormatterController.format(assertion, AssertionFormatterParameterObject.new(sb, assertionFilter))
override fun register(assertionFormatterFactory: (AssertionFormatterController) -> AssertionFormatter) =
assertionFormatterController.register(assertionFormatterFactory(assertionFormatterController))
}

View File

@@ -1,70 +0,0 @@
//TODO remove with 0.17.0
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.assertions.InvisibleAssertionGroupType
import ch.tutteli.atrium.reporting.AssertionFormatter
import ch.tutteli.atrium.reporting.AssertionFormatterController
import ch.tutteli.atrium.reporting.AssertionFormatterParameterObject
/**
* Represents an [AssertionFormatterController] which does nothing special in addition
* but just the job of the controller :)
*
* @see AssertionFormatterController
*/
@Deprecated("Use the implementation of atrium-core; will be removed with 0.17.0")
class AssertionFormatterControllerImpl : AssertionFormatterController {
private val assertionFormatters = mutableListOf<AssertionFormatter>()
override fun format(assertion: Assertion, parameterObject: AssertionFormatterParameterObject) {
if (noNeedToFormat(assertion, parameterObject)) return
val assertionFormatter = assertionFormatters
.firstOrNull { it.canFormat(assertion) }
?: AssertionFormatterController.noSuitableAssertionFormatterFound(assertion)
when (assertion) {
is AssertionGroup -> formatGroup(assertion, assertionFormatter, parameterObject)
else -> assertionFormatter.format(assertion, parameterObject)
}
}
private fun noNeedToFormat(assertion: Assertion, parameterObject: AssertionFormatterParameterObject): Boolean {
//assertionFilter only applies if:
// - we are not in an assertion group which should not be filtered (e.g. explanatory or summary group) and
// - if the given assertion is not an explanatory assertion group either.
return parameterObject.isNotInDoNotFilterGroup()
&& !isExplanatoryAssertionGroup(assertion)
&& !parameterObject.assertionFilter(assertion)
}
private fun formatGroup(
assertionGroup: AssertionGroup,
assertionFormatter: AssertionFormatter,
parameterObject: AssertionFormatterParameterObject
) {
assertionFormatter.formatGroup(
assertionGroup,
parameterObject
) { childParameterObject, formatAssertionInGroup ->
assertionGroup.assertions
.filter { !noNeedToFormat(it, childParameterObject) }
.forEach { formatChild(it, formatAssertionInGroup) }
}
}
private fun formatChild(it: Assertion, formatAssertionInGroup: (Assertion) -> Unit) {
if (it is AssertionGroup && it.type is InvisibleAssertionGroupType) {
it.assertions.forEach { formatChild(it, formatAssertionInGroup) }
} else {
formatAssertionInGroup(it)
}
}
override fun register(assertionFormatter: AssertionFormatter) {
assertionFormatters.add(assertionFormatter)
}
}

View File

@@ -1,84 +0,0 @@
//TODO remove with 0.17.0
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.core.polyfills.fullName
import ch.tutteli.atrium.reporting.*
import ch.tutteli.atrium.reporting.translating.Translatable
import ch.tutteli.atrium.reporting.translating.Translator
import kotlin.reflect.KClass
@Deprecated("Use the implementation of atrium-core; will be removed with 0.17.0")
expect class DetailedObjectFormatter(translator: Translator) : ObjectFormatter
/**
* Base class for the platform specific implementation of [DetailedObjectFormatter].
*
* It cannot format Java's `Class`, this has to be done in the JVM module. Moreover it requires a platform specific
* implementation of [identityHash] and [format] a [KClass].
*/
@Deprecated("Use the implementation of atrium-core; will be removed with 0.17.0")
abstract class DetailedObjectFormatterCommon(
private val translator: Translator
) : ObjectFormatter {
/**
* Returns a formatted version of the given [value].
*
* The following rules apply for the representation of an object:
* - `null` is represented as [Text.NULL].[Text.string]
* - [LazyRepresentation] is [evaluated][LazyRepresentation.eval] and then again [format]ted
* - [Char] is put in apostrophes
* - [Boolean] is represented with its [toString] representation
* - [String] is put in quotes and its [KClass.fullName] is omitted
* - [CharSequence] is put in quotes, but [KClass.fullName] is used in contrast to [String]
* - [Text] is represented as [Text.string]
* - [Translatable] is represented as result of its translation (by [translator])
* - [KClass]'s format is defined by the concrete platform specific subclass.
* - [Enum] is represented as "[toString] ([KClass.fullName])
* - [Throwable] is represented as "[KClass.fullName]"
* - All other objects are represented as "[toString] ([KClass.fullName] [identityHash])"
*
* @param value The value which shall be formatted.
*
* @return The formatted [value].
*/
@Suppress( /* TODO remove with 1.0.0 */ "DEPRECATION")
override fun format(value: Any?): String = when (value) {
null -> Text.NULL.string
is LazyRepresentation -> format(value.eval())
is Char -> "'$value'"
is Boolean -> value.toString()
is String -> format(value)
is CharSequence -> format(value)
is Text -> limitRepresentation(value.string)
is Translatable -> limitRepresentation(translator.translate(value))
is KClass<*> -> format(value)
is Enum<*> -> format(value)
is Throwable -> format(value)
//TODO remove with 1.0.0
is StringBasedRawString -> limitRepresentation(value.string)
is ch.tutteli.atrium.reporting.translating.TranslatableBasedRawString -> limitRepresentation(translator.translate(value.translatable))
else -> limitRepresentation(value.toString()) + classNameAndIdentity(value)
}
private fun format(string: String) = "\"${limitRepresentation(string)}\"" + identityHash(INDENT, string)
private fun format(charSequence: CharSequence) = "\"${limitRepresentation(charSequence.toString())}\"" + classNameAndIdentity(charSequence)
private fun format(enum: Enum<*>) =
limitRepresentation(enum.toString()) + INDENT + "(" + (enum::class.fullName) + ")"
private fun format(throwable: Throwable) = throwable::class.fullName
private fun classNameAndIdentity(any: Any): String = INDENT + "(${any::class.fullName}${identityHash(" ", any)})"
private fun limitRepresentation(value: String): String {
return if (value.length > 10000) "${value.substring(0, 10000)}..." else value
}
protected abstract fun format(kClass: KClass<*>): String
protected abstract fun identityHash(indent: String, any: Any): String
companion object {
internal const val INDENT: String = " "
}
}

View File

@@ -1,16 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
@Deprecated(
"Use MultiAtriumErrorAdjuster from atrium-core, will be removed with 0.17.0",
ReplaceWith("ch.tutteli.atrium.reporting.erroradjusters.MultiAtriumErrorAdjuster")
)
expect class MultiAtriumErrorAdjusterImpl(
firstAdjuster: AtriumErrorAdjuster,
secondAdjuster: AtriumErrorAdjuster,
otherAdjusters: List<AtriumErrorAdjuster>
) : AtriumErrorAdjuster

View File

@@ -1,28 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
/**
* An implementation of an [AtriumErrorAdjuster] which adjust nothings.
*/
@Deprecated(
"Use NoOpAtriumErrorAdjuster from atrium-core, will be removed with 0.17.0",
ReplaceWith("ch.tutteli.atrium.reporting.erroradjusters.NoOpAtriumErrorAdjuster")
)
expect object NoOpAtriumErrorAdjuster : AtriumErrorAdjuster
/**
* An implementation of an [AtriumErrorAdjuster] which adjust nothings and can be used by the platforms to provide the
* actual type of [NoOpAtriumErrorAdjuster].
*/
@Deprecated(
"Use NoOpAtriumErrorAdjuster from atrium-core, will be removed with 0.17.0",
ReplaceWith("ch.tutteli.atrium.reporting.erroradjusters.NoOpAtriumErrorAdjusterCommon")
)
abstract class NoOpAtriumErrorAdjusterCommon : AtriumErrorAdjuster {
override fun adjustOtherThanStacks(throwable: Throwable) {}
override fun adjust(throwable: Throwable) {}
}

View File

@@ -1,43 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.assertions.AssertionGroupType
import ch.tutteli.atrium.reporting.AssertionFormatter
import ch.tutteli.atrium.reporting.AssertionFormatterController
import ch.tutteli.atrium.reporting.AssertionFormatterParameterObject
import kotlin.reflect.KClass
/**
* A base type for [AssertionFormatter] which [canFormat][AssertionFormatter.canFormat] only
* [AssertionGroup]s of one specific [AssertionGroupType] and does nothing special when it comes to formatting
* [AssertionGroup.assertions] (merely delegates to [assertionFormatterController]).
*
* @param T The [AssertionGroupType] which the concrete sub class [canFormat][AssertionFormatter.canFormat].
*
* @property clazz The [AssertionGroupType] which the concrete sub class [canFormat][AssertionFormatter.canFormat].
*
* @constructor A base type for [AssertionFormatter] which [canFormat][AssertionFormatter.canFormat] only
* [AssertionGroup]s of one specific [AssertionGroupType].
* @param clazz The [AssertionGroupType] which the concrete sub class [canFormat][AssertionFormatter.canFormat].
* @param assertionFormatterController The controller to which this formatter gives back the control
* when it comes to format children of an [AssertionGroup].
*/
@Deprecated("Use the implementation of atrium-core; will be removed with 0.17.0")
abstract class NoSpecialChildFormattingSingleAssertionGroupTypeFormatter<in T : AssertionGroupType>(
clazz: KClass<T>,
private val assertionFormatterController: AssertionFormatterController
) : SingleAssertionGroupTypeFormatter<T>(clazz) {
override fun formatGroupAssertions(
formatAssertions: (AssertionFormatterParameterObject, (Assertion) -> Unit) -> Unit,
childParameterObject: AssertionFormatterParameterObject
) {
formatAssertions(childParameterObject) {
assertionFormatterController.format(it, childParameterObject)
}
}
}

View File

@@ -1,35 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("OverridingDeprecatedMember")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.reporting.AssertionFormatterFacade
import ch.tutteli.atrium.reporting.AtriumError
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
import ch.tutteli.atrium.reporting.Reporter
/**
* A [Reporter] which reports only failing assertions.
*
* @property assertionFormatterFacade The formatter used to format [Assertion]s.
*
* @constructor A [Reporter] which reports only failing assertions.
* @param assertionFormatterFacade The formatter used to format [Assertion]s.
* @param atriumErrorAdjuster The adjuster which should be used to adjust the resulting [AtriumError].
*/
@Deprecated("Reporting will fundamentally change with the replacement of Assertion with Proof in 0.17.0. There is a replacement in 0.16.0 in atrium-api-core which will be deprecated again in 0.17.0. This class will be removed with 0.17.0")
class OnlyFailureReporter(
private val assertionFormatterFacade: AssertionFormatterFacade,
override val atriumErrorAdjuster: AtriumErrorAdjuster
) : Reporter {
/**
* Formats the given [assertion] with the help of the defined [assertionFormatterFacade]
* and appends the result to the given [sb] but only in case the given [assertion] [holds][Assertion.holds].
*/
override fun format(assertion: Assertion, sb: StringBuilder): Unit =
assertionFormatterFacade.format(assertion, sb, this::assertionFilter)
private fun assertionFilter(assertion: Assertion) = !assertion.holds()
}

View File

@@ -1,12 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
@Deprecated(
"Use RemoveAtriumFromAtriumErrorAdjuster from atrium-core, will be removed with 0.17.0",
ReplaceWith("ch.tutteli.atrium.reporting.erroradjusters.impl.RemoveAtriumFromAtriumErrorAdjuster")
)
expect class RemoveAtriumFromAtriumErrorAdjuster() : AtriumErrorAdjuster

View File

@@ -1,12 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
@Deprecated(
"Use RemoveRunnerAtriumErrorAdjuster from atrium-core, will be removed with 0.17.0",
ReplaceWith("ch.tutteli.atrium.reporting.erroradjusters.impl.RemoveRunnerAtriumErrorAdjuster")
)
expect class RemoveRunnerAtriumErrorAdjuster() : AtriumErrorAdjuster

View File

@@ -1,115 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.assertions.Assertion
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.assertions.AssertionGroupType
import ch.tutteli.atrium.core.polyfills.fullName
import ch.tutteli.atrium.reporting.AssertionFormatter
import ch.tutteli.atrium.reporting.AssertionFormatterController
import ch.tutteli.atrium.reporting.AssertionFormatterParameterObject
import kotlin.reflect.KClass
/**
* A base type for [AssertionFormatter] which [canFormat][AssertionFormatter.canFormat] only
* [AssertionGroup]s of one specific [AssertionGroupType].
*
* @param T The [AssertionGroupType] which the concrete sub class [canFormat][AssertionFormatter.canFormat].
*
* @property clazz The [AssertionGroupType] which the concrete sub class [canFormat][AssertionFormatter.canFormat].
*
* @constructor A base type for [AssertionFormatter] which [canFormat][AssertionFormatter.canFormat] only
* [AssertionGroup]s of one specific [AssertionGroupType].
* @param clazz The [AssertionGroupType] which the concrete sub class [canFormat][AssertionFormatter.canFormat].
*/
@Deprecated("Use the implementation of atrium-core; will be removed with 0.17.0")
abstract class SingleAssertionGroupTypeFormatter<in T : AssertionGroupType>(
private val clazz: KClass<T>
) : AssertionFormatter {
/**
* Returns true if the given [assertion] is an [AssertionGroup] and its [type][AssertionGroup.type]
* is [T] or a sub type.
*/
final override fun canFormat(assertion: Assertion) = assertion is AssertionGroup && clazz.isInstance(assertion.type)
/**
* Always throws an [UnsupportedOperationException], because this [AssertionFormatter] can only format
* [AssertionGroup]s.
*
* @throws UnsupportedOperationException always!
*/
final override fun formatNonGroup(assertion: Assertion, parameterObject: AssertionFormatterParameterObject) =
throw UnsupportedOperationException(
"supports only ${clazz.fullName} for which one has to call ${AssertionFormatter::formatGroup.name}"
)
/**
* Checks whether [assertionGroup] is [T] or a sub type and if so, calls [formatGroupHeaderAndGetChildParameterObject]
* and uses the resulting child-[AssertionFormatterParameterObject] to format [AssertionGroup.assertions].
*
* If [assertionGroup] is *not* [T] or a sub type, then it throws an [UnsupportedOperationException].
*
* @param assertionGroup The assertion group which should be formatted.
* @param parameterObject The parameter object which contains inter alia the [sb][AssertionFormatterParameterObject.sb]
* to which the result will be appended.
* @param formatAssertions The function which should be called to format the
* [assertions][AssertionGroup.assertions] of the given [assertionGroup].
* It itself expects a function which formats single [Assertion]s in the context of the given
* [assertionGroup].
*
* @see [AssertionFormatter.formatGroup].
*
* @throws UnsupportedOperationException if the given [assertionGroup] is not [T] or a sub type of it.
*/
final override fun formatGroup(
assertionGroup: AssertionGroup,
parameterObject: AssertionFormatterParameterObject,
formatAssertions: (AssertionFormatterParameterObject, (Assertion) -> Unit) -> Unit
) = when {
clazz.isInstance(assertionGroup.type) -> formatSpecificGroup(assertionGroup, parameterObject, formatAssertions)
else -> throw UnsupportedOperationException("supports only ${clazz.fullName}")
}
private fun formatSpecificGroup(
assertionGroup: AssertionGroup,
parameterObject: AssertionFormatterParameterObject,
formatAssertions: (AssertionFormatterParameterObject, (Assertion) -> Unit) -> Unit
) {
val childParameterObject = formatGroupHeaderAndGetChildParameterObject(assertionGroup, parameterObject)
formatGroupAssertions(formatAssertions, childParameterObject)
}
/**
* Formats the group header of the given [assertionGroup] (with [type][AssertionGroup.type] [T]) -- appends the
* result to the [sb][AssertionFormatterParameterObject.sb] of the given [parameterObject] -- and returns the
* [AssertionFormatterParameterObject] which shall be used for the [AssertionGroup.assertions].
*
* @param assertionGroup The assertion group which should be formatted.
* @param parameterObject The parameter object which contains inter alia the [sb][AssertionFormatterParameterObject.sb]
* to which the result will be appended.
*
* @return The [AssertionFormatterParameterObject] which shall be used for the [AssertionGroup.assertions].
*/
protected abstract fun formatGroupHeaderAndGetChildParameterObject(
assertionGroup: AssertionGroup,
parameterObject: AssertionFormatterParameterObject
): AssertionFormatterParameterObject
/**
* Formats the [AssertionGroup.assertions] -- has to call the given [formatAssertions] function in order that
* the [AssertionFormatterController] can steer the process.
*
* @param formatAssertions The function which should be called to format the [assertions][AssertionGroup.assertions]
* of a given [AssertionGroup]. It itself expects a function which formats single [Assertion]s in the context
* of the given [AssertionGroup].
* @param childParameterObject The parameter object which shall be used to format [AssertionGroup.assertions] -- contains
* inter alia the [sb][AssertionFormatterParameterObject.sb] to which the result will be appended.
*/
protected abstract fun formatGroupAssertions(
formatAssertions: (AssertionFormatterParameterObject, (Assertion) -> Unit) -> Unit,
childParameterObject: AssertionFormatterParameterObject
)
}

View File

@@ -1,70 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.assertions.*
import ch.tutteli.atrium.reporting.AssertionFormatter
import ch.tutteli.atrium.reporting.AssertionFormatterController
import ch.tutteli.atrium.reporting.AssertionFormatterParameterObject
import kotlin.reflect.KClass
/**
* Represents an [AssertionFormatter] which formats [AssertionGroup]s with an [ExplanatoryAssertionGroupType] by
* neglecting the group header and defining an child-[AssertionFormatterParameterObject] which indicates that we are in an
* explanatory assertion.
*
* Furthermore it uses the bullet point defined for [WarningAssertionGroupType] in `bulletPoints` (see constructor)
* (`"❗❗ "` if absent) as prefix for the child-[AssertionFormatterParameterObject] if the [AssertionGroup.type] is a
* [WarningAssertionGroupType]. Otherwise it is using the bullet point defined for [ExplanatoryAssertionGroupType]
* (`"» "` if absent).
*
* Its usage is intended for text output (e.g. to the console).
*
* @constructor Represents an [AssertionFormatter] which formats [AssertionGroup]s with an
* [ExplanatoryAssertionGroupType] by defining only an [AssertionFormatterParameterObject] -- which indicates
* that we are in an explanatory assertion group and uses the `bulletPoints` (passed as argument) as prefix --
* and completely ignoring [AssertionGroup.description] and [AssertionGroup.representation].
*
* @param bulletPoints The formatter uses the bullet point defined for [WarningAssertionGroupType]
* (`"❗❗ "` if absent) or the bullet point defined for [ExplanatoryAssertionGroupType]
* (`"» "` if absent) as prefix of the child-[AssertionFormatterParameterObject].
*
* @param assertionFormatterController The controller to which this formatter gives back the control
* when it comes to format children of an [AssertionGroup].
*/
@Deprecated("Use the implementation of atrium-core; will be removed with 0.17.0")
class TextExplanatoryAssertionGroupFormatter(
bulletPoints: Map<KClass<out BulletPointIdentifier>, String>,
assertionFormatterController: AssertionFormatterController
) : NoSpecialChildFormattingSingleAssertionGroupTypeFormatter<ExplanatoryAssertionGroupType>(
ExplanatoryAssertionGroupType::class,
assertionFormatterController
) {
private val explanatoryBulletPoint = bulletPoints[ExplanatoryAssertionGroupType::class] ?: "» "
private val warningBulletPoint = bulletPoints[WarningAssertionGroupType::class] ?: "❗❗ "
private val informationBulletPoint = bulletPoints[InformationAssertionGroupType::class] ?: " "
override fun formatGroupHeaderAndGetChildParameterObject(
assertionGroup: AssertionGroup,
parameterObject: AssertionFormatterParameterObject
): AssertionFormatterParameterObject {
fun withIndent(bulletPoint: String) =
parameterObject.createForExplanatoryFilterAssertionGroup().createChildWithNewPrefix(bulletPoint)
fun withOrWithoutIndent(bulletPoint: String, withIndent: Boolean) =
if (withIndent) withIndent(bulletPoint)
else parameterObject.createForExplanatoryFilterAssertionGroup(bulletPoint)
//TODO 1.0.0 move val inside when
val assertionGroupType = assertionGroup.type
return when (assertionGroupType) {
is InformationAssertionGroupType -> withOrWithoutIndent(
informationBulletPoint,
assertionGroupType.withIndent
)
WarningAssertionGroupType -> withIndent(warningBulletPoint)
else -> withIndent(explanatoryBulletPoint)
}
}
}

View File

@@ -1,114 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.assertions.*
import ch.tutteli.atrium.core.polyfills.fullName
import ch.tutteli.atrium.reporting.*
import ch.tutteli.atrium.reporting.translating.Untranslatable
import kotlin.reflect.KClass
/**
* Formats an [Assertion] for text output (e.g. to the console) by using the given [assertionPairFormatter]
* to format the group header for [AssertionGroup]s and uses the bullet point defined for
* [RootAssertionGroupType] as prefix for the [AssertionGroup.assertions].
*
* The [assertionPairFormatter] is also used to format [DescriptiveAssertion]s.
*
* Currently the following [Assertion] types are supported:
* - [AssertionGroup] of type [RootAssertionGroupType]
* - [DescriptiveAssertion]
* - [ExplanatoryAssertion]
*
* In addition it defines a fallback for unknown [AssertionGroupType]s as well as for unknown [Assertion] types.
*
* @property assertionFormatterController The [AssertionFormatterController] used to steer the control flow of
* the reporting process.
* @property assertionPairFormatter The formatter used to format assertion pairs (e.g. [DescriptiveAssertion.description]
* and [DescriptiveAssertion.representation])
*
* @constructor Formats an [Assertion] for text output (e.g. for the console) where it uses a given
* [assertionPairFormatter] which defines how an assertion pair (e.g. [DescriptiveAssertion.description]
* and [DescriptiveAssertion.representation]) is formatted.
* @param bulletPoints The formatter uses the bullet point defined for [RootAssertionGroupType]
* (`"◆ "` if absent) as prefix of the child-[AssertionFormatterParameterObject].
* @param assertionFormatterController The [AssertionFormatterController] used to steer the control flow of
* the reporting process.
* @param assertionPairFormatter The formatter which is used to format assertion pairs
* (e.g. [DescriptiveAssertion.description] and [DescriptiveAssertion.representation])
*/
@Deprecated("Use the implementation of atrium-core; will be removed with 0.17.0")
class TextFallbackAssertionFormatter(
bulletPoints: Map<KClass<out BulletPointIdentifier>, String>,
private val assertionFormatterController: AssertionFormatterController,
private val assertionPairFormatter: AssertionPairFormatter,
private val objectFormatter: ObjectFormatter
) : AssertionFormatter {
private val rootPrefix = bulletPoints[RootAssertionGroupType::class] ?: "◆ "
private val formatter = TextPrefixBasedAssertionGroupFormatter(rootPrefix)
override fun canFormat(assertion: Assertion): Boolean {
// two fallback are implemented one for IAssertionGroup (uses always formatGroup)
// and the other one for any kind of IAssertion (fallback to formatFallback)
return true
}
override fun formatNonGroup(assertion: Assertion, parameterObject: AssertionFormatterParameterObject) {
parameterObject.appendLnIndentAndPrefix()
when (assertion) {
is DescriptiveAssertion -> appendDescriptiveAssertion(assertion, parameterObject)
is RepresentationOnlyAssertion -> appendRepresentationOnlyAssertion(assertion, parameterObject)
is ExplanatoryAssertion -> appendExplanatoryAssertion(assertion, parameterObject)
else -> formatFallback(assertion, parameterObject)
}
}
private fun appendDescriptiveAssertion(
assertion: DescriptiveAssertion,
parameterObject: AssertionFormatterParameterObject
) {
assertionPairFormatter.format(parameterObject, assertion.description, assertion.representation)
}
private fun appendRepresentationOnlyAssertion(
assertion: RepresentationOnlyAssertion,
parameterObject: AssertionFormatterParameterObject
) {
parameterObject.sb.append(objectFormatter.format(assertion.representation))
}
private fun appendExplanatoryAssertion(
assertion: ExplanatoryAssertion,
parameterObject: AssertionFormatterParameterObject
) {
parameterObject.sb.append(objectFormatter.format(assertion.explanation))
}
private fun formatFallback(assertion: Assertion, parameterObject: AssertionFormatterParameterObject) {
val translatable =
Untranslatable("Unsupported type ${assertion::class.fullName}, can only report whether it holds")
assertionPairFormatter.format(parameterObject, translatable, assertion.holds())
}
override fun formatGroup(
assertionGroup: AssertionGroup,
parameterObject: AssertionFormatterParameterObject,
formatAssertions: (AssertionFormatterParameterObject, (Assertion) -> Unit) -> Unit
) {
val childParameterObject = formatGroupHeaderAndGetChildParameterObject(assertionGroup, parameterObject)
formatAssertions(childParameterObject) {
assertionFormatterController.format(it, childParameterObject)
}
}
private fun formatGroupHeaderAndGetChildParameterObject(
assertionGroup: AssertionGroup, parameterObject: AssertionFormatterParameterObject
) = when (assertionGroup.type) {
RootAssertionGroupType -> formatter.formatAfterAppendLnEtc(
assertionPairFormatter, assertionGroup, parameterObject
)
else -> formatter.formatWithGroupName(assertionPairFormatter, assertionGroup, parameterObject)
}
}

View File

@@ -1,69 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.assertions.BulletPointIdentifier
import ch.tutteli.atrium.assertions.FeatureAssertionGroupType
import ch.tutteli.atrium.assertions.PrefixFeatureAssertionGroupHeader
import ch.tutteli.atrium.reporting.*
import ch.tutteli.atrium.reporting.translating.Translatable
import ch.tutteli.atrium.reporting.translating.TranslatableWithArgs
import ch.tutteli.atrium.reporting.translating.Untranslatable
import kotlin.reflect.KClass
/**
* Represents an [AssertionFormatter] which formats [AssertionGroup]s with a [FeatureAssertionGroupType] by
* using the given [assertionPairFormatter] to format the group header, additionally prefixing it with the
* "bullet point" (typically an arrow) defined for [PrefixFeatureAssertionGroupHeader] and uses the bullet point
* defined for [FeatureAssertionGroupType] as prefix for the [AssertionGroup.assertions].
*
* Its usage is intended for text output (e.g. to the console).
*
* @constructor Represents an [AssertionFormatter] which formats [AssertionGroup]s with an
* [FeatureAssertionGroupType] by using the given [assertionPairFormatter] to format the group header, additionally
* prefixing it with the "bullet point" (typically an arrow) defined for [PrefixFeatureAssertionGroupHeader] and uses
* the bullet point defined for [FeatureAssertionGroupType] as prefix for the [AssertionGroup.assertions].
*
* @param bulletPoints The formatter uses the bullet point defined for [PrefixFeatureAssertionGroupHeader]
* (`"▶ "` if absent) as prefix of the group header and [FeatureAssertionGroupType] (`"◾ "` if absent)
* as prefix of the child-[AssertionFormatterParameterObject].
* @param assertionFormatterController The controller to which this formatter gives back the control
* when it comes to format children of an [AssertionGroup].
* @param assertionPairFormatter The formatter which is used to format assertion pairs.
*/
@Deprecated("Use the implementation of atrium-core; will be removed with 0.17.0")
class TextFeatureAssertionGroupFormatter(
bulletPoints: Map<KClass<out BulletPointIdentifier>, String>,
assertionFormatterController: AssertionFormatterController,
private val assertionPairFormatter: AssertionPairFormatter
) : NoSpecialChildFormattingSingleAssertionGroupTypeFormatter<FeatureAssertionGroupType>(
FeatureAssertionGroupType::class,
assertionFormatterController
) {
private val prefix = (bulletPoints[FeatureAssertionGroupType::class] ?: "◾ ")
private val arrow = (bulletPoints[PrefixFeatureAssertionGroupHeader::class] ?: "▶ ")
override fun formatGroupHeaderAndGetChildParameterObject(
assertionGroup: AssertionGroup,
parameterObject: AssertionFormatterParameterObject
): AssertionFormatterParameterObject {
parameterObject.appendLnIndentAndPrefix()
val translatable = TranslatableWithArgs(Untranslatable("$arrow%s"), assertionGroup.description)
val group = DecoratedAssertionGroup(translatable, assertionGroup, parameterObject)
val newParameterObject = parameterObject.createChildWithNewPrefixAndAdditionalIndent(prefix, arrow.length)
assertionPairFormatter.formatGroupHeader(parameterObject, group, newParameterObject)
return newParameterObject
}
private class DecoratedAssertionGroup(
newName: Translatable,
assertionGroup: AssertionGroup,
parameterObject: AssertionFormatterParameterObject
) : AssertionGroup by assertionGroup {
override val description: Translatable = newName
override val representation: Any = if(parameterObject.isNotInExplanatoryFilterGroup()) assertionGroup.representation else Text.EMPTY
}
}

View File

@@ -1,40 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.assertions.BulletPointIdentifier
import ch.tutteli.atrium.assertions.ListAssertionGroupType
import ch.tutteli.atrium.reporting.AssertionFormatter
import ch.tutteli.atrium.reporting.AssertionFormatterController
import ch.tutteli.atrium.reporting.AssertionFormatterParameterObject
import ch.tutteli.atrium.reporting.AssertionPairFormatter
import kotlin.reflect.KClass
/**
* Represents an [AssertionFormatter] which formats [AssertionGroup]s with a [ListAssertionGroupType] by
* using the given [assertionPairFormatter] to format the group header and uses the bullet point defined for
* [ListAssertionGroupType] as prefix for the [AssertionGroup.assertions].
*
* Its usage is intended for text output (e.g. to the console).
*
* @constructor Represents an [AssertionFormatter] which formats [AssertionGroup]s with a [ListAssertionGroupType]
* by putting each assertion on an own line prefixed with a bullet point.
* @param bulletPoints The formatter uses the bullet point defined for [ListAssertionGroupType]
* (`" ⚬ "` if absent) as prefix of the child-[AssertionFormatterParameterObject].
* @param assertionFormatterController The controller to which this formatter gives back the control
* when it comes to format children of an [AssertionGroup].
* @param assertionPairFormatter The formatter which is used to format assertion pairs.
*/
@Deprecated("Use the implementation of atrium-core; will be removed with 0.17.0")
class TextListAssertionGroupFormatter(
bulletPoints: Map<KClass<out BulletPointIdentifier>, String>,
assertionFormatterController: AssertionFormatterController,
assertionPairFormatter: AssertionPairFormatter
) : TextListBasedAssertionGroupFormatter<ListAssertionGroupType>(
bulletPoints[ListAssertionGroupType::class] ?: "",
assertionFormatterController,
assertionPairFormatter,
ListAssertionGroupType::class
)

View File

@@ -1,44 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.assertions.AssertionGroupType
import ch.tutteli.atrium.reporting.AssertionFormatter
import ch.tutteli.atrium.reporting.AssertionFormatterController
import ch.tutteli.atrium.reporting.AssertionFormatterParameterObject
import ch.tutteli.atrium.reporting.AssertionPairFormatter
import kotlin.reflect.KClass
/**
* Represents an [AssertionFormatter] which formats [AssertionGroup]s with type [T] by using the given
* [assertionPairFormatter] to format the group header and using the given `bulletPoint` (see constructor) to prefix
* the [AssertionGroup.assertions].
*
* Its usage is intended for text output (e.g. to the console).
*
* @constructor Represents an [AssertionFormatter] which formats [AssertionGroup]s with type [T] by
* putting each assertion on an own line prefixed with a bullet point.
* @param bulletPoint The bullet point (might also be more than one character) which shall be used.
* @param assertionFormatterController The controller to which this formatter gives back the control
* when it comes to format children of an [AssertionGroup].
* @param assertionPairFormatter The formatter which is used to format assertion pairs.
* @param clazz The [AssertionGroupType] which the concrete sub class [canFormat][AssertionFormatter.canFormat].
*/
@Deprecated("Use the implementation of atrium-core; will be removed with 0.17.0")
abstract class TextListBasedAssertionGroupFormatter<in T : AssertionGroupType>(
bulletPoint: String,
assertionFormatterController: AssertionFormatterController,
private val assertionPairFormatter: AssertionPairFormatter,
clazz: KClass<T>
) : NoSpecialChildFormattingSingleAssertionGroupTypeFormatter<T>(clazz, assertionFormatterController) {
private val formatter =
TextPrefixBasedAssertionGroupFormatter(bulletPoint)
override fun formatGroupHeaderAndGetChildParameterObject(
assertionGroup: AssertionGroup,
parameterObject: AssertionFormatterParameterObject
): AssertionFormatterParameterObject =
formatter.formatWithGroupName(assertionPairFormatter, assertionGroup, parameterObject)
}

View File

@@ -1,32 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.reporting.MethodCallFormatter
import ch.tutteli.atrium.reporting.Text
/**
* Responsible to format a method call for text output (e.g. to the console) where it represents arguments of a
* method call by using their [Any.toString] representation with a few exceptions.
*
* The exceptions are:
* - [CharSequence], is wrapped in quotes (`"`) and \r as well as \n are escaped.
* - [Char] is wrapped in apostrophes (`'`)
*/
@Deprecated("Use the implementation of atrium-core; will be removed with 0.17.0")
object TextMethodCallFormatter : MethodCallFormatter {
override fun formatCall(methodName: String, arguments: Array<out Any?>): String =
arguments.joinToString(", ", prefix = "$methodName(", postfix = ")") { formatArgument(it) }
override fun format(methodName: String, arguments: Array<out Any?>): () -> String = {
formatCall(methodName, arguments)
}
override fun formatArgument(argument: Any?): String = when (argument) {
null -> Text.NULL.string
is CharSequence -> "\"$argument\"".replace("\r", "\\r").replace("\n", "\\n")
is Char -> "'$argument'"
else -> argument.toString()
}
}

View File

@@ -1,64 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.assertions.DescriptiveAssertion
import ch.tutteli.atrium.reporting.*
import ch.tutteli.atrium.reporting.translating.Translatable
import ch.tutteli.atrium.reporting.translating.Translator
/**
* Represents an [AssertionPairFormatter] formatter of assertion pairs -- which consists of a [Translatable]
* and a representation -- where it puts the translation on one line and the representation on the next line
* (including indentation as if the representation is a child).
*
* Its usage is intended for text output (e.g. to the console).
*
* @property objectFormatter Used to format objects such as [DescriptiveAssertion.representation].
* @property translator Used to translate [Translatable]s such as [DescriptiveAssertion.description].
*
* @constructor Represents an [AssertionPairFormatter] formatter of assertion pairs -- which consists of a
* [Translatable] and a representation -- where it puts them on the same line in the form:
* `translation: representation`.
* @param objectFormatter Used to format objects such as [DescriptiveAssertion.representation].
* @param translator Used to translate [Translatable]s such as [DescriptiveAssertion.description].
*/
@Deprecated("Use the implementation of atrium-core; will be removed with 0.17.0")
class TextNextLineAssertionPairFormatter(
private val objectFormatter: ObjectFormatter,
private val translator: Translator
) : AssertionPairFormatter {
override fun formatGroupHeader(
parameterObject: AssertionFormatterParameterObject,
assertionGroup: AssertionGroup,
newParameterObject: AssertionFormatterParameterObject
): Unit = format(parameterObject, assertionGroup.description, assertionGroup.representation, newParameterObject)
override fun format(
parameterObject: AssertionFormatterParameterObject,
translatable: Translatable,
representation: Any
): Unit = format(parameterObject, translatable, representation, parameterObject)
private fun format(
parameterObject: AssertionFormatterParameterObject,
translatable: Translatable,
representation: Any,
newParameterObject: AssertionFormatterParameterObject
) {
parameterObject.sb.append(translator.translate(translatable)).append(":")
@Suppress(/* TODO remove RawString.Empty with 1.0.0*/ "DEPRECATION")
// yes, we check only for Text.EMPTY and not for `representation !is Text || representation.string != ""`
// on purpose. You can only create an empty Text via a hack and not via the normal invoke function in
// the companion of Text
if (representation != Text.EMPTY && representation != RawString.EMPTY) {
newParameterObject.appendLnAndIndent()
newParameterObject.indent(newParameterObject.prefix.length)
parameterObject.sb.append(objectFormatter.format(representation))
}
}
}

View File

@@ -1,33 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.reporting.AssertionFormatterParameterObject
import ch.tutteli.atrium.reporting.AssertionPairFormatter
@Deprecated("Use the implementation of atrium-core; will be removed with 0.17.0")
class TextPrefixBasedAssertionGroupFormatter(
private val prefix: String
) {
fun formatWithGroupName(
assertionPairFormatter: AssertionPairFormatter,
assertionGroup: AssertionGroup,
parameterObject: AssertionFormatterParameterObject
): AssertionFormatterParameterObject {
parameterObject.appendLnIndentAndPrefix()
return formatAfterAppendLnEtc(assertionPairFormatter, assertionGroup, parameterObject)
}
fun formatAfterAppendLnEtc(
assertionPairFormatter: AssertionPairFormatter,
assertionGroup: AssertionGroup,
parameterObject: AssertionFormatterParameterObject
): AssertionFormatterParameterObject {
val newParameterObject = parameterObject.createChildWithNewPrefix(prefix)
assertionPairFormatter.formatGroupHeader(parameterObject, assertionGroup, newParameterObject)
return newParameterObject
}
}

View File

@@ -1,49 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.assertions.DescriptiveAssertion
import ch.tutteli.atrium.reporting.AssertionFormatterParameterObject
import ch.tutteli.atrium.reporting.AssertionPairFormatter
import ch.tutteli.atrium.reporting.ObjectFormatter
import ch.tutteli.atrium.reporting.translating.Translatable
import ch.tutteli.atrium.reporting.translating.Translator
/**
* Represents an [AssertionPairFormatter] formatter of assertion pairs -- which consists of a [Translatable]
* and a representation -- where it puts them on the same line in the form: `translation: representation`.
*
* Its usage is intended for text output (e.g. to the console).
*
* @property objectFormatter Used to format objects such as [DescriptiveAssertion.representation].
* @property translator Used to translate [Translatable]s such as [DescriptiveAssertion.description].
*
* @constructor Represents an [AssertionPairFormatter] formatter of assertion pairs -- which consists of a
* [Translatable] and a representation -- where it puts them on the same line in the form:
* `translation: representation`.
* @param objectFormatter Used to format objects such as [DescriptiveAssertion.representation].
* @param translator Used to translate [Translatable]s such as [DescriptiveAssertion.description].
*/
@Deprecated("Use the implementation of atrium-core; will be removed with 0.17.0")
class TextSameLineAssertionPairFormatter(
private val objectFormatter: ObjectFormatter,
private val translator: Translator
) : AssertionPairFormatter {
override fun formatGroupHeader(
parameterObject: AssertionFormatterParameterObject,
assertionGroup: AssertionGroup,
newParameterObject: AssertionFormatterParameterObject
): Unit = format(parameterObject, assertionGroup.description, assertionGroup.representation)
override fun format(
parameterObject: AssertionFormatterParameterObject,
translatable: Translatable,
representation: Any
) {
parameterObject.sb.append(translator.translate(translatable)).append(": ")
.append(objectFormatter.format(representation))
}
}

View File

@@ -1,67 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.assertions.*
import ch.tutteli.atrium.reporting.AssertionFormatter
import ch.tutteli.atrium.reporting.AssertionFormatterController
import ch.tutteli.atrium.reporting.AssertionFormatterParameterObject
import ch.tutteli.atrium.reporting.AssertionPairFormatter
import kotlin.reflect.KClass
/**
* Represents an [AssertionFormatter] which formats [AssertionGroup]s with a [SummaryAssertionGroupType] by
* using the given [assertionPairFormatter] to format the group header and uses the bullet point defined
* for [PrefixSuccessfulSummaryAssertion] as prefix for successful [AssertionGroup.assertions] and the bullet point
* defined for [PrefixFeatureAssertionGroupHeader] as prefix for failing [AssertionGroup.assertions].
*
* Its usage is intended for text output (e.g. to the console).
*
* @constructor Represents an [AssertionFormatter] which formats [AssertionGroup]s with an
* [SummaryAssertionGroupType] by using the given [assertionPairFormatter] to format the group header and uses the
* bullet point defined for [PrefixSuccessfulSummaryAssertion] as prefix for successful [AssertionGroup.assertions]
* and the bullet point defined for [PrefixFeatureAssertionGroupHeader] as prefix for failing [AssertionGroup.assertions].
*
* @param bulletPoints The formatter uses the bullet point defined for [PrefixSuccessfulSummaryAssertion]
* (`"✔ "` if absent) as prefix for successful assertions in [AssertionGroup.assertions] and the bullet point defined
* for [PrefixFailingSummaryAssertion] (`"✘ "` if absent) for failing assertions.
*
* @param assertionFormatterController The controller to which this formatter gives back the control
* when it comes to format children of an [AssertionGroup].
* @param assertionPairFormatter The formatter which is used to format assertion pairs.
*/
@Deprecated("Use the implementation of atrium-core; will be removed with 0.17.0")
class TextSummaryAssertionGroupFormatter(
bulletPoints: Map<KClass<out BulletPointIdentifier>, String>,
private val assertionFormatterController: AssertionFormatterController,
private val assertionPairFormatter: AssertionPairFormatter
) : SingleAssertionGroupTypeFormatter<SummaryAssertionGroupType>(SummaryAssertionGroupType::class) {
private val successful = (bulletPoints[PrefixSuccessfulSummaryAssertion::class] ?: "✔ ")
private val failing = (bulletPoints[PrefixFailingSummaryAssertion::class] ?: "✘ ")
override fun formatGroupHeaderAndGetChildParameterObject(
assertionGroup: AssertionGroup,
parameterObject: AssertionFormatterParameterObject
): AssertionFormatterParameterObject {
parameterObject.appendLnIndentAndPrefix()
assertionPairFormatter.format(parameterObject, assertionGroup.description, assertionGroup.representation)
//the prefix which should be used for assertions is defined in the formatGroupAssertions
return parameterObject.createForDoNotFilterAssertionGroup()
}
override fun formatGroupAssertions(
formatAssertions: (AssertionFormatterParameterObject, (Assertion) -> Unit) -> Unit,
childParameterObject: AssertionFormatterParameterObject
) {
val successfulParameterObject = childParameterObject.createChildWithNewPrefix(successful)
val failingParameterObject = childParameterObject.createChildWithNewPrefix(failing)
formatAssertions(childParameterObject) {
if (it.holds()) {
assertionFormatterController.format(it, successfulParameterObject)
} else {
assertionFormatterController.format(it, failingParameterObject)
}
}
}
}

View File

@@ -1,111 +0,0 @@
@file:Suppress("EXPERIMENTAL_FEATURE_WARNING", "DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting.translating
import ch.tutteli.atrium.reporting.translating.Locale
import ch.tutteli.atrium.reporting.translating.LocaleOrderDecider
import ch.tutteli.atrium.reporting.translating.getDefaultLocale
import ch.tutteli.kbox.forElementAndForEachIn
/**
* Responsible to determine in which order [Locale]s should be processed.
*
* Adopted from Java's `ResourceBundle.Control.getCandidateLocales()` and `ResourceBundle.Control.getFallbackLocale()`
* but there are a few differences:
* - is based on Atrium's [Locale] and not `java.util.java`
* - allows to define more than one fallback [Locale]
* - does not use [getDefaultLocale] implicitly (one can define it explicitly as fallback [Locale] though)
* - it does not return `java.util.Locale.ROOT`
*
* Further information can be found at [LocaleOrderDecider].
*/
@Deprecated("Use ResourceBundleInspiredLocaleOrderDecider from atrium-core; will be removed with 0.17.0")
class CoroutineBasedLocaleOrderDecider : LocaleOrderDecider {
override fun determineOrder(primaryLocale: Locale, fallbackLocales: List<Locale>): Sequence<Locale> {
val locales = mutableListOf<Locale>()
forElementAndForEachIn(primaryLocale, fallbackLocales) { locale ->
when (locale.language) {
"zh" -> locales.specialCaseChinese(locale)
else -> locales.normalCase(locale)
}
}
return locales.asSequence()
}
private fun MutableList<Locale>.specialCaseChinese(locale: Locale) {
val script = if (locale.script == null && locale.country != null) {
when (locale.country) {
"TW", "HK", "MO" -> "Hant"
"CN", "SG" -> "Hans"
else -> ""
}
} else {
locale.script
}
normalCase(locale, script = script)
}
private fun MutableList<Locale>.normalCase(
locale: Locale,
language: String = locale.language,
script: String? = locale.script,
country: String? = locale.country,
variant: String? = locale.variant
) {
fallbackDueToVariant(language, script, country, variant)
fallbackDueToCountry(language, script, country)
fallbackDueToScript(language, script, country, variant)
fallbackDueToLanguage(language)
}
private fun MutableList<Locale>.fallbackDueToVariant(
language: String,
script: String?,
country: String?,
variant: String?
) {
if (variant != null) {
var newVariant: String = variant
do {
val fallback = Locale(language, script, country, newVariant)
add(fallback)
newVariant = newVariant.substringBeforeLast('_', "")
} while (newVariant.isNotEmpty())
}
}
private fun MutableList<Locale>.fallbackDueToCountry(
language: String,
script: String?,
country: String?
) {
if (country != null) {
val fallback = Locale(language, script, country, null)
add(fallback)
}
}
private fun MutableList<Locale>.fallbackDueToScript(
language: String,
script: String?,
country: String?,
variant: String?
) {
if (script != null) {
val fallback = Locale(language, script, null, null)
add(fallback)
// fallback variants without considering script
fallbackDueToVariant(language, null, country, variant)
// fallback country without considering script
fallbackDueToCountry(language, null, country)
}
}
private fun MutableList<Locale>.fallbackDueToLanguage(language: String) {
val fallback = Locale(language)
add(fallback)
}
}

View File

@@ -1,40 +0,0 @@
package ch.tutteli.atrium.core.robstoll.lib.reporting.translating
import ch.tutteli.atrium.reporting.translating.*
/**
* Represents a [Translator] which uses a given [TranslationSupplier] to retrieve translations and
* a given [LocaleOrderDecider] to determine in which order it should try to find translations
* for a given [Translatable].
*
* @property translationSupplier The [TranslationSupplier] which provides available translations.
* @property localeOrderDecider Decides in which order [Locale]s are processed to find a translation for a
* given [Translatable].
*
* @constructor Represents a [Translator] which uses a [TranslationSupplier] to retrieve translations and
* [LocaleOrderDecider] to determine in which order it should try to find translations for a given
* [Translatable].
* @param translationSupplier The [TranslationSupplier] as such.
* @param localeOrderDecider Decides in which order [Locale]s are processed to find a translation for a
* given [Translatable].
* @param primaryLocale The [Locale] to which the translator translates per default as well as the [Locale]
* which will be used in [String.format], which in turn is used to substitute the placeholders in
* the resulting translation of [TranslatableWithArgs.translatable] with the [TranslatableWithArgs.arguments].
* @param fallbackLocales Used in case a translation for a given [Translatable] is not defined for
* [primaryLocale] or one of its secondary alternatives -- the fallback [Locale]s are used in the given order.
*/
@Deprecated("Use the one from atrium-core will be removed with 0.17.0", ReplaceWith("ch.tutteli.atrium.reporting.translating.impl.TranslationSupplierBasedTranslator"))
class TranslationSupplierBasedTranslator(
private val translationSupplier: TranslationSupplier,
private val localeOrderDecider: LocaleOrderDecider,
primaryLocale: Locale,
fallbackLocales: List<Locale>
) : ArgumentsSupportingTranslator(primaryLocale, fallbackLocales) {
override fun translateWithoutArgs(translatable: Translatable): String {
return localeOrderDecider.determineOrder(primaryLocale, fallbackLocales)
.map { translationSupplier.get(translatable, it) }
.firstOrNull { it != null }
?: translatable.getDefault()
}
}

View File

@@ -1,8 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
object AssertionFormatterControllerSpec : ch.tutteli.atrium.specs.reporting.AssertionFormatterControllerSpec(
::AssertionFormatterControllerImpl
)

View File

@@ -1,13 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
import ch.tutteli.atrium.reporting.Reporter
internal class DelegatingReporter(
reporter: Reporter,
override val atriumErrorAdjuster: AtriumErrorAdjuster
) : Reporter by reporter

View File

@@ -1,8 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
object OnlyFailureReporterSpec : ch.tutteli.atrium.specs.reporting.OnlyFailureReporterSpec(
::OnlyFailureReporter
)

View File

@@ -1,84 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.assertions.BulletPointIdentifier
import ch.tutteli.atrium.assertions.DefaultExplanatoryAssertionGroupType
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.spekframework.spek2.Spek
import kotlin.reflect.KClass
class TextExplanatoryAssertionGroupFormatterSpec : Spek({
include(AtriumsTextExplanatoryAssertionFormatterSpec)
include(AtriumsTextWarningAssertionFormatterSpec)
include(AtriumsTextInformationAssertionFormatterSpec)
include(AtriumsSingleAssertionGroupTypeFormatterSpec)
include(AtriumsAssertionFormatterSpec)
}) {
object AtriumsTextExplanatoryAssertionFormatterSpec :
ch.tutteli.atrium.specs.reporting.TextExplanatoryAssertionGroupFormatterSpec(
factory(), "[Atrium's TextExplanatory...Spec] "
)
object AtriumsTextWarningAssertionFormatterSpec :
ch.tutteli.atrium.specs.reporting.TextWarningAssertionGroupFormatterSpec(
factory(), "[Atrium's TextWarning...Spec] "
)
object AtriumsTextInformationWithIndentAssertionFormatterSpec :
ch.tutteli.atrium.specs.reporting.TextInformationAssertionGroupFormatterSpec(
factory(), withIndent = true, describePrefix = "[Atrium's TextInformation...Spec] "
)
object AtriumsTextInformationAssertionFormatterSpec :
ch.tutteli.atrium.specs.reporting.TextInformationAssertionGroupFormatterSpec(
factory(), withIndent = false, describePrefix = "[Atrium's TextInformation...Spec] "
)
object AtriumsEmptyNameAndSubjectAssertionGroupFormatterSpec :
ch.tutteli.atrium.specs.reporting.EmptyNameAndSubjectAssertionGroupFormatterSpec<ExplanatoryAssertionGroupType>(
factoryWithoutBulletPoint(),
ExplanatoryAssertionGroupType::class,
DefaultExplanatoryAssertionGroupType,
object : ExplanatoryAssertionGroupType {},
"[Atrium's EmptyNameAndSubject...Spec] "
)
object AtriumsSingleAssertionGroupTypeFormatterSpec :
ch.tutteli.atrium.specs.reporting.SingleAssertionGroupTypeFormatterSpec<ExplanatoryAssertionGroupType>(
factoryWithObjectFormatter(),
ExplanatoryAssertionGroupType::class,
object : ExplanatoryAssertionGroupType {},
DefaultExplanatoryAssertionGroupType,
"[Atrium's SingleAssertionGroupType...Spec] "
)
object AtriumsAssertionFormatterSpec : ch.tutteli.atrium.specs.reporting.AssertionFormatterSpec(
factoryWithObjectFormatter(), "[Atrium's AssertionFormatterSpec] "
)
companion object {
private fun factory() =
{ bulletPoints: Map<KClass<out BulletPointIdentifier>, String>, assertionFormatterController: AssertionFormatterController ->
TextExplanatoryAssertionGroupFormatter(
bulletPoints,
assertionFormatterController
)
}
private fun factoryWithoutBulletPoint() = { assertionFormatterController: AssertionFormatterController ->
factory()(mapOf(ExplanatoryAssertionGroupType::class to "*"), assertionFormatterController)
}
private fun factoryWithObjectFormatter() =
{ bulletPoints: Map<KClass<out BulletPointIdentifier>, String>, assertionFormatterController: AssertionFormatterController, _: ObjectFormatter, _: Translator ->
factory()(bulletPoints, assertionFormatterController)
}
}
}

View File

@@ -1,95 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.api.fluent.en_GB.toBe
import ch.tutteli.atrium.api.verbs.internal.AssertionVerb.EXPECT
import ch.tutteli.atrium.api.verbs.internal.expect
import ch.tutteli.atrium.assertions.AssertionGroup
import ch.tutteli.atrium.assertions.BulletPointIdentifier
import ch.tutteli.atrium.assertions.RootAssertionGroupType
import ch.tutteli.atrium.assertions.builders.assertionBuilder
import ch.tutteli.atrium.assertions.builders.root
import ch.tutteli.atrium.core.coreFactory
import ch.tutteli.atrium.reporting.AssertionFormatterController
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.lineSeparator
import ch.tutteli.atrium.specs.reporting.ToStringObjectFormatter
import ch.tutteli.atrium.specs.reporting.alwaysTrueAssertionFilter
import ch.tutteli.atrium.specs.toBeDescr
import ch.tutteli.atrium.translations.DescriptionAnyAssertion.NOT_TO_BE
import ch.tutteli.atrium.translations.DescriptionAnyAssertion.TO_BE
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
import kotlin.reflect.KClass
class TextFallbackAssertionFormatterSpec : Spek({
include(AtriumsTextFallbackAssertionFormatterSpec)
include(AtriumsAssertionFormatterSpec)
val squarePoint = ""
val facade = coreFactory.newAssertionFormatterFacade(coreFactory.newAssertionFormatterController())
facade.register {
TextFallbackAssertionFormatter(
mapOf(RootAssertionGroupType::class to "$squarePoint "),
it,
TextSameLineAssertionPairFormatter(
ToStringObjectFormatter,
UsingDefaultTranslator()
), ToStringObjectFormatter
)
}
var sb = StringBuilder()
afterEachTest {
sb = StringBuilder()
}
describe("fun ${TextFallbackAssertionFormatter::format.name}") {
context("a ${AssertionGroup::class.simpleName} of type ${RootAssertionGroupType::class.simpleName}") {
it("includes the group ${AssertionGroup::description.name}, its ${AssertionGroup::representation.name} as well as the ${AssertionGroup::assertions.name}") {
val assertionGroup = with(assertionBuilder) {
assertionBuilder.root.withDescriptionAndRepresentation(EXPECT, "subject")
.withAssertions(
descriptive.failing.withDescriptionAndRepresentation(TO_BE, "bli").build(),
descriptive.failing.withDescriptionAndRepresentation(NOT_TO_BE, "bye").build()
)
.build()
}
expect(mapOf("1" to 2).entries)
facade.format(assertionGroup, sb, alwaysTrueAssertionFilter)
expect(sb.toString()).toBe(
"${EXPECT.getDefault()}: subject$lineSeparator" +
"$squarePoint $toBeDescr: bli$lineSeparator" +
"$squarePoint ${NOT_TO_BE.getDefault()}: bye"
)
}
}
}
}) {
object AtriumsTextFallbackAssertionFormatterSpec :
ch.tutteli.atrium.specs.reporting.TextFallbackAssertionFormatterSpec(
factory(), "[Atrium's TextFallback..Spec] "
)
object AtriumsAssertionFormatterSpec : ch.tutteli.atrium.specs.reporting.AssertionFormatterSpec(
factory(), "[Atrium's AssertionFormatterSpec] "
)
companion object {
internal fun factory() =
{ bulletPoints: Map<KClass<out BulletPointIdentifier>, String>, assertionFormatterController: AssertionFormatterController, objectFormatter: ObjectFormatter, translator: Translator ->
TextFallbackAssertionFormatter(
bulletPoints,
assertionFormatterController,
TextSameLineAssertionPairFormatter(objectFormatter, translator),
objectFormatter
)
}
}
}

View File

@@ -1,8 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
object TextMethodCallFormatterSpec : ch.tutteli.atrium.specs.reporting.TextMethodCallFormatterSpec(
{ TextMethodCallFormatter }
)

View File

@@ -1,77 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.api.fluent.en_GB.toBe
import ch.tutteli.atrium.api.verbs.internal.expect
import ch.tutteli.atrium.assertions.builders.assertionBuilder
import ch.tutteli.atrium.assertions.builders.root
import ch.tutteli.atrium.reporting.Text
import ch.tutteli.atrium.reporting.translating.Untranslatable
import ch.tutteli.atrium.reporting.translating.UsingDefaultTranslator
import ch.tutteli.atrium.specs.describeFunTemplate
import ch.tutteli.atrium.specs.lineSeparator
import ch.tutteli.atrium.specs.reporting.AssertionFormatterSpecBase
import ch.tutteli.atrium.specs.reporting.ToStringObjectFormatter
import org.spekframework.spek2.style.specification.Suite
class TextNextLineAssertionPairFormatterSpec : AssertionFormatterSpecBase({
fun describeFun(vararg funName: String, body: Suite.() -> Unit) = describeFunTemplate("", funName, body = body)
val testee = TextNextLineAssertionPairFormatter(
ToStringObjectFormatter,
UsingDefaultTranslator()
)
val bulletPoint = "** "
val indentBulletPoint = " ".repeat(bulletPoint.length)
val name = "group name"
val subject = 123
describeFun(testee::formatGroupHeader.name) {
it("puts the representation on the next line indented as the bullet point used for newParameterObject") {
val newParameterObject = parameterObject.createChildWithNewPrefix(bulletPoint)
val assertionGroup = assertionBuilder.root
.withDescriptionAndRepresentation(name, subject)
.withAssertions(listOf())
.build()
testee.formatGroupHeader(parameterObject, assertionGroup, newParameterObject)
expect(sb.toString()).toBe("$name:$lineSeparator$indentBulletPoint$subject")
}
it("does not append a new line if the subject is ${Text::class.simpleName}${Text.Companion::EMPTY.name}") {
val assertionGroup = assertionBuilder.root
.withDescriptionAndEmptyRepresentation(name)
.withAssertions(listOf())
.build()
val newParameterObject = parameterObject.createChildWithNewPrefix(bulletPoint)
testee.formatGroupHeader(parameterObject, assertionGroup, newParameterObject)
expect(sb.toString()).toBe("$name:")
}
}
describeFun(testee::format.name) {
context("current indent 0, no prefix") {
it("puts the representation on the next line without indent") {
testee.format(parameterObject, Untranslatable(name), subject)
expect(sb.toString()).toBe("$name:$lineSeparator$subject")
}
}
context("current indent 2, new prefix length 2") {
it("puts the representation on the next line with 2 indent") {
val newParameterObject = parameterObject.createChildWithNewPrefix("==")
testee.format(newParameterObject, Untranslatable(name), subject)
expect(sb.toString()).toBe("$name:$lineSeparator $subject")
}
}
it("does not append a new line if the subject is ${Text::class.simpleName}${Text.Companion::EMPTY.name}") {
val newParameterObject = parameterObject.createChildWithNewPrefix(bulletPoint)
testee.format(newParameterObject, Untranslatable(name), Text.EMPTY)
expect(sb.toString()).toBe("$name:")
}
}
})

View File

@@ -1,67 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.assertions.BulletPointIdentifier
import ch.tutteli.atrium.assertions.DefaultSummaryAssertionGroupType
import ch.tutteli.atrium.assertions.SummaryAssertionGroupType
import ch.tutteli.atrium.reporting.AssertionFormatterController
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.spekframework.spek2.Spek
import kotlin.reflect.KClass
class TextSummaryAssertionGroupFormatterSpec : Spek({
include(AtriumsTextSummaryAssertionGroupFormatterSpec)
include(AtriumsSingleAssertionGroupTypeFormatterSpec)
include(AtriumsAssertionFormatterSpec)
}) {
object AtriumsTextSummaryAssertionGroupFormatterSpec :
ch.tutteli.atrium.specs.reporting.TextSummaryAssertionGroupFormatterSpec(
factoryWithoutObjectFormatter(), "[Atrium's SummaryGroup...Spec] "
)
object AtriumsSingleAssertionGroupTypeFormatterSpec :
ch.tutteli.atrium.specs.reporting.SingleAssertionGroupTypeFormatterSpec<SummaryAssertionGroupType>(
factory(),
SummaryAssertionGroupType::class,
DefaultSummaryAssertionGroupType,
object : SummaryAssertionGroupType {},
"[Atrium's SingleAssertionGroupType...Spec] "
)
object AtriumsAssertionFormatterSpec : ch.tutteli.atrium.specs.reporting.AssertionFormatterSpec(
factory(), "[Atrium's AssertionFormatterSpec] "
)
companion object {
private fun factoryWithoutObjectFormatter() =
{ bulletPoints: Map<KClass<out BulletPointIdentifier>, String>, controller: AssertionFormatterController ->
TextSummaryAssertionGroupFormatter(
bulletPoints,
controller,
TextSameLineAssertionPairFormatter(
ToStringObjectFormatter,
UsingDefaultTranslator()
)
)
}
private fun factory() =
{ bulletPoints: Map<KClass<out BulletPointIdentifier>, String>, controller: AssertionFormatterController, objectFormatter: ObjectFormatter, translator: Translator ->
TextSummaryAssertionGroupFormatter(
bulletPoints,
controller,
TextSameLineAssertionPairFormatter(
objectFormatter,
translator
)
)
}
}
}

View File

@@ -1,8 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting.translating
class LocaleOrderDeciderSpec : ch.tutteli.atrium.specs.reporting.translating.LocaleOrderDeciderSpec(
::CoroutineBasedLocaleOrderDecider
)

View File

@@ -1,22 +0,0 @@
description = 'Contains the bits and pieces behind robstoll\'s <rstoll@tutteli.ch> implementation ' +
'of Atrium for the JS platform. You should only depend on this module if you are ' +
'providing an implementation as well and want to reuse certain artifacts. If you are a consumer of ' +
'Atrium, then you should depend on atrium-core-robstoll instead.'
dependencies {
implementation "ch.tutteli.kbox:kbox-js:$kbox_version", excludeKotlin
api prefixedProject('core-api-js')
// it is up to the consumer of atrium-core-robstoll-lib which atrium-translations module is used at runtime
compileOnly prefixedProject('translations-en_GB-js')
testImplementation prefixedProject('api-fluent-en_GB-js')
testImplementation prefixedProject('specs-js')
}
//TODO 0.17.0 or 0.18.0 should not be necessary https://youtrack.jetbrains.com/issue/KT-27797
compileTestKotlin2Js.dependsOn(
prefixedProject('core-robstoll-js').jar,
prefixedProject('domain-robstoll-js').jar,
prefixedProject('domain-builders-js').jar
)

View File

@@ -1,47 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.reporting.ObjectFormatter
import ch.tutteli.atrium.reporting.translating.Translator
import kotlin.reflect.KClass
external class WeakMap {
fun set(k: dynamic, v: String)
fun get(k: dynamic): String?
}
private val pseudoIdentityHash = WeakMap()
private val primitiveIdentityHash = hashMapOf<Any, String?>()
private var count = 0
actual class DetailedObjectFormatter actual constructor(
translator: Translator
) : DetailedObjectFormatterCommon(translator), ObjectFormatter {
override fun format(kClass: KClass<*>): String {
return "${kClass.simpleName} (${kClass.js.name})"
}
override fun identityHash(indent: String, any: Any): String {
val current = getHash(any)
val hash = if (current != null) {
current
} else {
val newHash = (++count).toString()
setHash(any, newHash)
newHash
}
return "$indent<$hash>"
}
private fun getHash(any: Any): String? =
if (jsTypeOf(any) == "object") pseudoIdentityHash.get(any)
else primitiveIdentityHash[any]
private fun setHash(any: Any, newHash: String) {
if (jsTypeOf(any) == "object") pseudoIdentityHash.set(any, newHash)
else primitiveIdentityHash[any] = newHash
}
}

View File

@@ -1,26 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.core.polyfills.stackBacktrace
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
@Deprecated(
"Use FilterAtriumErrorAdjuster from atrium-core, will be removed with 0.17.0",
ReplaceWith("ch.tutteli.atrium.reporting.erroradjusters.FilterAtriumErrorAdjuster")
)
abstract class FilterAtriumErrorAdjuster : AtriumErrorAdjuster {
final override fun adjust(throwable: Throwable) {
val filteredStack = adjustStack(throwable.stackBacktrace.asSequence())
val prefix = " at "
throwable.asDynamic().stack = filteredStack.joinToString("\n$prefix", prefix)
throwable.cause?.let { adjust(it) }
}
/**
* Does nothing (no adjustments) - override in subclass if you want a different behaviour.
*/
override fun adjustOtherThanStacks(throwable: Throwable) {}
}

View File

@@ -1,26 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
@Deprecated(
"Use MultiAtriumErrorAdjuster from atrium-core, will be removed with 0.17.0",
ReplaceWith("ch.tutteli.atrium.reporting.erroradjusters.MultiAtriumErrorAdjuster")
)
actual class MultiAtriumErrorAdjusterImpl actual constructor(
private val firstAdjuster: AtriumErrorAdjuster,
private val secondAdjuster: AtriumErrorAdjuster,
private val otherAdjusters: List<AtriumErrorAdjuster>
) : FilterAtriumErrorAdjuster(), AtriumErrorAdjuster {
override fun adjustStack(stackTrace: Sequence<String>): Sequence<String> =
firstAdjuster.adjustStack(stackTrace)
.let { secondAdjuster.adjustStack(it) }
.let {
otherAdjusters.fold(it) { filteredStack, adjuster ->
adjuster.adjustStack(filteredStack)
}
}
}

View File

@@ -1,14 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
@Deprecated(
"Use NoOpAtriumErrorAdjuster from atrium-core, will be removed with 0.17.0",
ReplaceWith("ch.tutteli.atrium.reporting.erroradjusters.NoOpAtriumErrorAdjuster")
)
actual object NoOpAtriumErrorAdjuster : NoOpAtriumErrorAdjusterCommon(), AtriumErrorAdjuster {
override fun adjustStack(stackTrace: Sequence<String>): Sequence<String> = stackTrace
}

View File

@@ -1,20 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
@Deprecated(
"Use RemoveAtriumFromAtriumErrorAdjuster from atrium-core, will be removed with 0.17.0",
ReplaceWith("ch.tutteli.atrium.reporting.erroradjusters.impl.RemoveAtriumFromAtriumErrorAdjuster")
)
actual class RemoveAtriumFromAtriumErrorAdjuster : FilterAtriumErrorAdjuster(), AtriumErrorAdjuster {
override fun adjustStack(stackTrace: Sequence<String>): Sequence<String> = stackTrace.filter {
!atriumRegex.containsMatchIn(it)
}
companion object {
val atriumRegex = Regex("[\\\\|/]atrium-[a-zA-Z-]+.js")
}
}

View File

@@ -1,20 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
@Deprecated(
"Use RemoveRunnerAtriumErrorAdjuster from atrium-core, will be removed with 0.17.0",
ReplaceWith("ch.tutteli.atrium.reporting.erroradjusters.impl.RemoveRunnerAtriumErrorAdjuster")
)
actual class RemoveRunnerAtriumErrorAdjuster : FilterAtriumErrorAdjuster(), AtriumErrorAdjuster {
override fun adjustStack(stackTrace: Sequence<String>): Sequence<String> = stackTrace.takeWhile {
!runnerRegex.containsMatchIn(it)
}
companion object {
val runnerRegex: Regex = Regex("[\\\\|/]node_modules[\\\\|/](mocha|jasmine)[\\\\|/]")
}
}

View File

@@ -1,98 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.api.fluent.en_GB.*
import ch.tutteli.atrium.api.verbs.internal.AssertionVerb
import ch.tutteli.atrium.api.verbs.internal.expect
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
import ch.tutteli.atrium.core.coreFactory
import ch.tutteli.atrium.core.polyfills.stackBacktrace
import ch.tutteli.atrium.creating.ExperimentalComponentFactoryContainer
import ch.tutteli.atrium.logic.creating.RootExpectBuilder
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
import ch.tutteli.atrium.reporting.Reporter
import ch.tutteli.atrium.reporting.reporter
import kotlin.test.Test
@Deprecated("will be removed with 0.17.0")
class AdjustStackTest {
@Test
fun noOp_containsMochaAndAtrium() {
expect {
assertNoOp(1).toBe(2)
}.toThrow<AssertionError> {
feature(AssertionError::stackBacktrace).contains(
{ contains("mocha") },
{ contains("atrium-core-api-js.js") }
)
}
}
@Test
fun removeRunner_containsAtriumButNotMocha() {
expect {
assertRemoveRunner(1).toBe(2)
}.toThrow<AssertionError> {
feature(AssertionError::stackBacktrace)
.containsNot.entry { contains("mocha") }
.contains { contains("atrium-core-api-js.js") }
}
}
@Test
fun removeRunner_containsAtriumButNotMochaInCause() {
val adjuster = coreFactory.newRemoveRunnerAtriumErrorAdjuster()
val throwable = IllegalArgumentException("hello", UnsupportedOperationException("world"))
adjuster.adjust(throwable)
expect(throwable.cause!!.stackBacktrace)
.containsNot.entry { contains("mocha") }
.contains { contains("atrium-core-robstoll-lib-js") }
}
@Test
fun removeAtrium_containsMochaButNotAtrium() {
expect {
assertRemoveAtrium(1).toBe(2)
}.toThrow<AssertionError> {
feature(AssertionError::stackBacktrace)
.contains { contains("mocha") }
.containsNot.entry { contains("atrium-core-api-js.js") }
}
}
@Test
fun removeAtrium_containsMochaButNotAtriumInCause() {
val adjuster = coreFactory.newRemoveAtriumFromAtriumErrorAdjuster()
val throwable = IllegalArgumentException("hello", UnsupportedOperationException("world"))
adjuster.adjust(throwable)
expect(throwable.cause!!.stackBacktrace)
.contains { contains("mocha") }
.containsNot.entry { contains("atrium-core-robstoll-lib-js") }
}
private fun <T : Any> assertNoOp(subject: T) = createExpect(
subject, coreFactory.newNoOpAtriumErrorAdjuster()
)
private fun <T : Any> assertRemoveRunner(subject: T) = createExpect(
subject, coreFactory.newRemoveRunnerAtriumErrorAdjuster()
)
private fun <T : Any> assertRemoveAtrium(subject: T) = createExpect(
subject, coreFactory.newRemoveAtriumFromAtriumErrorAdjuster()
)
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
@UseExperimental(ExperimentalNewExpectTypes::class, ExperimentalComponentFactoryContainer::class)
private fun <T : Any> createExpect(subject: T, adjuster: AtriumErrorAdjuster) =
RootExpectBuilder.forSubject(subject)
.withVerb(AssertionVerb.EXPECT)
.withOptions {
withComponent(AtriumErrorAdjuster::class) { _ -> adjuster }
withComponent(Reporter::class) { _ -> DelegatingReporter(reporter, adjuster) }
}
.build()
}

View File

@@ -1,12 +0,0 @@
//TODO remove file with 1.0.0
@file:Suppress("DEPRECATION")
import ch.tutteli.atrium.core.robstoll.dependOn_atrium_core_robstoll
import ch.tutteli.atrium.domain.builders.dependOn_domain_builders
import ch.tutteli.atrium.domain.robstoll.dependOn_atrium_domain_robstoll
private val currentSetupWorkaround = dep()
private fun dep() {
dependOn_atrium_domain_robstoll()
dependOn_atrium_core_robstoll()
dependOn_domain_builders()
}

View File

@@ -1,22 +0,0 @@
description = 'Contains the bits and pieces behind robstoll\'s <rstoll@tutteli.ch> implementation ' +
'of Atrium for the JVM platform. You should only depend on this module if you are ' +
'providing an implementation as well and want to reuse certain artifacts. If you are a consumer of ' +
'Atrium, then you should depend on atrium-core-robstoll instead.'
dependencies {
api prefixedProject('core-api-jvm')
// it is up to the consumer of atrium-core-robstoll-lib which atrium-translations module is used at runtime
compileOnly prefixedProject('translations-en_GB-jvm')
testImplementation prefixedProject('api-fluent-en_GB-jvm')
testImplementation prefixedProject('specs-jvm')
}
//TODO 0.17.0 or 0.18.0 should not be necessary https://youtrack.jetbrains.com/issue/KT-28124
compileTestKotlin.dependsOn(
prefixedProject('core-robstoll-jvm').compileKotlin,
prefixedProject('core-robstoll-jvm').processResources,
prefixedProject('domain-robstoll-jvm').compileKotlin,
prefixedProject('domain-robstoll-jvm').processResources
)

View File

@@ -1,80 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress(
// TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed
"JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE", "DEPRECATION"
)
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.reporting.*
import ch.tutteli.atrium.reporting.translating.Translatable
import ch.tutteli.atrium.reporting.translating.Translator
import kotlin.reflect.KClass
@Deprecated("Use the implementation of atrium-core; will be removed with 0.17.0")
abstract class AbstractDetailedObjectFormatter(
private val translator: Translator
) : DetailedObjectFormatterCommon(translator) {
/**
* Returns a formatted version of the given [value].
*
* The following rules apply for the representation of an object:
* - `null` is represented as [Text.NULL].[Text.string]
* - [LazyRepresentation] is [evaluated][LazyRepresentation.eval] and then again [format]ted
* - [Char] is put in apostrophes
* - [Boolean] is represented with its [toString] representation
* - [String] is put in quotes and its [Class.getName] is omitted
* - [CharSequence] is put in quotes, but [KClass.qualifiedName] is used in contrast to [String]
* - [Text] is represented as [Text.string]
* - [Translatable] is represented as result of its translation (by [translator])
* - [Class] is represented as "[Class.getSimpleName] ([Class.getName])"
* - [KClass] is represented as "[KClass.simpleName] ([KClass.qualifiedName])" unless the [KClass.qualifiedName]
* differs from [Class.getName] in which case, "-- Class: [Class.getName]" is appended in addition
* - [Enum] is represented as "[toString] ([Class.getName])
* - [Throwable] is represented as "[Class.getName]"
* - All other objects are represented as "[toString] ([Class.getName] <[System.identityHashCode]>)"
*
* @param value The value which shall be formatted.
*
* @return The formatted [value].
*/
final override fun format(value: Any?): String = when (value) {
is Class<*> -> format(value)
else -> super.format(value)
}
private fun format(clazz: Class<*>) = "${clazz.simpleName} (${clazz.name})"
final override fun format(kClass: KClass<*>): String {
val kotlinClass = "${kClass.simpleName} (${kClass.qualifiedName})"
return when {
kClass.qualifiedName == kClass.java.name -> kotlinClass
kClass.java.isPrimitive -> "$kotlinClass -- Class: ${kClass.java.simpleName}"
else -> "$kotlinClass -- Class: ${kClass.java.name}"
}
}
override fun identityHash(indent: String, any: Any): String = "$indent<${System.identityHashCode(any)}>"
}
/**
* Formats an object by using its [toString] representation, its [Class.getName] and its [System.identityHashCode]
* (in most cases).
*
* Some objects are treated differently, refer to [format] for details.
*
* The aim of representing more information than just [toString] is to avoid situations where an assert may fail
* and [toString] does not distinguish two compared objects.
* Consider the following error message "error, assert: 1 to be 1" would not be very helpful.
* "error, assert: 1 (Int <123>) to be 1 (Double <456>)" on the other hand is helpful.
*
* @property translator The [Translator] used to translate [Translatable]s.
*
* @constructor Formats an object by using its [toString] representation, its [Class.getName] and its [System.identityHashCode]
* (in most cases).
* @param translator The [Translator] used to translate [Translatable]s.
*/
@Deprecated("Use the implementation of atrium-core; will be removed with 0.17.0")
actual class DetailedObjectFormatter actual constructor(
private val translator: Translator
) : AbstractDetailedObjectFormatter(translator), ObjectFormatter

View File

@@ -1,27 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
@Deprecated(
"Use FilterAtriumErrorAdjuster from atrium-core, will be removed with 0.17.0",
ReplaceWith("ch.tutteli.atrium.reporting.erroradjusters.FilterAtriumErrorAdjuster")
)
abstract class FilterAtriumErrorAdjuster : AtriumErrorAdjuster {
final override fun adjust(throwable: Throwable) {
val filteredStackTrace = adjustStackTrace(throwable.stackTrace.asSequence())
val arr = filteredStackTrace.toList().toTypedArray()
throwable.stackTrace = arr
throwable.cause?.let { adjust(it) }
throwable.suppressed.forEach { adjust(it) }
adjustOtherThanStacks(throwable)
}
/**
* Does nothing (no adjustments) - override in subclass if you want a different behaviour.
*/
override fun adjustOtherThanStacks(throwable: Throwable) {}
}

View File

@@ -1,26 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
@Deprecated(
"Use MultiAtriumErrorAdjuster from atrium-core, will be removed with 0.17.0",
ReplaceWith("ch.tutteli.atrium.reporting.erroradjusters.MultiAtriumErrorAdjuster")
)
actual class MultiAtriumErrorAdjusterImpl actual constructor(
private val firstAdjuster: AtriumErrorAdjuster,
private val secondAdjuster: AtriumErrorAdjuster,
private val otherAdjusters: List<AtriumErrorAdjuster>
) : FilterAtriumErrorAdjuster(), AtriumErrorAdjuster {
override fun adjustStackTrace(stackTrace: Sequence<StackTraceElement>): Sequence<StackTraceElement> =
firstAdjuster.adjustStackTrace(stackTrace)
.let { secondAdjuster.adjustStackTrace(it) }
.let {
otherAdjusters.fold(it) { filteredStack, adjuster ->
adjuster.adjustStackTrace(filteredStack)
}
}
}

View File

@@ -1,17 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION",
// TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed
"JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE"
)
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
@Deprecated(
"Use NoOpAtriumErrorAdjuster from atrium-core, will be removed with 0.17.0",
ReplaceWith("ch.tutteli.atrium.reporting.erroradjusters.NoOpAtriumErrorAdjuster")
)
actual object NoOpAtriumErrorAdjuster : NoOpAtriumErrorAdjusterCommon(), AtriumErrorAdjuster {
override fun adjustStackTrace(stackTrace: Sequence<StackTraceElement>): Sequence<StackTraceElement> = stackTrace
}

View File

@@ -1,16 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
@Deprecated(
"Use RemoveAtriumFromAtriumErrorAdjuster from atrium-core, will be removed with 0.17.0",
ReplaceWith("ch.tutteli.atrium.reporting.erroradjusters.impl.RemoveAtriumFromAtriumErrorAdjuster")
)
actual class RemoveAtriumFromAtriumErrorAdjuster : FilterAtriumErrorAdjuster(), AtriumErrorAdjuster {
override fun adjustStackTrace(stackTrace: Sequence<StackTraceElement>): Sequence<StackTraceElement> =
stackTrace.filter { !it.className.startsWith("ch.tutteli.atrium") }
}

View File

@@ -1,21 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
@Deprecated(
"Use RemoveRunnerAtriumErrorAdjuster from atrium-core, will be removed with 0.17.0",
ReplaceWith("ch.tutteli.atrium.reporting.erroradjusters.impl.RemoveRunnerAtriumErrorAdjuster")
)
actual class RemoveRunnerAtriumErrorAdjuster : FilterAtriumErrorAdjuster(), AtriumErrorAdjuster {
override fun adjustStackTrace(stackTrace: Sequence<StackTraceElement>): Sequence<StackTraceElement> =
stackTrace.takeWhile {
!it.className.startsWith("org.junit") &&
!it.className.startsWith("org.jetbrains.spek") &&
!it.className.startsWith("org.spekframework.spek2") &&
!it.className.startsWith("io.kotlintest")
}
}

View File

@@ -1,96 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress(
// TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed
"JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE", "DEPRECATION"
)
package ch.tutteli.atrium.core.robstoll.lib.reporting.translating
import ch.tutteli.atrium.reporting.translating.Locale
import ch.tutteli.atrium.reporting.translating.Translatable
import ch.tutteli.atrium.reporting.translating.TranslationSupplier
import java.util.*
import java.util.concurrent.ConcurrentHashMap
/**
* A base class for properties based [TranslationSupplier]s which provides a loading
* and caching mechanism of properties files.
*
* There is no way to purge the cache. This class is intended for a one run process where
* translations do not change in between.
*
* @param T Translations are grouped by a certain aspect (for instance, by [Locale]). [T] defines the type of it.
*/
@Deprecated("Use the implementation of atrium-core; will be removed with 0.17.0")
abstract class PropertiesBasedTranslationSupplier<in T> : TranslationSupplier {
/**
* The cached translations.
*/
private val translations = ConcurrentHashMap<T, Map<String, String>>()
/**
* Gets the cached [Properties] content as [Map] for the given [key] or
* loads the properties file with the given [fileName] and creates a map out of it using the given [keyCreator]
* function to create the keys of the map, based on a key of a property.
*
* @param key The key which identifies the [Properties]
* @param fileName The fileName of the properties file without file extension, including the package in which it resides
* as absolute path (no '../' are allowed). In case it does not start with '/' (which would be a
* relative path), then a '/' is prepended. Hence it is always searched with an
* absolute path -- which is the same behaviour as for a properties based [ResourceBundle].
* @param keyCreator The function used to create keys of the resulting [Map] (in case the properties file needs
* to be loaded). It is called passing in a key of a property of the properties file.
*
* @return A [Map] containing the resulting keys (based on the [Properties], see [keyCreator]) with its translations.
*/
protected fun getOrLoadProperties(key: T, fileName: String, keyCreator: (String) -> String): Map<String, String> {
require(!fileName.contains("../")) {
"only paths without any '../' are allowed"
}
return this.translations.getOrPut(key) {
val absoluteFileName = if (fileName.startsWith('/')) fileName else "/$fileName"
val file = this::class.java.getResourceAsStream("$absoluteFileName.properties")
if (file != null) {
val properties = Properties()
file.use {
properties.load(it)
}
properties.stringPropertyNames().associate {
keyCreator(it) to properties.getProperty(it)
}
} else {
emptyMap()
}
}
}
/**
* Returns the name of the properties file without extension -- including the package (as prefixed relative path)
* in which it resides if necessary -- in which we expect to find a translation in the given [locale] for
* [baseName].
*
* The implementation is based on [ResourceBundle.Control.toBundleName].
* @param baseName Usually the [Translatable] or another identifier for which we are searching translations. Has to
* contain the package name as well if necessary ('.' will be replaced with '/').
* @param locale The [Locale] for which we are searching a translation.
*
* @return The name of the properties file.
*/
protected fun getFileNameFor(baseName: String, locale: Locale): String {
val sb = StringBuilder(baseName)
//using _ as separator to be compatible with ResourceBundle
.append('_').append(locale.language)
if (locale.script != null) {
sb.append('_').append(locale.script)
}
if (locale.country != null) {
sb.append('_').append(locale.country)
}
if (locale.variant != null) {
sb.append('_').append(locale.variant)
}
return sb.toString().replace('.', '/')
}
}

View File

@@ -1,38 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress(
// TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed
"JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE", "DEPRECATION"
)
package ch.tutteli.atrium.core.robstoll.lib.reporting.translating
import ch.tutteli.atrium.core.polyfills.fullName
import ch.tutteli.atrium.reporting.translating.Locale
import ch.tutteli.atrium.reporting.translating.Translatable
import ch.tutteli.atrium.reporting.translating.TranslationSupplier
import java.util.*
/**
* Represents a [TranslationSupplier] which is based on properties-files which are structured per
* entity (enum, object or class) and [Locale].
*
* For instance, the translations for `ch.tutteli.atrium.DescriptionAnyAssertion` and the [Locale] `de_CH` are
* stored in a properties file named `DescriptionAnyAssertion_de_CH.properties` in the folder `/ch/tutteli/atrium/`
* (compatible with the behaviour of [ResourceBundle] - thus properties files should also use ISO-8859-1 as encoding).
*
* An entry in such a file would look like as follows:
* `TO_BE = a translation for TO_BE`
*/
@Deprecated("Use the implementation of atrium-core; will be removed with 0.17.0")
class PropertiesPerEntityAndLocaleTranslationSupplier : PropertiesBasedTranslationSupplier<String>() {
override fun get(translatable: Translatable, locale: Locale): String? {
val qualifiedName = translatable::class.java.name
val fileName = getFileNameFor(qualifiedName, locale)
val fullName = translatable::class.fullName(translatable)
val translations = getOrLoadProperties(fileName, fileName, keyCreator = {
fullName + Translatable.ID_SEPARATOR + it
})
return translations[translatable.id]
}
}

View File

@@ -1,33 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress(
// TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed
"JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE", "DEPRECATION"
)
package ch.tutteli.atrium.core.robstoll.lib.reporting.translating
import ch.tutteli.atrium.reporting.translating.Locale
import ch.tutteli.atrium.reporting.translating.Translatable
import ch.tutteli.atrium.reporting.translating.TranslationSupplier
/**
* Represents a [TranslationSupplier] which is based on properties-files which are structured per [Locale].
*
* For instance, the translations for `ch.tutteli.atrium.DescriptionAnyAssertion` and the [Locale] `de_CH` are
* stored in a properties file named `Atrium_de_CH.properties` in the folder `/ch/tutteli/atrium/reporting/translating`.
*
* For instance, the translations for the [Locale] `de_CH` are stored in a properties file named .
*
* An entry in such a file would look like the following:
* `ch.tutteli.atrium.DescriptionAnyAssertion-TO_BE = a translation for TO_BE`
*/
@Deprecated("Use the implementation of atrium-core; will be removed with 0.17.0")
class PropertiesPerLocaleTranslationSupplier : PropertiesBasedTranslationSupplier<Locale>() {
override fun get(translatable: Translatable, locale: Locale): String? {
val fileName = getFileNameFor(this::class.java.`package`.name + ".Atrium", locale)
val translations = getOrLoadProperties(locale, fileName, keyCreator = { it })
return translations[translatable.id]
}
}

View File

@@ -1,73 +0,0 @@
//TODO remove file with 0.17.0
@file:Suppress(
// TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed
"JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE", "DEPRECATION"
)
package ch.tutteli.atrium.core.robstoll.lib.reporting.translating
import ch.tutteli.atrium.reporting.translating.*
import ch.tutteli.atrium.reporting.translating.Locale
import ch.tutteli.kbox.forElementAndForEachIn
import java.util.*
/**
* Represents a [Translator] which reuses [ResourceBundle] properties based capabilities but uses an enhanced
* fallback mechanism.
*
* Instead of falling back to [java.util.Locale.getDefault] one is able to specify fallback [Locale] oneself.
* Whether this includes [java.util.Locale.getDefault] or not is up to the user.
*
* The translations are located in properties files structured per entity (enum, object or class).
* For instance, the translations for `ch.tutteli.atrium.DescriptionAnyAssertion` and the [Locale] `de_CH` are
* stored in a properties file named `DescriptionAnyAssertion_de_CH.properties` in the folder `/ch/tutteli/atrium/`.
*
* An entry in such a file would look like as follows:
* `TO_BE = a translation for TO_BE`
*
* This class is only used as reference implementation to see that compatibility with ResourceBundle is still given.
*
* @constructor Represents a [Translator] which reuses [ResourceBundle] properties based capabilities but uses
* an enhanced fallback mechanism. Instead of falling back to [java.util.Locale.getDefault] one is able to
* specify fallback [Locale] oneself. Whether this includes [java.util.Locale.getDefault] or not is up to the user.
* @param primaryLocale The [Locale] to which the translator translates per default as well as the [Locale]
* which will be used in [java.lang.String.format], which in turn is used to substitute the placeholders in the
* resulting translation of [TranslatableWithArgs.translatable] with the [TranslatableWithArgs.arguments].
* @param fallbackLocales Used in case a translation for a given [Translatable] is not defined for
* [primaryLocale] or one of its secondary alternatives -- the fallback [Locale]s are used in the given order.
*/
@Deprecated("Will be removed with 0.17.0")
internal class ResourceBundleBasedTranslator(
primaryLocale: Locale,
fallbackLocales: List<Locale>
) : ArgumentsSupportingTranslator(primaryLocale, fallbackLocales) {
override fun translateWithoutArgs(translatable: Translatable): String {
val control = ResourceBundle.Control.getNoFallbackControl(ResourceBundle.Control.FORMAT_PROPERTIES)
forElementAndForEachIn(primaryLocale, fallbackLocales) { locale ->
try {
val bundle = ResourceBundle.getBundle(translatable::class.java.name, locale.toJavaLocale(), control)
return bundle.getString(translatable.name)
} catch (ex: MissingResourceException) {
//that's fine we'll return getDefault below if no translation was found
}
}
return translatable.getDefault()
}
companion object {
/**
* Creates a [ResourceBundleBasedTranslator] and aggregates it with a [ResourceBundle.Control] which either
* makes use of the given [fallbackLocales] if provided or uses only the given [primaryLocale].
*
* @param primaryLocale The primary [Locale] which will be used in [java.lang.String.format] to substitute the
* placeholders in the resulting translation of [TranslatableWithArgs.translatable] with
* the [TranslatableWithArgs.arguments].
* @param fallbackLocales Used in case a translation for a given [Translatable] is not defined for
* [primaryLocale] or one of its secondary alternatives -- the [fallbackLocales] are used in the
* given order.
*/
fun create(primaryLocale: Locale, vararg fallbackLocales: Locale) =
ResourceBundleBasedTranslator(primaryLocale, fallbackLocales.toList())
}
}

View File

@@ -1,9 +0,0 @@
module ch.tutteli.atrium.core.robstoll.lib {
requires ch.tutteli.atrium.core.api;
requires ch.tutteli.kbox;
requires static ch.tutteli.atrium.translations.en_GB;
requires kotlin.stdlib;
exports ch.tutteli.atrium.core.robstoll.lib.reporting;
exports ch.tutteli.atrium.core.robstoll.lib.reporting.translating;
}

View File

@@ -1,195 +0,0 @@
//TODO remove with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.api.fluent.en_GB.*
import ch.tutteli.atrium.api.verbs.internal.AssertionVerb
import ch.tutteli.atrium.api.verbs.internal.expect
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
import ch.tutteli.atrium.core.coreFactory
import ch.tutteli.atrium.core.polyfills.stackBacktrace
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.creating.ExperimentalComponentFactoryContainer
import ch.tutteli.atrium.logic.creating.RootExpectBuilder
import ch.tutteli.atrium.logic.creating.RootExpectOptions
import ch.tutteli.atrium.logic.utils.expectLambda
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
import ch.tutteli.atrium.reporting.Reporter
import ch.tutteli.atrium.reporting.reporter
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
class AdjustStackSpec : Spek({
describe("no-op adjuster") {
fun <T : Any> assertNoOp(subject: T) = createExpect(
subject, coreFactory.newNoOpAtriumErrorAdjuster()
)
it("contains spek, junit, atrium.creating and atrium.reporting") {
expect {
assertNoOp(1).toBe(2)
}.toThrow<AssertionError> {
feature { f(it::stackBacktrace) }.contains(
{ startsWith("org.spekframework.spek2") },
{ startsWith("ch.tutteli.atrium.creating") },
{ startsWith("ch.tutteli.atrium.reporting") }
)
}
}
}
fun mapStartsWith(list: List<String>): Pair<Expect<String>.() -> Unit, Array<out Expect<String>.() -> Unit>> {
val asserts = list.map { c -> expectLambda<String> { startsWith(c) } }
return asserts.first() to asserts.drop(1).toTypedArray()
}
mapOf(
"remove test runner adjuster" to Triple(
coreFactory.newRemoveRunnerAtriumErrorAdjuster(),
listOf("org.spekframework.spek2", "kotlin.coroutines", "kotlinx.coroutines"),
listOf("ch.tutteli.atrium")
),
"remove atrium adjuster" to Triple(
coreFactory.newRemoveAtriumFromAtriumErrorAdjuster(),
listOf("ch.tutteli.atrium"),
listOf("org.spekframework.spek2")
)
).forEach { (description, triple) ->
val (adjuster, containsNot, contains) = triple
val (containsNotFirst, containsNotRest) = mapStartsWith(containsNot)
val (containsFirst, containsRest) = mapStartsWith(contains)
describe(description) {
it("does not contain $containsNot in stackBacktrace but $contains") {
expect {
createExpect(1, adjuster).toBe(2)
}.toThrow<AssertionError> {
feature { f(it::stackBacktrace) }
.containsNot.entries(containsNotFirst, *containsNotRest)
.contains(containsFirst, *containsRest)
}
}
it("does not contain $containsNot in stackBacktrace of cause, but $contains") {
val throwable = IllegalArgumentException("hello", UnsupportedOperationException("world"))
adjuster.adjust(throwable)
expect(throwable.cause!!.stackBacktrace)
.containsNot.entries(containsNotFirst, *containsNotRest)
.contains(containsFirst, *containsRest)
}
it("does not contain $containsNot in stackBacktrace of cause of cause, but $contains") {
val throwable = IllegalArgumentException(
"hello",
UnsupportedOperationException("world", IllegalStateException("and good night"))
)
adjuster.adjust(throwable)
expect(throwable.cause!!.cause!!.stackBacktrace)
.containsNot.entries(containsNotFirst, *containsNotRest)
.contains(containsFirst, *containsRest)
}
it("does not contain $containsNot in stackBacktrace of suppressed exception, but $contains") {
val throwable1 = IllegalArgumentException("hello", UnsupportedOperationException("world"))
val throwable2 = IllegalArgumentException("hello", UnsupportedOperationException("world"))
val throwable = IllegalStateException("with suppressed")
throwable.addSuppressed(throwable1)
throwable.addSuppressed(throwable2)
adjuster.adjust(throwable)
expect(throwable.suppressed).asList().all {
feature { f(it::stackBacktrace) }
.containsNot.entries(containsNotFirst, *containsNotRest)
.contains(containsFirst, *containsRest)
}
}
it("does not contain $containsNot in stackBacktrace of cause of suppressed exception, but $contains") {
val throwable1 = IllegalArgumentException("hello", UnsupportedOperationException("world"))
val throwable2 = IllegalArgumentException("hello", UnsupportedOperationException("world"))
val throwable = IllegalStateException("with suppressed")
throwable.addSuppressed(throwable1)
throwable.addSuppressed(throwable2)
adjuster.adjust(throwable)
expect(throwable.suppressed).asList().all {
cause<UnsupportedOperationException> {
feature { f(it::stackBacktrace) }
.containsNot.entries(containsNotFirst, *containsNotRest)
.contains(containsFirst, *containsRest)
}
}
}
}
}
mapOf(
"combine remove runner adjuster and remove atrium adjuster" to
coreFactory.newMultiAtriumErrorAdjuster(
coreFactory.newRemoveRunnerAtriumErrorAdjuster(),
coreFactory.newRemoveAtriumFromAtriumErrorAdjuster(),
listOf()
),
"combine remove atrium adjuster and remove runner adjuster" to
coreFactory.newMultiAtriumErrorAdjuster(
coreFactory.newRemoveAtriumFromAtriumErrorAdjuster(),
coreFactory.newRemoveRunnerAtriumErrorAdjuster(),
listOf()
),
"combine noop adjust, remove atrium adjuster and remove runner adjuster" to
coreFactory.newMultiAtriumErrorAdjuster(
coreFactory.newNoOpAtriumErrorAdjuster(),
coreFactory.newRemoveAtriumFromAtriumErrorAdjuster(),
listOf(coreFactory.newRemoveRunnerAtriumErrorAdjuster())
),
"combine remove atrium adjuster, remove runner adjuster and noop adjuster several times" to
coreFactory.newMultiAtriumErrorAdjuster(
coreFactory.newRemoveAtriumFromAtriumErrorAdjuster(),
coreFactory.newRemoveRunnerAtriumErrorAdjuster(),
listOf(
coreFactory.newNoOpAtriumErrorAdjuster(),
coreFactory.newRemoveRunnerAtriumErrorAdjuster(),
coreFactory.newNoOpAtriumErrorAdjuster()
)
)
).forEach { (description, adjuster) ->
describe(description) {
it("stackBacktrace is empty as we filter out everything") {
expect {
createExpect(1, adjuster).toBe(2)
}.toThrow<AssertionError> {
feature { f(it::stackBacktrace) }.isEmpty()
}
}
it("stackBacktrace of cause is empty as we filter out everything") {
val throwable = IllegalArgumentException("hello", UnsupportedOperationException("world"))
adjuster.adjust(throwable)
expect(throwable.cause!!.stackBacktrace).isEmpty()
}
it("stackBacktrace of suppressed is empty as we filter out everything") {
val throwable1 = IllegalArgumentException("hello", UnsupportedOperationException("world"))
val throwable2 = IllegalArgumentException("hello", UnsupportedOperationException("world"))
val throwable = IllegalStateException("with suppressed")
throwable.addSuppressed(throwable1)
throwable.addSuppressed(throwable2)
adjuster.adjust(throwable)
expect(throwable.suppressed).asList().all {
feature { f(it::stackBacktrace) }.isEmpty()
}
}
}
}
})
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
@UseExperimental(ExperimentalNewExpectTypes::class, ExperimentalComponentFactoryContainer::class)
private fun <T : Any> createExpect(subject: T, adjuster: AtriumErrorAdjuster) =
RootExpectBuilder.forSubject(subject)
.withVerb(AssertionVerb.EXPECT)
.withOptions {
withComponent(AtriumErrorAdjuster::class) { _ -> adjuster }
withComponent(Reporter::class) { _ -> DelegatingReporter(reporter, adjuster) }
}
.build()

View File

@@ -1,186 +0,0 @@
//TODO remove with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.api.fluent.en_GB.toBe
import ch.tutteli.atrium.api.verbs.internal.expect
import ch.tutteli.atrium.core.robstoll.lib.reporting.DetailedObjectFormatterCommon.Companion.INDENT
import ch.tutteli.atrium.reporting.translating.UsingDefaultTranslator
import ch.tutteli.atrium.specs.reporting.ObjectFormatterSpec
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
import kotlin.reflect.KClass
object DetailedObjectFormatterSpec : Spek({
include(AtriumsObjectFormatterSpec)
val testee = DetailedObjectFormatter(UsingDefaultTranslator())
describe("format") {
context("a ${Char::class.simpleName}") {
val result = testee.format('a')
it("returns the ${Char::class.simpleName} in apostrophes") {
expect(result).toBe("'a'")
}
}
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")
}
}
context("a ${String::class.simpleName}") {
it("returns two quotes including identity hash if empty ${String::class.simpleName}") {
val string = ""
val result = testee.format(string)
expect(result).toBe("\"\"" + INDENT + "<${System.identityHashCode(string)}>")
}
it("returns the ${String::class.simpleName} in quotes including identity hash") {
val string = "atrium"
val result = testee.format(string)
expect(result).toBe("\"$string\"" + INDENT + "<${System.identityHashCode(string)}>")
}
it("returns line breaks (does not escape") {
val string = "atrium\nAn assertion framework for Kotlin"
val result = testee.format(string)
expect(result).toBe("\"$string\"" + INDENT + "<${System.identityHashCode(string)}>")
}
}
val typeNameAndHash = "including type name and identity hash"
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)
expect(result).toBe(
"\"\"" + INDENT
+ "(${value::class.qualifiedName} <${System.identityHashCode(value)}>)"
)
}
it("returns ${CharSequence::class.simpleName} in quotes $typeNameAndHash") {
val value = StringBuilder("atrium")
val result = testee.format(value)
expect(result).toBe(
"\"$value\"" + INDENT
+ "(${value::class.qualifiedName} <${System.identityHashCode(value)}>)"
)
}
}
context("an enum") {
val enum = Color.Red
val result = testee.format(Color.Red)
it("returns its toString representation together with its Class.name but without System.identityHash") {
expect(result).toBe("Red" + INDENT + "(${enum::class.java.name})")
}
}
context("a Throwable") {
val result = testee.format(AssertionError("blablabla"))
it("returns only its Class.name") {
expect(result).toBe(AssertionError::class.java.name)
}
}
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
expect(result).toBe("${clazz.simpleName} (${clazz.name})")
}
}
context("on a ${KClass::class.simpleName}") {
context("java Class is the same (no special Kotlin class)") {
val result = testee.format(DetailedObjectFormatterSpec::class)
it("returns the simpleName and qualified in parenthesis") {
val clazz = DetailedObjectFormatterSpec::class
expect(result).toBe("${clazz.java.simpleName} (${clazz.java.name})")
expect(result).toBe("${clazz.simpleName} (${clazz.qualifiedName})")
}
}
context("a primitive Kotlin wrapper class (java Class is not the same)") {
val result = testee.format(Int::class)
it("returns the simpleName and qualified in parenthesis including java's simpleName") {
val clazz = Int::class
expect(result).toBe("${clazz.simpleName} (${clazz.qualifiedName}) -- Class: ${clazz.java.simpleName}")
}
}
context("a non primitive Kotlin class (java Class is not the same)") {
val result = testee.format(CharSequence::class)
it("returns the simpleName and qualified in parenthesis including java's name") {
val clazz = CharSequence::class
expect(result).toBe("${clazz.simpleName} (${clazz.qualifiedName}) -- Class: ${clazz.java.name}")
}
}
}
context("output type information") {
it("type information is still given in the output if no textual limiting occurs") {
val numbers = mutableListOf<Int>()
repeat(10) { numbers += it }
val result = testee.format(numbers)
val expected = "[${numbers.joinToString(", ")}]$INDENT(${numbers::class.qualifiedName} <${System.identityHashCode(numbers)}>)"
expect(result).toBe(expected)
}
it("type information is still given in the output if the textual representation is too long") {
val numbers = mutableListOf<Int>()
repeat(5000) { numbers += it }
val result = testee.format(numbers)
val expected =
"${numbers
.joinToString(prefix = "[", separator = ", ")
.substring(0, 10000)}...$INDENT(${numbers::class.qualifiedName} <${System.identityHashCode(numbers)}>)"
expect(result).toBe(expected)
}
}
mapOf(
java.lang.Byte::class.java.simpleName to 1.toByte(),
java.lang.Short::class.java.simpleName to 1.toShort(),
java.lang.Integer::class.java.simpleName to 1,
java.lang.Long::class.java.simpleName to 1L,
java.lang.Float::class.java.simpleName to 1.0f,
java.lang.Double::class.java.simpleName to 1.0
).forEach { (typeName, value) ->
context(typeName) {
val result = testee.format(value)
it("returns subject's toString() $typeNameAndHash") {
expect(result).toBe(
value.toString() + INDENT
+ "(${value::class.qualifiedName} <${System.identityHashCode(value)}>)"
)
}
}
}
context("an anonymous class") {
val anonymous = object : Any() {
override fun toString(): String = "anonymous type"
}
val result = testee.format(anonymous)
it("returns subject's toString() $typeNameAndHash") {
expect(result).toBe(
anonymous.toString() + INDENT
+ "(${anonymous::class.java.name} <${System.identityHashCode(anonymous)}>)"
)
}
}
}
}) {
object AtriumsObjectFormatterSpec : ObjectFormatterSpec(::DetailedObjectFormatter)
}
private enum class Color {
Red //, Blue, Green
}

View File

@@ -1,54 +0,0 @@
//TODO remove with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.assertions.BulletPointIdentifier
import ch.tutteli.atrium.assertions.DefaultFeatureAssertionGroupType
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.spekframework.spek2.Spek
import kotlin.reflect.KClass
class TextFeatureAssertionGroupFormatterSpec : Spek({
include(AtriumsTextFeatureAssertionGroupFormatterSpec)
include(AtriumsSingleAssertionGroupTypeFormatterSpec)
include(AtriumsAssertionFormatterSpec)
}) {
object AtriumsTextFeatureAssertionGroupFormatterSpec :
ch.tutteli.atrium.specs.reporting.TextFeatureAssertionGroupFormatterSpec(
factory(), "[Atrium's TextFeature...Spec] "
)
object AtriumsSingleAssertionGroupTypeFormatterSpec :
ch.tutteli.atrium.specs.reporting.SingleAssertionGroupTypeFormatterSpec<FeatureAssertionGroupType>(
factory(),
FeatureAssertionGroupType::class,
object : FeatureAssertionGroupType {},
DefaultFeatureAssertionGroupType,
"[Atrium's SingleAssertionGroupType...Spec] "
)
object AtriumsAssertionFormatterSpec : ch.tutteli.atrium.specs.reporting.AssertionFormatterSpec(
factory(), "[Atrium's AssertionFormatterSpec] "
)
companion object {
internal fun factory() =
{ bulletPoints: Map<KClass<out BulletPointIdentifier>, String>, controller: AssertionFormatterController, objectFormatter: ObjectFormatter, translator: Translator ->
TextFeatureAssertionGroupFormatter(
bulletPoints,
controller,
TextSameLineAssertionPairFormatter(
objectFormatter,
translator
)
)
}
}
}

View File

@@ -1,53 +0,0 @@
//TODO remove with 0.17.0
@file:Suppress("DEPRECATION")
package ch.tutteli.atrium.core.robstoll.lib.reporting
import ch.tutteli.atrium.assertions.BulletPointIdentifier
import ch.tutteli.atrium.assertions.DefaultListAssertionGroupType
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.spekframework.spek2.Spek
import kotlin.reflect.KClass
class TextListAssertionGroupFormatterSpec : Spek({
include(AtriumsTextListAssertionFormatterSpec)
include(AtriumsSingleAssertionGroupTypeFormatterSpec)
include(AtriumsAssertionFormatterSpec)
}) {
object AtriumsTextListAssertionFormatterSpec :
ch.tutteli.atrium.specs.reporting.TextListAssertionGroupFormatterSpec(
factoryWithBullet(), "[Atrium's TextList...Spec] "
)
object AtriumsSingleAssertionGroupTypeFormatterSpec :
ch.tutteli.atrium.specs.reporting.SingleAssertionGroupTypeFormatterSpec<ListAssertionGroupType>(
factoryWithBullet(),
ListAssertionGroupType::class,
object : ListAssertionGroupType {},
DefaultListAssertionGroupType,
"[Atrium's SingleAssertionGroupType...Spec] "
)
object AtriumsAssertionFormatterSpec : ch.tutteli.atrium.specs.reporting.AssertionFormatterSpec(
factoryWithBullet(), "[Atrium's AssertionFormatterSpec] "
)
companion object {
private fun factoryWithBullet() =
{ bulletPoints: Map<KClass<out BulletPointIdentifier>, String>, assertionFormatterController: AssertionFormatterController, objectFormatter: ObjectFormatter, translator: Translator ->
TextListAssertionGroupFormatter(
bulletPoints,
assertionFormatterController,
TextSameLineAssertionPairFormatter(
objectFormatter,
translator
)
)
}
}
}

Some files were not shown because too many files have changed in this diff Show More