Skip to content

Commit

Permalink
fix: EachValue matcher was applying the associated rule to the list a…
Browse files Browse the repository at this point in the history
…nd not the items in the list
  • Loading branch information
rholshausen committed Jun 22, 2023
1 parent d376e7e commit abf5fb8
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import au.com.dius.pact.core.model.matchingrules.MinEqualsIgnoreOrderMatcher
import au.com.dius.pact.core.model.matchingrules.MinMaxEqualsIgnoreOrderMatcher
import au.com.dius.pact.core.model.matchingrules.ValuesMatcher
import au.com.dius.pact.core.model.parsePath
import au.com.dius.pact.core.support.Either
import mu.KLogging
import java.math.BigInteger
import java.util.Comparator
Expand Down Expand Up @@ -175,6 +176,38 @@ object Matchers : KLogging() {
}
}
}
is EachValueMatcher -> if (!cascaded) {
logger.debug { "Matching $path with EachValue" }
val associatedRules = matcher.definition.rules.mapNotNull {
when (it) {
is Either.A -> it.value
is Either.B -> {
result.add(
BodyItemMatchResult(
constructPath(path),
listOf(
BodyMismatch(
expectedList, actualList,
"Found an un-resolved reference ${it.value.name}", constructPath(path), generateDiff()
)
)
)
)
null
}
}
}
val matcherPath = constructPath(path) + ".*"
val newContext = MatchingContext(
MatchingRuleCategory("body", mutableMapOf(
matcherPath to MatchingRuleGroup(associatedRules.toMutableList())
)),
context.allowUnexpectedKeys,
context.pluginConfiguration
)
result.addAll(compareListContent(expectedList.padTo(actualList.size, expectedList.first()),
actualList, path, newContext, generateDiff, callback))
}
else -> {
result.addAll(compareListContent(expectedList.padTo(actualList.size, expectedList.first()),
actualList, path, context, generateDiff, callback))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package au.com.dius.pact.core.matchers

import au.com.dius.pact.core.model.OptionalBody
import au.com.dius.pact.core.model.matchingrules.EachValueMatcher
import au.com.dius.pact.core.model.matchingrules.MatchingRuleCategory
import au.com.dius.pact.core.model.matchingrules.RegexMatcher
import au.com.dius.pact.core.model.matchingrules.TypeMatcher
import au.com.dius.pact.core.model.matchingrules.ValuesMatcher
import au.com.dius.pact.core.model.matchingrules.expressions.MatchingRuleDefinition
import spock.lang.Specification

class EachValueMatcherSpec extends Specification {

private MatchingContext context

def setup() {
context = new MatchingContext(new MatchingRuleCategory('body'), true)
}

def 'matching json bodies - return no mismatches - with each like matcher on unequal lists'() {
given:
def eachValue = new EachValueMatcher(new MatchingRuleDefinition('foo', TypeMatcher.INSTANCE, null))
def eachValueGroups = new EachValueMatcher(new MatchingRuleDefinition(
'00000000000000000000000000000000',
new RegexMatcher('[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|\\*'),
null))
context.matchers.addRule('$.resource_permissions', ValuesMatcher.INSTANCE)
context.matchers.addRule('$.resource_permissions.*', TypeMatcher.INSTANCE)
context.matchers.addRule('$.resource_permissions.*.resource.application_resource', TypeMatcher.INSTANCE)
context.matchers.addRule('$.resource_permissions.*.resource.permissions', eachValue)
context.matchers.addRule('$.resource_permissions.*.resource.groups', eachValueGroups)

def actualBody = OptionalBody.body('''{
"resource_permissions": {
"a": {
"resource": {
"application_resource": "value 1",
"permissions": ["a", "b", 100],
"groups": ["*", "163ad478-10b7-11ee-9e1c-dbbb1ffc4ea4", "x"]
},
"effect": {
"result": "ENFORCE_EFFECT_ALLOW"
}
}
}
}'''.bytes)
def expectedBody = OptionalBody.body('''{
"resource_permissions": {
"permission": {
"resource": {
"application_resource": "foo",
"permissions": ["foo"],
"groups": ["*"]
},
"effect": {
"result": "ENFORCE_EFFECT_ALLOW"
}
}
}
}'''.bytes)

when:
def result = JsonContentMatcher.INSTANCE.matchBody(expectedBody, actualBody, context)

then:
result.mismatches*.mismatch == [
'Expected 100 (Integer) to be the same type as "foo" (String)',
"Expected \"x\" to match '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|\\*'"
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@ import au.com.dius.pact.core.model.Request
import au.com.dius.pact.core.model.Response
import au.com.dius.pact.core.model.matchingrules.ContentTypeMatcher
import au.com.dius.pact.core.model.matchingrules.DateMatcher
import au.com.dius.pact.core.model.matchingrules.EachValueMatcher
import au.com.dius.pact.core.model.matchingrules.MatchingRuleCategory
import au.com.dius.pact.core.model.matchingrules.MatchingRulesImpl
import au.com.dius.pact.core.model.matchingrules.RegexMatcher
import au.com.dius.pact.core.model.matchingrules.TypeMatcher
import au.com.dius.pact.core.model.matchingrules.ValuesMatcher
import au.com.dius.pact.core.model.matchingrules.expressions.MatchingRuleDefinition
import spock.lang.Issue
import spock.lang.Specification

import static au.com.dius.pact.core.matchers.Matchers.domatch
import static au.com.dius.pact.core.model.PathExpressionsKt.constructPath

class MatchingSpec extends Specification {

private static Request request
Expand Down Expand Up @@ -219,4 +224,46 @@ class MatchingSpec extends Specification {
result[0].mismatch == 'Actual map is missing the following keys: system'
result[1].mismatch == 'Actual map is missing the following keys: id'
}

def 'each value matcher applying a regex to a list of strings'() {
given:
def eachValueMatcher = new EachValueMatcher(new MatchingRuleDefinition('00000000000000000000000000000000',
new RegexMatcher('[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|\\*'), null))
bodyContext.matchers
.addRule('$', eachValueMatcher)
def callback = { List<String> p, String a, String b, MatchingContext c ->
[new BodyItemMatchResult(constructPath(p), domatch(c, p, a, b, BodyMismatchFactory.INSTANCE))]
}

when:
def result = Matchers.INSTANCE.compareLists(
['$'],
eachValueMatcher,
['*'],
['*', '*'],
bodyContext,
{ -> '' },
false,
callback
)
def result2 = Matchers.INSTANCE.compareLists(
['$'],
eachValueMatcher,
['*'],
['*', 'x'],
bodyContext,
{ -> '' },
false,
callback
)

then:
result == [new BodyItemMatchResult('$.0', []), new BodyItemMatchResult('$.1', [])]
result2 == [
new BodyItemMatchResult('$.0', []),
new BodyItemMatchResult('$.1', [new BodyMismatch('*', 'x',
"Expected 'x' to match '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|\\*'",
'$.1', null)])
]
}
}

0 comments on commit abf5fb8

Please sign in to comment.