Skip to content

Commit

Permalink
Merge pull request #1457 from znsio/generative-tests-with-discriminator
Browse files Browse the repository at this point in the history
Test generation with discriminator value
  • Loading branch information
joelrosario authored Nov 29, 2024
2 parents bef90a2 + b8d3278 commit a14f07d
Show file tree
Hide file tree
Showing 6 changed files with 787 additions and 6 deletions.
25 changes: 22 additions & 3 deletions core/src/main/kotlin/io/specmatic/core/pattern/AnyPattern.kt
Original file line number Diff line number Diff line change
Expand Up @@ -169,16 +169,35 @@ data class AnyPattern(
}

override fun newBasedOn(row: Row, resolver: Resolver): Sequence<ReturnValue<Pattern>> {
resolver.resolveExample(example, pattern)?.let {
val updatedPatterns = discriminator?.let {
it.updatePatternsWithDiscriminator(pattern, resolver).let { updatedPatterns ->
if(updatedPatterns.any { it !is HasValue<Pattern> }) {
val failures = updatedPatterns.map { pattern ->
when(pattern) {
is HasValue -> null
is HasFailure -> pattern.failure
is HasException -> pattern.toFailure()
}
}.filterNotNull()

return sequenceOf(HasFailure(Failure.fromFailures(failures)))
}

updatedPatterns.listFold().value
}
} ?: pattern

resolver.resolveExample(example, updatedPatterns)?.let {
return sequenceOf(HasValue(ExactValuePattern(it)))
}

val isNullable = pattern.any { it is NullPattern }
val isNullable = updatedPatterns.any { it is NullPattern }
val patternResults: Sequence<Pair<Sequence<ReturnValue<Pattern>>?, Throwable?>> =
pattern.asSequence().sortedBy { it is NullPattern }.map { innerPattern ->
updatedPatterns.asSequence().sortedBy { it is NullPattern }.map { innerPattern ->
try {
val patterns =
resolver.withCyclePrevention(innerPattern, isNullable) { cyclePreventedResolver ->
val row = discriminator?.removeKeyFromRow(row) ?: row
innerPattern.newBasedOn(row, cyclePreventedResolver).map { it.value }
} ?: sequenceOf()
Pair(patterns.map { HasValue(it) }, null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,8 @@ class Discriminator(
breadCrumb = discriminatorProperty,
failureReason = FailureReason.DiscriminatorMismatch
)

fun removeKeyFromRow(row: Row): Row {
return row.removeKey(property)
}
}
7 changes: 7 additions & 0 deletions core/src/main/kotlin/io/specmatic/core/pattern/JSONExample.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ import io.specmatic.core.value.JSONObjectValue
import io.specmatic.core.value.ScalarValue

data class JSONExample(val jsonObject: JSONComposite, val originalRow: Row) {
fun removeKey(key: String): JSONExample {
if(jsonObject is JSONObjectValue)
return JSONExample(jsonObject.copy(jsonObject.jsonObject - key), originalRow)

return this
}

fun hasScalarValueForKey(key: String): Boolean {
return jsonObject.let {
it is JSONObjectValue && it.jsonObject[key] is ScalarValue
Expand Down
19 changes: 19 additions & 0 deletions core/src/main/kotlin/io/specmatic/core/pattern/Row.kt
Original file line number Diff line number Diff line change
Expand Up @@ -141,4 +141,23 @@ data class Row(
fun hasRequestParameters(): Boolean {
return values.isNotEmpty() || requestBodyJSONExample != null
}

fun isEmpty(): Boolean {
return columnNames.isEmpty() && values.isEmpty() && requestBodyJSONExample == null
}

fun removeKey(property: String): Row {
val columnIndex = columnNames.indexOf(property)

val withoutColumn = if(columnIndex >= 0) {
this.copy(columnNames = columnNames.filterIndexed { index, _ -> index != columnIndex }, values = values.filterIndexed { index, _ -> index != columnIndex })
} else {
this
}

return withoutColumn.requestBodyJSONExample?.let { jsonExample ->
val updatedJSONExample = jsonExample.removeKey(property)
withoutColumn.copy(requestBodyJSONExample = updatedJSONExample)
} ?: withoutColumn
}
}
Loading

0 comments on commit a14f07d

Please sign in to comment.