mirror of
https://github.com/jlengrand/atrium.git
synced 2026-03-10 08:01:19 +00:00
introduce ComponentFactoryContainer and AtriumErrorAdjusters in core
In order that one is able to exchange a component which is part of another component, we need to following to change: - introduce a ComponentFactoryContainer which stores all factories and provide a way to re-define factories - add val components to AssertionContainer which returns the specified ComponentFactoryContainer - remove withReporter from RootExpectBuilder.OptionsChooser and instead add a more generic withComponent (and withChainedComponent) - use AtriumErrorAdjustor not from Reporter (deprecated the property) but retrieve it from the ComponentFactoryContainer of the corresponding AssertionContainer moreover: - introduce @ExperimentalComponentFactoryContainer - deprecated the AtriumErrorAdjuster creating functions in CoreFactory - replace usages accordingly
This commit is contained in:
@@ -123,6 +123,6 @@ fun <T, R> FeatureExpect<T, R>.withOptions(configuration: FeatureExpectOptionsCh
|
||||
*/
|
||||
@ExperimentalWithOptions
|
||||
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class, ExperimentalComponentFactoryContainer::class)
|
||||
fun <T, R> FeatureExpect<T, R>.withOptions(options: FeatureExpectOptions<R>): Expect<R> =
|
||||
FeatureExpect(this, options)
|
||||
|
||||
@@ -118,6 +118,6 @@ infix fun <T, R> FeatureExpect<T, R>.withOptions(configuration: FeatureExpectOpt
|
||||
*/
|
||||
@ExperimentalWithOptions
|
||||
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class, ExperimentalComponentFactoryContainer::class)
|
||||
infix fun <T, R> FeatureExpect<T, R>.withOptions(options: FeatureExpectOptions<R>): Expect<R> =
|
||||
FeatureExpect(this, options)
|
||||
|
||||
@@ -316,6 +316,10 @@ interface CoreFactoryCommon {
|
||||
*
|
||||
* @return The newly created adjuster.
|
||||
*/
|
||||
@Deprecated(
|
||||
"Use NoOpAtriumErrorAdjuster instead; will be removed with 0.17.0",
|
||||
ReplaceWith("ch.tutteli.atrium.reporting.erroradjusters.NoOpAtriumErrorAdjuster")
|
||||
)
|
||||
fun newNoOpAtriumErrorAdjuster(): AtriumErrorAdjuster
|
||||
|
||||
/**
|
||||
@@ -323,6 +327,9 @@ interface CoreFactoryCommon {
|
||||
*
|
||||
* @return The newly created adjuster.
|
||||
*/
|
||||
@Deprecated(
|
||||
"Retrieve a RemoveRunnerAtriumErrorAdjuster from a ComponentContainer via getComponent; will be removed with 0.17.0"
|
||||
)
|
||||
fun newRemoveRunnerAtriumErrorAdjuster(): AtriumErrorAdjuster
|
||||
|
||||
/**
|
||||
@@ -330,6 +337,9 @@ interface CoreFactoryCommon {
|
||||
*
|
||||
* @return The newly created adjuster.
|
||||
*/
|
||||
@Deprecated(
|
||||
"Retrieve a RemoveAtriumFromAtriumErrorAdjuster from a ComponentContainer via getComponent; will be removed with 0.17.0"
|
||||
)
|
||||
fun newRemoveAtriumFromAtriumErrorAdjuster(): AtriumErrorAdjuster
|
||||
|
||||
/**
|
||||
@@ -342,6 +352,13 @@ interface CoreFactoryCommon {
|
||||
*
|
||||
* @return The newly created adjuster.
|
||||
*/
|
||||
@Deprecated(
|
||||
"Use MultiAtriumErrorAdjuster instead; will be removed with 0.17.0",
|
||||
ReplaceWith(
|
||||
"MultiAtriumErrorAdjuster(firstAdjuster, secondAdjuster, otherAdjusters)",
|
||||
"ch.tutteli.atrium.reporting.erroradjusters.MultiAtriumErrorAdjuster"
|
||||
)
|
||||
)
|
||||
fun newMultiAtriumErrorAdjuster(
|
||||
firstAdjuster: AtriumErrorAdjuster,
|
||||
secondAdjuster: AtriumErrorAdjuster,
|
||||
|
||||
@@ -17,6 +17,7 @@ import kotlin.reflect.KClass
|
||||
*
|
||||
* @param T The type of the subject of `this` expectation.
|
||||
*/
|
||||
//TODO 0.16.0 introduce ProofContainer
|
||||
interface AssertionContainer<T> : @kotlin.Suppress("DEPRECATION") SubjectProvider<T> {
|
||||
/**
|
||||
* Either [Some] wrapping the subject of an [Assertion] or [None] in case a previous subject transformation
|
||||
@@ -27,9 +28,16 @@ interface AssertionContainer<T> : @kotlin.Suppress("DEPRECATION") SubjectProvide
|
||||
/**
|
||||
* Do not use yet, this is experimental
|
||||
*/
|
||||
//TODO 0.16.0 replace by components
|
||||
@ExperimentalNewExpectTypes
|
||||
fun <I : Any> getImpl(kClass: KClass<I>, defaultFactory: () -> I): I
|
||||
|
||||
/**
|
||||
* Do not use yet, this is experimental
|
||||
*/
|
||||
@ExperimentalComponentFactoryContainer
|
||||
val components: ComponentFactoryContainer
|
||||
|
||||
// /**
|
||||
// * Appends the given [assertion] to this container and returns an [Expect] which includes it.
|
||||
// *
|
||||
|
||||
@@ -4,6 +4,7 @@ import ch.tutteli.atrium.assertions.Assertion
|
||||
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
|
||||
import ch.tutteli.atrium.core.Option
|
||||
import ch.tutteli.atrium.creating.impl.CollectingExpectImpl
|
||||
import ch.tutteli.atrium.creating.impl.DefaultComponentFactoryContainer
|
||||
|
||||
/**
|
||||
* Represents a container for [Assertion] which is intended to serve as receiver object for lambdas which create
|
||||
@@ -23,9 +24,21 @@ interface CollectingExpect<T> : Expect<T> {
|
||||
override fun addAssertionsCreatedBy(assertionCreator: Expect<T>.() -> Unit): CollectingExpect<T>
|
||||
|
||||
companion object {
|
||||
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class)
|
||||
@Suppress(
|
||||
"DEPRECATION",
|
||||
"DeprecatedCallableAddReplaceWith" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */
|
||||
)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class, ExperimentalComponentFactoryContainer::class)
|
||||
@Deprecated("Use the overload which expects a ComponentFactoryContainer; will be removed with 0.17.0")
|
||||
operator fun <T> invoke(maybeSubject: Option<T>): CollectingExpect<T> =
|
||||
CollectingExpectImpl(maybeSubject)
|
||||
CollectingExpectImpl(maybeSubject, DefaultComponentFactoryContainer)
|
||||
|
||||
@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)
|
||||
operator fun <T> invoke(
|
||||
maybeSubject: Option<T>,
|
||||
componentFactoryContainer: ComponentFactoryContainer
|
||||
): CollectingExpect<T> =
|
||||
CollectingExpectImpl(maybeSubject, componentFactoryContainer)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
package ch.tutteli.atrium.creating
|
||||
|
||||
import ch.tutteli.atrium.core.polyfills.cast
|
||||
import ch.tutteli.atrium.core.polyfills.fullName
|
||||
import ch.tutteli.atrium.creating.impl.ComponentFactoryContainerImpl
|
||||
import kotlin.reflect.KClass
|
||||
import ch.tutteli.atrium.reporting.Reporter
|
||||
|
||||
@Suppress("DEPRECATION" /* RequiresOptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@Experimental
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.LOCAL_VARIABLE)
|
||||
annotation class ExperimentalComponentFactoryContainer
|
||||
|
||||
@ExperimentalComponentFactoryContainer
|
||||
interface ComponentFactoryContainer {
|
||||
|
||||
/**
|
||||
* Returns the component of type [I] using a corresponding factory or `null` in case no factory was found
|
||||
* which is able to build a component of the given type.
|
||||
*
|
||||
* Delegates to [getFactoryOrNull] per default and applies a cast to the result (if not null)
|
||||
* to the specified [kClass].
|
||||
*
|
||||
* @throws ClassCastException in case
|
||||
*/
|
||||
fun <I : Any> buildOrNull(kClass: KClass<I>): I? =
|
||||
getFactoryOrNull(kClass)?.let { factory -> safeBuild(factory, kClass) }
|
||||
|
||||
/**
|
||||
* Returns a chain of components of type [I] using a corresponding factory or `null` in case no factory was found
|
||||
* which is able to build a chain of components of the given type.
|
||||
*
|
||||
* Delegates to [getFactoryForChainedOrNull] per default and applies a cast to the result (if not null)
|
||||
* to the specified [kClass].
|
||||
*/
|
||||
fun <I : Any> buildChainedOrNull(kClass: KClass<I>): Sequence<I>? =
|
||||
getFactoryForChainedOrNull(kClass)?.map { factory -> safeBuild(factory, kClass) }
|
||||
|
||||
private fun <I : Any> safeBuild(factory: (ComponentFactoryContainer) -> Any, kClass: KClass<I>): I {
|
||||
val component = factory(this)
|
||||
return kClass.cast(component)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a factory which is able to build a component for the given [kClass]
|
||||
* or `null` in case no factory was found which is able to build a component of the given type.
|
||||
*/
|
||||
fun getFactoryOrNull(kClass: KClass<*>): ((ComponentFactoryContainer) -> Any)?
|
||||
|
||||
/**
|
||||
* Returns a factory which is able to build a chain of components of the specified [kClass]
|
||||
* or `null` in case no factory was found which is able to build a chain of components of the given type.
|
||||
*/
|
||||
fun getFactoryForChainedOrNull(kClass: KClass<*>): (Sequence<(ComponentFactoryContainer) -> Any>)?
|
||||
|
||||
|
||||
/**
|
||||
* Merges the given [componentFactoryContainer] (if not `null`) with `this` [ComponentFactoryContainer]
|
||||
* creating a new [ComponentFactoryContainer] where defined dependencies in [componentFactoryContainer]
|
||||
* will have precedence over dependencies defined in this instance.
|
||||
*
|
||||
* For instance, this object has defined a [Reporter] and
|
||||
* the given [componentFactoryContainer] as well, then the resulting [ComponentFactoryContainer] will return the [Reporter]
|
||||
* of [componentFactoryContainer] when asked for it.
|
||||
*/
|
||||
fun merge(componentFactoryContainer: ComponentFactoryContainer?): ComponentFactoryContainer
|
||||
|
||||
companion object {
|
||||
// should create an immutable ComponentContainer in one go
|
||||
fun createIfNotEmpty(
|
||||
components: Map<out KClass<*>, (ComponentFactoryContainer) -> Any>,
|
||||
chainedComponents: Map<out KClass<*>, Sequence<(ComponentFactoryContainer) -> Any>>
|
||||
): ComponentFactoryContainer? =
|
||||
if (components.isEmpty() && chainedComponents.isEmpty()) null
|
||||
else ComponentFactoryContainerImpl(
|
||||
if (components.isEmpty()) emptyMap() else HashMap(components),
|
||||
if (chainedComponents.isEmpty()) emptyMap() else HashMap(chainedComponents)
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the component of type [I] using a corresponding factory or throws an [IllegalStateException]
|
||||
* in case no factory was found which is able to build a component of the given type.
|
||||
*
|
||||
* @throws IllegalStateException in case [ComponentFactoryContainer.buildOrNull] returns `null`
|
||||
* because not suitable factory was found.
|
||||
*/
|
||||
@ExperimentalComponentFactoryContainer
|
||||
inline fun <reified I : Any> ComponentFactoryContainer.build(): I = buildOrNull(I::class)
|
||||
?: throw IllegalStateException("No factory is registered in this ComponentContainer which is able to build a ${I::class.fullName}")
|
||||
|
||||
|
||||
/**
|
||||
* Returns a chain of components of type [I] using a corresponding factory or throws an [IllegalStateException]
|
||||
* in case no factory was found which is able to build a chain of components of the given type.
|
||||
|
||||
* @throws IllegalStateException in case [ComponentFactoryContainer.buildChainedOrNull] returns `null`
|
||||
* because no suitable factory was found.
|
||||
*/
|
||||
@ExperimentalComponentFactoryContainer
|
||||
inline fun <reified I : Any> ComponentFactoryContainer.buildChained(): Sequence<I> = buildChainedOrNull(I::class)
|
||||
?: throw IllegalStateException("No factory is registered in this ComponentContainer which is able to build a chain of ${I::class.fullName}")
|
||||
@@ -11,7 +11,7 @@ import ch.tutteli.atrium.creating.impl.DelegatingExpectImpl
|
||||
interface DelegatingExpect<T> : Expect<T> {
|
||||
companion object {
|
||||
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class, ExperimentalComponentFactoryContainer::class)
|
||||
operator fun <T> invoke(expect: AssertionContainer<*>, maybeSubject: Option<T>): Expect<T> =
|
||||
DelegatingExpectImpl(expect, maybeSubject)
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ interface FeatureExpect<T, R> : Expect<R> {
|
||||
|
||||
companion object {
|
||||
|
||||
@ExperimentalComponentFactoryContainer
|
||||
@ExperimentalNewExpectTypes
|
||||
operator fun <T, R> invoke(
|
||||
previousExpect: Expect<T>,
|
||||
@@ -28,6 +29,7 @@ interface FeatureExpect<T, R> : Expect<R> {
|
||||
* Use this overload if you want to modify the options of a [FeatureExpect].
|
||||
*/
|
||||
@ExperimentalNewExpectTypes
|
||||
@ExperimentalComponentFactoryContainer
|
||||
operator fun <T, R> invoke(
|
||||
featureExpect: FeatureExpect<T, R>,
|
||||
featureExpectOptions: FeatureExpectOptions<R>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package ch.tutteli.atrium.creating
|
||||
|
||||
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
|
||||
import ch.tutteli.atrium.reporting.Reporter
|
||||
import ch.tutteli.atrium.reporting.translating.Translatable
|
||||
|
||||
/**
|
||||
@@ -12,19 +11,21 @@ import ch.tutteli.atrium.reporting.translating.Translatable
|
||||
*
|
||||
* @property expectationVerb Defines a custom assertion verb if not null.
|
||||
* @property representationInsteadOfSubject Defines a custom representation based on a present subject if not null.
|
||||
* @property reporter Defines a custom reporter if not null.
|
||||
* @property componentFactoryContainer Defines a custom components.
|
||||
*/
|
||||
@ExperimentalNewExpectTypes
|
||||
@Suppress("DEPRECATION" /* RequiresOptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalComponentFactoryContainer::class)
|
||||
data class RootExpectOptions<T>(
|
||||
val expectationVerb: Translatable?,
|
||||
val representationInsteadOfSubject: ((T) -> Any)?,
|
||||
val reporter: Reporter?
|
||||
val componentFactoryContainer: ComponentFactoryContainer?
|
||||
) {
|
||||
@Deprecated("Use expectationVerb; will be removed latest with 1.0.0 (maybe earlier)")
|
||||
val assertionVerb = expectationVerb
|
||||
|
||||
/**
|
||||
* Merges the given [options] with this object creating a new [RootExpectOptions]
|
||||
* Merges the given [options] with `this` [RootExpectOptions] object creating a new [RootExpectOptions]
|
||||
* where defined properties in [options] will have precedence over properties defined in this instance.
|
||||
*
|
||||
* For instance, this object has defined [representationInsteadOfSubject] (meaning it is not `null`) and
|
||||
@@ -35,6 +36,6 @@ data class RootExpectOptions<T>(
|
||||
RootExpectOptions(
|
||||
options.expectationVerb ?: expectationVerb,
|
||||
options.representationInsteadOfSubject ?: representationInsteadOfSubject,
|
||||
options.reporter ?: reporter
|
||||
options.componentFactoryContainer?.let { c -> componentFactoryContainer?.merge(c) ?: c }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import ch.tutteli.atrium.reporting.Text
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
@ExperimentalNewExpectTypes
|
||||
@ExperimentalComponentFactoryContainer
|
||||
abstract class BaseExpectImpl<T>(
|
||||
override val maybeSubject: Option<T>
|
||||
) : ExpectInternal<T> {
|
||||
@@ -40,7 +41,7 @@ abstract class BaseExpectImpl<T>(
|
||||
}
|
||||
|
||||
override fun addAssertionsCreatedBy(assertionCreator: Expect<T>.() -> Unit): Expect<T> {
|
||||
val assertions = CollectingExpect(maybeSubject)
|
||||
val assertions = CollectingExpect(maybeSubject, components)
|
||||
.addAssertionsCreatedBy(assertionCreator)
|
||||
.getAssertions()
|
||||
return addAssertions(assertions)
|
||||
|
||||
@@ -7,15 +7,17 @@ import ch.tutteli.atrium.core.Option
|
||||
import ch.tutteli.atrium.creating.*
|
||||
|
||||
@ExperimentalNewExpectTypes
|
||||
internal class CollectingExpectImpl<T>(maybeSubject: Option<T>) : BaseExpectImpl<T>(maybeSubject), CollectingExpect<T> {
|
||||
@ExperimentalComponentFactoryContainer
|
||||
internal class CollectingExpectImpl<T>(
|
||||
maybeSubject: Option<T>,
|
||||
override val components: ComponentFactoryContainer
|
||||
) : BaseExpectImpl<T>(maybeSubject), CollectingExpect<T> {
|
||||
private val assertions = mutableListOf<Assertion>()
|
||||
|
||||
override fun getAssertions(): List<Assertion> = assertions.toList()
|
||||
|
||||
override fun addAssertion(assertion: Assertion): Expect<T> {
|
||||
assertions.add(assertion)
|
||||
return this
|
||||
}
|
||||
override fun addAssertion(assertion: Assertion): Expect<T> =
|
||||
apply { assertions.add(assertion) }
|
||||
|
||||
override fun addAssertionsCreatedBy(assertionCreator: Expect<T>.() -> Unit): CollectingExpect<T> {
|
||||
// in case we run into performance problems, the code below is certainly not ideal
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package ch.tutteli.atrium.creating.impl
|
||||
|
||||
import ch.tutteli.atrium.creating.ComponentFactoryContainer
|
||||
import ch.tutteli.atrium.creating.ExperimentalComponentFactoryContainer
|
||||
import ch.tutteli.atrium.creating.build
|
||||
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
|
||||
import ch.tutteli.atrium.reporting.Reporter
|
||||
import ch.tutteli.atrium.reporting.erroradjusters.MultiAtriumErrorAdjuster
|
||||
import ch.tutteli.atrium.reporting.erroradjusters.RemoveAtriumFromAtriumError
|
||||
import ch.tutteli.atrium.reporting.erroradjusters.RemoveRunnerAtriumError
|
||||
import ch.tutteli.atrium.reporting.erroradjusters.impl.RemoveAtriumFromAtriumErrorImpl
|
||||
import ch.tutteli.atrium.reporting.erroradjusters.impl.RemoveRunnerAtriumErrorImpl
|
||||
import ch.tutteli.atrium.reporting.reporter
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
@ExperimentalComponentFactoryContainer
|
||||
internal abstract class ComponentFactoryContainerImpl : ComponentFactoryContainer {
|
||||
|
||||
override fun merge(componentFactoryContainer: ComponentFactoryContainer?): ComponentFactoryContainer =
|
||||
if (componentFactoryContainer == null) this
|
||||
else RedefiningComponentFactoryContainer(this, componentFactoryContainer)
|
||||
|
||||
@ExperimentalComponentFactoryContainer
|
||||
private class RootComponentFactoryContainer(
|
||||
private val components: Map<out KClass<*>, (ComponentFactoryContainer) -> Any>,
|
||||
private val chainedComponents: Map<out KClass<*>, Sequence<(ComponentFactoryContainer) -> Any>>
|
||||
) : ComponentFactoryContainerImpl() {
|
||||
|
||||
override fun getFactoryOrNull(kClass: KClass<*>): ((ComponentFactoryContainer) -> Any)? =
|
||||
components[kClass]
|
||||
|
||||
override fun getFactoryForChainedOrNull(
|
||||
kClass: KClass<*>
|
||||
): (Sequence<(ComponentFactoryContainer) -> Any>)? = chainedComponents[kClass]
|
||||
}
|
||||
|
||||
private class RedefiningComponentFactoryContainer(
|
||||
private val previousFactoryContainer: ComponentFactoryContainer,
|
||||
private val redefiningFactoryContainer: ComponentFactoryContainer
|
||||
) : ComponentFactoryContainerImpl() {
|
||||
|
||||
override fun getFactoryOrNull(kClass: KClass<*>): ((ComponentFactoryContainer) -> Any)? =
|
||||
redefiningFactoryContainer.getFactoryOrNull(kClass) ?: previousFactoryContainer.getFactoryOrNull(kClass)
|
||||
|
||||
override fun getFactoryForChainedOrNull(kClass: KClass<*>): Sequence<(ComponentFactoryContainer) -> Any>? {
|
||||
//TODO 1.0.0 rewrite to sequence { ... }
|
||||
val previousSequence = previousFactoryContainer.getFactoryForChainedOrNull(kClass)
|
||||
return redefiningFactoryContainer.getFactoryForChainedOrNull(kClass)?.let { redefinedSequence ->
|
||||
if (previousSequence != null) redefinedSequence.plus(previousSequence)
|
||||
else redefinedSequence
|
||||
} ?: previousSequence
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
operator fun invoke(
|
||||
components: Map<out KClass<*>, (ComponentFactoryContainer) -> Any>,
|
||||
chainedComponents: Map<out KClass<*>, Sequence<(ComponentFactoryContainer) -> Any>>
|
||||
): ComponentFactoryContainer = RootComponentFactoryContainer(components, chainedComponents)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO 0.17.0 I guess it would make sense to cache instance here and only re-create them if this component was merged
|
||||
// with another because most Atrium users won't change the components and it would most likely just be a waste of
|
||||
// resources to re-create all over and over again. On the other hand they would be very short-lived an most likely
|
||||
// just be swept away when GC kicks in (not survive the young generation)
|
||||
@ExperimentalComponentFactoryContainer
|
||||
//TODO 0.17.0 or 0.18.0 make internal
|
||||
object DefaultComponentFactoryContainer : ComponentFactoryContainer by ComponentFactoryContainerImpl(
|
||||
mapOf(
|
||||
Reporter::class to { _ ->
|
||||
//TODO 0.16.0 exchange with new Reportable based Reporter
|
||||
reporter
|
||||
},
|
||||
RemoveAtriumFromAtriumError::class to { _ -> RemoveAtriumFromAtriumErrorImpl() },
|
||||
RemoveRunnerAtriumError::class to { _ -> RemoveRunnerAtriumErrorImpl() },
|
||||
AtriumErrorAdjuster::class to { c ->
|
||||
MultiAtriumErrorAdjuster(
|
||||
c.build<RemoveAtriumFromAtriumError>(),
|
||||
c.build<RemoveRunnerAtriumError>(),
|
||||
emptyList()
|
||||
)
|
||||
}
|
||||
),
|
||||
//TODO 0.16.0 define default chainable types like TextFormatter
|
||||
emptyMap()
|
||||
)
|
||||
@@ -3,16 +3,16 @@ package ch.tutteli.atrium.creating.impl
|
||||
import ch.tutteli.atrium.assertions.Assertion
|
||||
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
|
||||
import ch.tutteli.atrium.core.Option
|
||||
import ch.tutteli.atrium.creating.AssertionContainer
|
||||
import ch.tutteli.atrium.creating.DelegatingExpect
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.creating.*
|
||||
|
||||
@ExperimentalComponentFactoryContainer
|
||||
@ExperimentalNewExpectTypes
|
||||
internal class DelegatingExpectImpl<T>(private val container: AssertionContainer<*>, maybeSubject: Option<T>) :
|
||||
BaseExpectImpl<T>(maybeSubject), DelegatingExpect<T> {
|
||||
|
||||
override fun addAssertion(assertion: Assertion): Expect<T> {
|
||||
container.addAssertion(assertion)
|
||||
return this
|
||||
}
|
||||
override val components: ComponentFactoryContainer
|
||||
get() = container.components
|
||||
|
||||
override fun addAssertion(assertion: Assertion): Expect<T> =
|
||||
apply { container.addAssertion(assertion) }
|
||||
}
|
||||
|
||||
@@ -4,12 +4,11 @@ import ch.tutteli.atrium.assertions.Assertion
|
||||
import ch.tutteli.atrium.assertions.builders.assertionBuilder
|
||||
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
|
||||
import ch.tutteli.atrium.core.Option
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.creating.FeatureExpect
|
||||
import ch.tutteli.atrium.creating.FeatureExpectOptions
|
||||
import ch.tutteli.atrium.creating.*
|
||||
import ch.tutteli.atrium.reporting.translating.Translatable
|
||||
|
||||
@ExperimentalNewExpectTypes
|
||||
@ExperimentalComponentFactoryContainer
|
||||
internal class FeatureExpectImpl<T, R>(
|
||||
private val previousExpect: Expect<T>,
|
||||
maybeSubject: Option<R>,
|
||||
@@ -53,6 +52,11 @@ internal class FeatureExpectImpl<T, R>(
|
||||
addAssertions(assertions)
|
||||
}
|
||||
|
||||
override val components: ComponentFactoryContainer
|
||||
// TODO 0.16.0 the function to turn an Expect into a ProofContainer should be located in core
|
||||
get() = (previousExpect as AssertionContainer<*>).components
|
||||
|
||||
|
||||
override fun addAssertion(assertion: Assertion): Expect<R> {
|
||||
assertions.add(assertion)
|
||||
//Would be nice if we don't have to add it immediately to the previousExpect but only:
|
||||
|
||||
@@ -5,33 +5,34 @@ import ch.tutteli.atrium.assertions.builders.assertionBuilder
|
||||
import ch.tutteli.atrium.assertions.builders.root
|
||||
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
|
||||
import ch.tutteli.atrium.core.Option
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.creating.RootExpect
|
||||
import ch.tutteli.atrium.creating.RootExpectOptions
|
||||
import ch.tutteli.atrium.creating.*
|
||||
import ch.tutteli.atrium.reporting.AtriumError
|
||||
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
|
||||
import ch.tutteli.atrium.reporting.Reporter
|
||||
import ch.tutteli.atrium.reporting.translating.Translatable
|
||||
|
||||
@ExperimentalNewExpectTypes
|
||||
@Suppress("DEPRECATION" /* RequiresOptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalComponentFactoryContainer::class)
|
||||
internal class RootExpectImpl<T>(
|
||||
maybeSubject: Option<T>,
|
||||
private val expectationVerb: Translatable,
|
||||
private val representation: Any?,
|
||||
private val reporter: Reporter
|
||||
override val components: ComponentFactoryContainer
|
||||
) : BaseExpectImpl<T>(maybeSubject), RootExpect<T> {
|
||||
|
||||
constructor(
|
||||
maybeSubject: Option<T>,
|
||||
assertionVerb: Translatable,
|
||||
expectationVerb: Translatable,
|
||||
options: RootExpectOptions<T>?
|
||||
) : this(
|
||||
maybeSubject,
|
||||
options?.expectationVerb ?: assertionVerb,
|
||||
options?.expectationVerb ?: expectationVerb,
|
||||
determineRepresentation(
|
||||
options?.representationInsteadOfSubject,
|
||||
maybeSubject
|
||||
),
|
||||
options?.reporter ?: ch.tutteli.atrium.reporting.reporter
|
||||
DefaultComponentFactoryContainer.merge(options?.componentFactoryContainer)
|
||||
)
|
||||
|
||||
constructor(previous: RootExpectImpl<T>, options: RootExpectOptions<T>) : this(
|
||||
@@ -55,8 +56,10 @@ internal class RootExpectImpl<T>(
|
||||
.build()
|
||||
|
||||
val sb = StringBuilder()
|
||||
reporter.format(assertionGroup, sb)
|
||||
throw AtriumError.create(sb.toString(), reporter.atriumErrorAdjuster)
|
||||
components.build<Reporter>().format(assertionGroup, sb)
|
||||
|
||||
@Suppress("RemoveExplicitTypeArguments")
|
||||
throw AtriumError.create(sb.toString(), components.build<AtriumErrorAdjuster>())
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package ch.tutteli.atrium.reporting
|
||||
|
||||
|
||||
//TODO move to package erroradjusters with 1.0.0
|
||||
/**
|
||||
* Responsible to adjust a given [Throwable] (usually an [AtriumError]) for improved error reporting.
|
||||
*
|
||||
@@ -10,6 +10,7 @@ package ch.tutteli.atrium.reporting
|
||||
expect interface AtriumErrorAdjuster : AtriumErrorAdjusterCommon
|
||||
|
||||
|
||||
//TODO move to package erroradjusters with 1.0.0
|
||||
/**
|
||||
* Defines the general contract for [AtriumError] adjusters which all platforms have to fulfil.
|
||||
*/
|
||||
|
||||
@@ -11,6 +11,7 @@ interface Reporter {
|
||||
/**
|
||||
* The [AtriumErrorAdjuster] which shall be used to modify stack traces in reporting.
|
||||
*/
|
||||
@Deprecated("Do no longer use this but build the AtriumErrorAdjuster based on the configured ComponentFactoryContainer of the Expect/ProofContainer, so that you use the latest configured AtriumErrorAdjuster; will be removed with 0.17.0")
|
||||
val atriumErrorAdjuster: AtriumErrorAdjuster
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package ch.tutteli.atrium.reporting.erroradjusters
|
||||
|
||||
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
|
||||
|
||||
expect class MultiAtriumErrorAdjuster(
|
||||
firstAdjuster: AtriumErrorAdjuster,
|
||||
secondAdjuster: AtriumErrorAdjuster,
|
||||
otherAdjusters: List<AtriumErrorAdjuster>
|
||||
) : AtriumErrorAdjuster
|
||||
@@ -0,0 +1,17 @@
|
||||
package ch.tutteli.atrium.reporting.erroradjusters
|
||||
|
||||
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
|
||||
|
||||
/**
|
||||
* An implementation of an [AtriumErrorAdjuster] which adjusts nothing.
|
||||
*/
|
||||
expect object NoOpAtriumErrorAdjuster : AtriumErrorAdjuster
|
||||
|
||||
/**
|
||||
* An implementation of an [AtriumErrorAdjuster] which adjusts nothing and can be used by the platforms to provide the
|
||||
* actual type of [NoOpAtriumErrorAdjuster].
|
||||
*/
|
||||
abstract class NoOpAtriumErrorAdjusterCommon : AtriumErrorAdjuster {
|
||||
override fun adjustOtherThanStacks(throwable: Throwable) {}
|
||||
override fun adjust(throwable: Throwable) {}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package ch.tutteli.atrium.reporting.erroradjusters
|
||||
|
||||
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
|
||||
import ch.tutteli.atrium.reporting.AtriumError
|
||||
import ch.tutteli.atrium.creating.ComponentFactoryContainer
|
||||
|
||||
/**
|
||||
* Responsible to remove the stacktrace of Atrium from an [AtriumError].
|
||||
*
|
||||
* It is a marker interface so that one can [ComponentFactoryContainer.buildOrNull] an implementation of
|
||||
* a [AtriumErrorAdjuster] with the desired behaviour.
|
||||
*/
|
||||
interface RemoveAtriumFromAtriumError : AtriumErrorAdjuster
|
||||
@@ -0,0 +1,13 @@
|
||||
package ch.tutteli.atrium.reporting.erroradjusters
|
||||
|
||||
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
|
||||
import ch.tutteli.atrium.reporting.AtriumError
|
||||
import ch.tutteli.atrium.creating.ComponentFactoryContainer
|
||||
|
||||
/**
|
||||
* Responsible to remove the stacktrace of the test runner(s) from an [AtriumError].
|
||||
*
|
||||
* It is a marker interface so that one can [ComponentFactoryContainer.buildOrNull] an implementation of
|
||||
* a [AtriumErrorAdjuster] with the desired behaviour.
|
||||
*/
|
||||
interface RemoveRunnerAtriumError : AtriumErrorAdjuster
|
||||
@@ -0,0 +1,5 @@
|
||||
package ch.tutteli.atrium.reporting.erroradjusters.impl
|
||||
|
||||
import ch.tutteli.atrium.reporting.erroradjusters.RemoveAtriumFromAtriumError
|
||||
|
||||
expect class RemoveAtriumFromAtriumErrorImpl() : RemoveAtriumFromAtriumError
|
||||
@@ -0,0 +1,5 @@
|
||||
package ch.tutteli.atrium.reporting.erroradjusters.impl
|
||||
|
||||
import ch.tutteli.atrium.reporting.erroradjusters.RemoveRunnerAtriumError
|
||||
|
||||
expect class RemoveRunnerAtriumErrorImpl() : RemoveRunnerAtriumError
|
||||
@@ -2,14 +2,14 @@ package ch.tutteli.atrium.reporting
|
||||
|
||||
import ch.tutteli.atrium.api.infix.en_GB.*
|
||||
import ch.tutteli.atrium.api.verbs.internal.expect
|
||||
import ch.tutteli.atrium.core.coreFactory
|
||||
import ch.tutteli.atrium.reporting.erroradjusters.NoOpAtriumErrorAdjuster
|
||||
import org.spekframework.spek2.Spek
|
||||
import org.spekframework.spek2.style.specification.describe
|
||||
|
||||
class AtriumErrorSpec : Spek({
|
||||
describe("creating an AtriumError") {
|
||||
it("has `null` as cause - regression for #303") {
|
||||
val e = AtriumError.create("hello world", coreFactory.newNoOpAtriumErrorAdjuster())
|
||||
val e = AtriumError.create("hello world", NoOpAtriumErrorAdjuster)
|
||||
expect(e).feature(Throwable::cause).toBe(null)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package ch.tutteli.atrium.reporting.erroradjusters
|
||||
|
||||
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
|
||||
import ch.tutteli.atrium.reporting.Reporter
|
||||
|
||||
//TODO 0.16.0, remove again, only temporary
|
||||
internal class DelegatingReporter(
|
||||
reporter: Reporter,
|
||||
override val atriumErrorAdjuster: AtriumErrorAdjuster
|
||||
) : Reporter by reporter
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package ch.tutteli.atrium.reporting.erroradjusters
|
||||
|
||||
import ch.tutteli.atrium.core.polyfills.stackBacktrace
|
||||
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
|
||||
|
||||
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) {}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package ch.tutteli.atrium.reporting.erroradjusters
|
||||
|
||||
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
|
||||
|
||||
actual class MultiAtriumErrorAdjuster 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package ch.tutteli.atrium.reporting.erroradjusters
|
||||
|
||||
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
|
||||
|
||||
actual object NoOpAtriumErrorAdjuster : NoOpAtriumErrorAdjusterCommon(), AtriumErrorAdjuster {
|
||||
override fun adjustStack(stackTrace: Sequence<String>): Sequence<String> = stackTrace
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package ch.tutteli.atrium.reporting.erroradjusters.impl
|
||||
|
||||
import ch.tutteli.atrium.reporting.erroradjusters.FilterAtriumErrorAdjuster
|
||||
import ch.tutteli.atrium.reporting.erroradjusters.RemoveAtriumFromAtriumError
|
||||
|
||||
actual class RemoveAtriumFromAtriumErrorImpl : FilterAtriumErrorAdjuster(),
|
||||
RemoveAtriumFromAtriumError {
|
||||
override fun adjustStack(stackTrace: Sequence<String>): Sequence<String> =
|
||||
stackTrace.filter { !atriumRegex.containsMatchIn(it) }
|
||||
|
||||
companion object {
|
||||
val atriumRegex = Regex("[\\\\|/]atrium-[a-zA-Z-]+.js")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package ch.tutteli.atrium.reporting.erroradjusters.impl
|
||||
|
||||
import ch.tutteli.atrium.reporting.erroradjusters.FilterAtriumErrorAdjuster
|
||||
import ch.tutteli.atrium.reporting.erroradjusters.RemoveRunnerAtriumError
|
||||
|
||||
actual class RemoveRunnerAtriumErrorImpl : FilterAtriumErrorAdjuster(), RemoveRunnerAtriumError {
|
||||
override fun adjustStack(stackTrace: Sequence<String>): Sequence<String> =
|
||||
stackTrace.takeWhile { !runnerRegex.containsMatchIn(it) }
|
||||
|
||||
companion object {
|
||||
val runnerRegex: Regex = Regex("[\\\\|/]node_modules[\\\\|/](mocha|jasmine)[\\\\|/]")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package ch.tutteli.atrium.reporting.erroradjusters
|
||||
|
||||
import ch.tutteli.atrium.api.infix.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.polyfills.stackBacktrace
|
||||
import ch.tutteli.atrium.creating.ComponentFactoryContainer
|
||||
import ch.tutteli.atrium.creating.ExperimentalComponentFactoryContainer
|
||||
import ch.tutteli.atrium.creating.build
|
||||
import ch.tutteli.atrium.logic._logic
|
||||
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
|
||||
|
||||
class AdjustStackTest {
|
||||
|
||||
@Test
|
||||
fun noOp_containsMochaAndAtrium() {
|
||||
expect {
|
||||
assertNoOp(1).toBe(2)
|
||||
}.toThrow<AssertionError> {
|
||||
feature(AssertionError::stackBacktrace) contains entries(
|
||||
{ contains("mocha") },
|
||||
{ contains("atrium-core-api-js.js") }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun removeRunner_containsAtriumButNotMocha() {
|
||||
expect {
|
||||
assertRemoveRunner(1).toBe(2)
|
||||
}.toThrow<AssertionError> {
|
||||
it feature of(AssertionError::stackBacktrace) {
|
||||
it containsNot o entry { it contains "mocha" }
|
||||
it contains { it contains "atrium-core-api-js.js" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ExperimentalComponentFactoryContainer
|
||||
@Test
|
||||
fun removeRunner_containsAtriumButNotMochaInCause() {
|
||||
val adjuster = assertRemoveRunner(1)._logic.components.build<AtriumErrorAdjuster>()
|
||||
expect(adjuster).isA<RemoveRunnerAtriumError>()
|
||||
val throwable = IllegalArgumentException("hello", UnsupportedOperationException("world"))
|
||||
adjuster.adjust(throwable)
|
||||
expect(throwable.cause!!.stackBacktrace) {
|
||||
it containsNot o entry { it contains "mocha" }
|
||||
it contains { it contains "atrium-core-api-js" }
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun removeAtrium_containsMochaButNotAtrium() {
|
||||
expect {
|
||||
assertRemoveAtrium(1).toBe(2)
|
||||
}.toThrow<AssertionError> {
|
||||
it feature of(AssertionError::stackBacktrace) {
|
||||
it contains { it contains "mocha" }
|
||||
it containsNot o entry { it contains "atrium-core-api-js.js" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ExperimentalComponentFactoryContainer
|
||||
@Test
|
||||
fun removeAtrium_containsMochaButNotAtriumInCause() {
|
||||
val adjuster = assertRemoveAtrium(1)._logic.components.build<AtriumErrorAdjuster>()
|
||||
expect(adjuster).isA<RemoveAtriumFromAtriumError>()
|
||||
val throwable = IllegalArgumentException("hello", UnsupportedOperationException("world"))
|
||||
adjuster.adjust(throwable)
|
||||
expect(throwable.cause!!.stackBacktrace) {
|
||||
it contains { it contains "mocha" }
|
||||
it containsNot o entry { it contains "atrium-core-api-js" }
|
||||
}
|
||||
}
|
||||
|
||||
@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> assertNoOp(subject: T) = createExpect(subject) { _ -> NoOpAtriumErrorAdjuster }
|
||||
|
||||
@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> assertRemoveRunner(subject: T) =
|
||||
createExpect(subject) { c -> c.build<RemoveRunnerAtriumError>() }
|
||||
|
||||
@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> assertRemoveAtrium(subject: T) =
|
||||
createExpect(subject) { c -> c.build<RemoveAtriumFromAtriumError>() }
|
||||
|
||||
|
||||
@ExperimentalNewExpectTypes
|
||||
@ExperimentalComponentFactoryContainer
|
||||
private fun <T : Any> createExpect(subject: T, factory: (ComponentFactoryContainer) -> AtriumErrorAdjuster) =
|
||||
RootExpectBuilder.forSubject(subject)
|
||||
.withVerb(AssertionVerb.EXPECT)
|
||||
.withOptions {
|
||||
withComponent(AtriumErrorAdjuster::class, factory)
|
||||
//TODO 0.16.0 should not be necessary once CollectingExpect uses components
|
||||
withComponent(Reporter::class) { c -> DelegatingReporter(reporter, factory(c))}
|
||||
}
|
||||
.build()
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package ch.tutteli.atrium.reporting.erroradjusters
|
||||
|
||||
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
|
||||
|
||||
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) {}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package ch.tutteli.atrium.reporting.erroradjusters
|
||||
|
||||
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
|
||||
import ch.tutteli.kbox.joinToString
|
||||
|
||||
actual class MultiAtriumErrorAdjuster 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)
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String =
|
||||
"MultiAtriumErrorAdjuster[$firstAdjuster, $secondAdjuster, ${
|
||||
otherAdjusters.joinToString(", ", " and ") { it, sb -> sb.append(it) }
|
||||
}"
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
@file:Suppress(
|
||||
// TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed
|
||||
"JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE"
|
||||
)
|
||||
|
||||
package ch.tutteli.atrium.reporting.erroradjusters
|
||||
|
||||
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
|
||||
|
||||
actual object NoOpAtriumErrorAdjuster : NoOpAtriumErrorAdjusterCommon(), AtriumErrorAdjuster {
|
||||
override fun adjustStackTrace(stackTrace: Sequence<StackTraceElement>): Sequence<StackTraceElement> = stackTrace
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
@file:Suppress(
|
||||
// TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed
|
||||
"JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE"
|
||||
)
|
||||
package ch.tutteli.atrium.reporting.erroradjusters.impl
|
||||
|
||||
import ch.tutteli.atrium.reporting.erroradjusters.FilterAtriumErrorAdjuster
|
||||
import ch.tutteli.atrium.reporting.erroradjusters.RemoveAtriumFromAtriumError
|
||||
|
||||
actual class RemoveAtriumFromAtriumErrorImpl : FilterAtriumErrorAdjuster(),
|
||||
RemoveAtriumFromAtriumError {
|
||||
|
||||
override fun adjustStackTrace(stackTrace: Sequence<StackTraceElement>): Sequence<StackTraceElement> =
|
||||
stackTrace.filter { !it.className.startsWith("ch.tutteli.atrium") }
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
@file:Suppress(
|
||||
// TODO remove once https://youtrack.jetbrains.com/issue/KT-35343 is fixed
|
||||
"JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE"
|
||||
)
|
||||
package ch.tutteli.atrium.reporting.erroradjusters.impl
|
||||
|
||||
import ch.tutteli.atrium.reporting.erroradjusters.FilterAtriumErrorAdjuster
|
||||
import ch.tutteli.atrium.reporting.erroradjusters.RemoveRunnerAtriumError
|
||||
|
||||
actual class RemoveRunnerAtriumErrorImpl : FilterAtriumErrorAdjuster(), RemoveRunnerAtriumError {
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
@@ -11,5 +11,11 @@ module ch.tutteli.atrium.core.api {
|
||||
exports ch.tutteli.atrium.core.polyfills;
|
||||
exports ch.tutteli.atrium.creating;
|
||||
exports ch.tutteli.atrium.reporting;
|
||||
exports ch.tutteli.atrium.reporting.erroradjusters;
|
||||
exports ch.tutteli.atrium.reporting.translating;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
package ch.tutteli.atrium.reporting.erroradjusters
|
||||
|
||||
import ch.tutteli.atrium.api.infix.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.polyfills.stackBacktrace
|
||||
import ch.tutteli.atrium.creating.ComponentFactoryContainer
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.creating.ExperimentalComponentFactoryContainer
|
||||
import ch.tutteli.atrium.creating.build
|
||||
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
|
||||
|
||||
@ExperimentalNewExpectTypes
|
||||
@ExperimentalComponentFactoryContainer
|
||||
class AdjustStackSpec : Spek({
|
||||
|
||||
describe("no-op adjuster") {
|
||||
fun <T : Any> assertNoOp(subject: T) =
|
||||
createExpect(subject) { _ -> NoOpAtriumErrorAdjuster }
|
||||
|
||||
it("contains spek, junit, atrium.creating and atrium.reporting") {
|
||||
expect {
|
||||
assertNoOp(1).toBe(2)
|
||||
}.toThrow<AssertionError> {
|
||||
feature { f(it::stackBacktrace) } contains entries(
|
||||
{ it startsWith "org.spekframework.spek2" },
|
||||
{ it startsWith "ch.tutteli.atrium.creating" },
|
||||
{ it 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<String, Triple<(ComponentFactoryContainer) -> AtriumErrorAdjuster, List<String>, List<String>>>(
|
||||
"remove test runner adjuster" to Triple(
|
||||
{ c -> c.build<RemoveRunnerAtriumError>() },
|
||||
listOf("org.spekframework.spek2", "kotlin.coroutines", "kotlinx.coroutines"),
|
||||
listOf("ch.tutteli.atrium")
|
||||
),
|
||||
"remove atrium adjuster" to Triple(
|
||||
{ c -> c.build<RemoveAtriumFromAtriumError>() },
|
||||
listOf("ch.tutteli.atrium"),
|
||||
listOf("org.spekframework.spek2")
|
||||
)
|
||||
).forEach { (description, triple) ->
|
||||
val (factory, 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, factory).toBe(2)
|
||||
}.toThrow<AssertionError> {
|
||||
feature { f(it::stackBacktrace) } and {
|
||||
it containsNot o the entries(containsNotFirst, *containsNotRest)
|
||||
it contains entries(containsFirst, *containsRest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
it("does not contain $containsNot in stackBacktrace of cause, but $contains") {
|
||||
val throwable = IllegalArgumentException("hello", UnsupportedOperationException("world"))
|
||||
val adjuster = createExpect(1, factory)._logic.components.build<AtriumErrorAdjuster>()
|
||||
adjuster.adjust(throwable)
|
||||
expect(throwable.cause!!.stackBacktrace) {
|
||||
it containsNot o the entries(containsNotFirst, *containsNotRest)
|
||||
it contains entries(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"))
|
||||
)
|
||||
val adjuster = createExpect(1, factory)._logic.components.build<AtriumErrorAdjuster>()
|
||||
adjuster.adjust(throwable)
|
||||
expect(throwable.cause!!.cause!!.stackBacktrace) {
|
||||
it containsNot o the entries(containsNotFirst, *containsNotRest)
|
||||
it contains entries(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)
|
||||
val adjuster = createExpect(1, factory)._logic.components.build<AtriumErrorAdjuster>()
|
||||
adjuster.adjust(throwable)
|
||||
expect(throwable.suppressed) asList o all {
|
||||
feature { f(it::stackBacktrace) } and {
|
||||
it containsNot o the entries(containsNotFirst, *containsNotRest)
|
||||
it contains entries(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)
|
||||
val adjuster = createExpect(1, factory)._logic.components.build<AtriumErrorAdjuster>()
|
||||
adjuster.adjust(throwable)
|
||||
expect(throwable.suppressed) asList o all {
|
||||
cause<UnsupportedOperationException> {
|
||||
feature { f(it::stackBacktrace) } and {
|
||||
it containsNot o the entries(containsNotFirst, *containsNotRest)
|
||||
it contains entries(containsFirst, *containsRest)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mapOf<String, (ComponentFactoryContainer) -> AtriumErrorAdjuster>(
|
||||
"combine remove runner adjuster and remove atrium adjuster" to
|
||||
{ c ->
|
||||
MultiAtriumErrorAdjuster(
|
||||
c.build<RemoveRunnerAtriumError>(),
|
||||
c.build<RemoveAtriumFromAtriumError>(),
|
||||
listOf()
|
||||
)
|
||||
},
|
||||
"combine remove atrium adjuster and remove runner adjuster" to
|
||||
{ c ->
|
||||
MultiAtriumErrorAdjuster(
|
||||
c.build<RemoveAtriumFromAtriumError>(),
|
||||
c.build<RemoveRunnerAtriumError>(),
|
||||
listOf()
|
||||
)
|
||||
},
|
||||
"combine noop adjust, remove atrium adjuster and remove runner adjuster" to
|
||||
{ c ->
|
||||
MultiAtriumErrorAdjuster(
|
||||
NoOpAtriumErrorAdjuster,
|
||||
c.build<RemoveAtriumFromAtriumError>(),
|
||||
listOf(c.build<RemoveRunnerAtriumError>())
|
||||
)
|
||||
},
|
||||
"combine remove atrium adjuster, remove runner adjuster and noop adjuster several times" to
|
||||
{ c ->
|
||||
MultiAtriumErrorAdjuster(
|
||||
c.build<RemoveAtriumFromAtriumError>(),
|
||||
c.build<RemoveRunnerAtriumError>(),
|
||||
listOf(
|
||||
NoOpAtriumErrorAdjuster,
|
||||
c.build<RemoveRunnerAtriumError>(),
|
||||
NoOpAtriumErrorAdjuster
|
||||
)
|
||||
)
|
||||
}
|
||||
).forEach { (description, factory) ->
|
||||
describe(description) {
|
||||
it("stackBacktrace is empty as we filter out everything") {
|
||||
expect {
|
||||
createExpect(1, factory).toBe(2)
|
||||
}.toThrow<AssertionError> {
|
||||
it feature { f(it::stackBacktrace) } toBe empty
|
||||
}
|
||||
}
|
||||
|
||||
it("stackBacktrace of cause is empty as we filter out everything") {
|
||||
val throwable = IllegalArgumentException("hello", UnsupportedOperationException("world"))
|
||||
val adjuster = createExpect(1, factory)._logic.components.build<AtriumErrorAdjuster>()
|
||||
adjuster.adjust(throwable)
|
||||
expect(throwable.cause!!.stackBacktrace) toBe empty
|
||||
}
|
||||
|
||||
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)
|
||||
val adjuster = createExpect(1, factory)._logic.components.build<AtriumErrorAdjuster>()
|
||||
adjuster.adjust(throwable)
|
||||
expect(throwable.suppressed) asList o all {
|
||||
it feature { f(it::stackBacktrace) } toBe empty
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ExperimentalNewExpectTypes
|
||||
@ExperimentalComponentFactoryContainer
|
||||
private fun <T : Any> createExpect(subject: T, factory: (ComponentFactoryContainer) -> AtriumErrorAdjuster) =
|
||||
RootExpectBuilder.forSubject(subject)
|
||||
.withVerb(AssertionVerb.EXPECT)
|
||||
.withOptions {
|
||||
withComponent(AtriumErrorAdjuster::class, factory)
|
||||
//TODO 0.16.0 should not be necessary once CollectingExpect also uses ComponentFactoryContainer
|
||||
withComponent(Reporter::class) { c -> DelegatingReporter(reporter, factory(c))}
|
||||
}
|
||||
.build()
|
||||
@@ -1,7 +1,14 @@
|
||||
//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,
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
//TODO remove file with 0.17.0
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package ch.tutteli.atrium.core.robstoll.lib.reporting
|
||||
|
||||
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
|
||||
@@ -5,12 +8,20 @@ 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,3 +1,6 @@
|
||||
//TODO remove file with 0.17.0
|
||||
@file:Suppress("OverridingDeprecatedMember")
|
||||
|
||||
package ch.tutteli.atrium.core.robstoll.lib.reporting
|
||||
|
||||
import ch.tutteli.atrium.assertions.Assertion
|
||||
@@ -15,6 +18,7 @@ import ch.tutteli.atrium.reporting.Reporter
|
||||
* @param assertionFormatterFacade The formatter used to format [Assertion]s.
|
||||
* @param atriumErrorAdjuster The adjuster which should be used to adjust the resulting [AtriumError].
|
||||
*/
|
||||
//TODO deprecate with 0.16.0
|
||||
class OnlyFailureReporter(
|
||||
private val assertionFormatterFacade: AssertionFormatterFacade,
|
||||
override val atriumErrorAdjuster: AtriumErrorAdjuster
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
//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,5 +1,12 @@
|
||||
//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,8 +1,15 @@
|
||||
//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) {
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
//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,
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
//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,7 +1,14 @@
|
||||
//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)
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
//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)
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
//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.*
|
||||
@@ -6,9 +9,11 @@ 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.logic.creating.RootExpectOptions
|
||||
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
|
||||
import ch.tutteli.atrium.reporting.Reporter
|
||||
import ch.tutteli.atrium.reporting.reporter
|
||||
import kotlin.test.Test
|
||||
|
||||
@@ -81,10 +86,13 @@ class AdjustStackTest {
|
||||
)
|
||||
|
||||
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class, ExperimentalComponentFactoryContainer::class)
|
||||
private fun <T : Any> createExpect(subject: T, adjuster: AtriumErrorAdjuster) =
|
||||
RootExpectBuilder.forSubject(subject)
|
||||
.withVerb(AssertionVerb.EXPECT)
|
||||
.withOptions(RootExpectOptions(reporter = DelegatingReporter(reporter, adjuster)))
|
||||
.withOptions {
|
||||
withComponent(AtriumErrorAdjuster::class) { _ -> adjuster }
|
||||
withComponent(Reporter::class) { _ -> DelegatingReporter(reporter, adjuster) }
|
||||
}
|
||||
.build()
|
||||
}
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
//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) {
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
//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,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@file:Suppress(
|
||||
//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"
|
||||
)
|
||||
@@ -7,6 +8,10 @@ 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,7 +1,14 @@
|
||||
//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> =
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
//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> =
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
//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.*
|
||||
@@ -7,10 +10,12 @@ 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
|
||||
@@ -179,9 +184,12 @@ class AdjustStackSpec : Spek({
|
||||
})
|
||||
|
||||
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class, ExperimentalComponentFactoryContainer::class)
|
||||
private fun <T : Any> createExpect(subject: T, adjuster: AtriumErrorAdjuster) =
|
||||
RootExpectBuilder.forSubject(subject)
|
||||
.withVerb(AssertionVerb.EXPECT)
|
||||
.withOptions(RootExpectOptions(reporter = DelegatingReporter(reporter, adjuster)))
|
||||
.withOptions {
|
||||
withComponent(AtriumErrorAdjuster::class) { _ -> adjuster }
|
||||
withComponent(Reporter::class) { _ -> DelegatingReporter(reporter, adjuster) }
|
||||
}
|
||||
.build()
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
//TODO remove with 0.17.0
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package ch.tutteli.atrium.core.robstoll
|
||||
|
||||
import ch.tutteli.atrium.assertions.BulletPointIdentifier
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
//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"
|
||||
)
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
package ch.tutteli.atrium.logic.creating
|
||||
|
||||
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.creating.RootExpect
|
||||
import ch.tutteli.atrium.creating.RootExpectOptions
|
||||
import ch.tutteli.atrium.creating.*
|
||||
import ch.tutteli.atrium.logic.creating.impl.*
|
||||
import ch.tutteli.atrium.logic.reporting.ReporterBuilder
|
||||
import ch.tutteli.atrium.reporting.Reporter
|
||||
import ch.tutteli.atrium.reporting.Text
|
||||
import ch.tutteli.atrium.reporting.translating.Translatable
|
||||
import ch.tutteli.atrium.reporting.translating.Untranslatable
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* Defines the contract to create custom expectation verbs, `RootExpect<T>` respectively.
|
||||
@@ -63,7 +61,6 @@ interface RootExpectBuilder {
|
||||
*/
|
||||
val expectationVerb: Translatable
|
||||
|
||||
|
||||
/**
|
||||
* Allows to define the [RootExpectOptions] via an [OptionsChooser]-lambda which provides convenience functions.
|
||||
*
|
||||
@@ -140,12 +137,21 @@ interface RootExpectBuilder {
|
||||
fun withRepresentation(representationProvider: (T) -> Any)
|
||||
|
||||
/**
|
||||
* Uses the given [reporter] instead of the default [Reporter].
|
||||
* Expects a factory which creates the component of type [I] which is used instead of the currently specified
|
||||
* factory.
|
||||
*/
|
||||
fun withReporter(reporter: Reporter)
|
||||
@ExperimentalComponentFactoryContainer
|
||||
fun <I : Any> withComponent(kClass: KClass<I>, factory: (ComponentFactoryContainer) -> I)
|
||||
|
||||
//TODO 0.16.0 maybe we should change the name to prependChainedComponents
|
||||
// because we also use the once we defined so far?
|
||||
@ExperimentalComponentFactoryContainer
|
||||
fun <I : Any> withChainedComponents(kClass: KClass<I>, factories: Sequence<(ComponentFactoryContainer) -> I>)
|
||||
|
||||
companion object {
|
||||
@ExperimentalNewExpectTypes
|
||||
@Suppress("DEPRECATION" /* RequiresOptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalComponentFactoryContainer::class)
|
||||
operator fun <T> invoke(configuration: OptionsChooser<T>.() -> Unit): RootExpectOptions<T> =
|
||||
RootExpectOptionsChooserImpl<T>().apply(configuration).build()
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package ch.tutteli.atrium.logic.creating
|
||||
|
||||
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
|
||||
import ch.tutteli.atrium.creating.ComponentFactoryContainer
|
||||
import ch.tutteli.atrium.creating.ExperimentalComponentFactoryContainer
|
||||
import ch.tutteli.atrium.creating.RootExpectOptions
|
||||
import ch.tutteli.atrium.reporting.Reporter
|
||||
import ch.tutteli.atrium.reporting.translating.Translatable
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* Helper function to create a [RootExpectOptions] via
|
||||
@@ -14,18 +15,9 @@ fun <T> RootExpectOptions(configuration: RootExpectBuilder.OptionsChooser<T>.()
|
||||
RootExpectBuilder.OptionsChooser(configuration)
|
||||
|
||||
/**
|
||||
* Helper function to create a [RootExpectOptions] by specifying components via named parameters.
|
||||
*
|
||||
* You can use it as follows: `RootExpectOptions(reporter = myReporter)`
|
||||
* Convenience function which infers the [KClass] usually required for [RootExpectBuilder.OptionsChooser.withComponent].
|
||||
*/
|
||||
@ExperimentalNewExpectTypes
|
||||
@Suppress("FunctionName")
|
||||
fun <T> RootExpectOptions(
|
||||
expectationVerb: Translatable? = null,
|
||||
representationInsteadOfSubject: ((T) -> Any)? = null,
|
||||
reporter: Reporter? = null
|
||||
): RootExpectOptions<T> = RootExpectOptions(
|
||||
expectationVerb,
|
||||
representationInsteadOfSubject,
|
||||
reporter
|
||||
)
|
||||
@ExperimentalComponentFactoryContainer
|
||||
inline fun <reified I : Any, T> RootExpectBuilder.OptionsChooser<T>.withComponent(
|
||||
noinline factory: (ComponentFactoryContainer) -> I
|
||||
) = withComponent(I::class, factory)
|
||||
|
||||
@@ -7,6 +7,8 @@ import ch.tutteli.atrium.core.Option
|
||||
import ch.tutteli.atrium.core.Some
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
|
||||
//TODO 0.16.0 I am not sure this is actually needed, couldn't they just be helper methods?
|
||||
// moreover, we need to create it via ComponentFactoryContainer as the CollectingExpect which is used internally needs to use the components
|
||||
interface AssertionCollector {
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,10 +6,12 @@ import ch.tutteli.atrium.assertions.builders.invisibleGroup
|
||||
import ch.tutteli.atrium.core.Option
|
||||
import ch.tutteli.atrium.creating.CollectingExpect
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.creating.ExperimentalComponentFactoryContainer
|
||||
import ch.tutteli.atrium.creating.impl.DefaultComponentFactoryContainer
|
||||
import ch.tutteli.atrium.logic.creating.collectors.AssertionCollector
|
||||
|
||||
class DefaultAssertionCollector : AssertionCollector {
|
||||
|
||||
|
||||
override fun <T> collect(maybeSubject: Option<T>, assertionCreator: Expect<T>.() -> Unit): Assertion {
|
||||
val collectedAssertions = collectForComposition(maybeSubject, assertionCreator)
|
||||
return if (collectedAssertions.size > 1) {
|
||||
@@ -19,10 +21,13 @@ class DefaultAssertionCollector : AssertionCollector {
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION" /* RequiresOptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalComponentFactoryContainer::class)
|
||||
override fun <T> collectForComposition(
|
||||
maybeSubject: Option<T>,
|
||||
assertionCreator: Expect<T>.() -> Unit
|
||||
): List<Assertion> = CollectingExpect(maybeSubject)
|
||||
//TODO 0.16.0 don't use DefaultComponentFactoryContainer but the one from the container
|
||||
): List<Assertion> = CollectingExpect(maybeSubject, DefaultComponentFactoryContainer)
|
||||
.addAssertionsCreatedBy(assertionCreator)
|
||||
.getAssertions()
|
||||
}
|
||||
|
||||
@@ -7,4 +7,5 @@ import ch.tutteli.atrium.logic.creating.collectors.impl.DefaultAssertionCollecto
|
||||
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class)
|
||||
val <T> AssertionContainer<T>.assertionCollector: AssertionCollector
|
||||
//TODO 0.16.0 should be via ComponentFactoryContainer, hence move ProofCollector to core
|
||||
get() = getImpl(AssertionCollector::class) { DefaultAssertionCollector() }
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
package ch.tutteli.atrium.logic.creating.impl
|
||||
|
||||
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
|
||||
import ch.tutteli.atrium.creating.ComponentFactoryContainer
|
||||
import ch.tutteli.atrium.creating.ExperimentalComponentFactoryContainer
|
||||
import ch.tutteli.atrium.creating.RootExpectOptions
|
||||
import ch.tutteli.atrium.logic.creating.RootExpectBuilder
|
||||
import ch.tutteli.atrium.reporting.Reporter
|
||||
import ch.tutteli.atrium.reporting.translating.Translatable
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
@ExperimentalComponentFactoryContainer
|
||||
@ExperimentalNewExpectTypes
|
||||
class RootExpectOptionsChooserImpl<T> : RootExpectBuilder.OptionsChooser<T> {
|
||||
private var description: Translatable? = null
|
||||
private var representationInsteadOfSubject: ((T) -> Any)? = null
|
||||
private var reporter: Reporter? = null
|
||||
private var components = mutableMapOf<KClass<*>, (ComponentFactoryContainer) -> Any>()
|
||||
private var chainedComponents = mutableMapOf<KClass<*>, Sequence<(ComponentFactoryContainer) -> Any>>()
|
||||
|
||||
override fun withVerb(verb: Translatable) {
|
||||
this.description = verb
|
||||
@@ -20,9 +24,16 @@ class RootExpectOptionsChooserImpl<T> : RootExpectBuilder.OptionsChooser<T> {
|
||||
this.representationInsteadOfSubject = representationProvider
|
||||
}
|
||||
|
||||
override fun withReporter(reporter: Reporter) {
|
||||
this.reporter = reporter
|
||||
@ExperimentalComponentFactoryContainer
|
||||
override fun <I : Any> withComponent(kClass: KClass<I>, factory: (ComponentFactoryContainer) -> I) {
|
||||
components[kClass] = factory
|
||||
}
|
||||
|
||||
fun build(): RootExpectOptions<T> = RootExpectOptions(description, representationInsteadOfSubject, reporter)
|
||||
@ExperimentalComponentFactoryContainer
|
||||
override fun <I : Any> withChainedComponents(kClass: KClass<I>, factories: Sequence<(ComponentFactoryContainer) -> I>) {
|
||||
chainedComponents[kClass] = factories
|
||||
}
|
||||
|
||||
fun build(): RootExpectOptions<T> =
|
||||
RootExpectOptions(description, representationInsteadOfSubject, ComponentFactoryContainer.createIfNotEmpty(components, chainedComponents))
|
||||
}
|
||||
|
||||
@@ -24,7 +24,11 @@ class DefaultIterableLikeContainsInAnyOrderAssertions : IterableLikeContainsInAn
|
||||
expected: List<SC>,
|
||||
factory: ((T) -> Iterable<E>, S, List<IterableLikeContains.Checker>) -> IterableLikeContains.Creator<T, SC>
|
||||
): AssertionGroup {
|
||||
val creator = factory(checkerStepLogic.entryPointStepLogic.converter, checkerStepLogic.entryPointStepLogic.searchBehaviour, checkerStepLogic.checkers)
|
||||
val creator = factory(
|
||||
checkerStepLogic.entryPointStepLogic.converter,
|
||||
checkerStepLogic.entryPointStepLogic.searchBehaviour,
|
||||
checkerStepLogic.checkers
|
||||
)
|
||||
return creator.createAssertionGroup(checkerStepLogic.entryPointStepLogic.container, expected)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import ch.tutteli.atrium.core.getOrElse
|
||||
import ch.tutteli.atrium.creating.AssertionContainer
|
||||
import ch.tutteli.atrium.creating.CollectingExpect
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.creating.ExperimentalComponentFactoryContainer
|
||||
import ch.tutteli.atrium.creating.impl.DefaultComponentFactoryContainer
|
||||
import ch.tutteli.atrium.logic.collectForDifferentSubject
|
||||
import ch.tutteli.atrium.logic.creating.basic.contains.creators.impl.ContainsAssertionCreator
|
||||
import ch.tutteli.atrium.logic.creating.iterable.contains.IterableLikeContains
|
||||
@@ -94,6 +96,8 @@ class InAnyOrderEntriesAssertionCreator<E : Any, T : IterableLike>(
|
||||
//TODO 0.17.0 check if this is still state of the art to add a hint that no assertion was created
|
||||
// in the assertionCreator-lambda, maybe it is a special case and needs to be handled like this,
|
||||
// maybe it would be enough to collect
|
||||
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalComponentFactoryContainer::class)
|
||||
private fun addEmptyAssertionCreatorLambdaIfNecessary(
|
||||
container: AssertionContainer<*>,
|
||||
assertions: MutableList<Assertion>,
|
||||
@@ -101,7 +105,8 @@ class InAnyOrderEntriesAssertionCreator<E : Any, T : IterableLike>(
|
||||
count: Int
|
||||
) {
|
||||
if (searchCriterion != null && count == 0) {
|
||||
val collectingExpect = CollectingExpect<E>(None)
|
||||
// TODO if it is still state of the art, then use components from defined AssertionContainer
|
||||
val collectingExpect = CollectingExpect<E>(None, DefaultComponentFactoryContainer)
|
||||
// not using addAssertionsCreatedBy on purpose so that we don't append a failing assertion
|
||||
collectingExpect.searchCriterion()
|
||||
val collectedAssertions = collectingExpect.getAssertions()
|
||||
|
||||
@@ -5,10 +5,7 @@ import ch.tutteli.atrium.assertions.builders.assertionBuilder
|
||||
import ch.tutteli.atrium.assertions.builders.fixedClaimGroup
|
||||
import ch.tutteli.atrium.core.*
|
||||
import ch.tutteli.atrium.core.polyfills.fullName
|
||||
import ch.tutteli.atrium.creating.AssertionContainer
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.creating.FeatureExpect
|
||||
import ch.tutteli.atrium.creating.FeatureExpectOptions
|
||||
import ch.tutteli.atrium.creating.*
|
||||
import ch.tutteli.atrium.logic.creating.collectors.assertionCollector
|
||||
import ch.tutteli.atrium.logic.creating.collectors.collectAssertions
|
||||
import ch.tutteli.atrium.logic.creating.transformers.FeatureExtractor
|
||||
@@ -20,7 +17,7 @@ import ch.tutteli.atrium.translations.DescriptionFunLikeAssertion
|
||||
|
||||
class DefaultFeatureExtractor : FeatureExtractor {
|
||||
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class, ExperimentalComponentFactoryContainer::class)
|
||||
override fun <T, R> extract(
|
||||
container: AssertionContainer<T>,
|
||||
description: Translatable,
|
||||
@@ -42,7 +39,8 @@ class DefaultFeatureExtractor : FeatureExtractor {
|
||||
try {
|
||||
featureExtraction(subject).fold({ Left(None) }, { Right(it) })
|
||||
} catch (throwable: Throwable) {
|
||||
//TODO 0.16.0 should be taken from `container`
|
||||
// container.components.build<AtriumErrorAdjuster>().adjust(throwable)
|
||||
//TODO 0.16.0 use the above instead of this line as soon as CollectingExpect is also using the ComponentFactoryContainer
|
||||
reporter.atriumErrorAdjuster.adjust(throwable)
|
||||
Left(Some(throwable))
|
||||
}
|
||||
|
||||
@@ -4,9 +4,7 @@ import ch.tutteli.atrium.core.Either
|
||||
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
|
||||
import ch.tutteli.atrium.core.Left
|
||||
import ch.tutteli.atrium.core.Right
|
||||
import ch.tutteli.atrium.creating.AssertionContainer
|
||||
import ch.tutteli.atrium.creating.FeatureExpect
|
||||
import ch.tutteli.atrium.creating.FeatureExpectOptions
|
||||
import ch.tutteli.atrium.creating.*
|
||||
import ch.tutteli.atrium.logic.Fun0Assertions
|
||||
import ch.tutteli.atrium.logic.changeSubject
|
||||
import ch.tutteli.atrium.logic.creating.transformers.FeatureExtractorBuilder
|
||||
@@ -20,8 +18,6 @@ import kotlin.reflect.KClass
|
||||
|
||||
class DefaultFun0Assertions : Fun0Assertions {
|
||||
|
||||
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class)
|
||||
override fun <TExpected : Throwable> toThrow(
|
||||
container: AssertionContainer<out () -> Any?>,
|
||||
expectedType: KClass<TExpected>
|
||||
@@ -29,9 +25,11 @@ class DefaultFun0Assertions : Fun0Assertions {
|
||||
// we use manualFeature and not extractFeature since we never want to fail the feature extraction
|
||||
// because we want to show the planned downCast in the error message
|
||||
return container.manualFeature(THROWN_EXCEPTION_WHEN_CALLED) {
|
||||
catchAndAdjustThrowable(this)
|
||||
catchAndAdjustThrowable(container, this)
|
||||
.fold({ it }, { /* use null as subject in case no exception occurred */ null })
|
||||
}.transform().let { previousExpect ->
|
||||
@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)
|
||||
FeatureExpect(
|
||||
previousExpect,
|
||||
FeatureExpectOptions(representationInsteadOfFeature = { it ?: NO_EXCEPTION_OCCURRED })
|
||||
@@ -42,11 +40,17 @@ class DefaultFun0Assertions : Fun0Assertions {
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <R> catchAndAdjustThrowable(act: () -> R): Either<Throwable, R> =
|
||||
private inline fun <R> catchAndAdjustThrowable(
|
||||
container: AssertionContainer<*>,
|
||||
act: () -> R
|
||||
): Either<Throwable, R> =
|
||||
try {
|
||||
Right(act())
|
||||
} catch (throwable: Throwable) {
|
||||
//TODO should be taken from current expect once it is configured this way
|
||||
// @Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
// @UseExperimental(ExperimentalComponentFactoryContainer::class)
|
||||
// container.components.build<AtriumErrorAdjuster>().adjust(throwable)
|
||||
//TODO 0.16.0 use the above instead of this line as soon as CollectingExpect is also using the ComponentFactoryContainer
|
||||
reporter.atriumErrorAdjuster.adjust(throwable)
|
||||
Left(throwable)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package ch.tutteli.atrium.logic.impl
|
||||
|
||||
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
|
||||
import ch.tutteli.atrium.creating.AssertionContainer
|
||||
import ch.tutteli.atrium.creating.ExperimentalComponentFactoryContainer
|
||||
import ch.tutteli.atrium.creating.FeatureExpect
|
||||
import ch.tutteli.atrium.creating.FeatureExpectOptions
|
||||
import ch.tutteli.atrium.logic.*
|
||||
@@ -14,7 +15,7 @@ import kotlin.reflect.KClass
|
||||
class DefaultThrowableAssertions : ThrowableAssertions {
|
||||
|
||||
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class, ExperimentalComponentFactoryContainer::class)
|
||||
override fun <TExpected : Throwable> causeIsA(
|
||||
container: AssertionContainer<out Throwable>,
|
||||
expectedType: KClass<TExpected>
|
||||
|
||||
@@ -51,7 +51,6 @@ val <T> AssertionContainer<T>.changeSubject: SubjectChangerBuilder.KindStep<T>
|
||||
val <T> AssertionContainer<T>.extractFeature: FeatureExtractorBuilder.DescriptionStep<T>
|
||||
get() = FeatureExtractorBuilder(this)
|
||||
|
||||
|
||||
/**
|
||||
* Use this function if you want to make [Assertion]s about a feature or you perform a type transformation or any
|
||||
* other action which results in an [Expect] being created for a different subject and
|
||||
|
||||
@@ -3,6 +3,7 @@ package ch.tutteli.atrium.logic.kotlin_1_3.impl
|
||||
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
|
||||
import ch.tutteli.atrium.core.Option
|
||||
import ch.tutteli.atrium.creating.AssertionContainer
|
||||
import ch.tutteli.atrium.creating.ExperimentalComponentFactoryContainer
|
||||
import ch.tutteli.atrium.creating.FeatureExpect
|
||||
import ch.tutteli.atrium.creating.FeatureExpectOptions
|
||||
import ch.tutteli.atrium.logic.creating.transformers.SubjectChangerBuilder
|
||||
@@ -28,7 +29,7 @@ class DefaultResultAssertions : ResultAssertions {
|
||||
.build()
|
||||
|
||||
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class, ExperimentalComponentFactoryContainer::class)
|
||||
override fun <TExpected : Throwable> isFailureOfType(
|
||||
container: AssertionContainer<out Result<*>>,
|
||||
expectedType: KClass<TExpected>
|
||||
|
||||
@@ -7,9 +7,7 @@ import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
|
||||
import ch.tutteli.atrium.core.None
|
||||
import ch.tutteli.atrium.core.Option
|
||||
import ch.tutteli.atrium.core.Some
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.creating.RootExpect
|
||||
import ch.tutteli.atrium.creating.RootExpectOptions
|
||||
import ch.tutteli.atrium.creating.*
|
||||
import ch.tutteli.atrium.domain.builders.reporting.impl.verb.AssertionVerbStepImpl
|
||||
import ch.tutteli.atrium.domain.builders.reporting.impl.verb.FinalStepImpl
|
||||
import ch.tutteli.atrium.domain.builders.reporting.impl.verb.OptionsChooserImpl
|
||||
@@ -260,8 +258,18 @@ data class ExpectOptions<T>(
|
||||
)
|
||||
|
||||
@ExperimentalNewExpectTypes
|
||||
@Suppress("DEPRECATION" /* RequiresOptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalComponentFactoryContainer::class)
|
||||
fun toRootExpectOptions(): RootExpectOptions<T> =
|
||||
RootExpectOptions(assertionVerb, representationInsteadOfSubject, reporter)
|
||||
RootExpectOptions(
|
||||
assertionVerb,
|
||||
representationInsteadOfSubject,
|
||||
reporter?.let { r ->
|
||||
ComponentFactoryContainer.createIfNotEmpty(
|
||||
mapOf(Reporter::class to { _ -> r }),
|
||||
emptyMap()
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@Suppress("FunctionName")
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
//TODO remove file with 0.17.0
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package ch.tutteli.atrium.domain.builders.reporting.impl
|
||||
|
||||
import ch.tutteli.atrium.core.coreFactory
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
//TODO remove file with 0.17.0
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package ch.tutteli.atrium.domain.builders.reporting.impl
|
||||
|
||||
import ch.tutteli.atrium.core.coreFactory
|
||||
|
||||
@@ -4,19 +4,23 @@ import ch.tutteli.atrium.assertions.Assertion
|
||||
import ch.tutteli.atrium.assertions.AssertionGroup
|
||||
import ch.tutteli.atrium.assertions.builders.assertionBuilder
|
||||
import ch.tutteli.atrium.assertions.builders.invisibleGroup
|
||||
import ch.tutteli.atrium.assertions.builders.withExplanatoryAssertion
|
||||
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
|
||||
import ch.tutteli.atrium.core.Option
|
||||
import ch.tutteli.atrium.creating.CollectingExpect
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.creating.ExperimentalComponentFactoryContainer
|
||||
import ch.tutteli.atrium.creating.impl.DefaultComponentFactoryContainer
|
||||
import ch.tutteli.atrium.reporting.Text
|
||||
import ch.tutteli.atrium.translations.DescriptionBasic
|
||||
import ch.tutteli.atrium.translations.ErrorMessages
|
||||
|
||||
fun <T> _collect(
|
||||
maybeSubject: Option<T>,
|
||||
assertionCreator: Expect<T>.() -> Unit
|
||||
): Assertion {
|
||||
val collectedAssertions = CollectingExpect(maybeSubject)
|
||||
@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)
|
||||
//TODO 0.16.0 don't use DefaultComponentFactoryContainer but the one from the container
|
||||
val collectedAssertions = CollectingExpect(maybeSubject, DefaultComponentFactoryContainer)
|
||||
.addAssertionsCreatedBy(assertionCreator)
|
||||
.getAssertions()
|
||||
return if (collectedAssertions.size > 1) {
|
||||
@@ -29,7 +33,7 @@ fun <T> _collect(
|
||||
fun <T> _collectForComposition(
|
||||
maybeSubject: Option<T>,
|
||||
assertionCreatorOrNull: (Expect<T>.() -> Unit)?
|
||||
): List<Assertion> = collectAssertions(maybeSubject, assertionCreatorOrNull)
|
||||
): List<Assertion> = collectAssertions(maybeSubject, assertionCreatorOrNull)
|
||||
|
||||
//TODO 0.16.0: better replace by silentToBeNullIfNullGiven?
|
||||
private fun <T> collectAssertions(
|
||||
@@ -38,7 +42,10 @@ private fun <T> collectAssertions(
|
||||
): List<Assertion> {
|
||||
//TODO 0.16.0: almost same as in _containsKeyWithNullableValueAssertions
|
||||
return if (assertionCreatorOrNull != null) {
|
||||
CollectingExpect(maybeSubject)
|
||||
@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)
|
||||
//TODO 0.16.0 don't use DefaultComponentFactoryContainer but the one from the container
|
||||
CollectingExpect(maybeSubject, DefaultComponentFactoryContainer)
|
||||
.addAssertionsCreatedBy(assertionCreatorOrNull)
|
||||
.getAssertions()
|
||||
} else {
|
||||
|
||||
@@ -10,11 +10,13 @@ import ch.tutteli.atrium.assertions.ExplanatoryAssertionGroupType
|
||||
import ch.tutteli.atrium.assertions.builders.assertionBuilder
|
||||
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
|
||||
import ch.tutteli.atrium.core.None
|
||||
import ch.tutteli.atrium.core.coreFactory
|
||||
import ch.tutteli.atrium.creating.CollectingExpect
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.creating.ExperimentalComponentFactoryContainer
|
||||
import ch.tutteli.atrium.logic._logic
|
||||
import ch.tutteli.atrium.logic.creating.RootExpectBuilder
|
||||
import ch.tutteli.atrium.logic.creating.RootExpectOptions
|
||||
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
|
||||
import ch.tutteli.atrium.reporting.erroradjusters.NoOpAtriumErrorAdjuster
|
||||
import org.spekframework.spek2.Spek
|
||||
import org.spekframework.spek2.style.specification.describe
|
||||
|
||||
@@ -26,7 +28,9 @@ abstract class SubjectLessSpec<T>(
|
||||
describe("${groupPrefix}assertion function can be used in an ${AssertionGroup::class.simpleName} with an ${ExplanatoryAssertionGroupType::class.simpleName} and report without failure") {
|
||||
assertionCreator.forEach { (name, createAssertion) ->
|
||||
it("fun `$name`") {
|
||||
val assertions = CollectingExpect<T>(None)
|
||||
@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)
|
||||
val assertions = CollectingExpect<T>(None, expect(1)._logic.components)
|
||||
.addAssertionsCreatedBy(createAssertion)
|
||||
.getAssertions()
|
||||
|
||||
@@ -34,17 +38,12 @@ abstract class SubjectLessSpec<T>(
|
||||
|
||||
|
||||
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class, ExperimentalComponentFactoryContainer::class)
|
||||
val container = RootExpectBuilder.forSubject(1.0)
|
||||
.withVerb("custom assertion verb")
|
||||
.withOptions(
|
||||
RootExpectOptions(
|
||||
reporter = coreFactory.newOnlyFailureReporter(
|
||||
coreFactory.newAssertionFormatterFacade(coreFactory.newAssertionFormatterController()),
|
||||
coreFactory.newNoOpAtriumErrorAdjuster()
|
||||
)
|
||||
)
|
||||
)
|
||||
.withOptions {
|
||||
withComponent(AtriumErrorAdjuster::class) { _ -> NoOpAtriumErrorAdjuster }
|
||||
}
|
||||
.build()
|
||||
|
||||
val explanatoryGroup = assertionBuilder.explanatoryGroup
|
||||
@@ -59,7 +58,9 @@ abstract class SubjectLessSpec<T>(
|
||||
describe("${groupPrefix}assertion function does not hold if there is no subject") {
|
||||
assertionCreator.forEach { (name, createAssertion) ->
|
||||
it("fun `$name`") {
|
||||
val assertions = CollectingExpect<T>(None)
|
||||
@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)
|
||||
val assertions = CollectingExpect<T>(None, expect(1)._logic.components)
|
||||
.addAssertionsCreatedBy(createAssertion)
|
||||
.getAssertions()
|
||||
expect(assertions).all { feature(Assertion::holds).toBe(false) }
|
||||
|
||||
@@ -12,6 +12,7 @@ import ch.tutteli.atrium.core.coreFactory
|
||||
import ch.tutteli.atrium.reporting.AssertionFormatterFacade
|
||||
import ch.tutteli.atrium.reporting.AtriumErrorAdjuster
|
||||
import ch.tutteli.atrium.reporting.Reporter
|
||||
import ch.tutteli.atrium.reporting.erroradjusters.NoOpAtriumErrorAdjuster
|
||||
import ch.tutteli.atrium.reporting.translating.UsingDefaultTranslator
|
||||
import ch.tutteli.atrium.specs.AssertionVerb
|
||||
import ch.tutteli.atrium.specs.describeFunTemplate
|
||||
@@ -37,7 +38,7 @@ abstract class OnlyFailureReporterSpec(
|
||||
coreFactory.newDetailedObjectFormatter(translator), translator
|
||||
)
|
||||
}
|
||||
val testee = testeeFactory(facade, coreFactory.newNoOpAtriumErrorAdjuster())
|
||||
val testee = testeeFactory(facade, NoOpAtriumErrorAdjuster)
|
||||
|
||||
describeFun(testee::format.name) {
|
||||
val sb = StringBuilder()
|
||||
@@ -83,9 +84,7 @@ abstract class OnlyFailureReporterSpec(
|
||||
val assertionFormatterFacade = mockk<AssertionFormatterFacade>()
|
||||
every { assertionFormatterFacade.format(any(), any(), any()) } just Runs
|
||||
|
||||
val testeeWithMockedFacade = testeeFactory(
|
||||
assertionFormatterFacade, coreFactory.newNoOpAtriumErrorAdjuster()
|
||||
)
|
||||
val testeeWithMockedFacade = testeeFactory(assertionFormatterFacade, NoOpAtriumErrorAdjuster)
|
||||
|
||||
it("delegates to ${assertionFormatterFacade::class.simpleName}") {
|
||||
testeeWithMockedFacade.format(basicAssertion, sb)
|
||||
|
||||
@@ -4,11 +4,13 @@ import ch.tutteli.atrium.api.fluent.en_GB.*
|
||||
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
|
||||
import ch.tutteli.atrium.core.polyfills.fullName
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.creating.ExperimentalComponentFactoryContainer
|
||||
import ch.tutteli.atrium.domain.builders.reporting.ReporterBuilder
|
||||
import ch.tutteli.atrium.logic._logic
|
||||
import ch.tutteli.atrium.logic.changeSubject
|
||||
import ch.tutteli.atrium.logic.creating.RootExpectBuilder
|
||||
import ch.tutteli.atrium.logic.creating.RootExpectOptions
|
||||
import ch.tutteli.atrium.reporting.Reporter
|
||||
import ch.tutteli.atrium.specs.AssertionVerb
|
||||
import ch.tutteli.atrium.specs.prefixedDescribeTemplate
|
||||
import ch.tutteli.atrium.specs.toBeDescr
|
||||
@@ -174,12 +176,15 @@ private fun Suite.testNonNullableSubject(assertionVerb: (Int) -> Expect<Int>) {
|
||||
|
||||
|
||||
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class, ExperimentalComponentFactoryContainer::class)
|
||||
// does not make sense to test the verbs with the verbs themselves. Thus we create our own assertion verb here
|
||||
private fun <R> assert(act: () -> R): Expect<() -> R> =
|
||||
RootExpectBuilder.forSubject(act)
|
||||
.withVerb(AssertionVerb.EXPECT_THROWN)
|
||||
.withOptions(RootExpectOptions(reporter = AtriumReporterSupplier.REPORTER))
|
||||
.withOptions {
|
||||
//TODO we only use the default components here, I guess once we get rid of reporter we can get rid of this as well
|
||||
withComponent(Reporter::class) { _ -> AtriumReporterSupplier.REPORTER }
|
||||
}
|
||||
.build()
|
||||
|
||||
private object AtriumReporterSupplier {
|
||||
|
||||
@@ -3,8 +3,8 @@ package ch.tutteli.atrium.specs.reporting.translating
|
||||
import ch.tutteli.atrium.api.fluent.en_GB.*
|
||||
import ch.tutteli.atrium.api.verbs.internal.expect
|
||||
import ch.tutteli.atrium.core.ExperimentalNewExpectTypes
|
||||
import ch.tutteli.atrium.creating.ExperimentalComponentFactoryContainer
|
||||
import ch.tutteli.atrium.logic.creating.RootExpectBuilder
|
||||
import ch.tutteli.atrium.logic.creating.RootExpectOptions
|
||||
import ch.tutteli.atrium.reporting.Reporter
|
||||
import ch.tutteli.atrium.reporting.translating.Locale
|
||||
import ch.tutteli.atrium.reporting.translating.StringBasedTranslatable
|
||||
@@ -104,24 +104,28 @@ abstract class TranslatorIntSpec(
|
||||
fun prefixedDescribe(description: String, body: Suite.() -> Unit) =
|
||||
prefixedDescribeTemplate(describePrefix, description, body)
|
||||
|
||||
val reporterDeChFallbackFr = reporterFactory(Locale("de", "CH"), arrayOf(Locale("fr")))
|
||||
|
||||
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class, ExperimentalComponentFactoryContainer::class)
|
||||
fun <T : Any> assertWithDeCh_Fr(subject: T) =
|
||||
RootExpectBuilder.forSubject(subject)
|
||||
.withVerb(AssertionVerb.ASSERT)
|
||||
.withOptions(RootExpectOptions(reporter = reporterDeChFallbackFr))
|
||||
.withOptions {
|
||||
withComponent(Reporter::class) { _ ->
|
||||
reporterFactory(Locale("de", "CH"), arrayOf(Locale("fr")))
|
||||
}
|
||||
}
|
||||
.build()
|
||||
|
||||
val reporterDeChFallbackFrIt = reporterFactory(Locale("de", "CH"), arrayOf(Locale("fr", "CH"), Locale("it", "CH")))
|
||||
|
||||
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class, ExperimentalComponentFactoryContainer::class)
|
||||
fun <T : Any> assertWithDeCh_Fr_It(subject: T) =
|
||||
RootExpectBuilder.forSubject(subject)
|
||||
.withVerb(AssertionVerb.ASSERT)
|
||||
.withOptions(RootExpectOptions(reporter = reporterDeChFallbackFrIt))
|
||||
.withOptions {
|
||||
withComponent(Reporter::class) { _ ->
|
||||
reporterFactory(Locale("de", "CH"), arrayOf(Locale("fr", "CH"), Locale("it", "CH")))
|
||||
}
|
||||
}
|
||||
.build()
|
||||
|
||||
val descriptionAnyAssertion = DescriptionAnyAssertion::class.simpleName
|
||||
@@ -277,14 +281,17 @@ abstract class TranslatorIntSpec(
|
||||
val zhWithScript = "zh_$script"
|
||||
countries.forEach { country ->
|
||||
val locale = Locale("zh", country)
|
||||
val reporter = reporterFactory(locale, arrayOf())
|
||||
|
||||
|
||||
@Suppress("DEPRECATION" /* OptIn is only available since 1.3.70 which we cannot use if we want to support 1.2 */)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class)
|
||||
@UseExperimental(ExperimentalNewExpectTypes::class, ExperimentalComponentFactoryContainer::class)
|
||||
val assert = RootExpectBuilder.forSubject(1)
|
||||
.withVerb(AssertionVerb.ASSERT)
|
||||
.withOptions(RootExpectOptions(reporter = reporter))
|
||||
.withOptions {
|
||||
withComponent(Reporter::class) { _ ->
|
||||
reporterFactory(locale, arrayOf())
|
||||
}
|
||||
}
|
||||
.build()
|
||||
|
||||
prefixedDescribe("primary locale is 'zh_$country' and no fallback defined") {
|
||||
|
||||
Reference in New Issue
Block a user