mirror of
https://github.com/jlengrand/atrium.git
synced 2026-03-10 08:01:19 +00:00
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:
@@ -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`.
|
||||
|
||||
@@ -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`
|
||||
-> see [Iterable contains in any order](#iterable-contains-in-any-order) for more information
|
||||
|
||||
*atrium-api-fluent-en_GB*
|
||||
|
||||
@@ -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()
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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()
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
70
build.gradle
70
build.gradle
@@ -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) {
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
import ch.tutteli.atrium.fluent.en_GB.dependOnAtrium
|
||||
|
||||
@Suppress("unused")
|
||||
private val establishDependencyToAtrium = dependOnAtrium()
|
||||
@@ -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')
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
import ch.tutteli.atrium.infix.en_GB.dependOnAtrium
|
||||
|
||||
@Suppress("unused")
|
||||
private val establishDependencyToAtrium = dependOnAtrium()
|
||||
@@ -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')
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
/**
|
||||
|
||||
@@ -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}")
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
@@ -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() }
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
# TODO remove with 1.0.0
|
||||
ch.tutteli.atrium.core.polyfills.SingleService
|
||||
@@ -1,3 +0,0 @@
|
||||
# TODO remove with 1.0.0
|
||||
ch.tutteli.atrium.core.polyfills.Service1
|
||||
ch.tutteli.atrium.core.polyfills.Service2
|
||||
@@ -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
|
||||
|
||||
@@ -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!!
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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 = " "
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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) {}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
)
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 }
|
||||
)
|
||||
@@ -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:")
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -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
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
@@ -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
|
||||
)
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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) {}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
@@ -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)[\\\\|/]")
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
@@ -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
|
||||
@@ -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) {}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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") }
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
@@ -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('.', '/')
|
||||
}
|
||||
}
|
||||
@@ -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]
|
||||
}
|
||||
}
|
||||
@@ -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]
|
||||
}
|
||||
}
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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()
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
Reference in New Issue
Block a user