diff --git a/specs/spring-cloud-contract-spec-java/src/main/java/org/springframework/cloud/contract/spec/internal/OptionalProperty.java b/specs/spring-cloud-contract-spec-java/src/main/java/org/springframework/cloud/contract/spec/internal/OptionalProperty.java index 7d7d51b5d0..b4f9065184 100644 --- a/specs/spring-cloud-contract-spec-java/src/main/java/org/springframework/cloud/contract/spec/internal/OptionalProperty.java +++ b/specs/spring-cloud-contract-spec-java/src/main/java/org/springframework/cloud/contract/spec/internal/OptionalProperty.java @@ -54,6 +54,9 @@ public class OptionalProperty implements Serializable, CanBeDynamic { else if (value instanceof ClientDslProperty) { return valueToCheck(((ClientDslProperty) value).getClientValue()); } + else if (value instanceof ServerDslProperty) { + return valueToCheck(((ServerDslProperty) value).getServerValue()); + } else if (value instanceof RegexProperty || value instanceof Pattern) { return new RegexProperty(value).pattern(); } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentUtils.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentUtils.groovy index 9a95c501a3..3c94859745 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentUtils.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentUtils.groovy @@ -322,7 +322,7 @@ class ContentUtils { } protected static Object transformJSONStringValue(OptionalProperty optional, Closure valueProvider) { - return String.format(JSON_VALUE_PATTERN_FOR_OPTIONAL, optional.value) + return String.format(JSON_VALUE_PATTERN_FOR_OPTIONAL, optional.value()) } protected static Object transformJSONStringValue(ExecutionProperty property, Closure valueProvider) { diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilderSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilderSpec.groovy index 0526672946..438ac76587 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilderSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilderSpec.groovy @@ -2174,4 +2174,68 @@ response: } } + @Issue("1808") + def "should correctly process optional of DslProperty parameters"() { + given: + Contract contractDsl = Contract.make { + request { + method('GET') + url("/api/foo") + headers { + header 'Content-Type': 'application/json' + header 'Accept': 'application/json' + } + body([ + key1: $(client(optional(anyOf("foo", "bar"))), server("bar")), + key2: $(client(optional(anyNonBlankString())), server("bar")), + key3: $(client(optional(anyEmail())), server("foo@bar.com")), + key4: $(optional(anyNumber())) + ]) + } + response { + status OK() + headers { + header 'Content-Type': 'application/json' + } + body([ + key1: $(client("bar"), server(optional(anyOf("foo", "bar")))), + key2: $(client("bar"), server(optional(anyNonBlankString()))), + key3: $(client("foo@bar.com"), server(optional(anyEmail()))), + key4: $(optional(anyNumber())) + ]) + } + } + methodBuilder() + when: + String test = singleTestGenerator(contractDsl) + then: + SyntaxChecker.tryToCompile(methodBuilderName, test) + then: + test.contains('assertThatJson(parsedJson).field("[\'key1\']").matches("(^foo' + endOfLineRegexSymbol + '|^bar' + endOfLineRegexSymbol + ')?")') + test.contains('assertThatJson(parsedJson).field("[\'key2\']").matches("(^\\\\s*\\\\S[\\\\S\\\\s]*)?")') + test.contains('assertThatJson(parsedJson).field("[\'key3\']").matches("([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,6})?")') + test.contains('assertThatJson(parsedJson).field("[\'key4\']").matches("(-?(\\\\d*\\\\.\\\\d+|\\\\d+))?")') + and: + stubMappingIsValidWireMockStub(contractDsl) + where: + methodBuilderName | methodBuilder | endOfLineRegexSymbol + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | '\\$' + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | '\$' + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | '\\$' + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | '\$' + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | '\$' + "testNG" | { + properties.testFramework = TestFramework.TESTNG + } | '\$' + } } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/WireMockGroovyDslSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/WireMockGroovyDslSpec.groovy index 53e6e4aa73..e700b83c01 100755 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/WireMockGroovyDslSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/WireMockGroovyDslSpec.groovy @@ -3130,6 +3130,74 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie stubMappingIsValidWireMockStub(wireMockStub) } + @Issue("1808") + def "should correctly process optional of DslProperty parameters"() { + given: + org.springframework.cloud.contract.spec.Contract groovyDsl = org.springframework.cloud.contract.spec.Contract. + make { + request { + method('GET') + url("/api/foo") + headers { + header("Content-Type", "application/json") + header("Accept", "application/json") + } + body( + key1: $(client(optional(anyOf("foo", "bar"))), server("bar")), + key2: $(client(optional(anyNonBlankString())), server("bar")), + key3: $(client(optional(anyEmail())), server("foo@bar.com")), + key4: $(optional(anyNumber())), + ) + } + response { + status OK() + body("ok") + headers { + header 'Content-Type': 'text/plain' + } + } + } + when: + String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, groovyDsl), groovyDsl). + toWireMockClientStub() + then: + AssertionUtil.assertThatJsonsAreEqual(''' + { + "request" : { + "url" : "/api/foo", + "method" : "GET", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + }, + "Accept" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "matchesJsonPath" : "$[?(@.['key1'] =~ /(^foo$|^bar$)?/)]" + }, { + "matchesJsonPath" : "$[?(@.['key2'] =~ /(^\\\\s*\\\\S[\\\\S\\\\s]*)?/)]" + }, { + "matchesJsonPath" : "$[?(@.['key3'] =~ /([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,6})?/)]" + }, { + "matchesJsonPath" : "$[?(@.['key4'] =~ /(-?(\\\\d*\\\\.\\\\d+|\\\\d+))?/)]" + } ] + }, + "response" : { + "status" : 200, + "body" : "ok", + "headers" : { + "Content-Type" : "text/plain" + }, + "transformers" : [ "response-template", "foo-transformer" ] + } + } + ''', wireMockStub) + and: + stubMappingIsValidWireMockStub(wireMockStub) + } + WireMockConfiguration config() { return new WireMockConfiguration().extensions(responseTemplateTransformer()) }