fix indentation for explanatory assertion group with info bullet-point

This commit is contained in:
Robert Stoll
2020-12-21 14:38:36 +01:00
parent 35679b6e6b
commit 880ccb2f9e
12 changed files with 110 additions and 55 deletions

View File

@@ -36,7 +36,6 @@ class AnyAssertionsSpec : ch.tutteli.atrium.specs.integration.AnyAssertionsSpec(
fun1(Expect<DataClass?>::isNotIn).withNullableSuffix(),
fun2(Expect<String>::because),
fun2(Expect<Int>::because),
" ",
"${Expect<Int?>::toBe.name}(null)" to Companion::toBeNull,
fun1(Expect<Int?>::toBeNullIfNullGivenElse),
@@ -52,7 +51,7 @@ class AnyAssertionsSpec : ch.tutteli.atrium.specs.integration.AnyAssertionsSpec(
getAndImmediatePair(),
getAndLazyPair(),
" "
"◆ ", "", " "
) {
companion object {
@@ -71,7 +70,10 @@ class AnyAssertionsSpec : ch.tutteli.atrium.specs.integration.AnyAssertionsSpec(
expect.isA<SuperType>()
@Suppress("RemoveExplicitTypeArguments")
private fun isASuperType(expect: Expect<out Any?>, assertionCreator: Expect<SuperType>.() -> Unit): Expect<SuperType> =
private fun isASuperType(
expect: Expect<out Any?>,
assertionCreator: Expect<SuperType>.() -> Unit
): Expect<SuperType> =
expect.isA<SuperType> { assertionCreator() }
@Suppress("RemoveExplicitTypeArguments")
@@ -79,7 +81,10 @@ class AnyAssertionsSpec : ch.tutteli.atrium.specs.integration.AnyAssertionsSpec(
expect.isA<SubType>()
@Suppress("RemoveExplicitTypeArguments")
private fun isASubType(expect: Expect<out Any?>, assertionCreator: Expect<SubType>.() -> Unit): Expect<SubType> =
private fun isASubType(
expect: Expect<out Any?>,
assertionCreator: Expect<SubType>.() -> Unit
): Expect<SubType> =
expect.isA<SubType> { assertionCreator() }
private val andImmediate: KProperty1<Expect<Int>, Expect<Int>> = Expect<Int>::and

View File

@@ -36,7 +36,6 @@ class AnyAssertionsSpec : ch.tutteli.atrium.specs.integration.AnyAssertionsSpec(
fun1(Expect<DataClass?>::isNotIn).withNullableSuffix(),
fun2<String, String, Expect<String>.() -> Unit>(Companion::because),
fun2<Int, String, Expect<Int>.() -> Unit>(Companion::becauseOfInt),
"(i) ",
"${Expect<Int?>::toBe.name}(null)" to Companion::toBeNull,
fun1(Expect<Int?>::toBeNullIfNullGivenElse),
@@ -52,7 +51,7 @@ class AnyAssertionsSpec : ch.tutteli.atrium.specs.integration.AnyAssertionsSpec(
getAndImmediatePair(),
getAndLazyPair(),
"- "
"* ", "- ","(i) "
) {
companion object : WithAsciiReporter() {

View File

@@ -1,6 +1,6 @@
package ch.tutteli.atrium.api.infix.en_GB.samples
import ch.tutteli.atrium.api.fluent.en_GB.toBe
import ch.tutteli.atrium.api.infix.en_GB.toBe
import ch.tutteli.atrium.api.infix.en_GB.*
import ch.tutteli.atrium.api.verbs.internal.expect
import kotlin.test.Test

View File

@@ -40,7 +40,8 @@ class AssertionFormatterParameterObject private constructor(
*
* @return The newly created [AssertionFormatterParameterObject].
*/
fun createChildWithNewPrefix(newPrefix: String) = createChildWithNewPrefixAndAdditionalIndent(newPrefix, 0)
fun createChildWithNewPrefix(newPrefix: String) =
createChildWithNewPrefixAndAdditionalIndent(newPrefix, additionalIndent = 0)
/**
@@ -75,7 +76,14 @@ class AssertionFormatterParameterObject private constructor(
* @return The newly created [AssertionFormatterParameterObject].
*/
fun createForDoNotFilterAssertionGroup(): AssertionFormatterParameterObject =
AssertionFormatterParameterObject(sb, prefix, indentLevel, assertionFilter, numberOfDoNotFilterGroups + 1, numberOfExplanatoryGroups)
AssertionFormatterParameterObject(
sb,
prefix,
indentLevel,
assertionFilter,
numberOfDoNotFilterGroups + 1,
numberOfExplanatoryGroups
)
/**
@@ -85,8 +93,15 @@ class AssertionFormatterParameterObject private constructor(
*
* @return The newly created [AssertionFormatterParameterObject].
*/
fun createForExplanatoryFilterAssertionGroup(): AssertionFormatterParameterObject =
AssertionFormatterParameterObject(sb, prefix, indentLevel, assertionFilter, numberOfDoNotFilterGroups + 1, numberOfExplanatoryGroups + 1)
fun createForExplanatoryFilterAssertionGroup(newPrefix : String = prefix): AssertionFormatterParameterObject =
AssertionFormatterParameterObject(
sb,
newPrefix,
indentLevel,
assertionFilter,
numberOfDoNotFilterGroups + 1,
numberOfExplanatoryGroups + 1
)
/**

View File

@@ -45,11 +45,15 @@ class TextExplanatoryAssertionGroupFormatter(
assertionGroup: AssertionGroup,
parameterObject: AssertionFormatterParameterObject
): AssertionFormatterParameterObject {
val bulletPoint = when (assertionGroup.type) {
WarningAssertionGroupType -> warningBulletPoint
InformationAssertionGroupType -> informationBulletPoint
else -> explanatoryBulletPoint
// we don't indent in case of an InformationAssertionGroupType
return if (assertionGroup.type == InformationAssertionGroupType) {
parameterObject.createForExplanatoryFilterAssertionGroup(informationBulletPoint)
} else {
val bulletPoint = when (assertionGroup.type) {
WarningAssertionGroupType -> warningBulletPoint
else -> explanatoryBulletPoint
}
parameterObject.createForExplanatoryFilterAssertionGroup().createChildWithNewPrefix(bulletPoint)
}
return parameterObject.createForExplanatoryFilterAssertionGroup().createChildWithNewPrefix(bulletPoint)
}
}

View File

@@ -36,13 +36,13 @@ class DefaultAnyAssertions : AnyAssertions {
reason: String,
assertionCreator: Expect<T>.() -> Unit
): Assertion {
val assertion = assertionCollector.collect(container.maybeSubject, assertionCreator)
return assertionBuilder.invisibleGroup.withAssertions(
assertionCollector.collect(container.maybeSubject, assertionCreator),
ExplanatoryGroup
.GroupTypeOption
.create()
assertion,
assertionBuilder.explanatoryGroup
.withInformationType
.withExplanatoryAssertion(TranslatableWithArgs(BECAUSE, reason)).build()
.withExplanatoryAssertion(TranslatableWithArgs(BECAUSE, reason))
.build()
).build()
}

View File

@@ -3,10 +3,12 @@ package ch.tutteli.atrium.specs.integration
import ch.tutteli.atrium.api.fluent.en_GB.*
import ch.tutteli.atrium.api.verbs.internal.expect
import ch.tutteli.atrium.assertions.DescriptiveAssertion
import ch.tutteli.atrium.core.polyfills.format
import ch.tutteli.atrium.core.polyfills.fullName
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.reporting.Text
import ch.tutteli.atrium.specs.*
import ch.tutteli.atrium.specs.integration.MapLikeContainsSpecBase.Companion.separator
import ch.tutteli.atrium.translations.DescriptionAnyAssertion.*
import ch.tutteli.atrium.translations.DescriptionAnyAssertion.NOT_TO_BE
import ch.tutteli.atrium.translations.DescriptionAnyAssertion.TO_BE
@@ -42,7 +44,6 @@ abstract class AnyAssertionsSpec(
isNotInNullableDataClass: Fun1<DataClass?, Iterable<DataClass?>>,
because: Fun2<String, String, Expect<String>.() -> Unit>,
becauseInt: Fun2<Int, String, Expect<Int>.() -> Unit>,
informationBulletPoint: String,
toBeNull: Fun0<Int?>,
toBeNullIfNullGivenElse: Fun1<Int?, (Expect<Int>.() -> Unit)?>,
@@ -60,7 +61,10 @@ abstract class AnyAssertionsSpec(
andPair: Fun0<Int>,
andLazyPair: Fun1<Int, Expect<Int>.() -> Unit>,
rootBulletPoint: String,
listBulletPoint: String,
informationBulletPoint: String,
describePrefix: String = "[Atrium] "
) : Spek({
@@ -117,6 +121,8 @@ abstract class AnyAssertionsSpec(
fun describeFun(vararg pairs: SpecPair<*>, body: Suite.() -> Unit) =
describeFunTemplate(describePrefix, pairs.map { it.name }.toTypedArray(), body = body)
val indentBulletPoint = " ".repeat(rootBulletPoint.length)
fun <T : Int?> Suite.checkInt(
description: String,
expectSubject: Expect<T>,
@@ -177,7 +183,10 @@ abstract class AnyAssertionsSpec(
expectSubject.isNoneOfFun(1, arrayOf(2))
}.toThrow<AssertionError> {
message {
contains(IS_NONE_OF.getDefault(), "${listBulletPoint}1")
containsRegex(
"\\Q$rootBulletPoint${IS_NONE_OF.getDefault()}\\E:.*$separator" +
"$indentBulletPoint${listBulletPoint}1"
)
containsNot("$listBulletPoint 2")
}
}
@@ -751,6 +760,9 @@ abstract class AnyAssertionsSpec(
val becauseFun = because.lambda
val becauseFunForInt = becauseInt.lambda
fun Expect<String>.containsBecause(reason: String) =
contains.exactly(1).value("$separator${informationBulletPoint}${BECAUSE.getDefault().format(reason)}")
it("the test on the supplied subject is not throwing an assertion error") {
expect("filename")
.becauseFun("? is not allowed in file names on Windows") {
@@ -766,7 +778,9 @@ abstract class AnyAssertionsSpec(
startsWith("f")
}
}.toThrow<AssertionError> {
messageContains("${informationBulletPoint}${String.format(BECAUSE.getDefault(), "? is not allowed in file names on Windows")}")
message {
containsBecause("? is not allowed in file names on Windows")
}
}
}
@@ -779,7 +793,9 @@ abstract class AnyAssertionsSpec(
isNoneOf(21)
}
}.toThrow<AssertionError> {
messageContains("${informationBulletPoint}${String.format(BECAUSE.getDefault(), "we use the definition that teens are between 12 and 18 years old")}")
message {
containsBecause( "we use the definition that teens are between 12 and 18 years old")
}
}
}
}

View File

@@ -43,6 +43,7 @@ abstract class AssertionFormatterSpecBase(spec: Root.() -> Unit) : Spek({
fun createFacade() = coreFactory.newAssertionFormatterFacade(coreFactory.newAssertionFormatterController())
//TODO remove with 1.0.0
fun createFacade(testeeFactory: (Map<KClass<out BulletPointIdentifier>, String>, AssertionFormatterController, ObjectFormatter, Translator) -> AssertionFormatter): AssertionFormatterFacade =
createFacade(mapOf(), testeeFactory)

View File

@@ -15,4 +15,5 @@ abstract class TextExplanatoryAssertionGroupFormatterSpec(
ExplanatoryAssertionGroupType::class,
object : ExplanatoryAssertionGroupType {},
{ assertionBuilder.explanatoryGroup.withDefaultType.withAssertions(it).build() },
describePrefix)
describePrefix
)

View File

@@ -14,15 +14,17 @@ abstract class TextExplanatoryBasedAssertionGroupFormatterSpec<T : ExplanatoryAs
assertionGroupTypeClass: KClass<T>,
anonymousAssertionGroupType: T,
groupFactory: (List<Assertion>) -> AssertionGroup,
describePrefix: String = "[Atrium] "
describePrefix: String = "[Atrium] ",
withIndent: Boolean = true
) : Spek({
@Suppress("DEPRECATION" /* TODO remove with 1.0.0 */)
@Suppress("DEPRECATION" /* TODO inline TextIndentBasedAssertionGroupFormatterSpec with 1.0.0 */)
include(object : TextIndentBasedAssertionGroupFormatterSpec<T>(
testeeFactory,
assertionGroupTypeClass,
anonymousAssertionGroupType,
groupFactory,
describePrefix
describePrefix,
withIndent
) {})
})

View File

@@ -1,5 +1,6 @@
package ch.tutteli.atrium.specs.reporting
import ch.tutteli.atrium.api.fluent.en_GB.feature
import ch.tutteli.atrium.api.fluent.en_GB.toBe
import ch.tutteli.atrium.api.verbs.internal.expect
import ch.tutteli.atrium.assertions.*
@@ -19,7 +20,8 @@ abstract class TextIndentBasedAssertionGroupFormatterSpec<T : AssertionGroupType
assertionGroupTypeClass: KClass<T>,
anonymousAssertionGroupType: T,
groupFactory: (List<Assertion>) -> AssertionGroup,
describePrefix: String = "[Atrium] "
describePrefix: String = "[Atrium] ",
withIndent: Boolean = true
) : AssertionFormatterSpecBase({
fun describeFun(vararg funName: String, body: Suite.() -> Unit) =
@@ -28,21 +30,21 @@ abstract class TextIndentBasedAssertionGroupFormatterSpec<T : AssertionGroupType
val indentBulletPoint = " +"
val indentIndentBulletPoint = " ".repeat(indentBulletPoint.length + 1)
val facade =
createFacade(assertionGroupTypeClass to "$indentBulletPoint ") { bulletPoints, controller, _, _ ->
testeeFactory(bulletPoints, controller)
}
val facade = createFacade(assertionGroupTypeClass to "$indentBulletPoint ") { bulletPoints, controller, _, _ ->
testeeFactory(bulletPoints, controller)
}
describeFun(AssertionFormatter::canFormat.name) {
val testee = testeeFactory(bulletPoints, coreFactory.newAssertionFormatterController())
it("returns true for an ${AssertionGroup::class.simpleName} with type object: ${assertionGroupTypeClass.simpleName}") {
val result = testee.canFormat(
assertionBuilder.customType(anonymousAssertionGroupType)
.withDescriptionAndRepresentation(Untranslatable.EMPTY, 1)
.withAssertions(listOf())
.build()
)
expect(result).toBe(true)
expect(testee).feature {
f(
it::canFormat, assertionBuilder.customType(anonymousAssertionGroupType)
.withDescriptionAndRepresentation(Untranslatable.EMPTY, 1)
.withAssertions(listOf())
.build()
)
}.toBe(true)
}
}
@@ -61,7 +63,7 @@ abstract class TextIndentBasedAssertionGroupFormatterSpec<T : AssertionGroupType
val indentAssertionGroup = groupFactory(assertions)
context("format directly the group (no prefix given)") {
it("puts the assertions one under the other and indents the second one including a prefix") {
it("puts the assertions one under the other including a prefix") {
facade.format(
indentAssertionGroup,
sb,
@@ -75,8 +77,10 @@ abstract class TextIndentBasedAssertionGroupFormatterSpec<T : AssertionGroupType
}
}
context("in an ${AssertionGroup::class.simpleName} of type ${FeatureAssertionGroupType::class.simpleName}") {
it("puts the assertions one under the other and indents the second one including a prefix") {
it("puts the assertions one under the other including a prefix ${if(withIndent) "and indent" else "but without indent"}") {
val featureAssertions = listOf(
indentAssertionGroup,
assertionBuilder.descriptive.failing.withDescriptionAndRepresentation(
@@ -93,11 +97,14 @@ abstract class TextIndentBasedAssertionGroupFormatterSpec<T : AssertionGroupType
sb,
alwaysTrueAssertionFilter
)
val indent = if(withIndent) indentFeatureBulletPoint else ""
expect(sb.toString()).toBe(
lineSeperator
+ "$arrow ${AssertionVerb.ASSERT.getDefault()}: 10$lineSeperator"
+ "$indentArrow$indentFeatureBulletPoint$indentBulletPoint ${AssertionVerb.ASSERT.getDefault()}: 1$lineSeperator"
+ "$indentArrow$indentFeatureBulletPoint$indentBulletPoint ${AssertionVerb.EXPECT_THROWN.getDefault()}: 2$lineSeperator"
+ "$indentArrow$indent$indentBulletPoint ${AssertionVerb.ASSERT.getDefault()}: 1$lineSeperator"
+ "$indentArrow$indent$indentBulletPoint ${AssertionVerb.EXPECT_THROWN.getDefault()}: 2$lineSeperator"
+ "$indentArrow$featureBulletPoint ${AssertionVerb.ASSERT.getDefault()}: 20"
)
}
@@ -116,7 +123,9 @@ abstract class TextIndentBasedAssertionGroupFormatterSpec<T : AssertionGroupType
.withAssertions(listAssertions)
.build()
it("puts the assertions one under the other and indents the second one including a prefix") {
val indent = if(withIndent) indentListBulletPoint else ""
it("puts the assertions one under the other including a prefix ${if(withIndent) "and indent" else "but without indent"}") {
facade.format(
listAssertionGroup,
sb,
@@ -125,14 +134,14 @@ abstract class TextIndentBasedAssertionGroupFormatterSpec<T : AssertionGroupType
expect(sb.toString()).toBe(
lineSeperator
+ "${AssertionVerb.ASSERT.getDefault()}: 10$lineSeperator"
+ "$indentListBulletPoint$indentBulletPoint ${AssertionVerb.ASSERT.getDefault()}: 1$lineSeperator"
+ "$indentListBulletPoint$indentBulletPoint ${AssertionVerb.EXPECT_THROWN.getDefault()}: 2$lineSeperator"
+ "$indent$indentBulletPoint ${AssertionVerb.ASSERT.getDefault()}: 1$lineSeperator"
+ "$indent$indentBulletPoint ${AssertionVerb.EXPECT_THROWN.getDefault()}: 2$lineSeperator"
+ "$listBulletPoint ${AssertionVerb.ASSERT.getDefault()}: 20"
)
}
context("in another ${AssertionGroup::class.simpleName} of type ${ListAssertionGroupType::class.simpleName}") {
it("puts the assertions one under the other and indents as the other assertions but adds an extra indent to the second assertion including a prefix") {
it("puts the assertions one under the other and indents as the other assertions but ${if(withIndent) "adds an extra indent including a prefix" else "uses a different prefix"} ") {
val listAssertions2 = listOf(
listAssertionGroup,
assertionBuilder.descriptive.failing.withDescriptionAndRepresentation(
@@ -153,8 +162,8 @@ abstract class TextIndentBasedAssertionGroupFormatterSpec<T : AssertionGroupType
lineSeperator
+ "${AssertionVerb.ASSERT.getDefault()}: 5$lineSeperator"
+ "$listBulletPoint ${AssertionVerb.ASSERT.getDefault()}: 10$lineSeperator"
+ "$indentListBulletPoint$indentListBulletPoint$indentBulletPoint ${AssertionVerb.ASSERT.getDefault()}: 1$lineSeperator"
+ "$indentListBulletPoint$indentListBulletPoint$indentBulletPoint ${AssertionVerb.EXPECT_THROWN.getDefault()}: 2$lineSeperator"
+ "$indentListBulletPoint$indent$indentBulletPoint ${AssertionVerb.ASSERT.getDefault()}: 1$lineSeperator"
+ "$indentListBulletPoint$indent$indentBulletPoint ${AssertionVerb.EXPECT_THROWN.getDefault()}: 2$lineSeperator"
+ "$indentListBulletPoint$listBulletPoint ${AssertionVerb.ASSERT.getDefault()}: 20$lineSeperator"
+ "$listBulletPoint ${AssertionVerb.EXPECT_THROWN.getDefault()}: 30"
)
@@ -178,7 +187,9 @@ abstract class TextIndentBasedAssertionGroupFormatterSpec<T : AssertionGroupType
.withAssertions(indentAssertions)
.build()
it("puts the assertions one under the other and adds an extra indent to the second one") {
val indent = if(withIndent) indentIndentBulletPoint else ""
it("puts the assertions one under the other ${if(withIndent) "but adds an extra indent including" else ""}") {
facade.format(
indentAssertionGroup2,
sb,
@@ -187,8 +198,8 @@ abstract class TextIndentBasedAssertionGroupFormatterSpec<T : AssertionGroupType
expect(sb.toString()).toBe(
lineSeperator
+ "$indentBulletPoint ${AssertionVerb.ASSERT.getDefault()}: 21$lineSeperator"
+ "$indentIndentBulletPoint$indentBulletPoint ${AssertionVerb.ASSERT.getDefault()}: 1$lineSeperator"
+ "$indentIndentBulletPoint$indentBulletPoint ${AssertionVerb.EXPECT_THROWN.getDefault()}: 2$lineSeperator"
+ "$indent$indentBulletPoint ${AssertionVerb.ASSERT.getDefault()}: 1$lineSeperator"
+ "$indent$indentBulletPoint ${AssertionVerb.EXPECT_THROWN.getDefault()}: 2$lineSeperator"
+ "$indentBulletPoint ${AssertionVerb.ASSERT.getDefault()}: 20"
)
}

View File

@@ -15,5 +15,6 @@ abstract class TextInformationAssertionGroupFormatterSpec(
InformationAssertionGroupType::class,
InformationAssertionGroupType,
{ assertionBuilder.explanatoryGroup.withInformationType.withAssertions(it).build() },
describePrefix
describePrefix,
withIndent = false
)