diff --git a/consumer/junit5/src/test/java/au/com/dius/pact/consumer/junit5/EachKeyLikeTest.java b/consumer/junit5/src/test/java/au/com/dius/pact/consumer/junit5/EachKeyLikeTest.java new file mode 100644 index 000000000..ffac88dc6 --- /dev/null +++ b/consumer/junit5/src/test/java/au/com/dius/pact/consumer/junit5/EachKeyLikeTest.java @@ -0,0 +1,61 @@ +package au.com.dius.pact.consumer.junit5; + +import au.com.dius.pact.consumer.MockServer; +import au.com.dius.pact.consumer.dsl.PactDslJsonRootValue; +import au.com.dius.pact.consumer.dsl.PactDslWithProvider; +import au.com.dius.pact.core.model.PactSpecVersion; +import au.com.dius.pact.core.model.V4Pact; +import au.com.dius.pact.core.model.annotations.Pact; +import org.apache.hc.client5.http.fluent.Request; +import org.apache.hc.core5.http.ClassicHttpResponse; +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; + +import java.io.IOException; + +import static au.com.dius.pact.consumer.dsl.LambdaDsl.newJsonBody; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +// Issue #1813 +@ExtendWith(PactConsumerTestExt.class) +@PactTestFor(providerName = "eachkeylike_provider", pactVersion = PactSpecVersion.V4) +public class EachKeyLikeTest { + + @Pact(consumer="eachkeylike__consumer") + public V4Pact createFragment(PactDslWithProvider builder) { + return builder + .uponReceiving("A request") + .path("/") + .method("POST") + .body(newJsonBody(body -> + body.object("a", aObj -> { + aObj.eachKeyLike("prop1", PactDslJsonRootValue.stringMatcher("prop\\d+", "prop1")); + aObj.eachKeyLike("prop1", propObj -> propObj.stringType("value", "x")); + })).build()) + .willRespondWith() + .status(200) + .toPact(V4Pact.class); + } + + @Test + void runTest(MockServer mockServer) throws IOException { + String json = "{\n" + + " \"a\": {\n" + + " \"prop1\": {\n" + + " \"value\": \"x\"\n" + + " },\n" + + " \"prop\": {\n" + + " \"value\": \"y\"\n" + + " }\n" + + " }\n" + + "}"; + ClassicHttpResponse httpResponse = (ClassicHttpResponse) Request.post(mockServer.getUrl()) + .body(new StringEntity(json, ContentType.APPLICATION_JSON)) + .execute() + .returnResponse(); + assertThat(httpResponse.getCode(), is(200)); + } +} 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 6abd1f16e..d2be00b16 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 @@ -1,20 +1,16 @@ package au.com.dius.pact.consumer.dsl; -import au.com.dius.pact.core.matchers.UrlMatcherSupport; import au.com.dius.pact.core.model.matchingrules.MatchingRule; import java.math.BigDecimal; import java.time.Instant; import java.time.LocalDate; import java.time.ZonedDateTime; -import java.util.Arrays; import java.util.Date; import java.util.TimeZone; import java.util.UUID; import java.util.function.Consumer; -import static au.com.dius.pact.consumer.dsl.Dsl.matcherKey; - public class LambdaDslObject { private final PactDslJsonBody object; @@ -949,8 +945,31 @@ public LambdaDslObject eachKeyMappedToAnArrayLike(String exampleKey, Consumer nestedObject) { + return eachValueLike(exampleKey, nestedObject); + } + + /** + * Accepts any key, and each key is mapped to a map that must match the provided object definition + * + * @param exampleKey Example key to use for generating bodies + * @param value Value to use for matching and generated bodies + * @deprecated Use eachValueLike instead + */ + @Deprecated + public LambdaDslObject eachKeyLike(String exampleKey, PactDslJsonRootValue value) { + return eachValueLike(exampleKey, value); + } + + /** + * Accepts any key in a map, and each key is mapped to a value that must match the following object definition. + * + * @param exampleKey Example key to use for generating bodies + */ + public LambdaDslObject eachValueLike(String exampleKey, Consumer nestedObject) { final PactDslJsonBody objectLike = object.eachKeyLike(exampleKey); final LambdaDslObject dslObject = new LambdaDslObject(objectLike); nestedObject.accept(dslObject); @@ -959,12 +978,12 @@ public LambdaDslObject eachKeyLike(String exampleKey, Consumer } /** - * Accepts any key, and each key is mapped to a map that must match the provided object definition + * Accepts any key, and each key is mapped to a value that must match the provided object definition * * @param exampleKey Example key to use for generating bodies * @param value Value to use for matching and generated bodies */ - public LambdaDslObject eachKeyLike(String exampleKey, PactDslJsonRootValue value) { + public LambdaDslObject eachValueLike(String exampleKey, PactDslJsonRootValue value) { object.eachKeyLike(exampleKey, value); return this; } 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 cf53c3238..e297457ec 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 @@ -1832,7 +1832,26 @@ open class PactDslJsonBody : DslPart { * Accepts any key, and each key is mapped to a map that must match the following object definition * @param exampleKey Example key to use for generating bodies */ + @Deprecated("Use eachValueLike instead", ReplaceWith("eachValueLike(exampleKey)")) fun eachKeyLike(exampleKey: String): PactDslJsonBody { + return eachValueLike(exampleKey) + } + + /** + * Accepts any key, and each key is mapped to a map that must match the provided object definition + * @param exampleKey Example key to use for generating bodies + * @param value Value to use for matching and generated bodies + */ + @Deprecated("Use eachValueLike instead", ReplaceWith("eachValueLike(exampleKey, value)")) + fun eachKeyLike(exampleKey: String, value: PactDslJsonRootValue): PactDslJsonBody { + return eachValueLike(exampleKey, value) + } + + /** + * Accepts any key, and each key is mapped to a value that must match the following object definition + * @param exampleKey Example key to use for generating bodies + */ + fun eachValueLike(exampleKey: String): PactDslJsonBody { matchers.addRule( if (rootPath.endsWith(".")) rootPath.substring(0, rootPath.length - 1) else rootPath, ValuesMatcher ) @@ -1844,7 +1863,7 @@ open class PactDslJsonBody : DslPart { * @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 { + fun eachValueLike(exampleKey: String, value: PactDslJsonRootValue): PactDslJsonBody { when (val body = body) { is JsonValue.Object -> body.add(exampleKey, value.body) is JsonValue.Array -> {