Added a json schema definition and added it to the docs

fixes gh-1250
This commit is contained in:
Marcin Grzejszczak
2019-10-22 10:59:04 +02:00
parent 6b388b4972
commit 239cc36f0e
5 changed files with 237 additions and 0 deletions

View File

@@ -14,6 +14,7 @@
<name>Spring Cloud Contract Docs</name>
<description>Spring Cloud Docs</description>
<properties>
<jackson-module-jsonSchema.version>2.10.0</jackson-module-jsonSchema.version>
<docs.main>spring-cloud-contract</docs.main>
<main.basedir>${basedir}/..</main.basedir>
<maven.plugin.plugin.version>3.4</maven.plugin.plugin.version>
@@ -29,6 +30,40 @@
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>schema-test-compilation</id>
<phase>generate-test-resources</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>schema-generation</id>
<phase>generate-test-resources</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<includes>
<include>**/*Tests.*</include>
<include>**/*Test.*</include>
</includes>
<reportFormat>plain</reportFormat>
<failIfNoTests>true</failIfNoTests>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
@@ -40,6 +75,12 @@
<groupId>${project.groupId}</groupId>
<artifactId>spring-cloud-starter-contract-verifier</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jsonSchema</artifactId>
<version>${jackson-module-jsonSchema.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>

View File

@@ -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

View File

@@ -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]
----
====

View File

@@ -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<Contract> contracts = new YamlContractConverter().convertFrom(ymlFile);
BDDAssertions.then(contracts).isNotEmpty();
}
}

View File

@@ -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: