
net.serenitybdd.screenplay.ensure.Expectation.kt Maven / Gradle / Ivy
package net.serenitybdd.screenplay.ensure
import net.serenitybdd.screenplay.Actor
import net.thucydides.core.steps.ExecutedStepDescription
import net.thucydides.core.steps.StepEventBus
import java.time.LocalDate
typealias BooleanPredicate = (actor: Actor?, actual: A) -> Boolean
typealias SingleValuePredicate = (actor: Actor?, actual: A, expected: E) -> Boolean
typealias DoubleValuePredicate = (actor: Actor?, actual: A, startRange: E, endRange: E) -> Boolean
fun expectThatActualIs(message: String, predicate: SingleValuePredicate) = Expectation("is $message", "is not $message", predicate)
fun expectThatActualIs(message: String, negatedMessage: String, predicate: SingleValuePredicate) = Expectation(message, negatedMessage, predicate)
fun expectThatActualIs(message: String, predicate: DoubleValuePredicate) = DoubleValueExpectation(message, predicate)
fun expectThatActualIs(message: String, predicate: BooleanPredicate) = PredicateExpectation("is $message", "is not $message", predicate)
fun expectThatActualIs(message: String, negatedMessage: String, predicate: BooleanPredicate) = PredicateExpectation(message, negatedMessage, predicate)
fun expectThatActualIs(message: String, predicate: SingleValuePredicate, predicateDescription: String) = Expectation("is $message", "is not $message", predicate, predicateDescription)
fun expectThatActualIs(message: String, negatedMessage: String, predicate: SingleValuePredicate, predicateDescription: String) = Expectation(message, negatedMessage, predicate, predicateDescription)
fun expectThatActualContainsElementsThat(message: String,
predicate: BooleanPredicate,
predicateDescription: String,
qualifier: ElementQualifier,
predicateNumber: GrammaticalNumber) =
CollectionPredicateExpectation(message,
predicateDescription,
qualifier,
predicate,
predicateNumber)
/**
* Models a single value predicate with a description
*/
class Expectation(private val expectation: String,
private val negatedExpectation: String,
val predicate: SingleValuePredicate,
private val readableExpectedValue: String? = null) {
fun describe(expected: E?, isNegated: Boolean = false, expectedDescription: String?) =
expectationDescription(expectation,
negatedExpectation,
expected,
isNegated,
if (expectedDescription != null) expectedDescription else readableExpectedValue)
fun compareActualWithExpected(actual: A?, expected: E, isNegated: Boolean = false, expectedDescription: String?) =
compareExpectedWithActual(expectation,
negatedExpectation,
actual as Any?,
expected as Any?,
isNegated,
if (expectedDescription != null) expectedDescription else readableExpectedValue)
fun apply(actual: A, expected: E, actor: Actor?) = predicate(actor, actual, expected)
}
/**
* Models a value predicate with a description that takes no parameters
*/
open class PredicateExpectation(val expectation: String,
private val negatedExpression: String,
val predicate: BooleanPredicate,
private val isNegated: Boolean = false) {
open fun compareActualWithExpected(actual: A?, isNegated: Boolean = false, expectedDescription: String? = "a value") =
compareExpectedWithActual(expectation, negatedExpression, actual as Any?, isNegated, expectedDescription)
fun describe(isNegated: Boolean = false, expectedDescription: String?) =
predicateDescription(expectation,
negatedExpression,
isNegated,
expectedDescription
)
fun apply(actual: A, actor: Actor?) = if (isNegated) !predicate(actor, actual) else predicate(actor, actual)
}
class CollectionPredicateExpectation(expectation: String,
private val predicateDescription: String,
private val qualifier: ElementQualifier,
predicate: BooleanPredicate,
private val number: GrammaticalNumber) : PredicateExpectation(expectation, "not $expectation", predicate) {
override fun compareActualWithExpected(actual: A?, isNegated: Boolean, expectedDescription: String?) = collectionPredicateDescription(
expectation,
qualifier,
predicateDescription,
number,
actual as Any?,
isNegated)
}
/**
* Models a value predicate with a description that takes two parameters
*/
class DoubleValueExpectation(val expectation: String, val predicate: DoubleValuePredicate) {
fun compareActualWithExpected(actual: A,
startRange: E?,
endRange: E?,
isNegated: Boolean,
expectedDescription: String?) = rangeDescription(expectation,
actual,
startRange as Any?,
endRange as Any?,
isNegated,
expectedDescription)
fun describeRange(startRange: E?,
endRange: E?,
isNegated: Boolean,
expectedDescription: String?) = rangeDescription(expectation,
startRange as Any?,
endRange as Any?,
isNegated,
expectedDescription)
fun apply(actual: A, startRange: E?, endRange: E?, actor: Actor?) = predicate(actor, actual, startRange!!, endRange!!)
}
private fun compareExpectedWithActual(expectation: String,
negatedExpectation: String,
actual: Any?,
expected: Any?,
isNegated: Boolean,
readableExpectedValue: String?): String {
val expectedAsText = specifiedDesciptionOrDescriptionFromType(expected, readableExpectedValue)
val actualAsText = if (BlackBox.hasLastEntry()) BlackBox.lastEntry().actual else actual.toString()// else specifiedDesciptionOrDescriptionFromType(actualValue(actual), readableActualDescription)
val expressionAsText = if (isNegated) negatedExpectation else expectation
val expectedDescription = "Expecting $expectedAsText that $expressionAsText"
val butGot = "But got".padEnd(expectedDescription.length, '.')
val expectedValue = if (BlackBox.hasLastEntry()) BlackBox.lastEntry().expected else expectedValue(expected)
return """
$expectedDescription: <$expectedValue>
$butGot: <$actualAsText>"""
}
private fun expectationDescription(expectation: String,
negatedExpectation: String,
expected: Any?,
isNegated: Boolean,
readableExpectedValue: String?): String {
val expectedAsText = specifiedDesciptionOrDescriptionFromType(expected, readableExpectedValue)
val expressionAsText = if (isNegated) negatedExpectation else expectation
val expectedDescription = "$expectedAsText that $expressionAsText"
val expectedValue = expectedValue(expected)
return """$expectedDescription: <$expectedValue>"""
}
private fun specifiedDesciptionOrDescriptionFromType(actual: Any?, readableActualDescription: String?): String {
if (readableActualDescription != null) return readableActualDescription else return expectedType(actual)
}
private fun rangeDescription(expectation: String,
actual: Any?,
startRange: Any?,
endRange: Any?,
isNegated: Boolean,
expectedDescription: String?): String {
val expecedType = if (expectedDescription == null) expectedType(actual) else expectedDescription
val expectedAsText = "Expecting $expecedType ${thatIsOrIsnt(isNegated)}$expectation ${expectedValue(startRange)} and ${expectedValue(endRange)}"
val actualAsText = if (BlackBox.hasLastEntry()) BlackBox.lastEntry().actual else actualValue(actual)
return """
$expectedAsText
But got: $actualAsText"""
}
private fun rangeDescription(expectation: String,
startRange: Any?,
endRange: Any?,
isNegated: Boolean,
expectedDescription: String?): String {
val expecedType = if (expectedDescription == null) "a value" else expectedDescription
return "$expecedType ${thatIsOrIsnt(isNegated)}$expectation ${expectedValue(startRange)} and ${expectedValue(endRange)}"
}
private fun compareExpectedWithActual(expectation: String, negatedExpectation: String, actual: Any?, isNegated: Boolean, expectedDescription: String? = "value"): String {
val expectedExpression = if (!isNegated) expectation else negatedExpectation
val expectedType = if (expectedDescription == null) expectedType(actual) else expectedDescription
val expectedAsString = "Expecting $expectedType that $expectedExpression"
val actualAsText = if (BlackBox.hasLastEntry()) BlackBox.lastEntry().actual else actualValue(actual)// else specifiedDesciptionOrDescriptionFromType(actualValue(actual), readableActualDescription)
return """
$expectedAsString
But got: $actualAsText"""
}
private fun predicateDescription(expectation: String, negatedExpectation: String, isNegated: Boolean, expectedDescription: String? = "value"): String {
val expectedExpression = if (!isNegated) expectation else negatedExpectation
val expectedType = if (expectedDescription == null) "a value" else expectedDescription
return "$expectedType that $expectedExpression"
}
private fun collectionPredicateDescription(expectation: String,
qualifier: ElementQualifier,
predicateDescription: String,
number: GrammaticalNumber,
actual: Any?,
isNegated: Boolean): String {
// Expecting a collection that [matches|does not match]: [all elements|no element] [have size|has size] [greater than 4]
val resolvedQualifier = qualifier.resolve(number)
val matchesOrDoesNotMatch = matchesOrDoesNotMatch(isNegated)
val expected = "Expecting a collection that $matchesOrDoesNotMatch: $expectation $resolvedQualifier $predicateDescription"
val actualAsText = if (BlackBox.hasLastEntry()) BlackBox.lastEntry().actual else actualValue(actual)
return """
$expected
But got: ${actualAsText}"""
}
fun expectedType(expected: Any?) = if (expected is Collection<*>) "a collection" else "a value"
fun thatIsOrIsnt(isNegated: Boolean) = if (isNegated) "that is not " else "that is "
fun matchesOrDoesNotMatch(isNegated: Boolean) = if (isNegated) "does not match" else "matches"
fun expectedValue(expected: Any?) = if (expected is String) "\"$expected\"" else expected
fun actualValue(actual: Any?) = if (actual is String) "\"$actual\"" else actual
© 2015 - 2025 Weber Informatics LLC | Privacy Policy