From 08bb852a37758ff6bc1241033a50b5c3916297b6 Mon Sep 17 00:00:00 2001 From: Ronald Holshausen Date: Tue, 30 Aug 2022 14:15:39 +1000 Subject: [PATCH] feat: add matching functions to consumer DSL to matcher numbers with a regex #1600 --- .../junit5/NumberMatcherBodyTest.groovy | 39 ++++++++ .../pact/consumer/dsl/LambdaDslJsonArray.java | 31 ++++++ .../pact/consumer/dsl/LambdaDslObject.java | 40 +++++++- .../pact/consumer/dsl/PactDslJsonArray.kt | 69 ++++++++++++- .../dius/pact/consumer/dsl/PactDslJsonBody.kt | 98 ++++++++++++++++++- .../pact/consumer/dsl/PactDslJsonRootValue.kt | 73 +++++++++++++- .../pact/consumer/dsl/PactDslRootValue.kt | 74 +++++++++++++- .../consumer/dsl/PactDslJsonArraySpec.groovy | 19 ++++ .../consumer/dsl/PactDslJsonBodySpec.groovy | 17 ++++ .../dsl/PactDslJsonRootValueSpec.groovy | 19 ++++ 10 files changed, 462 insertions(+), 17 deletions(-) create mode 100644 consumer/junit5/src/test/groovy/au/com/dius/pact/consumer/junit5/NumberMatcherBodyTest.groovy diff --git a/consumer/junit5/src/test/groovy/au/com/dius/pact/consumer/junit5/NumberMatcherBodyTest.groovy b/consumer/junit5/src/test/groovy/au/com/dius/pact/consumer/junit5/NumberMatcherBodyTest.groovy new file mode 100644 index 0000000000..c7bf7e6467 --- /dev/null +++ b/consumer/junit5/src/test/groovy/au/com/dius/pact/consumer/junit5/NumberMatcherBodyTest.groovy @@ -0,0 +1,39 @@ +package au.com.dius.pact.consumer.junit5 + +import au.com.dius.pact.consumer.MockServer +import au.com.dius.pact.consumer.dsl.PactDslJsonBody +import au.com.dius.pact.consumer.dsl.PactDslWithProvider +import au.com.dius.pact.core.model.PactSpecVersion +import au.com.dius.pact.core.model.RequestResponsePact +import au.com.dius.pact.core.model.annotations.Pact +import org.apache.hc.client5.http.fluent.Request +import org.apache.hc.core5.http.ContentType +import org.apache.hc.core5.http.io.entity.StringEntity +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(PactConsumerTestExt) +@PactTestFor(providerName = 'NumberMatcherBodyTest', pactVersion = PactSpecVersion.V3) +class NumberMatcherBodyTest { + @Pact(consumer = 'Consumer') + RequestResponsePact pact(PactDslWithProvider builder) { + builder + .uponReceiving('a request to fetch a number') + .path('/path') + .method('POST') + .body(new PactDslJsonBody().integerMatching("num", "\\d{5}", 12345)) + .willRespondWith() + .status(200) + .body(new PactDslJsonBody().decimalMatching("num", '\\d+\\.\\d{2}', 100.02)) + .toPact() + } + + @Test + void test(MockServer mockServer) { + def httpResponse = Request.post("${mockServer.url}/path") + .body(new StringEntity("{\"num\": 12345}", ContentType.APPLICATION_JSON)) + .execute().returnResponse() + assert httpResponse.code == 200 + assert httpResponse.entity.content.text == '{"num":100.02}' + } +} diff --git a/consumer/src/main/java/au/com/dius/pact/consumer/dsl/LambdaDslJsonArray.java b/consumer/src/main/java/au/com/dius/pact/consumer/dsl/LambdaDslJsonArray.java index 25c5290b36..68dd697059 100644 --- a/consumer/src/main/java/au/com/dius/pact/consumer/dsl/LambdaDslJsonArray.java +++ b/consumer/src/main/java/au/com/dius/pact/consumer/dsl/LambdaDslJsonArray.java @@ -189,6 +189,37 @@ public LambdaDslJsonArray decimalType(final Double example) { return this; } + /** + * Attribute that can be any number and which must match the provided regular expression + * @param regex Regular expression that the numbers string form must match + * @param example example number to use for generated bodies + */ + public LambdaDslJsonArray numberMatching(String regex, Number example) { + pactArray.numberMatching(regex, example); + return this; + } + + /** + * Attribute that can be any number decimal number (has significant digits after the decimal point) and which must + * match the provided regular expression + * @param regex Regular expression that the numbers string form must match + * @param example example number to use for generated bodies + */ + public LambdaDslJsonArray decimalMatching(String regex, Double example) { + pactArray.decimalMatching(regex, example); + return this; + } + + /** + * Attribute that can be any integer and which must match the provided regular expression + * @param regex Regular expression that the numbers string form must match + * @param example example integer to use for generated bodies + */ + public LambdaDslJsonArray integerMatching(String regex, Integer example) { + pactArray.integerMatching(regex, example); + return this; + } + /** * Element that must be the specified value * diff --git a/consumer/src/main/java/au/com/dius/pact/consumer/dsl/LambdaDslObject.java b/consumer/src/main/java/au/com/dius/pact/consumer/dsl/LambdaDslObject.java index c7b62c0634..9f9e4b41f4 100644 --- a/consumer/src/main/java/au/com/dius/pact/consumer/dsl/LambdaDslObject.java +++ b/consumer/src/main/java/au/com/dius/pact/consumer/dsl/LambdaDslObject.java @@ -147,7 +147,7 @@ public LambdaDslObject integerType(final String... names) { } /** - * Attribute that must be a decimalType value + * Attribute that must be a decimalType value (has significant digits after the decimal point) * * @param name attribute name * @param example example decimalType value @@ -158,7 +158,7 @@ public LambdaDslObject decimalType(final String name, final BigDecimal example) } /** - * Attribute that must be a decimalType value + * Attribute that must be a decimalType value (has significant digits after the decimal point) * * @param name attribute name * @param example example decimalType value @@ -169,7 +169,7 @@ public LambdaDslObject decimalType(final String name, final Double example) { } /** - * Attributes that must be decimal values + * Attributes that must be decimal values (have significant digits after the decimal point) * * @param names attribute names */ @@ -178,6 +178,40 @@ public LambdaDslObject decimalType(final String... names) { return this; } + /** + * Attribute that can be any number and which must match the provided regular expression + * @param name attribute name + * @param regex Regular expression that the numbers string form must match + * @param example example number to use for generated bodies + */ + public LambdaDslObject numberMatching(String name, String regex, Number example) { + object.numberMatching(name, regex, example); + return this; + } + + /** + * Attribute that can be any number decimal number (has significant digits after the decimal point) and which must + * match the provided regular expression + * @param name attribute name + * @param regex Regular expression that the numbers string form must match + * @param example example number to use for generated bodies + */ + public LambdaDslObject decimalMatching(String name, String regex, Double example) { + object.decimalMatching(name, regex, example); + return this; + } + + /** + * Attribute that can be any integer and which must match the provided regular expression + * @param name attribute name + * @param regex Regular expression that the numbers string form must match + * @param example example integer to use for generated bodies + */ + public LambdaDslObject integerMatching(String name, String regex, Integer example) { + object.integerMatching(name, regex, example); + return this; + } + /** * Attribute that must be the specified boolean * diff --git a/consumer/src/main/kotlin/au/com/dius/pact/consumer/dsl/PactDslJsonArray.kt b/consumer/src/main/kotlin/au/com/dius/pact/consumer/dsl/PactDslJsonArray.kt index d60a20bf92..768d90029c 100644 --- a/consumer/src/main/kotlin/au/com/dius/pact/consumer/dsl/PactDslJsonArray.kt +++ b/consumer/src/main/kotlin/au/com/dius/pact/consumer/dsl/PactDslJsonArray.kt @@ -22,9 +22,9 @@ import au.com.dius.pact.core.model.matchingrules.MaxEqualsIgnoreOrderMatcher 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.NumberTypeMatcher +import au.com.dius.pact.core.model.matchingrules.RegexMatcher import au.com.dius.pact.core.model.matchingrules.RuleLogic import au.com.dius.pact.core.model.matchingrules.TypeMatcher -import au.com.dius.pact.core.support.Json import au.com.dius.pact.core.support.Json.toJson import au.com.dius.pact.core.support.expressions.DataType.Companion.from import au.com.dius.pact.core.support.json.JsonValue @@ -379,7 +379,7 @@ open class PactDslJsonArray : DslPart { } /** - * Element that must be a decimal value + * Element that must be a decimal value (has significant digits after the decimal point) */ fun decimalType(): PactDslJsonArray { generators.addGenerator(Category.BODY, rootPath + appendArrayIndex(1), RandomDecimalGenerator(10)) @@ -387,7 +387,7 @@ open class PactDslJsonArray : DslPart { } /** - * Element that must be a decimalType value + * Element that must be a decimalType value (has significant digits after the decimal point) * * @param number example decimalType value */ @@ -398,7 +398,7 @@ open class PactDslJsonArray : DslPart { } /** - * Attribute that must be a decimalType value + * Attribute that must be a decimalType value (has significant digits after the decimal point) * * @param number example decimalType value */ @@ -408,6 +408,67 @@ open class PactDslJsonArray : DslPart { return this } + /** + * Attribute that can be any number and which must match the provided regular expression + * @param regex Regular expression that the numbers string form must match + * @param example example number to use for generated bodies + */ + fun numberMatching(regex: String, example: Number): PactDslJsonArray { + require(example.toString().matches(Regex(regex))) { + "Example value $example does not match the provided regular expression '$regex'" + } + + body.add(JsonValue.Decimal(example.toString().toCharArray())) + + matchers.addRules(rootPath + appendArrayIndex(0), listOf( + NumberTypeMatcher(NumberTypeMatcher.NumberType.NUMBER), + RegexMatcher(regex, example.toString()) + )) + + return this + } + + /** + * Attribute that can be any number decimal number (has significant digits after the decimal point) and which must + * match the provided regular expression + * @param regex Regular expression that the numbers string form must match + * @param example example number to use for generated bodies + */ + fun decimalMatching(regex: String, example: Double): PactDslJsonArray { + require(example.toString().matches(Regex(regex))) { + "Example value $example does not match the provided regular expression '$regex'" + } + + body.add(JsonValue.Decimal(example.toString().toCharArray())) + + matchers.addRules(rootPath + appendArrayIndex(0), listOf( + NumberTypeMatcher(NumberTypeMatcher.NumberType.DECIMAL), + RegexMatcher(regex, example.toString()) + )) + + return this + } + + /** + * Attribute that can be any integer and which must match the provided regular expression + * @param regex Regular expression that the numbers string form must match + * @param example example integer to use for generated bodies + */ + fun integerMatching(regex: String, example: Int): PactDslJsonArray { + require(example.toString().matches(Regex(regex))) { + "Example value $example does not match the provided regular expression $regex" + } + + body.add(JsonValue.Integer(example.toString().toCharArray())) + + matchers.addRules(rootPath + appendArrayIndex(0), listOf( + NumberTypeMatcher(NumberTypeMatcher.NumberType.INTEGER), + RegexMatcher(regex, example.toString()) + )) + + return this + } + /** * Element that must be a boolean */ diff --git a/consumer/src/main/kotlin/au/com/dius/pact/consumer/dsl/PactDslJsonBody.kt b/consumer/src/main/kotlin/au/com/dius/pact/consumer/dsl/PactDslJsonBody.kt index b21a6d117a..d9c2705c2f 100755 --- a/consumer/src/main/kotlin/au/com/dius/pact/consumer/dsl/PactDslJsonBody.kt +++ b/consumer/src/main/kotlin/au/com/dius/pact/consumer/dsl/PactDslJsonBody.kt @@ -3,6 +3,7 @@ package au.com.dius.pact.consumer.dsl import au.com.dius.pact.consumer.InvalidMatcherException import au.com.dius.pact.consumer.dsl.Dsl.matcherKey import au.com.dius.pact.core.matchers.UrlMatcherSupport +import au.com.dius.pact.core.model.constructValidPath import au.com.dius.pact.core.model.generators.Category import au.com.dius.pact.core.model.generators.DateGenerator import au.com.dius.pact.core.model.generators.DateTimeGenerator @@ -23,6 +24,7 @@ import au.com.dius.pact.core.model.matchingrules.MaxEqualsIgnoreOrderMatcher 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.NumberTypeMatcher +import au.com.dius.pact.core.model.matchingrules.RegexMatcher import au.com.dius.pact.core.model.matchingrules.RuleLogic import au.com.dius.pact.core.model.matchingrules.TypeMatcher import au.com.dius.pact.core.model.matchingrules.ValuesMatcher @@ -468,7 +470,7 @@ open class PactDslJsonBody : DslPart { } /** - * Attribute that must be a decimal value + * Attribute that must be a decimal value (has significant digits after the decimal point) * @param name attribute name */ fun decimalType(name: String): PactDslJsonBody { @@ -477,7 +479,7 @@ open class PactDslJsonBody : DslPart { } /** - * Attributes that must be a decimal values + * Attributes that must be a decimal values (have significant digits after the decimal point) * @param names attribute names */ fun decimalTypes(vararg names: String): PactDslJsonBody { @@ -488,7 +490,7 @@ open class PactDslJsonBody : DslPart { } /** - * Attribute that must be a decimalType value + * Attribute that must be a decimalType value (has significant digits after the decimal point) * @param name attribute name * @param number example decimalType value */ @@ -517,7 +519,7 @@ open class PactDslJsonBody : DslPart { } /** - * Attribute that must be a decimalType value + * Attribute that must be a decimalType value (has significant digits after the decimal point) * @param name attribute name * @param number example decimalType value */ @@ -545,6 +547,94 @@ open class PactDslJsonBody : DslPart { return this } + /** + * Attribute that can be any number and which must match the provided regular expression + * @param name attribute name + * @param regex Regular expression that the numbers string form must match + * @param example example number to use for generated bodies + */ + fun numberMatching(name: String, regex: String, example: Number): PactDslJsonBody { + require(example.toString().matches(Regex(regex))) { + "Example value $example does not match the provided regular expression '$regex'" + } + + when (val body = body) { + is JsonValue.Object -> body.add(name, JsonValue.Decimal(example.toString().toCharArray())) + is JsonValue.Array -> { + body.values.forEach { value -> + value.asObject()!!.add(name, JsonValue.Decimal(example.toString().toCharArray())) + } + } + else -> {} + } + + matchers.addRules(constructValidPath(name, rootPath), listOf( + NumberTypeMatcher(NumberTypeMatcher.NumberType.NUMBER), + RegexMatcher(regex, example.toString()) + )) + + return this + } + + /** + * Attribute that can be any number decimal number (has significant digits after the decimal point) and which must + * match the provided regular expression + * @param name attribute name + * @param regex Regular expression that the numbers string form must match + * @param example example number to use for generated bodies + */ + fun decimalMatching(name: String, regex: String, example: Double): PactDslJsonBody { + require(example.toString().matches(Regex(regex))) { + "Example value $example does not match the provided regular expression '$regex'" + } + + when (val body = body) { + is JsonValue.Object -> body.add(name, JsonValue.Decimal(example.toString().toCharArray())) + is JsonValue.Array -> { + body.values.forEach { value -> + value.asObject()!!.add(name, JsonValue.Decimal(example.toString().toCharArray())) + } + } + else -> {} + } + + matchers.addRules(constructValidPath(name, rootPath), listOf( + NumberTypeMatcher(NumberTypeMatcher.NumberType.DECIMAL), + RegexMatcher(regex, example.toString()) + )) + + return this + } + + /** + * Attribute that can be any integer and which must match the provided regular expression + * @param name attribute name + * @param regex Regular expression that the numbers string form must match + * @param example example integer to use for generated bodies + */ + fun integerMatching(name: String, regex: String, example: Int): PactDslJsonBody { + require(example.toString().matches(Regex(regex))) { + "Example value $example does not match the provided regular expression $regex" + } + + when (val body = body) { + is JsonValue.Object -> body.add(name, JsonValue.Integer(example.toString().toCharArray())) + is JsonValue.Array -> { + body.values.forEach { value -> + value.asObject()!!.add(name, JsonValue.Integer(example.toString().toCharArray())) + } + } + else -> {} + } + + matchers.addRules(constructValidPath(name, rootPath), listOf( + NumberTypeMatcher(NumberTypeMatcher.NumberType.INTEGER), + RegexMatcher(regex, example.toString()) + )) + + return this + } + /** * Attributes that must be a boolean * @param names attribute names diff --git a/consumer/src/main/kotlin/au/com/dius/pact/consumer/dsl/PactDslJsonRootValue.kt b/consumer/src/main/kotlin/au/com/dius/pact/consumer/dsl/PactDslJsonRootValue.kt index 544d9507f2..cfe4ef6591 100644 --- a/consumer/src/main/kotlin/au/com/dius/pact/consumer/dsl/PactDslJsonRootValue.kt +++ b/consumer/src/main/kotlin/au/com/dius/pact/consumer/dsl/PactDslJsonRootValue.kt @@ -472,7 +472,7 @@ open class PactDslJsonRootValue : DslPart("", "") { } /** - * Value that must be a decimal value + * Value that must be a decimal value (has significant digits after the decimal point) */ @JvmStatic fun decimalType(): PactDslJsonRootValue { @@ -484,7 +484,7 @@ open class PactDslJsonRootValue : DslPart("", "") { } /** - * Value that must be a decimalType value + * Value that must be a decimalType value (has significant digits after the decimal point) * @param number example decimalType value */ @JvmStatic @@ -496,7 +496,7 @@ open class PactDslJsonRootValue : DslPart("", "") { } /** - * Value that must be a decimalType value + * Value that must be a decimalType value (has significant digits after the decimal point) * @param number example decimalType value */ @JvmStatic @@ -507,6 +507,73 @@ open class PactDslJsonRootValue : DslPart("", "") { return value } + /** + * Attribute that can be any number and which must match the provided regular expression + * @param regex Regular expression that the numbers string form must match + * @param example example number to use for generated bodies + */ + @JvmStatic + fun numberMatching(regex: String, example: Number): PactDslJsonRootValue { + require(example.toString().matches(Regex(regex))) { + "Example value $example does not match the provided regular expression '$regex'" + } + + val value = PactDslJsonRootValue() + value.value = example + + value.matchers.addRules("", listOf( + NumberTypeMatcher(NumberTypeMatcher.NumberType.NUMBER), + RegexMatcher(regex, example.toString()) + )) + + return value + } + + /** + * Attribute that can be any number decimal number (has significant digits after the decimal point) and which must + * match the provided regular expression + * @param regex Regular expression that the numbers string form must match + * @param example example number to use for generated bodies + */ + @JvmStatic + fun decimalMatching(regex: String, example: Double): PactDslJsonRootValue { + require(example.toString().matches(Regex(regex))) { + "Example value $example does not match the provided regular expression '$regex'" + } + + val value = PactDslJsonRootValue() + value.value = example + + value.matchers.addRules("", listOf( + NumberTypeMatcher(NumberTypeMatcher.NumberType.DECIMAL), + RegexMatcher(regex, example.toString()) + )) + + return value + } + + /** + * Attribute that can be any integer and which must match the provided regular expression + * @param regex Regular expression that the numbers string form must match + * @param example example integer to use for generated bodies + */ + @JvmStatic + fun integerMatching(regex: String, example: Int): PactDslJsonRootValue { + require(example.toString().matches(Regex(regex))) { + "Example value $example does not match the provided regular expression $regex" + } + + val value = PactDslJsonRootValue() + value.value = example + + value.matchers.addRules("", listOf( + NumberTypeMatcher(NumberTypeMatcher.NumberType.INTEGER), + RegexMatcher(regex, example.toString()) + )) + + return value + } + /** * Value that must be a boolean * @param example example boolean to use for generated bodies diff --git a/consumer/src/main/kotlin/au/com/dius/pact/consumer/dsl/PactDslRootValue.kt b/consumer/src/main/kotlin/au/com/dius/pact/consumer/dsl/PactDslRootValue.kt index 990aa7f864..b1885679aa 100644 --- a/consumer/src/main/kotlin/au/com/dius/pact/consumer/dsl/PactDslRootValue.kt +++ b/consumer/src/main/kotlin/au/com/dius/pact/consumer/dsl/PactDslRootValue.kt @@ -14,6 +14,7 @@ import au.com.dius.pact.core.model.generators.UuidGenerator import au.com.dius.pact.core.model.matchingrules.MatchingRule import au.com.dius.pact.core.model.matchingrules.MatchingRuleGroup import au.com.dius.pact.core.model.matchingrules.NumberTypeMatcher +import au.com.dius.pact.core.model.matchingrules.RegexMatcher import au.com.dius.pact.core.model.matchingrules.RuleLogic import au.com.dius.pact.core.model.matchingrules.TypeMatcher import au.com.dius.pact.core.support.Json.toJson @@ -453,7 +454,7 @@ open class PactDslRootValue : DslPart("", "") { } /** - * Value that must be a decimal value + * Value that must be a decimal value (has significant digits after the decimal point) */ @JvmStatic fun decimalType(): PactDslRootValue { @@ -465,7 +466,7 @@ open class PactDslRootValue : DslPart("", "") { } /** - * Value that must be a decimalType value + * Value that must be a decimalType value (has significant digits after the decimal point) * @param number example decimalType value */ @JvmStatic @@ -477,7 +478,7 @@ open class PactDslRootValue : DslPart("", "") { } /** - * Value that must be a decimalType value + * Value that must be a decimalType value (has significant digits after the decimal point) * @param number example decimalType value */ @JvmStatic @@ -488,6 +489,73 @@ open class PactDslRootValue : DslPart("", "") { return value } + /** + * Attribute that can be any number and which must match the provided regular expression + * @param regex Regular expression that the numbers string form must match + * @param example example number to use for generated bodies + */ + @JvmStatic + fun numberMatching(regex: String, example: Number): PactDslRootValue { + require(example.toString().matches(Regex(regex))) { + "Example value $example does not match the provided regular expression '$regex'" + } + + val value = PactDslRootValue() + value.setValue(example) + + value.matchers.addRules("", listOf( + NumberTypeMatcher(NumberTypeMatcher.NumberType.NUMBER), + RegexMatcher(regex, example.toString()) + )) + + return value + } + + /** + * Attribute that can be any number decimal number (has significant digits after the decimal point) and which must + * match the provided regular expression + * @param regex Regular expression that the numbers string form must match + * @param example example number to use for generated bodies + */ + @JvmStatic + fun decimalMatching(regex: String, example: Double): PactDslRootValue { + require(example.toString().matches(Regex(regex))) { + "Example value $example does not match the provided regular expression '$regex'" + } + + val value = PactDslRootValue() + value.setValue(example) + + value.matchers.addRules("", listOf( + NumberTypeMatcher(NumberTypeMatcher.NumberType.DECIMAL), + RegexMatcher(regex, example.toString()) + )) + + return value + } + + /** + * Attribute that can be any integer and which must match the provided regular expression + * @param regex Regular expression that the numbers string form must match + * @param example example integer to use for generated bodies + */ + @JvmStatic + fun integerMatching(regex: String, example: Int): PactDslRootValue { + require(example.toString().matches(Regex(regex))) { + "Example value $example does not match the provided regular expression $regex" + } + + val value = PactDslRootValue() + value.setValue(example) + + value.matchers.addRules("", listOf( + NumberTypeMatcher(NumberTypeMatcher.NumberType.INTEGER), + RegexMatcher(regex, example.toString()) + )) + + return value + } + /** * Value that must be a boolean * @param example example boolean to use for generated bodies diff --git a/consumer/src/test/groovy/au/com/dius/pact/consumer/dsl/PactDslJsonArraySpec.groovy b/consumer/src/test/groovy/au/com/dius/pact/consumer/dsl/PactDslJsonArraySpec.groovy index 211da8f89d..869ecb1672 100644 --- a/consumer/src/test/groovy/au/com/dius/pact/consumer/dsl/PactDslJsonArraySpec.groovy +++ b/consumer/src/test/groovy/au/com/dius/pact/consumer/dsl/PactDslJsonArraySpec.groovy @@ -1,6 +1,9 @@ package au.com.dius.pact.consumer.dsl 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.NumberTypeMatcher +import au.com.dius.pact.core.model.matchingrules.RegexMatcher import au.com.dius.pact.core.model.matchingrules.RuleLogic import spock.lang.Issue import spock.lang.Specification @@ -313,4 +316,20 @@ class PactDslJsonArraySpec extends Specification { '[1]': [matchers: [[match: 'type']], combine: 'AND'] ] } + + @Issue('1600') + def 'Match number type with Regex'() { + when: + PactDslJsonArray body = new PactDslJsonArray() + .numberMatching('\\d+\\.\\d{2}', 2.01) + .decimalMatching('\\d+\\.\\d{2}', 2.01) + .integerMatching('\\d{5}', 90210) + .close() + + then: + body.toString() == '[2.01,2.01,90210]' + body.matchers.matchingRules['$[0]'] == new MatchingRuleGroup([new NumberTypeMatcher(NumberTypeMatcher.NumberType.NUMBER), new RegexMatcher('\\d+\\.\\d{2}', '2.01')]) + body.matchers.matchingRules['$[1]'] == new MatchingRuleGroup([new NumberTypeMatcher(NumberTypeMatcher.NumberType.DECIMAL), new RegexMatcher('\\d+\\.\\d{2}', '2.01')]) + body.matchers.matchingRules['$[2]'] == new MatchingRuleGroup([new NumberTypeMatcher(NumberTypeMatcher.NumberType.INTEGER), new RegexMatcher('\\d{5}', '90210')]) + } } diff --git a/consumer/src/test/groovy/au/com/dius/pact/consumer/dsl/PactDslJsonBodySpec.groovy b/consumer/src/test/groovy/au/com/dius/pact/consumer/dsl/PactDslJsonBodySpec.groovy index 14e8fa5391..1b9d33451e 100644 --- a/consumer/src/test/groovy/au/com/dius/pact/consumer/dsl/PactDslJsonBodySpec.groovy +++ b/consumer/src/test/groovy/au/com/dius/pact/consumer/dsl/PactDslJsonBodySpec.groovy @@ -412,4 +412,21 @@ class PactDslJsonBodySpec extends Specification { '$.foo[*].baz': new MatchingRuleGroup([new NumberTypeMatcher(NumberTypeMatcher.NumberType.INTEGER)]) ] } + + @Issue('1600') + def 'Match number type with Regex'() { + when: + PactDslJsonBody body = new PactDslJsonBody() + .numberMatching('foo', '\\d+\\.\\d{2}', 2.01) + .decimalMatching('bar', '\\d+\\.\\d{2}', 2.01) + .integerMatching('baz', '\\d{5}', 90210) + .close() + + then: + body.toString() == '{"bar":2.01,"baz":90210,"foo":2.01}' + body.matchers.matchingRules.keySet() == ['$.foo', '$.bar', '$.baz'] as Set + body.matchers.matchingRules['$.foo'] == new MatchingRuleGroup([new NumberTypeMatcher(NumberTypeMatcher.NumberType.NUMBER), new RegexMatcher('\\d+\\.\\d{2}', '2.01')]) + body.matchers.matchingRules['$.bar'] == new MatchingRuleGroup([new NumberTypeMatcher(NumberTypeMatcher.NumberType.DECIMAL), new RegexMatcher('\\d+\\.\\d{2}', '2.01')]) + body.matchers.matchingRules['$.baz'] == new MatchingRuleGroup([new NumberTypeMatcher(NumberTypeMatcher.NumberType.INTEGER), new RegexMatcher('\\d{5}', '90210')]) + } } diff --git a/consumer/src/test/groovy/au/com/dius/pact/consumer/dsl/PactDslJsonRootValueSpec.groovy b/consumer/src/test/groovy/au/com/dius/pact/consumer/dsl/PactDslJsonRootValueSpec.groovy index 8c8f7c6255..b0eddf9834 100644 --- a/consumer/src/test/groovy/au/com/dius/pact/consumer/dsl/PactDslJsonRootValueSpec.groovy +++ b/consumer/src/test/groovy/au/com/dius/pact/consumer/dsl/PactDslJsonRootValueSpec.groovy @@ -1,6 +1,10 @@ package au.com.dius.pact.consumer.dsl 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.NumberTypeMatcher +import au.com.dius.pact.core.model.matchingrules.RegexMatcher +import spock.lang.Issue import spock.lang.Shared import spock.lang.Specification import spock.lang.Unroll @@ -54,4 +58,19 @@ class PactDslJsonRootValueSpec extends Specification { '': [type: 'DateTime', format: 'yyyy-MM-dd\'T\'HH:mm:ss', expression: 'today + 1 hour']]] } + @Issue('1600') + def 'Match number type with Regex'() { + when: + def number = PactDslJsonRootValue.numberMatching('\\d+\\.\\d{2}', 2.01) + def decimal = PactDslJsonRootValue.decimalMatching('\\d+\\.\\d{2}', 2.01) + def integer = PactDslJsonRootValue.integerMatching('\\d{5}', 90210) + + then: + number.toString() == '2.01' + number.matchers.matchingRules[''] == new MatchingRuleGroup([new NumberTypeMatcher(NumberTypeMatcher.NumberType.NUMBER), new RegexMatcher('\\d+\\.\\d{2}', '2.01')]) + decimal.toString() == '2.01' + decimal.matchers.matchingRules[''] == new MatchingRuleGroup([new NumberTypeMatcher(NumberTypeMatcher.NumberType.DECIMAL), new RegexMatcher('\\d+\\.\\d{2}', '2.01')]) + integer.toString() == '90210' + integer.matchers.matchingRules[''] == new MatchingRuleGroup([new NumberTypeMatcher(NumberTypeMatcher.NumberType.INTEGER), new RegexMatcher('\\d{5}', '90210')]) + } }