io.specmatic.core.Results.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of specmatic-core Show documentation
Show all versions of specmatic-core Show documentation
Turn your contracts into executable specifications. Contract Driven Development - Collaboratively Design & Independently Deploy MicroServices & MicroFrontends.
package io.specmatic.core
const val PATH_NOT_RECOGNIZED_ERROR = "Match not found"
data class Results(val results: List = emptyList()) {
fun hasResults(): Boolean = results.isNotEmpty()
fun hasFailures(): Boolean = results.any { it is Result.Failure }
fun success(): Boolean = if(hasResults()) successCount > 0 && failureCount == 0 else true
fun withoutFluff(fluffLevel: Int): Results = copy(results = results.filterNot { it.isFluffy(fluffLevel) })
fun withoutFluff(): Results = copy(results = minimumFluff())
private fun minimumFluff() =
results.filterNot {
it.isFluffy()
}.ifEmpty {
results.filterNot { it.isFluffy(1) }
}
fun toResultIfAny(): Result {
return results.find { it is Result.Success } ?: Result.Failure(results.joinToString("\n\n") { it.toReport().toText() })
}
val failureCount
get(): Int = results.count { it is Result.Failure }
val successCount
get(): Int = results.count { it is Result.Success }
fun generateErrorHttpResponse(httpRequest: HttpRequest): HttpResponse {
val report = report("").trim()
val defaultHeaders = mapOf("Content-Type" to "text/plain", SPECMATIC_RESULT_HEADER to "failure")
val headers = when {
report.isEmpty() -> defaultHeaders.plus(SPECMATIC_EMPTY_HEADER to "true")
else -> defaultHeaders
}
val message = httpRequest.let { httpRequest.requestNotRecognized() }
return HttpResponse(400, report(message), headers)
}
fun report(httpRequest: HttpRequest): String {
return report(httpRequest.requestNotRecognized())
}
fun strictModeReport(httpRequest: HttpRequest): String {
return report(httpRequest.requestNotRecognizedInStrictMode())
}
fun report(defaultMessage: String = PATH_NOT_RECOGNIZED_ERROR): String {
val filteredResults = withoutFluff().results.filterIsInstance()
return when {
filteredResults.isNotEmpty() -> listToReport(filteredResults)
else -> defaultMessage.trim()
}
}
fun distinctReport(defaultMessage: String = PATH_NOT_RECOGNIZED_ERROR): String {
val filteredResults = withoutFluff().results.filterIsInstance()
return when {
filteredResults.isNotEmpty() -> listToDistinctReport(filteredResults)
else -> if(successCount > 0 && failureCount == 0) "" else defaultMessage.trim()
}
}
fun plus(other: Results): Results = Results(results.plus(other.results))
fun distinct(): Results {
val filteredResults = withoutFluff().results
val resultReports = filteredResults.map {
when(it) {
is Result.Failure -> it.toFailureReport().toText()
else -> ""
}
}
val uniqueResults: List = filteredResults.foldIndexed(emptyList()) { index, acc, result ->
val report = resultReports[index]
when(result) {
is Result.Failure -> {
if(resultReports.indexOf(report) == index)
acc.plus(result)
else
acc
}
else -> acc.plus(result)
}
}
return Results(uniqueResults)
}
fun summary(): String {
return when {
successCount > 0 && failureCount == 0 -> "All $successCount example(s) are valid."
successCount == 0 && failureCount > 0 -> "All $failureCount example(s) are invalid."
else -> "$successCount example(s) are valid. $failureCount example(s) are invalid."
}
}
}
private fun listToReport(results: List): String {
return results.filterIsInstance()
.joinToString("${System.lineSeparator()}${System.lineSeparator()}") {
it.toFailureReport().toText()
}
}
private fun listToDistinctReport(results: List): String {
return results.filterIsInstance().map {
it.toFailureReport().toText()
}.distinct().joinToString("${System.lineSeparator()}${System.lineSeparator()}")
}