diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/ContractDslSnippet.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/ContractDslSnippet.java index 345e4cae3a..a69fdbacc4 100644 --- a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/ContractDslSnippet.java +++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/ContractDslSnippet.java @@ -17,8 +17,10 @@ import org.springframework.restdocs.RestDocumentationContext; import org.springframework.restdocs.operation.Operation; import org.springframework.restdocs.operation.OperationRequest; import org.springframework.restdocs.operation.OperationResponse; +import org.springframework.restdocs.snippet.RestDocumentationContextPlaceholderResolver; import org.springframework.restdocs.snippet.TemplatedSnippet; import org.springframework.restdocs.templates.TemplateEngine; +import org.springframework.util.PropertyPlaceholderHelper; import org.springframework.util.StringUtils; /** @@ -35,6 +37,8 @@ public class ContractDslSnippet extends TemplatedSnippet { private Map model = new HashMap<>(); private static final Set IGNORED_HEADERS = new HashSet<>(Arrays.asList(HttpHeaders.HOST, HttpHeaders.CONTENT_LENGTH)); + private final PropertyPlaceholderHelper propertyPlaceholderHelper = new PropertyPlaceholderHelper( + "{", "}"); /** * Creates a new {@code ContractDslSnippet} with no additional attributes. @@ -134,13 +138,20 @@ public class ContractDslSnippet extends TemplatedSnippet { throws IOException { RestDocumentationContext context = (RestDocumentationContext) operation .getAttributes().get(RestDocumentationContext.class.getName()); + RestDocumentationContextPlaceholderResolver resolver = new + RestDocumentationContextPlaceholderResolver(context); + String resolvedName = replacePlaceholders(resolver, operation.getName()); File output = new File(context.getOutputDirectory(), - CONTRACTS_FOLDER + "/" + operation.getName() + ".groovy"); + CONTRACTS_FOLDER + "/" + resolvedName + ".groovy"); output.getParentFile().mkdirs(); try (Writer writer = new OutputStreamWriter(Files.newOutputStream(output.toPath()))) { writer.append(content); } } + + private String replacePlaceholders(PropertyPlaceholderHelper.PlaceholderResolver resolver, String input) { + return this.propertyPlaceholderHelper.replacePlaceholders(input, resolver); + } } class JsonPaths { diff --git a/spring-cloud-contract-wiremock/src/test/java/org/springframework/cloud/contract/wiremock/restdocs/ContractDslSnippetTests.java b/spring-cloud-contract-wiremock/src/test/java/org/springframework/cloud/contract/wiremock/restdocs/ContractDslSnippetTests.java index e79284651e..47475a1b6f 100644 --- a/spring-cloud-contract-wiremock/src/test/java/org/springframework/cloud/contract/wiremock/restdocs/ContractDslSnippetTests.java +++ b/spring-cloud-contract-wiremock/src/test/java/org/springframework/cloud/contract/wiremock/restdocs/ContractDslSnippetTests.java @@ -97,6 +97,43 @@ public class ContractDslSnippetTests { then(parsedContract.getResponse().getBody().getClientValue()).isNotNull(); } + @Test + public void should_create_contract_template_and_doc_with_placeholder_names() throws Exception { + this.mockMvc.perform(post("/foo") + .accept(MediaType.APPLICATION_PDF) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"foo\": 23, \"bar\" : \"baz\" }")) + .andExpect(status().isOk()) + .andExpect(content().string("bar")) + // first WireMock + .andDo(WireMockRestDocs.verify() + .jsonPath("$[?(@.foo >= 20)]") + .jsonPath("$[?(@.bar in ['baz','bazz','bazzz'])]") + .contentType(MediaType.valueOf("application/json")) + .stub("shouldGrantABeerIfOldEnough")) + // then Contract DSL documentation + .andDo(document("{methodName}", SpringCloudContractRestDocs.dslContract())); + + then(file("/contracts/should_create_contract_template_and_doc_with_placeholder_names.groovy")).exists(); + then(file("/should_create_contract_template_and_doc_with_placeholder_names/dsl-contract.adoc")).exists(); + Collection parsedContracts = ContractVerifierDslConverter.convertAsCollection(new File("/"), file("/contracts/should_create_contract_template_and_doc_with_placeholder_names.groovy")); + Contract parsedContract = parsedContracts.iterator().next(); + then(parsedContract.getRequest().getHeaders().getEntries()).isNotNull(); + then(headerNames(parsedContract.getRequest().getHeaders().getEntries())).doesNotContain + (HttpHeaders.HOST, HttpHeaders.CONTENT_LENGTH); + then(headerNames(parsedContract.getResponse().getHeaders().getEntries())).doesNotContain + (HttpHeaders.HOST, HttpHeaders.CONTENT_LENGTH); + then(parsedContract.getRequest().getMethod().getClientValue()).isNotNull(); + then(parsedContract.getRequest().getUrl().getClientValue()).isNotNull(); + then(parsedContract.getRequest().getUrl().getClientValue().toString()).startsWith("/"); + then(parsedContract.getRequest().getBody().getClientValue()).isNotNull(); + then(parsedContract.getRequest().getMatchers().hasMatchers()).isTrue(); + then(parsedContract.getResponse().getStatus().getClientValue()).isNotNull(); + then(parsedContract.getResponse().getHeaders().getEntries()).isNotEmpty(); + then(parsedContract.getResponse().getBody().getClientValue()).isNotNull(); + } + @Test public void should_create_contract_template_and_doc_without_body_and_headers() throws Exception { this.mockMvc.perform(MockMvcRequestBuilders.get("/foo"))