Skip to content

Commit

Permalink
refactor: remove old wild-card matching logic in favor of using the V…
Browse files Browse the repository at this point in the history
…alueMatcher
  • Loading branch information
Ronald Holshausen committed Mar 1, 2021
1 parent 4d37371 commit cce1cfc
Show file tree
Hide file tree
Showing 19 changed files with 96 additions and 259 deletions.
7 changes: 0 additions & 7 deletions consumer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -354,13 +354,6 @@ DslPart body = new PactDslJsonBody()

For an example, have a look at [WildcardKeysTest](https://github.com/DiUS/pact-jvm/blob/master/consumer/junit/src/test/java/au/com/dius/pact/consumer/junit/WildcardKeysTest.java).

**NOTE:** The `eachKeyLike` method adds a `*` to the matching path, so the matching definition will be applied to all keys
of the map if there is not a more specific matcher defined for a particular key. Having more than one `eachKeyLike` condition
applied to a map will result in only one being applied when the pact is verified (probably the last).

**Further Note: From version 3.5.22 onwards pacts with wildcards applied to map keys will require the Java system property
"pact.matching.wildcard" set to value "true" when the pact file is verified.**

### Matching on paths

You can use regular expressions to match incoming requests. The DSL has a `matchPath` method for this. You can provide
Expand Down
7 changes: 0 additions & 7 deletions consumer/groovy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -520,13 +520,6 @@ withBody {

For an example, have a look at [WildcardPactSpec](https://github.com/DiUS/pact-jvm/blob/master/consumer/groovy/src/test/groovy/au/com/dius/pact/consumer/groovy/WildcardPactSpec.groovy).

**NOTE:** The `keyLike` method adds a `*` to the matching path, so the matching definition will be applied to all keys
of the map if there is not a more specific matcher defined for a particular key. Having more than one `keyLike` condition
applied to a map will result in only one being applied when the pact is verified (probably the last).

**Further Note: From version 3.5.22 onwards pacts with wildcards applied to map keys will require the Java system property
"pact.matching.wildcard" set to value "true" when the pact file is verified.**

### Matching with an OR

The V3 spec allows multiple matchers to be combined using either AND or OR for a value. The main use of this would be to
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package au.com.dius.pact.consumer.groovy

import au.com.dius.pact.core.model.Feature
import au.com.dius.pact.core.model.FeatureToggles
import au.com.dius.pact.core.model.generators.Category
import au.com.dius.pact.core.model.generators.Generators
import au.com.dius.pact.core.model.generators.ProviderStateGenerator
Expand Down Expand Up @@ -289,17 +287,12 @@ class PactBodyBuilder extends GroovyBuilder {
}

/**
* Matches the values of the map ignoring the keys. Note: this needs the Java system property
* "pact.matching.wildcard" set to value "true" when the pact file is verified.
* Matches the values of the map ignoring the keys.
*/
def keyLike(String key, def value) {
if (FeatureToggles.isFeatureSet(Feature.UseMatchValuesMatcher)) {
setMatcherAttribute(new ValuesMatcher(), path)
if (value instanceof Closure) {
bodyRepresentation[key] = invokeClosure(value, buildPath(STAR))
} else {
addAttribute(key, STAR, value)
}
setMatcherAttribute(new ValuesMatcher(), path)
if (value instanceof Closure) {
bodyRepresentation[key] = invokeClosure(value, buildPath(STAR))
} else {
addAttribute(key, STAR, value)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package au.com.dius.pact.consumer.groovy

import au.com.dius.pact.consumer.PactVerificationResult
import au.com.dius.pact.core.model.FeatureToggles
import groovy.json.JsonSlurper
import groovyx.net.http.ContentTypes
import groovyx.net.http.FromServer
Expand All @@ -11,10 +10,10 @@ import spock.lang.Specification
import static groovyx.net.http.ContentTypes.JSON

@SuppressWarnings(['AbcMetric'])
class WildcardPactSpec extends Specification {
class ValuesMatcherPactSpec extends Specification {

@SuppressWarnings(['NestedBlockDepth'])
def 'pact test requiring wildcards'() {
def 'pact test using values matcher'() {
given:
def articleService = new PactBuilder()
articleService {
Expand Down Expand Up @@ -74,21 +73,22 @@ class WildcardPactSpec extends Specification {
articleService.interactions[0].response.matchingRules.rulesForCategory('body').matchingRules.keySet() == [
'$.articles',
'$.articles[*].variants',
'$.articles[*].variants[*]',
'$.articles[*].variants[*].*',
'$.articles[*].variants[*].*[*].bundles',
'$.articles[*].variants[*].*[*].bundles[*].*',
'$.articles[*].variants[*].*[*].bundles[*]',
'$.articles[*].variants[*].*[*].bundles[*].*.description',
'$.articles[*].variants[*].*[*].bundles[*].*.referencedArticles',
'$.articles[*].variants[*].*[*].bundles[*].*.referencedArticles[*].bundleId',
'$.articles[*].variants[*].*[*].bundles[*].*.referencedArticles[*]',
'$.articles[*].variants[*].*[*].bundles[*].*.referencedArticles[*].*'
] as Set

}

@SuppressWarnings(['NestedBlockDepth'])
def 'key like test with useMatchValuesMatcher turned on'() {
def 'key like test'() {
given:
FeatureToggles.toggleFeature('pact.feature.matchers.useMatchValuesMatcher', true)
def articleService = new PactBuilder()
articleService {
serviceConsumer 'ArticleConsumer'
Expand Down Expand Up @@ -144,9 +144,5 @@ class WildcardPactSpec extends Specification {
'$.events.*.references.*',
'$.events.*.references.*[*].eventId'
] as Set

cleanup:
FeatureToggles.reset()

}
}
7 changes: 0 additions & 7 deletions consumer/junit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -561,13 +561,6 @@ DslPart body = new PactDslJsonBody()

For an example, have a look at [WildcardKeysTest](https://github.com/DiUS/pact-jvm/blob/master/consumer/junit/src/test/java/au/com/dius/pact/consumer/junit/WildcardKeysTest.java).

**NOTE:** The `eachKeyLike` method adds a `*` to the matching path, so the matching definition will be applied to all keys
of the map if there is not a more specific matcher defined for a particular key. Having more than one `eachKeyLike` condition
applied to a map will result in only one being applied when the pact is verified (probably the last).

**Further Note: From version 3.5.22 onwards pacts with wildcards applied to map keys will require the Java system property
"pact.matching.wildcard" set to value "true" when the pact file is verified.**

#### Combining matching rules with AND/OR

Matching rules can be combined with AND/OR. There are two methods available on the DSL for this. For example:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.is;

public class WildcardKeysTest {
public class ValueMatcherTest {

private static final String APPLICATION_JSON = "application/json";

@Rule
public PactProviderRule provider = new PactProviderRule("WildcardKeysProvider", "localhost", 8111, this);
public PactProviderRule provider = new PactProviderRule("ValueMatcherProvider", this);

@Pact(provider="WildcardKeysProvider", consumer="WildcardKeysConsumer")
@Pact(provider="ValueMatcherProvider", consumer="ValueMatcherConsumer")
public RequestResponsePact createFragment(PactDslWithProvider builder) {
DslPart body = new PactDslJsonBody()
.eachLike("articles")
Expand Down Expand Up @@ -67,23 +67,25 @@ public RequestResponsePact createFragment(PactDslWithProvider builder) {
MatcherTestUtils.assertResponseMatcherKeysEqualTo(pact, "body",
"$.articles",
"$.articles[*].variants",
"$.articles[*].variants[*].*",
"$.articles[*].variants[*]",
"$.articles[*].variants[*].*[*].bundles",
"$.articles[*].variants[*].*[*].bundles[*].*",
"$.articles[*].variants[*].*[*].bundles[*]",
"$.articles[*].variants[*].*[*].bundles[*].*.description",
"$.articles[*].variants[*].*[*].bundles[*].*.referencedArticles",
"$.articles[*].variants[*].*[*].bundles[*].*.referencedArticles[*]",
"$.articles[*].variants[*].*[*].bundles[*].*.referencedArticles[*].*",
"$.articles[*].variants[*].*[*].bundles[*].*.referencedArticles[*].bundleId",
"$.foo",
"$.foo.*"
);

return pact;
}

@Test
@PactVerification("WildcardKeysProvider")
@PactVerification("ValueMatcherProvider")
public void runTest() throws IOException {
String result = Request.Get("http://localhost:8111/")
String result = Request.Get(provider.getUrl())
.addHeader("Accept", APPLICATION_JSON)
.execute().returnContent().asString();
Map<String, Object> body = (Map<String, Object>) new JsonSlurper().parseText(result);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -943,7 +943,6 @@ public LambdaDslObject eachArrayWithMinMaxLike(String name, Integer minSize, Int

/**
* Accepts any key, and each key is mapped to a list of items that must match the following object definition.
* Note: this needs the Java system property "pact.matching.wildcard" set to value "true" when the pact file is verified.
*
* @param exampleKey Example key to use for generating bodies
*/
Expand All @@ -957,7 +956,6 @@ public LambdaDslObject eachKeyMappedToAnArrayLike(String exampleKey, Consumer<La

/**
* Accepts any key, and each key is mapped to a map that must match the following object definition.
* Note: this needs the Java system property "pact.matching.wildcard" set to value "true" when the pact file is verified.
*
* @param exampleKey Example key to use for generating bodies
*/
Expand All @@ -971,7 +969,6 @@ public LambdaDslObject eachKeyLike(String exampleKey, Consumer<LambdaDslObject>

/**
* Accepts any key, and each key is mapped to a map that must match the provided object definition
* Note: this needs the Java system property "pact.matching.wildcard" set to value "true" when the pact file is verified.
*
* @param exampleKey Example key to use for generating bodies
* @param value Value to use for matching and generated bodies
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1109,54 +1109,38 @@ open class PactDslJsonBody : DslPart {

/**
* Accepts any key, and each key is mapped to a list of items that must match the following object definition
* Note: this needs the Java system property "pact.matching.wildcard" set to value "true" when the pact file
* is verified.
* @param exampleKey Example key to use for generating bodies
*/
fun eachKeyMappedToAnArrayLike(exampleKey: String): PactDslJsonBody {
if (isFeatureSet(Feature.UseMatchValuesMatcher)) {
matchers.addRule(
if (rootPath.endsWith(".")) rootPath.substring(0, rootPath.length - 1) else rootPath, ValuesMatcher
)
} else {
matchers.addRule("$rootPath*", TypeMatcher)
}
matchers.addRule(
if (rootPath.endsWith(".")) rootPath.substring(0, rootPath.length - 1) else rootPath, ValuesMatcher
)
val parent = PactDslJsonArray("$rootPath*", exampleKey, this, true)
return PactDslJsonBody(".", "", parent)
}

/**
* Accepts any key, and each key is mapped to a map that must match the following object definition
* Note: this needs the Java system property "pact.matching.wildcard" set to value "true" when the pact file
* is verified.
* @param exampleKey Example key to use for generating bodies
*/
fun eachKeyLike(exampleKey: String): PactDslJsonBody {
if (isFeatureSet(Feature.UseMatchValuesMatcher)) {
matchers.addRule(
if (rootPath.endsWith(".")) rootPath.substring(0, rootPath.length - 1) else rootPath, ValuesMatcher
)
} else {
matchers.addRule("$rootPath*", TypeMatcher)
}
matchers.addRule(
if (rootPath.endsWith(".")) rootPath.substring(0, rootPath.length - 1) else rootPath, ValuesMatcher
)
return PactDslJsonBody("$rootPath*.", exampleKey, this)
}

/**
* Accepts any key, and each key is mapped to a map that must match the provided object definition
* Note: this needs the Java system property "pact.matching.wildcard" set to value "true" when the pact file
* is verified.
* @param exampleKey Example key to use for generating bodies
* @param value Value to use for matching and generated bodies
*/
fun eachKeyLike(exampleKey: String, value: PactDslJsonRootValue): PactDslJsonBody {
val body = body as JsonValue.Object
body.add(exampleKey, value.body)
if (isFeatureSet(Feature.UseMatchValuesMatcher)) {
matchers.addRule(
if (rootPath.endsWith(".")) rootPath.substring(0, rootPath.length - 1) else rootPath, ValuesMatcher
)
}
matchers.addRule(
if (rootPath.endsWith(".")) rootPath.substring(0, rootPath.length - 1) else rootPath, ValuesMatcher
)
for (matcherName in value.matchers.matchingRules.keys) {
matchers.addRules("$rootPath*$matcherName", value.matchers.matchingRules[matcherName]!!.rules)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ class LambdaDslSpec extends Specification {
def result = LambdaDsl.newJsonBody(jsonObject).build()

then:
result.matchers.matchingRules.keySet() == ['.offer.prices.*', '.offer.shippingCosts.*'] as Set
result.matchers.matchingRules.keySet() == ['.offer.prices', '.offer.prices.*', '.offer.shippingCosts'] as Set
result.toString() == '{"offer":{"prices":{"DE":1620},"shippingCosts":{"DE":{"cia":300}}}}'

}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package au.com.dius.pact.consumer.dsl

import au.com.dius.pact.core.model.Feature
import au.com.dius.pact.core.model.FeatureToggles
import au.com.dius.pact.core.model.PactSpecVersion
import au.com.dius.pact.core.model.matchingrules.MatchingRuleGroup
import au.com.dius.pact.core.model.matchingrules.RegexMatcher
Expand Down Expand Up @@ -214,46 +212,8 @@ class PactDslJsonBodySpec extends Specification {
]
}

def 'eachKey - generate a wildcard matcher pattern if useMatchValuesMatcher is not set'() {
def 'eachKey - generate a match values matcher'() {
given:
FeatureToggles.toggleFeature(Feature.UseMatchValuesMatcher, false)

def pactDslJsonBody = new PactDslJsonBody()
.object('one')
.eachKeyLike('key1')
.id()
.closeObject()
.closeObject()
.object('two')
.eachKeyLike('key2', PactDslJsonRootValue.stringMatcher('\\w+', 'test'))
.closeObject()
.object('three')
.eachKeyMappedToAnArrayLike('key3')
.id('key3-id')
.closeObject()
.closeArray()
.closeObject()

when:
pactDslJsonBody.close()

then:
pactDslJsonBody.matchers.matchingRules == [
'$.one.*': new MatchingRuleGroup([TypeMatcher.INSTANCE]),
'$.one.*.id': new MatchingRuleGroup([TypeMatcher.INSTANCE]),
'$.two.*': new MatchingRuleGroup([new RegexMatcher('\\w+', 'test')]),
'$.three.*': new MatchingRuleGroup([TypeMatcher.INSTANCE]),
'$.three.*[*].key3-id': new MatchingRuleGroup([TypeMatcher.INSTANCE])
]

cleanup:
FeatureToggles.reset()
}

def 'eachKey - generate a match values matcher if useMatchValuesMatcher is set'() {
given:
FeatureToggles.toggleFeature(Feature.UseMatchValuesMatcher, true)

def pactDslJsonBody = new PactDslJsonBody()
.object('one')
.eachKeyLike('key1')
Expand Down Expand Up @@ -282,9 +242,6 @@ class PactDslJsonBodySpec extends Specification {
'$.three': new MatchingRuleGroup([ValuesMatcher.INSTANCE]),
'$.three.*[*].key3-id': new MatchingRuleGroup([TypeMatcher.INSTANCE])
]

cleanup:
FeatureToggles.reset()
}

def 'Allow an attribute to be defined from a DSL part'() {
Expand Down
Loading

0 comments on commit cce1cfc

Please sign in to comment.