run.qontract.core.MultiPartFormDataPattern.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of qontract-core Show documentation
Show all versions of qontract-core Show documentation
A Contract Testing Tool that leverages Gherkin to describe APIs in a human readable and machine enforceable manner
package run.qontract.core
import run.qontract.core.Result.Failure
import run.qontract.core.Result.Success
import run.qontract.core.pattern.*
import run.qontract.core.value.StringValue
sealed class MultiPartFormDataPattern(open val name: String) {
abstract fun newBasedOn(row: Row, resolver: Resolver): List
abstract fun generate(resolver: Resolver): MultiPartFormDataValue
abstract fun matches(value: MultiPartFormDataValue, resolver: Resolver): Result
abstract fun nonOptional(): MultiPartFormDataPattern
}
data class MultiPartContentPattern(override val name: String, val content: Pattern) : MultiPartFormDataPattern(name) {
override fun newBasedOn(row: Row, resolver: Resolver): List =
newBasedOn(row, withoutOptionality(name), content, resolver).map { newContent -> MultiPartContentPattern(withoutOptionality(name), newContent) }.let {
when{
isOptional(name) && !row.containsField(withoutOptionality(name)) -> listOf(null).plus(it)
else -> it
}
}
override fun generate(resolver: Resolver): MultiPartFormDataValue =
MultiPartContentValue(name, content.generate(resolver))
override fun matches(value: MultiPartFormDataValue, resolver: Resolver): Result {
return when {
name != value.name -> Failure("The contract expected a part name to be $name, but got ${value.name}", failureReason = FailureReason.PartNameMisMatch)
value !is MultiPartContentValue -> Failure("The contract expected content, but got a file.")
value.content is StringValue -> {
try {
val parsedContent = try { content.parse(value.content.toStringValue(), resolver) } catch (e: Throwable) { StringValue(value.content.toStringValue()) }
resolver.matchesPattern(name, content, parsedContent)
} catch (e: ContractException) {
Failure(e.report(), breadCrumb = "content")
} catch (e: Throwable) {
Failure("Expected a ${content.typeName} but got ${value.content.toStringValue()}", breadCrumb = "content")
}
}
else -> {
content.matches(value.content, resolver)
}
}
}
override fun nonOptional(): MultiPartFormDataPattern {
return copy(name = withoutOptionality(name))
}
}
data class MultiPartFilePattern(override val name: String, val filename: String, val contentType: String? = null, val contentEncoding: String? = null) : MultiPartFormDataPattern(name) {
override fun newBasedOn(row: Row, resolver: Resolver): List = listOf(this)
override fun generate(resolver: Resolver): MultiPartFormDataValue =
MultiPartFileValue(name, filename, contentType, contentEncoding)
override fun matches(value: MultiPartFormDataValue, resolver: Resolver): Result {
return when {
name != value.name -> Failure("The contract expected a part name to be $name, but got ${value.name}.", failureReason = FailureReason.PartNameMisMatch)
value !is MultiPartFileValue -> Failure("The contract expected a file, but got content instead.")
contentType != null && value.contentType != contentType -> Failure("The contract expected ${contentType.let { "content type $contentType" }}, but got ${value.contentType?.let { "content type $value.contentType" } ?: "no content type."}.")
contentEncoding != null && value.contentEncoding != contentEncoding -> {
val contentEncodingMessage = contentEncoding.let { "content encoding $contentEncoding" }
val receivedContentEncodingMessage = value.contentEncoding?.let { "content encoding ${value.contentEncoding}" }
?: "no content encoding"
Failure("The contract expected ${contentEncodingMessage}, but got ${receivedContentEncodingMessage}.", breadCrumb = "contentEncoding")
}
else -> Success()
}
}
override fun nonOptional(): MultiPartFormDataPattern {
return copy(name = withoutOptionality(name))
}
}