From 239cc36f0ed846fa4eecfe4f975b3bfef3e54767 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Tue, 22 Oct 2019 10:59:04 +0200 Subject: [PATCH] Added a json schema definition and added it to the docs fixes gh-1250 --- docs/pom.xml | 41 ++++++ .../asciidoc/_project-features-contract.adoc | 5 + docs/src/main/asciidoc/yml-schema.adoc | 12 ++ .../cloud/contract/docs/JsonSchemaTests.java | 120 ++++++++++++++++++ docs/src/test/resources/contract.yml | 59 +++++++++ 5 files changed, 237 insertions(+) create mode 100644 docs/src/main/asciidoc/yml-schema.adoc create mode 100644 docs/src/test/java/org/springframework/cloud/contract/docs/JsonSchemaTests.java create mode 100644 docs/src/test/resources/contract.yml diff --git a/docs/pom.xml b/docs/pom.xml index 91aa75acf6..667afba308 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -14,6 +14,7 @@ Spring Cloud Contract Docs Spring Cloud Docs + 2.10.0 spring-cloud-contract ${basedir}/.. 3.4 @@ -29,6 +30,40 @@ true + + org.apache.maven.plugins + maven-compiler-plugin + + + schema-test-compilation + generate-test-resources + + testCompile + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + schema-generation + generate-test-resources + + test + + + + **/*Tests.* + **/*Test.* + + plain + true + + + + @@ -40,6 +75,12 @@ ${project.groupId} spring-cloud-starter-contract-verifier + + com.fasterxml.jackson.module + jackson-module-jsonSchema + ${jackson-module-jsonSchema.version} + test + diff --git a/docs/src/main/asciidoc/_project-features-contract.adoc b/docs/src/main/asciidoc/_project-features-contract.adoc index 02e05b300c..85daf731d5 100644 --- a/docs/src/main/asciidoc/_project-features-contract.adoc +++ b/docs/src/main/asciidoc/_project-features-contract.adoc @@ -164,6 +164,11 @@ IMPORTANT: Remember that, inside the Kotlin Script file, you have to provide the Generally you would use its contract function like this: `org.springframework.cloud.contract.spec.ContractDsl.contract { ... }`. You can also provide an import to the `contract` function (`import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract`) and then call `contract { ... }`. +[[contract-yml]] +=== Contract DSL in YML + +In order to see a schema of a YAML contract, you can check out the link:yml-schema.html[YML Schema] page. + [[contract-limitations]] === Limitations diff --git a/docs/src/main/asciidoc/yml-schema.adoc b/docs/src/main/asciidoc/yml-schema.adoc new file mode 100644 index 0000000000..0bae1f161d --- /dev/null +++ b/docs/src/main/asciidoc/yml-schema.adoc @@ -0,0 +1,12 @@ +[[yml-schema]] +== YML Schema +include::_attributes.adoc[] + +Below you can find a JSON schema definition of a YAML contract. + +==== +[source,json,indent=0] +---- +include::{project-root}/docs/target/contract_schema.json[indent=0] +---- +==== diff --git a/docs/src/test/java/org/springframework/cloud/contract/docs/JsonSchemaTests.java b/docs/src/test/java/org/springframework/cloud/contract/docs/JsonSchemaTests.java new file mode 100644 index 0000000000..49b16e2192 --- /dev/null +++ b/docs/src/test/java/org/springframework/cloud/contract/docs/JsonSchemaTests.java @@ -0,0 +1,120 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.docs; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.Collection; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.module.jsonSchema.JsonSchema; +import com.fasterxml.jackson.module.jsonSchema.JsonSchemaGenerator; +import org.assertj.core.api.BDDAssertions; +import org.junit.jupiter.api.Test; + +import org.springframework.cloud.contract.spec.Contract; +import org.springframework.cloud.contract.verifier.converter.YamlContract; +import org.springframework.cloud.contract.verifier.converter.YamlContractConverter; + +class JsonSchemaTests { + + // @formatter:off + private static final String CONTRACT = "description: Some description\n" + + "name: some name\n" + + "priority: 8\n" + + "ignored: true\n" + + "inProgress: true\n" + + "request:\n" + + " method: PUT\n" + + " url: /foo\n" + + " queryParameters:\n" + + " a: b\n" + + " b: c\n" + + " headers:\n" + + " foo: bar\n" + + " fooReq: baz\n" + + " cookies:\n" + + " foo: bar\n" + + " fooReq: baz\n" + + " body:\n" + + " foo: bar\n" + + " matchers:\n" + + " body:\n" + + " - path: $.foo\n" + + " type: by_regex\n" + + " value: bar\n" + + " headers:\n" + + " - key: foo\n" + + " regex: bar\n" + + "response:\n" + + " status: 200\n" + + " fixedDelayMilliseconds: 1000\n" + + " headers:\n" + + " foo2: bar\n" + + " foo3: foo33\n" + + " fooRes: baz\n" + + " body:\n" + + " foo2: bar\n" + + " foo3: baz\n" + + " nullValue: null\n" + + " matchers:\n" + + " body:\n" + + " - path: $.foo2\n" + + " type: by_regex\n" + + " value: bar\n" + + " - path: $.foo3\n" + + " type: by_command\n" + + " value: executeMe($it)\n" + + " - path: $.nullValue\n" + + " type: by_null\n" + + " value: null\n" + + " headers:\n" + + " - key: foo2\n" + + " regex: bar\n" + + " - key: foo3\n" + + " command: andMeToo($it)\n" + + " cookies:\n" + + " - key: foo2\n" + + " regex: bar\n" + + " - key: foo3\n" + + " predefined:\n"; + // @formatter:on + + @Test + void should_produce_a_json_schema_of_a_yaml_model() throws IOException { + ObjectMapper mapper = new ObjectMapper(); + mapper.enable(SerializationFeature.INDENT_OUTPUT); + JsonSchemaGenerator schemaGen = new JsonSchemaGenerator(mapper); + JsonSchema schema = schemaGen.generateSchema(YamlContract.class); + String schemaString = mapper.writeValueAsString(schema); + File schemaFile = new File("target/contract_schema.json"); + Files.write(schemaFile.toPath(), schemaString.getBytes()); + } + + @Test + void should_convert_yaml_to_contract() throws IOException { + File ymlFile = new File("target/contract.yml"); + Files.write(ymlFile.toPath(), CONTRACT.getBytes()); + + Collection contracts = new YamlContractConverter().convertFrom(ymlFile); + + BDDAssertions.then(contracts).isNotEmpty(); + } + +} diff --git a/docs/src/test/resources/contract.yml b/docs/src/test/resources/contract.yml new file mode 100644 index 0000000000..5322f630b8 --- /dev/null +++ b/docs/src/test/resources/contract.yml @@ -0,0 +1,59 @@ +description: Some description +name: some name +priority: 8 +ignored: true +inProgress: true +request: + method: PUT + url: /foo + queryParameters: + a: b + b: c + headers: + foo: bar + fooReq: baz + cookies: + foo: bar + fooReq: baz + body: + foo: bar + matchers: + body: + - path: $.foo + type: by_regex + value: bar + headers: + - key: foo + regex: bar +response: + status: 200 + fixedDelayMilliseconds: 1000 + headers: + foo2: bar + foo3: foo33 + fooRes: baz + body: + foo2: bar + foo3: baz + nullValue: null + matchers: + body: + - path: $.foo2 + type: by_regex + value: bar + - path: $.foo3 + type: by_command + value: executeMe($it) + - path: $.nullValue + type: by_null + value: null + headers: + - key: foo2 + regex: bar + - key: foo3 + command: andMeToo($it) + cookies: + - key: foo2 + regex: bar + - key: foo3 + predefined: