Merge remote-tracking branch 'origin/master'
# Conflicts: # spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentUtils.groovy # spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/ContentUtilsSpec.groovy
This commit is contained in:
@@ -1,32 +1,33 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.PackageScope
|
||||
import groovy.util.logging.Commons
|
||||
import org.springframework.cloud.contract.verifier.builder.SingleTestGenerator
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import java.nio.file.StandardOpenOption
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.PackageScope
|
||||
import groovy.util.logging.Commons
|
||||
|
||||
import org.springframework.cloud.contract.verifier.builder.SingleTestGenerator
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.beforeLast
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.capitalize
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.packageToDirectory
|
||||
@@ -48,16 +49,20 @@ class FileSaver {
|
||||
|
||||
void saveClassFile(Path classPath, byte[] classBytes) {
|
||||
log.info("Creating new class file [$classPath]")
|
||||
Files.write(classPath, classBytes, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)
|
||||
Files.
|
||||
write(classPath, classBytes, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)
|
||||
}
|
||||
|
||||
protected Path pathToClass(Path testBaseDir, String fileName) {
|
||||
return Paths.get(testBaseDir.toString(), capitalize(fileName) + generator.fileExtension(this.properties)).toAbsolutePath()
|
||||
return Paths.get(testBaseDir.toString(),
|
||||
capitalize(fileName) + generator.fileExtension(this.properties)).
|
||||
toAbsolutePath()
|
||||
}
|
||||
|
||||
protected Path generateTestBaseDir(String basePackageClass, String includedDirectoryRelativePath) {
|
||||
Path testBaseDir = Paths.get(targetDirectory.absolutePath, packageToDirectory(basePackageClass),
|
||||
beforeLast(includedDirectoryRelativePath, File.separator))
|
||||
Path testBaseDir = Paths.
|
||||
get(targetDirectory.absolutePath, packageToDirectory(basePackageClass),
|
||||
beforeLast(includedDirectoryRelativePath, File.separator))
|
||||
Files.createDirectories(testBaseDir)
|
||||
return testBaseDir
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier
|
||||
@@ -42,6 +42,7 @@ import static org.springframework.cloud.contract.verifier.util.NamesUtil.beforeL
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.convertIllegalPackageChars
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.directoryToPackage
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.toLastDot
|
||||
|
||||
/**
|
||||
* @author Jakub Kubrynski, codearte.io
|
||||
*/
|
||||
@@ -60,11 +61,13 @@ class TestGenerator {
|
||||
|
||||
TestGenerator(ContractVerifierConfigProperties configProperties) {
|
||||
this(configProperties, singleTestGenerator(),
|
||||
new FileSaver(configProperties.generatedTestSourcesDir, singleTestGenerator(), configProperties))
|
||||
new FileSaver(configProperties.generatedTestSourcesDir,
|
||||
singleTestGenerator(), configProperties))
|
||||
}
|
||||
|
||||
private static SingleTestGenerator singleTestGenerator() {
|
||||
List<SingleTestGenerator> factories = SpringFactoriesLoader.loadFactories(SingleTestGenerator, null)
|
||||
List<SingleTestGenerator> factories = SpringFactoriesLoader.
|
||||
loadFactories(SingleTestGenerator, null)
|
||||
if (factories.empty) {
|
||||
return new JavaTestGenerator()
|
||||
}
|
||||
@@ -97,9 +100,11 @@ class TestGenerator {
|
||||
private String basePackageName() {
|
||||
if (configProperties.basePackageForTests) {
|
||||
return configProperties.basePackageForTests
|
||||
} else if (configProperties.baseClassForTests) {
|
||||
}
|
||||
else if (configProperties.baseClassForTests) {
|
||||
return toLastDot(configProperties.baseClassForTests)
|
||||
} else if (configProperties.packageWithBaseClasses) {
|
||||
}
|
||||
else if (configProperties.packageWithBaseClasses) {
|
||||
return configProperties.packageWithBaseClasses
|
||||
}
|
||||
return DEFAULT_TEST_PACKAGE
|
||||
@@ -107,14 +112,19 @@ class TestGenerator {
|
||||
|
||||
@PackageScope
|
||||
void generateTestClasses(final String basePackageName) {
|
||||
ListMultimap<Path, ContractMetadata> contracts = contractFileScanner.findContracts()
|
||||
ListMultimap<Path, ContractMetadata> contracts = contractFileScanner.
|
||||
findContracts()
|
||||
contracts.asMap().entrySet().each {
|
||||
Map.Entry<Path, Collection<ContractMetadata>> entry -> processIncludedDirectory(relativizeContractPath(entry), (Collection<ContractMetadata>) entry.getValue(), basePackageName)
|
||||
Map.Entry<Path, Collection<ContractMetadata>> entry ->
|
||||
processIncludedDirectory(
|
||||
relativizeContractPath(entry), (Collection<ContractMetadata>) entry.
|
||||
getValue(), basePackageName)
|
||||
}
|
||||
}
|
||||
|
||||
private String relativizeContractPath(Map.Entry<Path, Collection<ContractMetadata>> entry) {
|
||||
Path relativePath = configProperties.contractsDslDir.toPath().relativize(entry.getKey())
|
||||
Path relativePath = configProperties.contractsDslDir.toPath().
|
||||
relativize(entry.getKey())
|
||||
if (StringUtils.isEmpty(relativePath.toString())) {
|
||||
return DEFAULT_CLASS_PREFIX
|
||||
}
|
||||
@@ -129,11 +139,15 @@ class TestGenerator {
|
||||
if (contracts.size()) {
|
||||
def className = afterLast(includedDirectoryRelativePath.toString(), File.separator) + resolveNameSuffix()
|
||||
def convertedClassName = convertIllegalPackageChars(className)
|
||||
def packageName = buildPackage(basePackageNameForClass, includedDirectoryRelativePath)
|
||||
Path dir = saver.generateTestBaseDir(basePackageNameForClass, convertIllegalPackageChars(includedDirectoryRelativePath.toString()))
|
||||
def packageName =
|
||||
buildPackage(basePackageNameForClass, includedDirectoryRelativePath)
|
||||
Path dir = saver.generateTestBaseDir(basePackageNameForClass,
|
||||
convertIllegalPackageChars(includedDirectoryRelativePath.toString()))
|
||||
Path classPath = saver.pathToClass(dir, convertedClassName)
|
||||
def classBytes = generator.buildClass(configProperties, contracts, includedDirectoryRelativePath,
|
||||
new SingleTestGenerator.GeneratedClassData(convertedClassName, packageName, classPath)).getBytes(StandardCharsets.UTF_8)
|
||||
def classBytes = generator.
|
||||
buildClass(configProperties, contracts, includedDirectoryRelativePath,
|
||||
new SingleTestGenerator.GeneratedClassData(convertedClassName, packageName, classPath)).
|
||||
getBytes(StandardCharsets.UTF_8)
|
||||
saver.saveClassFile(classPath, classBytes)
|
||||
counter.incrementAndGet()
|
||||
}
|
||||
@@ -149,4 +163,4 @@ class TestGenerator {
|
||||
return !directory.empty ? convertedPackage : packageNameForClass
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.builder
|
||||
@@ -108,13 +108,16 @@ class BlockBuilder {
|
||||
*/
|
||||
BlockBuilder addAtTheEnd(String toAdd) {
|
||||
String lastChar = builder.charAt(builder.length() - 1) as String
|
||||
String secondLastChar = builder.length() >= 2 ? builder.charAt(builder.length() - 2) as String : ""
|
||||
String secondLastChar = builder.length() >= 2 ? builder.
|
||||
charAt(builder.length() - 2) as String : ""
|
||||
if (endsWithNewLine(lastChar) && aSpecialSign(secondLastChar, toAdd)) {
|
||||
return this
|
||||
} else if (endsWithNewLine(lastChar) && !aSpecialSign(secondLastChar, toAdd)) {
|
||||
}
|
||||
else if (endsWithNewLine(lastChar) && !aSpecialSign(secondLastChar, toAdd)) {
|
||||
builder.replace(builder.length() - 1, builder.length(), toAdd)
|
||||
builder << '\n'
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
builder << toAdd
|
||||
}
|
||||
return this
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.builder
|
||||
@@ -51,7 +51,7 @@ trait BodyMethodGeneration {
|
||||
}
|
||||
|
||||
void addBodyMatchingBlock(List<BodyMatcher> matchers, BlockBuilder blockBuilder,
|
||||
Object responseBody, boolean shouldCommentOutBDDBlocks) {
|
||||
Object responseBody, boolean shouldCommentOutBDDBlocks) {
|
||||
blockBuilder.endBlock()
|
||||
blockBuilder.addLine(getAssertionJoiner(shouldCommentOutBDDBlocks))
|
||||
blockBuilder.startBlock()
|
||||
@@ -59,8 +59,10 @@ trait BodyMethodGeneration {
|
||||
if (it.matchingType() == MatchingType.NULL) {
|
||||
methodForNullCheck(it, blockBuilder)
|
||||
}
|
||||
else if (MatchingType.regexRelated(it.matchingType()) || it
|
||||
.matchingType() == MatchingType.EQUALITY) {
|
||||
else if (MatchingType.regexRelated(it.matchingType())
|
||||
|| it
|
||||
.matchingType()
|
||||
== MatchingType.EQUALITY) {
|
||||
methodForEqualityCheck(it, blockBuilder, responseBody)
|
||||
}
|
||||
else if (it.matchingType() == MatchingType.COMMAND) {
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.builder
|
||||
@@ -21,9 +21,9 @@ import groovy.transform.PackageScope
|
||||
import org.apache.commons.logging.Log
|
||||
import org.apache.commons.logging.LogFactory
|
||||
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
import org.springframework.cloud.contract.verifier.config.TestFramework
|
||||
import org.springframework.cloud.contract.verifier.util.NamesUtil
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
|
||||
/**
|
||||
* Builds a class. Adds all the imports, static imports etc.
|
||||
@@ -62,28 +62,34 @@ class ClassBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link ClassBuilder} for the given parameters
|
||||
* @return a{@link ClassBuilder} for the given parameters
|
||||
*/
|
||||
static ClassBuilder createClass(String className, String classPackage, ContractVerifierConfigProperties properties,
|
||||
String includedDirectoryRelativePath) {
|
||||
String includedDirectoryRelativePath) {
|
||||
String baseClassForTests
|
||||
if (properties.testFramework == TestFramework.SPOCK && !properties.baseClassForTests
|
||||
&& !properties.packageWithBaseClasses && !properties.baseClassMappings) {
|
||||
&& !properties.packageWithBaseClasses
|
||||
&& !properties.baseClassMappings) {
|
||||
baseClassForTests = 'spock.lang.Specification'
|
||||
} else {
|
||||
baseClassForTests = retrieveBaseClass(properties, includedDirectoryRelativePath)
|
||||
}
|
||||
else {
|
||||
baseClassForTests =
|
||||
retrieveBaseClass(properties, includedDirectoryRelativePath)
|
||||
}
|
||||
return new ClassBuilder(className, classPackage, baseClassForTests, properties.testFramework)
|
||||
}
|
||||
|
||||
protected static String retrieveBaseClass(ContractVerifierConfigProperties properties, String includedDirectoryRelativePath) {
|
||||
String contractPathAsPackage = includedDirectoryRelativePath.replace(File.separator, ".")
|
||||
String contractPackage = includedDirectoryRelativePath.replace(File.separator, SEPARATOR)
|
||||
String contractPathAsPackage = includedDirectoryRelativePath.
|
||||
replace(File.separator, ".")
|
||||
String contractPackage = includedDirectoryRelativePath.
|
||||
replace(File.separator, SEPARATOR)
|
||||
// package mapping takes super precedence
|
||||
if (properties.baseClassMappings) {
|
||||
Map.Entry<String, String> mapping = properties.baseClassMappings.find { String pattern, String fqn ->
|
||||
return contractPathAsPackage.matches(pattern)
|
||||
}
|
||||
Map.Entry<String, String> mapping = properties.baseClassMappings.
|
||||
find { String pattern, String fqn ->
|
||||
return contractPathAsPackage.matches(pattern)
|
||||
}
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Matching pattern for contract package [${contractPathAsPackage}] with setup ${properties.baseClassMappings} is [${mapping}]")
|
||||
}
|
||||
@@ -94,12 +100,14 @@ class ClassBuilder {
|
||||
if (!properties.packageWithBaseClasses) {
|
||||
return properties.baseClassForTests
|
||||
}
|
||||
String generatedClassName = generateDefaultBaseClassName(contractPackage, properties)
|
||||
String generatedClassName =
|
||||
generateDefaultBaseClassName(contractPackage, properties)
|
||||
return "${generatedClassName}Base"
|
||||
}
|
||||
|
||||
private static String generateDefaultBaseClassName(String classPackage, ContractVerifierConfigProperties properties) {
|
||||
String[] splitPackage = NamesUtil.convertIllegalPackageChars(classPackage).split(SEPARATOR)
|
||||
String[] splitPackage = NamesUtil.convertIllegalPackageChars(classPackage).
|
||||
split(SEPARATOR)
|
||||
if (splitPackage.size() > 1) {
|
||||
String last = NamesUtil.capitalize(splitPackage[-1])
|
||||
String butLast = NamesUtil.capitalize(splitPackage[-2])
|
||||
@@ -182,7 +190,8 @@ class ClassBuilder {
|
||||
clazz.startBlock()
|
||||
rules.sort().each {
|
||||
clazz.addLine("@Rule")
|
||||
clazz.addLine("public $it ${NamesUtil.camelCase(it)} = new $it()$lang.lineSuffix")
|
||||
clazz.
|
||||
addLine("public $it ${NamesUtil.camelCase(it)} = new $it()$lang.lineSuffix")
|
||||
}
|
||||
clazz.endBlock()
|
||||
if (!rules.empty) {
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.builder
|
||||
@@ -28,14 +28,14 @@ trait ClassVerifier {
|
||||
|
||||
Class classToCheck(Object elementFromBody) {
|
||||
switch (elementFromBody.getClass()) {
|
||||
case List:
|
||||
return List
|
||||
case Set:
|
||||
return Set
|
||||
case Map:
|
||||
return Map
|
||||
default:
|
||||
return elementFromBody.class
|
||||
case List:
|
||||
return List
|
||||
case Set:
|
||||
return Set
|
||||
case Map:
|
||||
return Map
|
||||
default:
|
||||
return elementFromBody.class
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.verifier.builder
|
||||
@@ -28,4 +27,4 @@ import groovy.transform.CompileStatic
|
||||
@CompileStatic
|
||||
enum CommunicationType {
|
||||
REQUEST, RESPONSE, INPUT, OUTPUT
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.builder
|
||||
|
||||
import groovy.transform.PackageScope
|
||||
import groovy.transform.TypeChecked
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
|
||||
@@ -33,8 +34,8 @@ import org.springframework.cloud.contract.verifier.config.ContractVerifierConfig
|
||||
class ExplicitJUnitMethodBodyBuilder extends RestAssuredJUnitMethodBodyBuilder {
|
||||
|
||||
ExplicitJUnitMethodBodyBuilder(Contract stubDefinition,
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
super(stubDefinition, configProperties, classDataForMethod)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +1,26 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.builder
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
import groovy.transform.PackageScope
|
||||
import groovy.transform.TypeChecked
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.spec.internal.Cookie
|
||||
import org.springframework.cloud.contract.spec.internal.ExecutionProperty
|
||||
@@ -26,7 +29,6 @@ import org.springframework.cloud.contract.spec.internal.NotToEscapePattern
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
import org.springframework.cloud.contract.verifier.util.MapConverter
|
||||
|
||||
import java.util.regex.Pattern
|
||||
/**
|
||||
* A {@link SpockMethodRequestProcessingBodyBuilder} implementation that uses MockMvc to send requests.
|
||||
*
|
||||
@@ -37,8 +39,8 @@ import java.util.regex.Pattern
|
||||
class HttpSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequestProcessingBodyBuilder {
|
||||
|
||||
HttpSpockMethodRequestProcessingBodyBuilder(Contract stubDefinition,
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
super(stubDefinition, configProperties, classDataForMethod)
|
||||
}
|
||||
|
||||
@@ -73,9 +75,11 @@ class HttpSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequestProc
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Object value) {
|
||||
if (value instanceof NotToEscapePattern) {
|
||||
blockBuilder.addLine("response.header('$property') " +
|
||||
blockBuilder.addLine("response.header('$property') "
|
||||
+
|
||||
"${patternComparison(((NotToEscapePattern) value).serverValue.pattern().replace("\\", "\\\\"))}")
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// fallback
|
||||
processHeaderElement(blockBuilder, property, value.toString())
|
||||
}
|
||||
@@ -84,9 +88,11 @@ class HttpSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequestProc
|
||||
@Override
|
||||
protected void processCookieElement(BlockBuilder blockBuilder, String key, Object value) {
|
||||
if (value instanceof NotToEscapePattern) {
|
||||
blockBuilder.addLine("response.cookie('$key') " +
|
||||
blockBuilder.addLine("response.cookie('$key') "
|
||||
+
|
||||
"${patternComparison(((NotToEscapePattern) value).serverValue.pattern().replace("\\", "\\\\"))}")
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
processCookieElement(blockBuilder, key, value.toString())
|
||||
}
|
||||
}
|
||||
@@ -103,18 +109,21 @@ class HttpSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequestProc
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) {
|
||||
blockBuilder.addLine("response.header('$property') ${convertHeaderComparison(value)}")
|
||||
blockBuilder.
|
||||
addLine("response.header('$property') ${convertHeaderComparison(value)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern value) {
|
||||
blockBuilder.addLine("response.header('$property') ${convertHeaderComparison(value)}")
|
||||
blockBuilder.
|
||||
addLine("response.header('$property') ${convertHeaderComparison(value)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCookieElement(BlockBuilder blockBuilder, String key, Pattern pattern) {
|
||||
blockBuilder.addLine("response.cookie('$key') != null")
|
||||
blockBuilder.addLine("response.cookie('$key') ${convertCookieComparison(pattern)}")
|
||||
blockBuilder.
|
||||
addLine("response.cookie('$key') ${convertCookieComparison(pattern)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -131,4 +140,4 @@ class HttpSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequestProc
|
||||
}
|
||||
return jsonPath.replace('$', '\\$')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.builder
|
||||
@@ -53,8 +53,8 @@ import static org.springframework.cloud.contract.verifier.config.TestFramework.J
|
||||
class JUnitMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder {
|
||||
|
||||
JUnitMessagingMethodBodyBuilder(Contract stubDefinition,
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
super(stubDefinition, configProperties, classDataForMethod)
|
||||
}
|
||||
|
||||
@@ -108,25 +108,29 @@ class JUnitMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder {
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) {
|
||||
blockBuilder.addLine("assertThat(response.getHeader(\"$property\")).isNotNull();")
|
||||
blockBuilder.addLine("assertThat(response.getHeader(\"$property\").toString()).${createHeaderComparison(value)}")
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getHeader(\"$property\").toString()).${createHeaderComparison(value)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Number value) {
|
||||
blockBuilder.addLine("assertThat(response.getHeader(\"$property\")).isNotNull();")
|
||||
blockBuilder.addLine("assertThat(response.getHeader(\"$property\")).isEqualTo(${value});")
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getHeader(\"$property\")).isEqualTo(${value});")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern pattern) {
|
||||
blockBuilder.addLine("assertThat(response.getHeader(\"$property\")).isNotNull();")
|
||||
blockBuilder.addLine("assertThat(response.getHeader(\"$property\").toString()).${createHeaderComparison(pattern)}")
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getHeader(\"$property\").toString()).${createHeaderComparison(pattern)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) {
|
||||
blockBuilder.addLine("assertThat(response.getHeader(\"$property\")).isNotNull();")
|
||||
blockBuilder.addLine("${exec.insertValue("response.getHeader(\"$property\").toString()")};")
|
||||
blockBuilder.
|
||||
addLine("${exec.insertValue("response.getHeader(\"$property\").toString()")};")
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -149,7 +153,9 @@ class JUnitMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder {
|
||||
|
||||
@Override
|
||||
protected void validateResponseHeadersBlock(BlockBuilder bb) {
|
||||
bb.addLine("""ContractVerifierMessage response = contractVerifierMessaging.receive(${sentToValue(outputMessage.sentTo.serverValue)});""")
|
||||
bb.addLine("""ContractVerifierMessage response = contractVerifierMessaging.receive(${
|
||||
sentToValue(outputMessage.sentTo.serverValue)
|
||||
});""")
|
||||
bb.addLine("""assertThat(response).isNotNull();""")
|
||||
outputMessage.headers?.executeForEachHeader { Header header ->
|
||||
processHeaderElement(bb, header.name, header.serverValue instanceof NotToEscapePattern ?
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.builder
|
||||
@@ -37,6 +37,7 @@ import static groovy.json.StringEscapeUtils.escapeJava
|
||||
import static org.springframework.cloud.contract.verifier.config.TestFramework.JUNIT
|
||||
import static org.springframework.cloud.contract.verifier.config.TestFramework.JUNIT5
|
||||
import static org.springframework.cloud.contract.verifier.util.ContentUtils.getJavaMultipartFileParameterContent
|
||||
|
||||
/**
|
||||
* Root class for JUnit method building
|
||||
*
|
||||
@@ -52,7 +53,7 @@ import static org.springframework.cloud.contract.verifier.util.ContentUtils.getJ
|
||||
abstract class JUnitMethodBodyBuilder extends RequestProcessingMethodBodyBuilder {
|
||||
|
||||
JUnitMethodBodyBuilder(Contract stubDefinition, ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
super(stubDefinition, configProperties, classDataForMethod)
|
||||
}
|
||||
|
||||
@@ -120,7 +121,8 @@ abstract class JUnitMethodBodyBuilder extends RequestProcessingMethodBodyBuilder
|
||||
|
||||
@Override
|
||||
protected void processBodyElement(BlockBuilder blockBuilder, String property, Map.Entry entry) {
|
||||
processBodyElement(blockBuilder, property, getMapKeyReferenceString(property, entry), entry.value)
|
||||
processBodyElement(blockBuilder, property,
|
||||
getMapKeyReferenceString(property, entry), entry.value)
|
||||
}
|
||||
|
||||
private String getMapKeyReferenceString(String property, Map.Entry entry) {
|
||||
@@ -178,12 +180,14 @@ abstract class JUnitMethodBodyBuilder extends RequestProcessingMethodBodyBuilder
|
||||
String value
|
||||
if (body instanceof ExecutionProperty) {
|
||||
value = body.toString()
|
||||
} else if (body instanceof FromFileProperty) {
|
||||
}
|
||||
else if (body instanceof FromFileProperty) {
|
||||
FromFileProperty fileProperty = (FromFileProperty) body
|
||||
value = fileProperty.isByte() ?
|
||||
readBytesFromFileString(fileProperty, CommunicationType.REQUEST) :
|
||||
readStringFromFileString(fileProperty, CommunicationType.REQUEST)
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
String escaped = escapeRequestSpecialChars(body.toString())
|
||||
value = "\"$escaped\""
|
||||
}
|
||||
@@ -192,12 +196,16 @@ abstract class JUnitMethodBodyBuilder extends RequestProcessingMethodBodyBuilder
|
||||
|
||||
@Override
|
||||
protected String getMultipartFileParameterContent(String propertyName, NamedProperty propertyValue) {
|
||||
return getJavaMultipartFileParameterContent(propertyName, propertyValue, { FromFileProperty fileProp -> readBytesFromFileString(fileProp, CommunicationType.REQUEST) })
|
||||
return getJavaMultipartFileParameterContent(propertyName, propertyValue, { FromFileProperty fileProp ->
|
||||
readBytesFromFileString(fileProp, CommunicationType.REQUEST)
|
||||
})
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getParameterString(Map.Entry<String, Object> parameter) {
|
||||
return """.param("${escapeJava(parameter.key)}", "${escapeJava(parameter.value as String)}")"""
|
||||
return """.param("${escapeJava(parameter.key)}", "${
|
||||
escapeJava(parameter.value as String)
|
||||
}")"""
|
||||
}
|
||||
|
||||
protected String createHeaderComparison(Object headerValue) {
|
||||
@@ -211,11 +219,12 @@ abstract class JUnitMethodBodyBuilder extends RequestProcessingMethodBodyBuilder
|
||||
|
||||
protected String createBodyComparison(Pattern bodyValue) {
|
||||
String patternAsString = bodyValue.pattern()
|
||||
return createMatchesMethod(RegexpBuilders.buildGStringRegexpForTestSide(patternAsString)) + ";"
|
||||
return createMatchesMethod(RegexpBuilders.
|
||||
buildGStringRegexpForTestSide(patternAsString)) + ";"
|
||||
}
|
||||
|
||||
protected String createCookieComparison(Object cookieValue) {
|
||||
String escapedCookie = convertUnicodeEscapesIfRequired("$cookieValue")
|
||||
String escapedCookie = convertUnicodeEscapesIfRequired("$cookieValue")
|
||||
return "isEqualTo(\"$escapedCookie\");"
|
||||
}
|
||||
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.builder
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
|
||||
import java.lang.invoke.MethodHandles
|
||||
|
||||
import groovy.transform.Canonical
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.PackageScope
|
||||
import org.apache.commons.logging.Log
|
||||
@@ -53,13 +52,15 @@ class JavaTestGenerator implements SingleTestGenerator {
|
||||
// TODO: Remove in next major
|
||||
private static final String REST_ASSURED_2_0_CLASS = 'com.jayway.restassured.RestAssured'
|
||||
|
||||
@PackageScope ClassPresenceChecker checker = new ClassPresenceChecker()
|
||||
@PackageScope
|
||||
ClassPresenceChecker checker = new ClassPresenceChecker()
|
||||
|
||||
@Override
|
||||
String buildClass(ContractVerifierConfigProperties configProperties, Collection<ContractMetadata> listOfFiles, String includedDirectoryRelativePath, GeneratedClassData generatedClassData) {
|
||||
String className = generatedClassData.className
|
||||
String classPackage = generatedClassData.classPackage
|
||||
ClassBuilder clazz = ClassBuilder.createClass(capitalize(className), classPackage, configProperties, includedDirectoryRelativePath)
|
||||
ClassBuilder clazz = ClassBuilder.createClass(
|
||||
capitalize(className), classPackage, configProperties, includedDirectoryRelativePath)
|
||||
if (configProperties.imports) {
|
||||
configProperties.imports.each { String it ->
|
||||
clazz.addImport(it)
|
||||
@@ -72,7 +73,8 @@ class JavaTestGenerator implements SingleTestGenerator {
|
||||
}
|
||||
if (isScenarioClass(listOfFiles)) {
|
||||
clazz.addImports(configProperties.testFramework.getOrderAnnotationImports())
|
||||
clazz.addClassLevelAnnotation(configProperties.testFramework.getOrderAnnotation())
|
||||
clazz.addClassLevelAnnotation(configProperties.testFramework.
|
||||
getOrderAnnotation())
|
||||
}
|
||||
// FIXME: change during Hoxton refactoring: we should only add either Json or Xml imports and not both
|
||||
addJsonPathRelatedImports(clazz)
|
||||
@@ -90,7 +92,7 @@ class JavaTestGenerator implements SingleTestGenerator {
|
||||
Map<ParsedDsl, TestType> contracts = mapContractsToTheirTestTypes(listOfFiles)
|
||||
boolean conditionalImportsAdded = false
|
||||
boolean toIgnore = listOfFiles.find { it.ignored }
|
||||
contracts.each {ParsedDsl key, TestType value ->
|
||||
contracts.each { ParsedDsl key, TestType value ->
|
||||
if (!conditionalImportsAdded) {
|
||||
clazz.addImports(getImports(configProperties.testFramework))
|
||||
clazz.addStaticImports(getStaticImports(configProperties.testFramework))
|
||||
@@ -119,16 +121,20 @@ class JavaTestGenerator implements SingleTestGenerator {
|
||||
clazz.addImport(getRuleImport(configProperties.testFramework))
|
||||
if (configProperties.testFramework.annotationLevelRules()) {
|
||||
clazz.addClassLevelAnnotation(configProperties.testFramework
|
||||
.getRuleAnnotation(configProperties.ruleClassForTests))
|
||||
} else {
|
||||
.getRuleAnnotation(configProperties.ruleClassForTests))
|
||||
}
|
||||
else {
|
||||
clazz.addRule(configProperties.ruleClassForTests)
|
||||
}
|
||||
}
|
||||
|
||||
private void addHttpRelatedEntries(ClassBuilder clazz, ContractVerifierConfigProperties configProperties) {
|
||||
HttpImportProvider httpImportProvider = new HttpImportProvider(getRestAssuredPackage())
|
||||
clazz.addImports(httpImportProvider.getImports(configProperties.testFramework, configProperties.testMode))
|
||||
clazz.addStaticImports(httpImportProvider.getStaticImports(configProperties.testFramework, configProperties.testMode))
|
||||
HttpImportProvider httpImportProvider = new HttpImportProvider(
|
||||
getRestAssuredPackage())
|
||||
clazz.addImports(httpImportProvider.
|
||||
getImports(configProperties.testFramework, configProperties.testMode))
|
||||
clazz.addStaticImports(httpImportProvider.
|
||||
getStaticImports(configProperties.testFramework, configProperties.testMode))
|
||||
}
|
||||
|
||||
// TODO for 2.2: leave only RestAssured 3
|
||||
@@ -154,10 +160,11 @@ class JavaTestGenerator implements SingleTestGenerator {
|
||||
log.debug("Stub content from file [${stubsFile.text}]")
|
||||
}
|
||||
Collection<Contract> stubContents = metadata.convertedContract
|
||||
Map<ParsedDsl, TestType> entries = stubContents.collectEntries { Contract stubContent ->
|
||||
TestType testType = (stubContent.input || stubContent.outputMessage) ? TestType.MESSAGING : TestType.HTTP
|
||||
return [(new ParsedDsl(metadata, stubContent, stubsFile)): testType]
|
||||
}
|
||||
Map<ParsedDsl, TestType> entries = stubContents.
|
||||
collectEntries { Contract stubContent ->
|
||||
TestType testType = (stubContent.input || stubContent.outputMessage) ? TestType.MESSAGING : TestType.HTTP
|
||||
return [(new ParsedDsl(metadata, stubContent, stubsFile)): testType]
|
||||
}
|
||||
dsls.putAll(entries)
|
||||
}
|
||||
return dsls
|
||||
@@ -182,7 +189,7 @@ class JavaTestGenerator implements SingleTestGenerator {
|
||||
|
||||
private void addJsonPathRelatedImports(ClassBuilder clazz) {
|
||||
clazz.addImports(['com.jayway.jsonpath.DocumentContext',
|
||||
'com.jayway.jsonpath.JsonPath',
|
||||
'com.jayway.jsonpath.JsonPath',
|
||||
])
|
||||
if (this.checker.isClassPresent(JSON_ASSERT_CLASS)) {
|
||||
clazz.addStaticImport(JSON_ASSERT_STATIC_IMPORT)
|
||||
@@ -191,15 +198,15 @@ class JavaTestGenerator implements SingleTestGenerator {
|
||||
|
||||
private void addXPathRelatedImports(ClassBuilder clazz) {
|
||||
clazz.addImports(['javax.xml.parsers.DocumentBuilder',
|
||||
'javax.xml.parsers.DocumentBuilderFactory',
|
||||
'org.w3c.dom.Document',
|
||||
'org.xml.sax.InputSource',
|
||||
'java.io.StringReader'])
|
||||
'javax.xml.parsers.DocumentBuilderFactory',
|
||||
'org.w3c.dom.Document',
|
||||
'org.xml.sax.InputSource',
|
||||
'java.io.StringReader'])
|
||||
}
|
||||
|
||||
private void addMessagingRelatedEntries(ClassBuilder clazz) {
|
||||
clazz.addField(['@Inject ContractVerifierMessaging contractVerifierMessaging',
|
||||
'@Inject ContractVerifierObjectMapper contractVerifierObjectMapper'
|
||||
'@Inject ContractVerifierObjectMapper contractVerifierObjectMapper'
|
||||
])
|
||||
clazz.addImports(MessagingImportProvider.getImports())
|
||||
clazz.addStaticImports(MessagingImportProvider.getStaticImports())
|
||||
@@ -214,7 +221,8 @@ class ClassPresenceChecker {
|
||||
try {
|
||||
Class.forName(className)
|
||||
return true
|
||||
} catch (ClassNotFoundException ex) {
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("[${className}] is not present on classpath. Will not add a static import.")
|
||||
}
|
||||
|
||||
@@ -1,37 +1,38 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.builder
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
import groovy.transform.PackageScope
|
||||
import groovy.transform.TypeChecked
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.spec.internal.Cookie
|
||||
import org.springframework.cloud.contract.spec.internal.DslProperty
|
||||
import org.springframework.cloud.contract.spec.internal.ExecutionProperty
|
||||
import org.springframework.cloud.contract.spec.internal.FromFileProperty
|
||||
import org.springframework.cloud.contract.spec.internal.Header
|
||||
import org.springframework.cloud.contract.spec.internal.NotToEscapePattern
|
||||
import org.springframework.cloud.contract.spec.internal.QueryParameter
|
||||
import org.springframework.cloud.contract.spec.internal.ExecutionProperty
|
||||
import org.springframework.cloud.contract.spec.internal.QueryParameters
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
import org.springframework.cloud.contract.verifier.util.MapConverter
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
import static org.springframework.cloud.contract.verifier.config.TestFramework.JUNIT
|
||||
|
||||
/**
|
||||
@@ -49,8 +50,8 @@ import static org.springframework.cloud.contract.verifier.config.TestFramework.J
|
||||
class JaxRsClientJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder {
|
||||
|
||||
JaxRsClientJUnitMethodBodyBuilder(Contract stubDefinition,
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
super(stubDefinition, configProperties, classDataForMethod)
|
||||
}
|
||||
|
||||
@@ -85,7 +86,8 @@ class JaxRsClientJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder {
|
||||
if (request.url) {
|
||||
bb.addLine(".path(${concreteUrl(request.url)})")
|
||||
appendQueryParams(request.url.queryParameters, bb)
|
||||
} else if (request.urlPath) {
|
||||
}
|
||||
else if (request.urlPath) {
|
||||
bb.addLine(".path(${concreteUrl(request.urlPath)})")
|
||||
appendQueryParams(request.urlPath.queryParameters, bb)
|
||||
}
|
||||
@@ -103,9 +105,10 @@ class JaxRsClientJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder {
|
||||
if (!queryParameters?.parameters) {
|
||||
return
|
||||
}
|
||||
queryParameters.parameters.findAll(this.&allowedQueryParameter).each { QueryParameter param ->
|
||||
bb.addLine(".queryParam(\"$param.name\", \"${resolveParamValue(param).toString()}\")")
|
||||
}
|
||||
queryParameters.parameters.findAll(this.&allowedQueryParameter).
|
||||
each { QueryParameter param ->
|
||||
bb.addLine(".queryParam(\"$param.name\", \"${resolveParamValue(param).toString()}\")")
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -120,21 +123,25 @@ class JaxRsClientJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder {
|
||||
protected void appendMethodAndBody(BlockBuilder bb) {
|
||||
String method = request.method.serverValue.toString().toLowerCase()
|
||||
if (request.body) {
|
||||
String contentType = getHeader('Content-Type') ?: getRequestContentType().mimeType
|
||||
String contentType =
|
||||
getHeader('Content-Type') ?: getRequestContentType().mimeType
|
||||
Object body = request.body.serverValue
|
||||
String value
|
||||
if (body instanceof ExecutionProperty) {
|
||||
value = body.toString()
|
||||
} else if (body instanceof FromFileProperty) {
|
||||
}
|
||||
else if (body instanceof FromFileProperty) {
|
||||
FromFileProperty fileProperty = (FromFileProperty) body
|
||||
value = fileProperty.isByte() ?
|
||||
readBytesFromFileString(fileProperty, CommunicationType.REQUEST) :
|
||||
readStringFromFileString(fileProperty, CommunicationType.REQUEST)
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
value = "\"${getBodyAsString()}\""
|
||||
}
|
||||
bb.addLine(".method(\"${method.toUpperCase()}\", entity(${value}, \"$contentType\"))")
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
bb.addLine(".method(\"${method.toUpperCase()}\")")
|
||||
}
|
||||
}
|
||||
@@ -144,7 +151,9 @@ class JaxRsClientJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder {
|
||||
if (headerOfAbsentType(header)) {
|
||||
return
|
||||
}
|
||||
if (header.name == 'Content-Type' || header.name == 'Accept') return
|
||||
if (header.name == 'Content-Type' || header.name == 'Accept') {
|
||||
return
|
||||
}
|
||||
bb.addLine(".header(\"${header.name}\", \"${header.serverValue}\")")
|
||||
}
|
||||
}
|
||||
@@ -163,7 +172,8 @@ class JaxRsClientJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder {
|
||||
String acceptHeader = getHeader("Accept")
|
||||
if (acceptHeader) {
|
||||
bb.addLine(".request(\"$acceptHeader\")")
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
bb.addLine(".request()")
|
||||
}
|
||||
}
|
||||
@@ -203,8 +213,10 @@ class JaxRsClientJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder {
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Object value) {
|
||||
if (value instanceof NotToEscapePattern) {
|
||||
blockBuilder.addLine("assertThat(response.getHeaderString(\"$property\")).${createHeaderComparison(((NotToEscapePattern) value).serverValue)}")
|
||||
} else {
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getHeaderString(\"$property\")).${createHeaderComparison(((NotToEscapePattern) value).serverValue)}")
|
||||
}
|
||||
else {
|
||||
// fallback
|
||||
processHeaderElement(blockBuilder, property, value.toString())
|
||||
}
|
||||
@@ -212,34 +224,42 @@ class JaxRsClientJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder {
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) {
|
||||
blockBuilder.addLine("assertThat(response.getHeaderString(\"$property\")).${createHeaderComparison(value)}")
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getHeaderString(\"$property\")).${createHeaderComparison(value)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Number value) {
|
||||
blockBuilder.addLine("assertThat(response.getHeaderString(\"$property\")).isEqualTo(${value});")
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getHeaderString(\"$property\")).isEqualTo(${value});")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern pattern) {
|
||||
blockBuilder.addLine("assertThat(response.getHeaderString(\"$property\")).${createHeaderComparison(pattern)}")
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getHeaderString(\"$property\")).${createHeaderComparison(pattern)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) {
|
||||
blockBuilder.addLine("${exec.insertValue("response.getHeaderString(\"$property\")")};")
|
||||
blockBuilder.
|
||||
addLine("${exec.insertValue("response.getHeaderString(\"$property\")")};")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCookieElement(BlockBuilder blockBuilder, String key, Pattern pattern) {
|
||||
blockBuilder.addLine("assertThat(response.getCookies().get(\"$key\")).isNotNull();")
|
||||
blockBuilder.addLine("assertThat(response.getCookies().get(\"$key\").getValue()).${createCookieComparison(pattern)}")
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getCookies().get(\"$key\")).isNotNull();")
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getCookies().get(\"$key\").getValue()).${createCookieComparison(pattern)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCookieElement(BlockBuilder blockBuilder, String key, String value) {
|
||||
blockBuilder.addLine("assertThat(response.getCookies().get(\"$key\")).isNotNull();")
|
||||
blockBuilder.addLine("assertThat(response.getCookies().get(\"$key\").getValue()).${createCookieComparison(value)}")
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getCookies().get(\"$key\")).isNotNull();")
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getCookies().get(\"$key\").getValue()).${createCookieComparison(value)}")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,37 +1,38 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.builder
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
import groovy.transform.PackageScope
|
||||
import groovy.transform.TypeChecked
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.spec.internal.Cookie
|
||||
import org.springframework.cloud.contract.spec.internal.DslProperty
|
||||
import org.springframework.cloud.contract.spec.internal.ExecutionProperty
|
||||
import org.springframework.cloud.contract.spec.internal.FromFileProperty
|
||||
import org.springframework.cloud.contract.spec.internal.Header
|
||||
import org.springframework.cloud.contract.spec.internal.NotToEscapePattern
|
||||
import org.springframework.cloud.contract.spec.internal.QueryParameter
|
||||
import org.springframework.cloud.contract.spec.internal.QueryParameters
|
||||
import org.springframework.cloud.contract.spec.internal.ExecutionProperty
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
import org.springframework.cloud.contract.verifier.util.MapConverter
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
/**
|
||||
* Knows how to build a Spock test method for JaxRs.
|
||||
*
|
||||
@@ -46,8 +47,8 @@ import java.util.regex.Pattern
|
||||
class JaxRsClientSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequestProcessingBodyBuilder {
|
||||
|
||||
JaxRsClientSpockMethodRequestProcessingBodyBuilder(Contract stubDefinition,
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
super(stubDefinition, configProperties, classDataForMethod)
|
||||
}
|
||||
|
||||
@@ -81,7 +82,8 @@ class JaxRsClientSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequ
|
||||
String acceptHeader = getHeader("Accept")
|
||||
if (acceptHeader) {
|
||||
bb.addLine(".request('$acceptHeader')")
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
bb.addLine(".request()")
|
||||
}
|
||||
}
|
||||
@@ -90,7 +92,8 @@ class JaxRsClientSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequ
|
||||
if (request.url) {
|
||||
bb.addLine(".path(${concreteUrl(request.url)})")
|
||||
appendQueryParams(request.url.queryParameters, bb)
|
||||
} else if (request.urlPath) {
|
||||
}
|
||||
else if (request.urlPath) {
|
||||
bb.addLine(".path(${concreteUrl(request.urlPath)})")
|
||||
appendQueryParams(request.urlPath.queryParameters, bb)
|
||||
}
|
||||
@@ -108,9 +111,10 @@ class JaxRsClientSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequ
|
||||
if (!queryParameters?.parameters) {
|
||||
return
|
||||
}
|
||||
queryParameters.parameters.findAll(this.&allowedQueryParameter).each { QueryParameter param ->
|
||||
bb.addLine(".queryParam('$param.name', '${resolveParamValue(param).toString()}')")
|
||||
}
|
||||
queryParameters.parameters.findAll(this.&allowedQueryParameter).
|
||||
each { QueryParameter param ->
|
||||
bb.addLine(".queryParam('$param.name', '${resolveParamValue(param).toString()}')")
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -125,21 +129,25 @@ class JaxRsClientSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequ
|
||||
protected void appendMethodAndBody(BlockBuilder bb) {
|
||||
String method = request.method.serverValue.toString().toLowerCase()
|
||||
if (request.body) {
|
||||
String contentType = getHeader('Content-Type') ?: getRequestContentType().mimeType
|
||||
String contentType =
|
||||
getHeader('Content-Type') ?: getRequestContentType().mimeType
|
||||
Object body = request.body.serverValue
|
||||
String value
|
||||
if (body instanceof ExecutionProperty) {
|
||||
value = body.toString()
|
||||
} else if (body instanceof FromFileProperty) {
|
||||
}
|
||||
else if (body instanceof FromFileProperty) {
|
||||
FromFileProperty fileProperty = (FromFileProperty) body
|
||||
value = fileProperty.isByte() ?
|
||||
readBytesFromFileString(fileProperty, CommunicationType.REQUEST) :
|
||||
readStringFromFileString(fileProperty, CommunicationType.REQUEST)
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
value = "'${bodyAsString}'"
|
||||
}
|
||||
bb.addLine(".method('${method.toUpperCase()}', entity(${value}, '$contentType'))")
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
bb.addLine(".method('${method.toUpperCase()}')")
|
||||
}
|
||||
}
|
||||
@@ -149,7 +157,9 @@ class JaxRsClientSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequ
|
||||
if (headerOfAbsentType(header)) {
|
||||
return
|
||||
}
|
||||
if (header.name == 'Content-Type' || header.name == 'Accept') return // Particular headers are set via 'request' / 'entity' methods
|
||||
if (header.name == 'Content-Type' || header.name == 'Accept') {
|
||||
return
|
||||
} // Particular headers are set via 'request' / 'entity' methods
|
||||
bb.addLine(".header('${header.name}', '${header.serverValue}')")
|
||||
}
|
||||
}
|
||||
@@ -199,8 +209,10 @@ class JaxRsClientSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequ
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Object value) {
|
||||
if (value instanceof NotToEscapePattern) {
|
||||
blockBuilder.addLine("response.getHeaderString('$property') ${convertHeaderComparison(((NotToEscapePattern) value).serverValue)}")
|
||||
} else {
|
||||
blockBuilder.
|
||||
addLine("response.getHeaderString('$property') ${convertHeaderComparison(((NotToEscapePattern) value).serverValue)}")
|
||||
}
|
||||
else {
|
||||
// fallback
|
||||
processHeaderElement(blockBuilder, property, value.toString())
|
||||
}
|
||||
@@ -208,12 +220,14 @@ class JaxRsClientSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequ
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) {
|
||||
blockBuilder.addLine("${exec.insertValue("response.getHeaderString(\'$property\')")}")
|
||||
blockBuilder.
|
||||
addLine("${exec.insertValue("response.getHeaderString(\'$property\')")}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) {
|
||||
blockBuilder.addLine("response.getHeaderString('$property') ${convertHeaderComparison(value)}")
|
||||
blockBuilder.
|
||||
addLine("response.getHeaderString('$property') ${convertHeaderComparison(value)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -223,19 +237,22 @@ class JaxRsClientSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequ
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern value) {
|
||||
blockBuilder.addLine("response.getHeaderString('$property') ${convertHeaderComparison(value)}")
|
||||
blockBuilder.
|
||||
addLine("response.getHeaderString('$property') ${convertHeaderComparison(value)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCookieElement(BlockBuilder blockBuilder, String key, Pattern pattern) {
|
||||
blockBuilder.addLine("response.getCookies().get('$key') != null")
|
||||
blockBuilder.addLine("response.getCookies().get('$key').getValue() ${convertCookieComparison(pattern)}")
|
||||
blockBuilder.
|
||||
addLine("response.getCookies().get('$key').getValue() ${convertCookieComparison(pattern)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCookieElement(BlockBuilder blockBuilder, String key, String value) {
|
||||
blockBuilder.addLine("response.getCookies().get('$key') != null")
|
||||
blockBuilder.addLine("response.getCookies().get('$key').getValue() ${convertCookieComparison(value)}")
|
||||
blockBuilder.
|
||||
addLine("response.getCookies().get('$key').getValue() ${convertCookieComparison(value)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.verifier.builder
|
||||
@@ -38,12 +37,12 @@ import org.springframework.cloud.contract.verifier.template.TemplateProcessor
|
||||
import org.springframework.cloud.contract.verifier.util.JsonPaths
|
||||
import org.springframework.cloud.contract.verifier.util.JsonToJsonPathsConverter
|
||||
import org.springframework.cloud.contract.verifier.util.MapConverter
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @since 2.1.0
|
||||
*/
|
||||
|
||||
@PackageScope
|
||||
@CompileStatic
|
||||
class JsonBodyVerificationBuilder implements BodyMethodGeneration, ClassVerifier {
|
||||
@@ -63,11 +62,11 @@ class JsonBodyVerificationBuilder implements BodyMethodGeneration, ClassVerifier
|
||||
// Passing way more arguments here than I would like to, but since we are planning a major
|
||||
// refactoring of this module for Hoxton release, leaving it this way for now
|
||||
JsonBodyVerificationBuilder(ContractVerifierConfigProperties configProperties,
|
||||
TemplateProcessor templateProcessor,
|
||||
ContractTemplate contractTemplate,
|
||||
Contract contract,
|
||||
Optional<String> lineSuffix,
|
||||
Closure postProcessJsonPathCall) {
|
||||
TemplateProcessor templateProcessor,
|
||||
ContractTemplate contractTemplate,
|
||||
Contract contract,
|
||||
Optional<String> lineSuffix,
|
||||
Closure postProcessJsonPathCall) {
|
||||
this.configProperties = configProperties
|
||||
this.templateProcessor = templateProcessor
|
||||
this.contractTemplate = contractTemplate
|
||||
@@ -77,9 +76,9 @@ class JsonBodyVerificationBuilder implements BodyMethodGeneration, ClassVerifier
|
||||
}
|
||||
|
||||
Object addJsonResponseBodyCheck(BlockBuilder bb, Object convertedResponseBody,
|
||||
BodyMatchers bodyMatchers,
|
||||
String responseString,
|
||||
boolean shouldCommentOutBDDBlocks) {
|
||||
BodyMatchers bodyMatchers,
|
||||
String responseString,
|
||||
boolean shouldCommentOutBDDBlocks) {
|
||||
appendJsonPath(bb, responseString)
|
||||
DocumentContext parsedRequestBody
|
||||
boolean dontParseStrings = convertedResponseBody instanceof Map
|
||||
@@ -252,7 +251,8 @@ class JsonBodyVerificationBuilder implements BodyMethodGeneration, ClassVerifier
|
||||
return entry
|
||||
}
|
||||
String entryAsString = (String) entry
|
||||
if (templateProcessor.containsTemplateEntry(entryAsString) &&
|
||||
if (templateProcessor.containsTemplateEntry(entryAsString)
|
||||
&&
|
||||
!templateProcessor.containsJsonPathTemplateEntry(entryAsString)) {
|
||||
// TODO: HANDLEBARS LEAKING VIA request.
|
||||
String justEntry = entryAsString - contractTemplate.
|
||||
@@ -306,8 +306,7 @@ class JsonBodyVerificationBuilder implements BodyMethodGeneration, ClassVerifier
|
||||
}
|
||||
|
||||
private void doBodyMatchingIfPresent(BodyMatchers bodyMatchers, BlockBuilder bb,
|
||||
Object responseBody,
|
||||
boolean shouldCommentOutBDDBlocks) {
|
||||
Object responseBody, boolean shouldCommentOutBDDBlocks) {
|
||||
if (bodyMatchers?.hasMatchers()) {
|
||||
addBodyMatchingBlock(bodyMatchers.
|
||||
matchers(), bb, responseBody, shouldCommentOutBDDBlocks)
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.verifier.builder
|
||||
@@ -50,8 +49,8 @@ abstract class MessagingMethodBodyBuilder extends MethodBodyBuilder {
|
||||
protected final OutputMessage outputMessage
|
||||
|
||||
MessagingMethodBodyBuilder(Contract stubDefinition,
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
super(configProperties, stubDefinition, classDataForMethod)
|
||||
this.inputMessage = stubDefinition.input
|
||||
this.outputMessage = stubDefinition.outputMessage
|
||||
@@ -88,7 +87,8 @@ abstract class MessagingMethodBodyBuilder extends MethodBodyBuilder {
|
||||
bb.endBlock()
|
||||
if (outputMessage.headers) {
|
||||
bb.addLine(addCommentSignIfRequired('and:')).startBlock()
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
bb.startBlock()
|
||||
}
|
||||
validateResponseBodyBlock(bb, outputMessage.bodyMatchers, outputMessage.body.serverValue)
|
||||
@@ -102,7 +102,8 @@ abstract class MessagingMethodBodyBuilder extends MethodBodyBuilder {
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, GString value) {
|
||||
String gstringValue = ContentUtils.extractValueForGString(value, ContentUtils.GET_TEST_SIDE).toString()
|
||||
String gstringValue = ContentUtils.
|
||||
extractValueForGString(value, ContentUtils.GET_TEST_SIDE).toString()
|
||||
processHeaderElement(blockBuilder, property, gstringValue)
|
||||
}
|
||||
|
||||
@@ -118,12 +119,15 @@ abstract class MessagingMethodBodyBuilder extends MethodBodyBuilder {
|
||||
|
||||
protected String getBodyAsString() {
|
||||
ContentType contentType = contentType()
|
||||
Object bodyValue = extractServerValueFromBody(contentType, inputMessage.messageBody.serverValue)
|
||||
Object bodyValue =
|
||||
extractServerValueFromBody(contentType, inputMessage.messageBody.serverValue)
|
||||
if (bodyValue instanceof FromFileProperty) {
|
||||
FromFileProperty fileProperty = (FromFileProperty) bodyValue
|
||||
return fileProperty.isByte() ?
|
||||
indentBody(readBytesFromFileString(fileProperty, CommunicationType.REQUEST)) :
|
||||
indentStringBody(readStringFromFileString(fileProperty, CommunicationType.REQUEST))
|
||||
indentBody(
|
||||
readBytesFromFileString(fileProperty, CommunicationType.REQUEST)) :
|
||||
indentStringBody(
|
||||
readStringFromFileString(fileProperty, CommunicationType.REQUEST))
|
||||
}
|
||||
String json = new JsonOutput().toJson(bodyValue)
|
||||
json = convertUnicodeEscapesIfRequired(json)
|
||||
|
||||
@@ -5,14 +5,13 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.verifier.builder
|
||||
@@ -50,6 +49,7 @@ import static org.springframework.cloud.contract.verifier.util.ContentType.JSON
|
||||
import static org.springframework.cloud.contract.verifier.util.ContentType.TEXT
|
||||
import static org.springframework.cloud.contract.verifier.util.ContentType.XML
|
||||
import static org.springframework.cloud.contract.verifier.util.ContentUtils.extractValue
|
||||
|
||||
/**
|
||||
* Main class for building method body.
|
||||
*
|
||||
@@ -64,7 +64,9 @@ import static org.springframework.cloud.contract.verifier.util.ContentUtils.extr
|
||||
@PackageScope
|
||||
abstract class MethodBodyBuilder implements ClassVerifier {
|
||||
|
||||
private static final Closure GET_SERVER_VALUE = { it instanceof DslProperty ? it.serverValue : it }
|
||||
private static final Closure GET_SERVER_VALUE = {
|
||||
it instanceof DslProperty ? it.serverValue : it
|
||||
}
|
||||
|
||||
protected final ContractVerifierConfigProperties configProperties
|
||||
protected final TemplateProcessor templateProcessor
|
||||
@@ -75,8 +77,8 @@ abstract class MethodBodyBuilder implements ClassVerifier {
|
||||
private final XmlBodyVerificationBuilder xmlBodyVerificationBuilder
|
||||
|
||||
protected MethodBodyBuilder(ContractVerifierConfigProperties configProperties,
|
||||
Contract contract,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
Contract contract,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
this.configProperties = configProperties
|
||||
this.templateProcessor = processor()
|
||||
this.contractTemplate = template()
|
||||
@@ -86,7 +88,7 @@ abstract class MethodBodyBuilder implements ClassVerifier {
|
||||
templateProcessor, contractTemplate, this.contract,
|
||||
lineSuffix(), { String jsonPath ->
|
||||
postProcessJsonPathCall(jsonPath)
|
||||
})
|
||||
})
|
||||
this.xmlBodyVerificationBuilder = new XmlBodyVerificationBuilder(contract,
|
||||
lineSuffix())
|
||||
}
|
||||
@@ -152,12 +154,12 @@ abstract class MethodBodyBuilder implements ClassVerifier {
|
||||
protected abstract String getResponseAsString()
|
||||
|
||||
/**
|
||||
* Returns the given string with comment sign if required by the given implementation
|
||||
* @return the given string with comment sign if required by the given implementation
|
||||
*/
|
||||
protected abstract String addCommentSignIfRequired(String baseString)
|
||||
|
||||
/**
|
||||
* Returns true if the BDD-syntax blocks should be commented out for a given framework
|
||||
* @return true if the BDD-syntax blocks should be commented out for a given framework
|
||||
*/
|
||||
protected abstract boolean shouldCommentOutBDDBlocks()
|
||||
|
||||
@@ -167,7 +169,7 @@ abstract class MethodBodyBuilder implements ClassVerifier {
|
||||
protected abstract BlockBuilder addColonIfRequired(BlockBuilder blockBuilder)
|
||||
|
||||
/**
|
||||
* Returns line suffix appropriate for test builder if required
|
||||
* @return line suffix appropriate for test builder if required
|
||||
*/
|
||||
protected abstract Optional<String> lineSuffix()
|
||||
|
||||
@@ -232,7 +234,7 @@ abstract class MethodBodyBuilder implements ClassVerifier {
|
||||
* Appends to the {@link BlockBuilder} the assertion for the given header path
|
||||
*/
|
||||
protected abstract void processHeaderElement(BlockBuilder blockBuilder, String property, String value)
|
||||
|
||||
|
||||
/**
|
||||
* Appends to the {@link BlockBuilder} the assertion for the given header path
|
||||
*/
|
||||
@@ -320,7 +322,7 @@ abstract class MethodBodyBuilder implements ClassVerifier {
|
||||
protected abstract void then(BlockBuilder bb)
|
||||
|
||||
/**
|
||||
* Returns a {@link org.springframework.cloud.contract.verifier.util.ContentType} for the given request
|
||||
* @return a{@link org.springframework.cloud.contract.verifier.util.ContentType} for the given request
|
||||
*/
|
||||
protected abstract ContentType getResponseContentType()
|
||||
|
||||
@@ -330,7 +332,7 @@ abstract class MethodBodyBuilder implements ClassVerifier {
|
||||
protected abstract String getBodyAsString()
|
||||
|
||||
/**
|
||||
* Returns {@code true} if given section should be created
|
||||
* @return {@code true} if given section should be created
|
||||
*/
|
||||
protected abstract boolean hasGivenSection()
|
||||
|
||||
@@ -412,14 +414,18 @@ abstract class MethodBodyBuilder implements ClassVerifier {
|
||||
convertedResponseBody = convertedResponseBody.asString()
|
||||
}
|
||||
if (convertedResponseBody instanceof GString) {
|
||||
convertedResponseBody = extractValue(convertedResponseBody as GString, contentType, { Object o -> o instanceof DslProperty ? o.serverValue : o })
|
||||
convertedResponseBody =
|
||||
extractValue(convertedResponseBody as GString, contentType, { Object o -> o instanceof DslProperty ? o.serverValue : o })
|
||||
}
|
||||
if (TEXT != contentType && FORM != contentType) {
|
||||
boolean dontParseStrings = contentType == JSON && convertedResponseBody instanceof Map
|
||||
Closure parsingClosure = dontParseStrings ? Closure.IDENTITY : MapConverter.JSON_PARSING_CLOSURE
|
||||
convertedResponseBody = MapConverter.getTestSideValues(convertedResponseBody, parsingClosure)
|
||||
} else {
|
||||
convertedResponseBody = StringEscapeUtils.escapeJava(convertedResponseBody.toString())
|
||||
convertedResponseBody = MapConverter.
|
||||
getTestSideValues(convertedResponseBody, parsingClosure)
|
||||
}
|
||||
else {
|
||||
convertedResponseBody = StringEscapeUtils.
|
||||
escapeJava(convertedResponseBody.toString())
|
||||
}
|
||||
if (JSON == contentType) {
|
||||
addJsonBodyVerification(bb, convertedResponseBody, bodyMatchers)
|
||||
@@ -427,7 +433,8 @@ abstract class MethodBodyBuilder implements ClassVerifier {
|
||||
else if (XML == contentType) {
|
||||
xmlBodyVerificationBuilder.addXmlResponseBodyCheck(bb, convertedResponseBody,
|
||||
bodyMatchers, getResponseAsString(), shouldCommentOutBDDBlocks())
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
simpleTextResponseBodyCheck(bb, convertedResponseBody)
|
||||
}
|
||||
}
|
||||
@@ -499,7 +506,8 @@ abstract class MethodBodyBuilder implements ClassVerifier {
|
||||
if (toTrim.startsWith('"')) {
|
||||
return toTrim.replaceAll('"', '')
|
||||
//#261
|
||||
} else if (toTrim.startsWith('\\"') && toTrim.endsWith('\\"')) {
|
||||
}
|
||||
else if (toTrim.startsWith('\\"') && toTrim.endsWith('\\"')) {
|
||||
return toTrim.substring(2, toTrim.length() - 2)
|
||||
}
|
||||
return toTrim
|
||||
@@ -562,7 +570,7 @@ abstract class MethodBodyBuilder implements ClassVerifier {
|
||||
|
||||
/**
|
||||
* Extracts the executable test side values and
|
||||
* returns the code of the executable
|
||||
* @return the code of the executable
|
||||
*/
|
||||
protected String getTestSideValue(ExecutionProperty executionProperty) {
|
||||
return executionProperty.toString()
|
||||
@@ -604,7 +612,7 @@ abstract class MethodBodyBuilder implements ClassVerifier {
|
||||
}
|
||||
|
||||
private void byteResponseBodyCheck(BlockBuilder bb,
|
||||
FromFileProperty convertedResponseBody) {
|
||||
FromFileProperty convertedResponseBody) {
|
||||
processText(bb, "", convertedResponseBody)
|
||||
addColonIfRequired(bb)
|
||||
}
|
||||
@@ -613,4 +621,4 @@ abstract class MethodBodyBuilder implements ClassVerifier {
|
||||
return s.substring(1)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.builder
|
||||
@@ -49,7 +49,7 @@ class MethodBuilder {
|
||||
private final boolean ignored
|
||||
|
||||
private MethodBuilder(String methodName, Contract stubContent, ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod generatedClassDataForMethod, boolean ignored) {
|
||||
GeneratedClassDataForMethod generatedClassDataForMethod, boolean ignored) {
|
||||
this.ignored = ignored
|
||||
this.stubContent = stubContent
|
||||
this.methodName = methodName
|
||||
@@ -71,15 +71,17 @@ class MethodBuilder {
|
||||
|
||||
static String methodName(ContractMetadata contract, File stubsFile, Contract stubContent) {
|
||||
if (stubContent.name) {
|
||||
String name = NamesUtil.camelCase(NamesUtil.convertIllegalPackageChars(stubContent.name))
|
||||
String name = NamesUtil.
|
||||
camelCase(NamesUtil.convertIllegalPackageChars(stubContent.name))
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Overriding the default test name with [" + name + "]")
|
||||
}
|
||||
return name
|
||||
} else if (contract.convertedContract.size() > 1) {
|
||||
int index = contract.convertedContract.findIndexOf { it == stubContent}
|
||||
}
|
||||
else if (contract.convertedContract.size() > 1) {
|
||||
int index = contract.convertedContract.findIndexOf { it == stubContent }
|
||||
String name = "${camelCasedMethodFromFileName(stubsFile)}_${index}"
|
||||
if (log.isDebugEnabled()) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Scenario found. The method name will be [" + name + "]")
|
||||
}
|
||||
return name
|
||||
@@ -92,7 +94,8 @@ class MethodBuilder {
|
||||
}
|
||||
|
||||
private static String camelCasedMethodFromFileName(File stubsFile) {
|
||||
return NamesUtil.camelCase(NamesUtil.convertIllegalMethodNameChars(NamesUtil.toLastDot(NamesUtil.afterLast(stubsFile.path, File.separator))))
|
||||
return NamesUtil.camelCase(NamesUtil.convertIllegalMethodNameChars(NamesUtil.
|
||||
toLastDot(NamesUtil.afterLast(stubsFile.path, File.separator))))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,7 +108,8 @@ class MethodBuilder {
|
||||
if (ignored) {
|
||||
blockBuilder.addLine(configProperties.testFramework.ignoreAnnotation)
|
||||
}
|
||||
blockBuilder.addLine(configProperties.testFramework.methodModifier + "validate_$methodName() throws Exception {")
|
||||
blockBuilder.
|
||||
addLine(configProperties.testFramework.methodModifier + "validate_$methodName() throws Exception {")
|
||||
getMethodBodyBuilder().appendTo(blockBuilder)
|
||||
blockBuilder.addLine('}')
|
||||
}
|
||||
@@ -122,18 +126,21 @@ class MethodBuilder {
|
||||
return new JaxRsClientJUnitMethodBodyBuilder(stubContent, configProperties, this.generatedClassDataForMethod)
|
||||
}
|
||||
return new JaxRsClientSpockMethodRequestProcessingBodyBuilder(stubContent, configProperties, this.generatedClassDataForMethod)
|
||||
} else if (configProperties.testMode == TestMode.WEBTESTCLIENT) {
|
||||
}
|
||||
else if (configProperties.testMode == TestMode.WEBTESTCLIENT) {
|
||||
if (isJUnitType()) {
|
||||
return new WebTestClientJUnitMethodBodyBuilder(stubContent, configProperties, this.generatedClassDataForMethod)
|
||||
}
|
||||
return new HttpSpockMethodRequestProcessingBodyBuilder(stubContent, configProperties, this.generatedClassDataForMethod)
|
||||
} else if (configProperties.testMode == TestMode.EXPLICIT) {
|
||||
}
|
||||
else if (configProperties.testMode == TestMode.EXPLICIT) {
|
||||
if (isJUnitType()) {
|
||||
return new ExplicitJUnitMethodBodyBuilder(stubContent, configProperties, this.generatedClassDataForMethod)
|
||||
}
|
||||
// in Groovy we're using def so we don't have to update the imports
|
||||
return new HttpSpockMethodRequestProcessingBodyBuilder(stubContent, configProperties, this.generatedClassDataForMethod)
|
||||
} else if (configProperties.testFramework == SPOCK) {
|
||||
}
|
||||
else if (configProperties.testFramework == SPOCK) {
|
||||
return new HttpSpockMethodRequestProcessingBodyBuilder(stubContent, configProperties, this.generatedClassDataForMethod)
|
||||
}
|
||||
return new MockMvcJUnitMethodBodyBuilder(stubContent, configProperties, this.generatedClassDataForMethod)
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.builder
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.PackageScope
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
|
||||
@@ -33,7 +34,7 @@ import org.springframework.cloud.contract.verifier.config.ContractVerifierConfig
|
||||
class MockMvcJUnitMethodBodyBuilder extends RestAssuredJUnitMethodBodyBuilder {
|
||||
|
||||
MockMvcJUnitMethodBodyBuilder(Contract stubDefinition, ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
super(stubDefinition, configProperties, classDataForMethod)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.verifier.builder
|
||||
@@ -75,7 +74,7 @@ abstract class RequestProcessingMethodBodyBuilder extends MethodBodyBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns code used to retrieve a response for the given {@link Request}
|
||||
* @return code used to retrieve a response for the given {@link Request}
|
||||
*/
|
||||
protected abstract String getInputString(Request request)
|
||||
|
||||
@@ -85,28 +84,28 @@ abstract class RequestProcessingMethodBodyBuilder extends MethodBodyBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if a response body is expected
|
||||
* @return {@code true} if a response body is expected
|
||||
*/
|
||||
protected boolean expectsResponseBody() {
|
||||
return response.body != null
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the query parameter is allowed
|
||||
* @return {@code true} if the query parameter is allowed
|
||||
*/
|
||||
protected boolean allowedQueryParameter(QueryParameter param) {
|
||||
return allowedQueryParameter(param.serverValue)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the query parameter is allowed
|
||||
* @return {@code true} if the query parameter is allowed
|
||||
*/
|
||||
protected boolean allowedQueryParameter(MatchingStrategy matchingStrategy) {
|
||||
return matchingStrategy.type != MatchingStrategy.Type.ABSENT
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the query parameter is allowed
|
||||
* @return {@code true} if the query parameter is allowed
|
||||
*/
|
||||
protected boolean allowedQueryParameter(Object o) {
|
||||
return true
|
||||
@@ -131,17 +130,20 @@ abstract class RequestProcessingMethodBodyBuilder extends MethodBodyBuilder {
|
||||
if (request.body) {
|
||||
Object body = null
|
||||
switch (request.body.serverValue) {
|
||||
case ExecutionProperty:
|
||||
case FromFileProperty:
|
||||
body = request.body?.serverValue
|
||||
break
|
||||
default:
|
||||
body = getBodyAsString()
|
||||
case ExecutionProperty:
|
||||
case FromFileProperty:
|
||||
body = request.body?.serverValue
|
||||
break
|
||||
default:
|
||||
body = getBodyAsString()
|
||||
}
|
||||
bb.addLine(getBodyString(body))
|
||||
}
|
||||
if (request.multipart) {
|
||||
multipartParameters?.each { Map.Entry<String, Object> entry -> bb.addLine(getMultipartParameterLine(entry)) }
|
||||
multipartParameters?.each { Map.Entry<String, Object> entry ->
|
||||
bb.
|
||||
addLine(getMultipartParameterLine(entry))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,8 +181,9 @@ abstract class RequestProcessingMethodBodyBuilder extends MethodBodyBuilder {
|
||||
|
||||
@TypeChecked(TypeCheckingMode.SKIP)
|
||||
protected addQueryParameters(Url buildUrl, BlockBuilder bb) {
|
||||
if(hasQueryParams(buildUrl)){
|
||||
List<QueryParameter> queryParameters = buildUrl.queryParameters.parameters.findAll(this.&allowedQueryParameter)
|
||||
if (hasQueryParams(buildUrl)) {
|
||||
List<QueryParameter> queryParameters = buildUrl.queryParameters.parameters.
|
||||
findAll(this.&allowedQueryParameter)
|
||||
for (queryParam in queryParameters) {
|
||||
addQueryParameter(queryParam, bb)
|
||||
}
|
||||
@@ -189,10 +192,12 @@ abstract class RequestProcessingMethodBodyBuilder extends MethodBodyBuilder {
|
||||
|
||||
@TypeChecked(TypeCheckingMode.SKIP)
|
||||
protected addQueryParameter(QueryParameter queryParam, BlockBuilder bb) {
|
||||
bb.addLine(/.${QUERY_PARAM_METHOD}(${DOUBLE_QUOTE}${queryParam.name}${DOUBLE_QUOTE},${DOUBLE_QUOTE}${resolveParamValue(queryParam).toString()}${DOUBLE_QUOTE})/)
|
||||
bb.addLine(".${QUERY_PARAM_METHOD}(${DOUBLE_QUOTE}${queryParam.name}"
|
||||
+
|
||||
"${DOUBLE_QUOTE},${DOUBLE_QUOTE}${resolveParamValue(queryParam).toString()}${DOUBLE_QUOTE})")
|
||||
}
|
||||
|
||||
protected addUrl(Url buildUrl, BlockBuilder bb){
|
||||
|
||||
protected addUrl(Url buildUrl, BlockBuilder bb) {
|
||||
Object testSideUrl = MapConverter.getTestSideValues(buildUrl)
|
||||
String method = request.method.serverValue.toString().toLowerCase()
|
||||
String url = testSideUrl.toString()
|
||||
@@ -227,13 +232,15 @@ abstract class RequestProcessingMethodBodyBuilder extends MethodBodyBuilder {
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, GString value) {
|
||||
String gstringValue = ContentUtils.extractValueForGString(value, ContentUtils.GET_TEST_SIDE).toString()
|
||||
String gstringValue = ContentUtils.
|
||||
extractValueForGString(value, ContentUtils.GET_TEST_SIDE).toString()
|
||||
processHeaderElement(blockBuilder, property, gstringValue)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCookieElement(BlockBuilder blockBuilder, String key, GString value) {
|
||||
String gStringValue = ContentUtils.extractValueForGString(value, ContentUtils.GET_TEST_SIDE).toString()
|
||||
String gStringValue = ContentUtils.
|
||||
extractValueForGString(value, ContentUtils.GET_TEST_SIDE).toString()
|
||||
processCookieElement(blockBuilder, key, gStringValue)
|
||||
}
|
||||
|
||||
@@ -245,20 +252,23 @@ abstract class RequestProcessingMethodBodyBuilder extends MethodBodyBuilder {
|
||||
@Override
|
||||
protected String getBodyAsString() {
|
||||
ContentType contentType = contentType()
|
||||
Object bodyValue = extractServerValueFromBody(contentType, request.body.serverValue)
|
||||
Object bodyValue =
|
||||
extractServerValueFromBody(contentType, request.body.serverValue)
|
||||
if (contentType == ContentType.FORM) {
|
||||
if (bodyValue instanceof Map) {
|
||||
// [a:3, b:4] == "a=3&b=4"
|
||||
return ((Map) bodyValue).collect {
|
||||
convertUnicodeEscapesIfRequired(it.key.toString() + "=" + it.value)
|
||||
}.join("&")
|
||||
} else if (bodyValue instanceof List) {
|
||||
}
|
||||
else if (bodyValue instanceof List) {
|
||||
// ["a=3", "b=4"] == "a=3&b=4"
|
||||
return ((List) bodyValue).collect {
|
||||
convertUnicodeEscapesIfRequired(it.toString())
|
||||
}.join("&")
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
String json = new JsonOutput().toJson(bodyValue)
|
||||
json = convertUnicodeEscapesIfRequired(json)
|
||||
return trimRepeatedQuotes(json)
|
||||
@@ -266,7 +276,7 @@ abstract class RequestProcessingMethodBodyBuilder extends MethodBodyBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of server side multipart parameters
|
||||
* @return a map of server side multipart parameters
|
||||
*/
|
||||
protected Map<String, Object> getMultipartParameters() {
|
||||
return (Map<String, Object>) request?.multipart?.serverValue
|
||||
@@ -280,19 +290,21 @@ abstract class RequestProcessingMethodBodyBuilder extends MethodBodyBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a String URL from {@link Request}'s test side values. It can be
|
||||
* @return a String URL from {@link Request}'s test side values. It can be
|
||||
* a concrete value of the URL or a path.
|
||||
*/
|
||||
protected Url getUrl(Request request) {
|
||||
if (request.url)
|
||||
if (request.url) {
|
||||
return request.url
|
||||
if (request.urlPath)
|
||||
}
|
||||
if (request.urlPath) {
|
||||
return request.urlPath
|
||||
}
|
||||
throw new IllegalStateException("URL is not set!")
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a line of code to send a multi part parameter in the request
|
||||
* @return a line of code to send a multi part parameter in the request
|
||||
*/
|
||||
protected String getMultipartParameterLine(Map.Entry<String, Object> parameter) {
|
||||
if (parameter.value instanceof NamedProperty) {
|
||||
@@ -304,4 +316,4 @@ abstract class RequestProcessingMethodBodyBuilder extends MethodBodyBuilder {
|
||||
private boolean hasQueryParams(Url url) {
|
||||
return url.queryParameters
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,26 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.builder
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
import groovy.transform.PackageScope
|
||||
import groovy.transform.TypeChecked
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.spec.internal.Cookie
|
||||
import org.springframework.cloud.contract.spec.internal.ExecutionProperty
|
||||
@@ -26,7 +29,6 @@ import org.springframework.cloud.contract.spec.internal.NotToEscapePattern
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
import org.springframework.cloud.contract.verifier.util.MapConverter
|
||||
|
||||
import java.util.regex.Pattern
|
||||
/**
|
||||
* A {@link JUnitMethodBodyBuilder} implementation that uses Rest Assured.
|
||||
*
|
||||
@@ -39,7 +41,7 @@ import java.util.regex.Pattern
|
||||
class RestAssuredJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder {
|
||||
|
||||
RestAssuredJUnitMethodBodyBuilder(Contract stubDefinition, ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
super(stubDefinition, configProperties, classDataForMethod)
|
||||
}
|
||||
|
||||
@@ -79,9 +81,11 @@ class RestAssuredJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder {
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Object value) {
|
||||
if (value instanceof NotToEscapePattern) {
|
||||
blockBuilder.addLine("assertThat(response.header(\"$property\"))." +
|
||||
blockBuilder.addLine("assertThat(response.header(\"$property\"))."
|
||||
+
|
||||
"${createMatchesMethod((value as NotToEscapePattern).serverValue.pattern().replace("\\", "\\\\"))};")
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// fallback
|
||||
processHeaderElement(blockBuilder, property, value.toString())
|
||||
}
|
||||
@@ -89,17 +93,20 @@ class RestAssuredJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder {
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) {
|
||||
blockBuilder.addLine("assertThat(response.header(\"$property\")).${createHeaderComparison(value)}")
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.header(\"$property\")).${createHeaderComparison(value)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Number value) {
|
||||
blockBuilder.addLine("assertThat(response.header(\"$property\")).isEqualTo(${value});")
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.header(\"$property\")).isEqualTo(${value});")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern pattern) {
|
||||
blockBuilder.addLine("assertThat(response.header(\"$property\")).${createHeaderComparison(pattern)}")
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.header(\"$property\")).${createHeaderComparison(pattern)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -110,12 +117,14 @@ class RestAssuredJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder {
|
||||
@Override
|
||||
protected void processCookieElement(BlockBuilder blockBuilder, String key, Pattern pattern) {
|
||||
blockBuilder.addLine("assertThat(response.getCookie(\"$key\")).isNotNull();")
|
||||
blockBuilder.addLine("assertThat(response.getCookie(\"$key\")).${createCookieComparison(pattern)}")
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getCookie(\"$key\")).${createCookieComparison(pattern)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCookieElement(BlockBuilder blockBuilder, String key, String value) {
|
||||
blockBuilder.addLine("assertThat(response.getCookie(\"$key\")).isNotNull();")
|
||||
blockBuilder.addLine("assertThat(response.getCookie(\"$key\")).${createCookieComparison(value)}")
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getCookie(\"$key\")).${createCookieComparison(value)}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,24 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.builder
|
||||
|
||||
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
import org.springframework.cloud.contract.verifier.file.ContractMetadata
|
||||
import org.springframework.cloud.contract.verifier.file.ContractMetadata
|
||||
|
||||
/**
|
||||
* Builds a single test.
|
||||
@@ -15,13 +31,13 @@ trait SingleTestGenerator {
|
||||
* Creates contents of a single test class in which all test scenarios from
|
||||
* the contract metadata should be placed.
|
||||
*
|
||||
* @param properties - properties passed to the plugin
|
||||
* @param listOfFiles - list of parsed contracts with additional metadata
|
||||
* @param className - the name of the generated test class
|
||||
* @param classPackage - the name of the package in which the test class should be stored
|
||||
* @param properties - properties passed to the plugin
|
||||
* @param listOfFiles - list of parsed contracts with additional metadata
|
||||
* @param className - the name of the generated test class
|
||||
* @param classPackage - the name of the package in which the test class should be stored
|
||||
* @param includedDirectoryRelativePath - relative path to the included directory
|
||||
* @return contents of a single test class
|
||||
* @deprecated use {@link SingleTestGenerator#buildClass(ContractVerifierConfigProperties, Collection, String, GeneratedClassData)}
|
||||
* @deprecated use{@link SingleTestGenerator#buildClass(ContractVerifierConfigProperties, Collection, String, GeneratedClassData)}
|
||||
*/
|
||||
@Deprecated
|
||||
abstract String buildClass(ContractVerifierConfigProperties properties,
|
||||
@@ -31,15 +47,18 @@ trait SingleTestGenerator {
|
||||
* Creates contents of a single test class in which all test scenarios from
|
||||
* the contract metadata should be placed.
|
||||
*
|
||||
* @param properties - properties passed to the plugin
|
||||
* @param listOfFiles - list of parsed contracts with additional metadata
|
||||
* @param generatedClassData - information about the generated class
|
||||
* @param properties - properties passed to the plugin
|
||||
* @param listOfFiles - list of parsed contracts with additional metadata
|
||||
* @param generatedClassData - information about the generated class
|
||||
* @param includedDirectoryRelativePath - relative path to the included directory
|
||||
* @return contents of a single test class
|
||||
*/
|
||||
String buildClass(ContractVerifierConfigProperties properties,
|
||||
Collection<ContractMetadata> listOfFiles, String includedDirectoryRelativePath, GeneratedClassData generatedClassData) {
|
||||
return buildClass(properties, listOfFiles, generatedClassData.className, generatedClassData.classPackage, includedDirectoryRelativePath)
|
||||
String className = generatedClassData.className
|
||||
String classPackage = generatedClassData.classPackage
|
||||
String path = includedDirectoryRelativePath
|
||||
return buildClass(properties, listOfFiles, className, classPackage, path)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,24 +1,27 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.builder
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
import groovy.json.StringEscapeUtils
|
||||
import groovy.transform.PackageScope
|
||||
import groovy.transform.TypeChecked
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.spec.internal.Cookie
|
||||
import org.springframework.cloud.contract.spec.internal.ExecutionProperty
|
||||
@@ -31,8 +34,6 @@ import org.springframework.cloud.contract.spec.internal.RegexProperty
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
import org.springframework.cloud.contract.verifier.util.MapConverter
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
import static org.apache.commons.text.StringEscapeUtils.escapeJava
|
||||
|
||||
/**
|
||||
@@ -44,8 +45,8 @@ import static org.apache.commons.text.StringEscapeUtils.escapeJava
|
||||
class SpockMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder {
|
||||
|
||||
SpockMessagingMethodBodyBuilder(Contract stubDefinition,
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
super(stubDefinition, configProperties, classDataForMethod)
|
||||
}
|
||||
|
||||
@@ -84,12 +85,14 @@ class SpockMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder {
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) {
|
||||
blockBuilder.addLine("${exec.insertValue("response.getHeader(\'$property\')?.toString()")}")
|
||||
blockBuilder.
|
||||
addLine("${exec.insertValue("response.getHeader(\'$property\')?.toString()")}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) {
|
||||
blockBuilder.addLine("response.getHeader('$property')?.toString() ${convertHeaderComparison(value)}")
|
||||
blockBuilder.
|
||||
addLine("response.getHeader('$property')?.toString() ${convertHeaderComparison(value)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -99,7 +102,8 @@ class SpockMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder {
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern value) {
|
||||
blockBuilder.addLine("response.getHeader('$property')?.toString() ${convertHeaderComparison(value)}")
|
||||
blockBuilder.
|
||||
addLine("response.getHeader('$property')?.toString() ${convertHeaderComparison(value)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -117,9 +121,12 @@ class SpockMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder {
|
||||
@Override
|
||||
protected void validateResponseCodeBlock(BlockBuilder bb) {
|
||||
if (outputMessage) {
|
||||
bb.addLine("""ContractVerifierMessage response = contractVerifierMessaging.receive(${sentToValue(outputMessage.sentTo.serverValue)})""")
|
||||
bb.addLine("""ContractVerifierMessage response = contractVerifierMessaging.receive(${
|
||||
sentToValue(outputMessage.sentTo.serverValue)
|
||||
})""")
|
||||
bb.addLine("""assert response != null""")
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
bb.addLine('noExceptionThrown()')
|
||||
}
|
||||
}
|
||||
@@ -262,7 +269,8 @@ class SpockMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder {
|
||||
}
|
||||
|
||||
protected String convertHeaderComparison(Pattern headerValue) {
|
||||
String converted = escapeJava(convertUnicodeEscapesIfRequired(headerValue.pattern()))
|
||||
String converted =
|
||||
escapeJava(convertUnicodeEscapesIfRequired(headerValue.pattern()))
|
||||
return "==~ java.util.regex.Pattern.compile('${converted}')"
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.builder
|
||||
@@ -49,8 +49,8 @@ import static org.springframework.cloud.contract.verifier.util.ContentUtils.getG
|
||||
abstract class SpockMethodRequestProcessingBodyBuilder extends RequestProcessingMethodBodyBuilder {
|
||||
|
||||
SpockMethodRequestProcessingBodyBuilder(Contract stubDefinition,
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
super(stubDefinition, configProperties, classDataForMethod)
|
||||
}
|
||||
|
||||
@@ -153,12 +153,14 @@ abstract class SpockMethodRequestProcessingBodyBuilder extends RequestProcessing
|
||||
String value
|
||||
if (body instanceof ExecutionProperty) {
|
||||
value = body.toString()
|
||||
} else if (body instanceof FromFileProperty) {
|
||||
}
|
||||
else if (body instanceof FromFileProperty) {
|
||||
FromFileProperty fileProperty = (FromFileProperty) body
|
||||
value = fileProperty.isByte() ?
|
||||
readBytesFromFileString(fileProperty, CommunicationType.REQUEST) :
|
||||
readStringFromFileString(fileProperty, CommunicationType.REQUEST)
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
String escaped = escapeRequestSpecialChars(body.toString())
|
||||
value = "'''$escaped'''"
|
||||
}
|
||||
@@ -167,7 +169,9 @@ abstract class SpockMethodRequestProcessingBodyBuilder extends RequestProcessing
|
||||
|
||||
@Override
|
||||
protected String getMultipartFileParameterContent(String propertyName, NamedProperty propertyValue) {
|
||||
return getGroovyMultipartFileParameterContent(propertyName, propertyValue, { FromFileProperty fileProp -> readBytesFromFileString(fileProp, CommunicationType.REQUEST) })
|
||||
return getGroovyMultipartFileParameterContent(propertyName, propertyValue, { FromFileProperty fileProp ->
|
||||
readBytesFromFileString(fileProp, CommunicationType.REQUEST)
|
||||
})
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -177,13 +181,15 @@ abstract class SpockMethodRequestProcessingBodyBuilder extends RequestProcessing
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, GString value) {
|
||||
String gstringValue = ContentUtils.extractValueForGString(value, ContentUtils.GET_TEST_SIDE).toString()
|
||||
String gstringValue = ContentUtils.
|
||||
extractValueForGString(value, ContentUtils.GET_TEST_SIDE).toString()
|
||||
processHeaderElement(blockBuilder, property, gstringValue)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCookieElement(BlockBuilder blockBuilder, String key, GString value) {
|
||||
String gStringValue = ContentUtils.extractValueForGString(value, ContentUtils.GET_TEST_SIDE).toString()
|
||||
String gStringValue = ContentUtils.
|
||||
extractValueForGString(value, ContentUtils.GET_TEST_SIDE).toString()
|
||||
processCookieElement(blockBuilder, key, gStringValue)
|
||||
}
|
||||
|
||||
@@ -209,7 +215,8 @@ abstract class SpockMethodRequestProcessingBodyBuilder extends RequestProcessing
|
||||
|
||||
protected String createBodyComparison(Pattern bodyValue) {
|
||||
String patternAsString = bodyValue.pattern()
|
||||
return patternComparison(RegexpBuilders.buildGStringRegexpForTestSide(patternAsString)) + ";"
|
||||
return patternComparison(RegexpBuilders.
|
||||
buildGStringRegexpForTestSide(patternAsString)) + ";"
|
||||
}
|
||||
|
||||
protected String convertCookieComparison(Pattern cookieValue) {
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.builder
|
||||
|
||||
import groovy.json.JsonOutput
|
||||
@@ -9,6 +25,7 @@ import org.springframework.cloud.contract.spec.internal.FromFileProperty
|
||||
import org.springframework.cloud.contract.spec.internal.Request
|
||||
import org.springframework.cloud.contract.verifier.util.ContentUtils
|
||||
import org.springframework.cloud.contract.verifier.util.MapConverter
|
||||
|
||||
/**
|
||||
* Representation of the request side to be used for response templating in
|
||||
* the generated tests.
|
||||
@@ -61,7 +78,7 @@ class TestSideRequestTemplateModel {
|
||||
String url = MapConverter.getTestSideValues(request.url ?: request.urlPath)
|
||||
Path paths = new Path(buildPathsFromUrl(url))
|
||||
Map<String, List<String>> query = (Map<String, List<String>>) (request.url ?: request.urlPath)
|
||||
.queryParameters?.parameters?.groupBy { it.name }?.collectEntries {
|
||||
.queryParameters?.parameters?.groupBy { it.name }?.collectEntries {
|
||||
[(it.key): it.value.collect { MapConverter.getTestSideValues(it) }]
|
||||
}
|
||||
String fullUrl = (query == null || query.isEmpty()) ? url :
|
||||
@@ -99,7 +116,8 @@ class TestSideRequestTemplateModel {
|
||||
Object bodyValue = extractServerValueFromBody(body)
|
||||
if (bodyValue instanceof GString || bodyValue instanceof String) {
|
||||
return bodyValue.toString()
|
||||
} else if (bodyValue instanceof FromFileProperty) {
|
||||
}
|
||||
else if (bodyValue instanceof FromFileProperty) {
|
||||
return null
|
||||
}
|
||||
return bodyValue != null ? new JsonOutput().toJson(bodyValue) : bodyValue
|
||||
@@ -107,8 +125,10 @@ class TestSideRequestTemplateModel {
|
||||
|
||||
protected static Object extractServerValueFromBody(bodyValue) {
|
||||
if (bodyValue instanceof GString) {
|
||||
bodyValue = ContentUtils.extractValue(bodyValue, { DslProperty dslProperty -> dslProperty.serverValue } as Closure)
|
||||
} else {
|
||||
bodyValue = ContentUtils.
|
||||
extractValue(bodyValue, { DslProperty dslProperty -> dslProperty.serverValue } as Closure)
|
||||
}
|
||||
else {
|
||||
bodyValue = MapConverter.transformValues(bodyValue, {
|
||||
it instanceof DslProperty ? it.serverValue : it
|
||||
})
|
||||
|
||||
@@ -1,7 +1,24 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.builder
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.PackageScope
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.spec.internal.Url
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
@@ -17,31 +34,31 @@ import org.springframework.cloud.contract.verifier.config.ContractVerifierConfig
|
||||
@PackageScope
|
||||
class WebTestClientJUnitMethodBodyBuilder extends RestAssuredJUnitMethodBodyBuilder {
|
||||
|
||||
WebTestClientJUnitMethodBodyBuilder(Contract stubDefinition,
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
super(stubDefinition, configProperties, classDataForMethod)
|
||||
}
|
||||
WebTestClientJUnitMethodBodyBuilder(Contract stubDefinition,
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
super(stubDefinition, configProperties, classDataForMethod)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String returnedResponseType() {
|
||||
return 'WebTestClientResponse'
|
||||
}
|
||||
@Override
|
||||
protected String returnedResponseType() {
|
||||
return 'WebTestClientResponse'
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String returnedRequestType() {
|
||||
return 'WebTestClientRequestSpecification'
|
||||
}
|
||||
@Override
|
||||
protected String returnedRequestType() {
|
||||
return 'WebTestClientRequestSpecification'
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void when(BlockBuilder bb) {
|
||||
bb.addLine(getInputString(request))
|
||||
bb.indent()
|
||||
@Override
|
||||
protected void when(BlockBuilder bb) {
|
||||
bb.addLine(getInputString(request))
|
||||
bb.indent()
|
||||
|
||||
Url url = getUrl(request)
|
||||
addQueryParameters(url, bb)
|
||||
addUrl(url, bb)
|
||||
addColonIfRequired(bb)
|
||||
bb.unindent()
|
||||
}
|
||||
Url url = getUrl(request)
|
||||
addQueryParameters(url, bb)
|
||||
addUrl(url, bb)
|
||||
addColonIfRequired(bb)
|
||||
bb.unindent()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2018-2019 the original author or authors.
|
||||
* Copyright 2018-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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.builder
|
||||
@@ -43,8 +43,8 @@ class XmlBodyVerificationBuilder implements BodyMethodGeneration {
|
||||
}
|
||||
|
||||
void addXmlResponseBodyCheck(BlockBuilder blockBuilder, Object responseBody,
|
||||
BodyMatchers bodyMatchers, String responseString,
|
||||
boolean shouldCommentOutBDDBlocks) {
|
||||
BodyMatchers bodyMatchers, String responseString,
|
||||
boolean shouldCommentOutBDDBlocks) {
|
||||
addXmlProcessingLines(blockBuilder, responseString)
|
||||
Object processedBody = XmlToXPathsConverter
|
||||
.removeMatchingXPaths(responseBody, bodyMatchers)
|
||||
@@ -62,7 +62,7 @@ class XmlBodyVerificationBuilder implements BodyMethodGeneration {
|
||||
.each {
|
||||
blockBuilder.addLine(it as String)
|
||||
addColonIfRequired(lineSuffix, blockBuilder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,11 +1,29 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.builder.handlebars
|
||||
|
||||
import wiremock.com.github.jknack.handlebars.Helper
|
||||
import wiremock.com.github.jknack.handlebars.Options
|
||||
import com.github.tomakehurst.wiremock.extension.responsetemplating.RequestTemplateModel
|
||||
import groovy.transform.CompileStatic
|
||||
import org.apache.commons.text.StringEscapeUtils
|
||||
import wiremock.com.github.jknack.handlebars.Helper
|
||||
import wiremock.com.github.jknack.handlebars.Options
|
||||
|
||||
import org.springframework.cloud.contract.verifier.builder.TestSideRequestTemplateModel
|
||||
|
||||
/**
|
||||
* A Handlebars helper for the {@code escapejsonbody} helper function.
|
||||
*
|
||||
@@ -23,7 +41,8 @@ class HandlebarsEscapeHelper implements Helper<Map<String, Object>> {
|
||||
Object model = context.get(REQUEST_MODEL_NAME)
|
||||
if (model instanceof TestSideRequestTemplateModel) {
|
||||
return StringEscapeUtils.escapeJson(returnObjectForTest(model).toString())
|
||||
} else if (model instanceof RequestTemplateModel) {
|
||||
}
|
||||
else if (model instanceof RequestTemplateModel) {
|
||||
return StringEscapeUtils.escapeJson(returnObjectForStub(model).toString())
|
||||
}
|
||||
throw new IllegalArgumentException("Unsupported model")
|
||||
|
||||
@@ -1,15 +1,31 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.builder.handlebars
|
||||
|
||||
import com.github.tomakehurst.wiremock.extension.responsetemplating.helpers.WireMockHelpers
|
||||
import org.apache.commons.text.StringEscapeUtils
|
||||
import wiremock.com.github.jknack.handlebars.Helper
|
||||
import wiremock.com.github.jknack.handlebars.Options
|
||||
import com.github.tomakehurst.wiremock.extension.responsetemplating.RequestTemplateModel
|
||||
import com.github.tomakehurst.wiremock.extension.responsetemplating.helpers.WireMockHelpers
|
||||
import com.jayway.jsonpath.DocumentContext
|
||||
import com.jayway.jsonpath.JsonPath
|
||||
import groovy.transform.CompileStatic
|
||||
import wiremock.com.github.jknack.handlebars.Helper
|
||||
import wiremock.com.github.jknack.handlebars.Options
|
||||
|
||||
import org.springframework.cloud.contract.verifier.builder.TestSideRequestTemplateModel
|
||||
|
||||
/**
|
||||
* A Handlebars helper for the {@code jsonpath} helper function.
|
||||
*
|
||||
@@ -31,11 +47,13 @@ class HandlebarsJsonPathHelper implements Helper<Object> {
|
||||
Object model = oldContext.get(REQUEST_MODEL_NAME)
|
||||
if (model instanceof TestSideRequestTemplateModel) {
|
||||
return returnObjectForTest(model, jsonPath)
|
||||
} else if (model instanceof RequestTemplateModel) {
|
||||
}
|
||||
else if (model instanceof RequestTemplateModel) {
|
||||
return returnObjectForStub(model, jsonPath)
|
||||
}
|
||||
throw new IllegalArgumentException("Unsupported model")
|
||||
} else if (context instanceof String) {
|
||||
}
|
||||
else if (context instanceof String) {
|
||||
Object value = WireMockHelpers.jsonPath.apply(context, options)
|
||||
if (testSideModel(options)) {
|
||||
return processTestResponseValue(value)
|
||||
@@ -55,7 +73,8 @@ class HandlebarsJsonPathHelper implements Helper<Object> {
|
||||
}
|
||||
|
||||
private Object returnObjectForStub(Object model, String jsonPath) {
|
||||
DocumentContext documentContext = JsonPath.parse(((RequestTemplateModel) model).body)
|
||||
DocumentContext documentContext = JsonPath.
|
||||
parse(((RequestTemplateModel) model).body)
|
||||
return documentContext.read(jsonPath)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.builder.imports
|
||||
@@ -60,16 +60,17 @@ class BaseImportProvider {
|
||||
* @return list of imports
|
||||
*/
|
||||
static List<String> getImports(TestFramework testFramework) {
|
||||
return GENERAL_IMPORTS.imports + TEST_FRAMEWORK_SPECIFIC_IMPORTS.get(testFramework).imports
|
||||
return GENERAL_IMPORTS.imports +
|
||||
TEST_FRAMEWORK_SPECIFIC_IMPORTS.get(testFramework).imports
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of static imports for provided test framework.
|
||||
* @param testFramework
|
||||
* @return
|
||||
* @param testFramework test framework to pick the static imports for
|
||||
* @return list of static imports for provided test framework.
|
||||
*/
|
||||
static List<String> getStaticImports(TestFramework testFramework) {
|
||||
return GENERAL_IMPORTS.staticImports + TEST_FRAMEWORK_SPECIFIC_IMPORTS.get(testFramework).staticImports
|
||||
return GENERAL_IMPORTS.staticImports +
|
||||
TEST_FRAMEWORK_SPECIFIC_IMPORTS.get(testFramework).staticImports
|
||||
}
|
||||
|
||||
static String getRuleImport(TestFramework testFramework) {
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.builder.imports
|
||||
@@ -59,7 +59,7 @@ class HttpImportProvider {
|
||||
'io.restassured.module.webtestclient.specification.WebTestClientRequestSpecification',
|
||||
'io.restassured.module.webtestclient.response.WebTestClientResponse']),
|
||||
(new Tuple2(JUNIT, EXPLICIT)) : new ImportDefinitions(["${restAssuredPackage}.specification.RequestSpecification",
|
||||
"${restAssuredPackage}.response.Response"]),
|
||||
"${restAssuredPackage}.response.Response"]),
|
||||
(new Tuple2(JUNIT5, EXPLICIT)) : new ImportDefinitions(["${restAssuredPackage}.specification.RequestSpecification",
|
||||
"${restAssuredPackage}.response.Response"]),
|
||||
(new Tuple2(SPOCK, JAXRSCLIENT)) : new ImportDefinitions([]),
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.builder.imports
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
@@ -19,4 +35,4 @@ class ImportDefinitions {
|
||||
this.imports = imports
|
||||
this.staticImports = staticImports
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.builder.imports
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
@@ -17,9 +33,9 @@ class MessagingImportProvider {
|
||||
*/
|
||||
static List<String> getImports() {
|
||||
return ['javax.inject.Inject',
|
||||
'org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper',
|
||||
'org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage',
|
||||
'org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging',
|
||||
'org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper',
|
||||
'org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage',
|
||||
'org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging',
|
||||
]
|
||||
}
|
||||
|
||||
@@ -27,6 +43,6 @@ class MessagingImportProvider {
|
||||
* @return list of static imports for messaging test contracts.
|
||||
*/
|
||||
static List<String> getStaticImports() {
|
||||
return ['org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers','org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes']
|
||||
return ['org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers', 'org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes']
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.config
|
||||
@@ -83,10 +83,10 @@ class ContractVerifierConfigProperties {
|
||||
*/
|
||||
List<String> excludedFiles = []
|
||||
|
||||
/**
|
||||
* Patterns that should be taken into account for processing
|
||||
*/
|
||||
List<String> includedFiles = []
|
||||
/**
|
||||
* Patterns that should be taken into account for processing
|
||||
*/
|
||||
List<String> includedFiles = []
|
||||
|
||||
/**
|
||||
* Patterns for which generated tests should be @Ignored
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.config
|
||||
@@ -46,7 +46,7 @@ enum TestFramework {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #TestFramework(TestFrameworkDefinition)}
|
||||
* @deprecated use{@link #TestFramework(TestFrameworkDefinition)}
|
||||
* @param classModifier
|
||||
* @param methodModifier
|
||||
* @param lineSuffix
|
||||
@@ -58,7 +58,7 @@ enum TestFramework {
|
||||
*/
|
||||
@Deprecated
|
||||
TestFramework(String classModifier, String methodModifier, String lineSuffix, String classExtension, String classNameSuffix,
|
||||
String ignoreClass, List<String> orderAnnotationImports, String orderAnnotation) {
|
||||
String ignoreClass, List<String> orderAnnotationImports, String orderAnnotation) {
|
||||
testFrameworkDefinition = new TestFrameworkDefinition() {
|
||||
|
||||
@Override
|
||||
@@ -117,4 +117,4 @@ enum TestFramework {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.config
|
||||
@@ -43,4 +43,4 @@ enum TestMode {
|
||||
* Uses Spring's reactive WebTestClient
|
||||
*/
|
||||
WEBTESTCLIENT
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.config.framework
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.config.framework
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.config.framework
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.config.framework
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.config.framework
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
@@ -13,63 +29,63 @@ import groovy.transform.CompileStatic
|
||||
interface TestFrameworkDefinition {
|
||||
|
||||
/**
|
||||
* Returns the class access level modifier. E.g. for Java tests that would mean {@code public}
|
||||
**/
|
||||
* @return the class access level modifier. E.g. for Java tests that would mean {@code public}
|
||||
* */
|
||||
String getClassModifier()
|
||||
|
||||
/**
|
||||
* Returns the method access level modifier along with the return type.
|
||||
* @return the method access level modifier along with the return type.
|
||||
* E.g. for Java tests that would mean {@code public void}
|
||||
**/
|
||||
* */
|
||||
String getMethodModifier()
|
||||
|
||||
/**
|
||||
* Returns the characters that should end each line. E.g. for Java tests that would mean {@code ;}
|
||||
**/
|
||||
* @return the characters that should end each line. E.g. for Java tests that would mean {@code ;}
|
||||
* */
|
||||
String getLineSuffix()
|
||||
|
||||
/**
|
||||
* Returns the file extension. E.g. for Java tests that would be {@code .java}
|
||||
**/
|
||||
* @return the file extension. E.g. for Java tests that would be {@code .java}
|
||||
* */
|
||||
String getClassExtension()
|
||||
|
||||
/**
|
||||
* Returns the test class name suffix. E.g. for JUnit tests that would be {@code Test}
|
||||
**/
|
||||
* @return the test class name suffix. E.g. for JUnit tests that would be {@code Test}
|
||||
* */
|
||||
String getClassNameSuffix()
|
||||
|
||||
/**
|
||||
* Returns the qualified name of the class used to ignore or disable tests. E.g. for JUnit 4 tests that would
|
||||
* @return the qualified name of the class used to ignore or disable tests. E.g. for JUnit 4 tests that would
|
||||
* be {@code org.junit.Ignore}
|
||||
**/
|
||||
* */
|
||||
String getIgnoreClass()
|
||||
|
||||
/**
|
||||
* Returns the qualified names of the classes that are used for arranging tests into scenarios.
|
||||
* @return the qualified names of the classes that are used for arranging tests into scenarios.
|
||||
* E.g. for JUnit 4 tests that would be {@code 'org.junit.FixMethodOrder'}, {@code 'org.junit.runners.MethodSorters'}
|
||||
**/
|
||||
* */
|
||||
List<String> getOrderAnnotationImports()
|
||||
|
||||
/**
|
||||
* Returns the annotation used for arranging tests into scenarios.
|
||||
* @return the annotation used for arranging tests into scenarios.
|
||||
* E.g. for JUnit test that would be {@code @FixMethodOrder(MethodSorters.NAME_ASCENDING)}
|
||||
**/
|
||||
* */
|
||||
String getOrderAnnotation()
|
||||
|
||||
/**
|
||||
* Returns the annotation used for ignoring or disabling tests. E.g. for JUnit tests that would mean {@code @Ignore}
|
||||
**/
|
||||
* @return the annotation used for ignoring or disabling tests. E.g. for JUnit tests that would mean {@code @Ignore}
|
||||
* */
|
||||
String getIgnoreAnnotation()
|
||||
|
||||
/**
|
||||
* Returns a boolean indicating whether an annotation-type rule or extension is being used or not.
|
||||
* @return a boolean indicating whether an annotation-type rule or extension is being used or not.
|
||||
* E.g. for JUnit 5 tests that would return {@code true}
|
||||
**/
|
||||
* */
|
||||
boolean annotationLevelRules()
|
||||
|
||||
/**
|
||||
* Returns the test rule or extension annotation with the {@annotationValue} passed as an argument.
|
||||
* @return the test rule or extension annotation with the {@annotationValue} passed as an argument.
|
||||
* E.g. for JUnit 5 tests that could be {@code @ExtendWith(Example.class)}
|
||||
**/
|
||||
* */
|
||||
String getRuleAnnotation(String annotationValue)
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.converter
|
||||
@@ -75,8 +75,10 @@ class ContractsToYaml {
|
||||
ContentType contentType = evaluateContentType(contract.response?.headers,
|
||||
contract.response?.body)
|
||||
yamlContract.outputMessage = new YamlContract.OutputMessage()
|
||||
yamlContract.outputMessage.sentTo = MapConverter.getStubSideValues(contract.outputMessage.sentTo)
|
||||
yamlContract.outputMessage.headers = (contract.outputMessage?.headers as Headers)?.asStubSideMap()
|
||||
yamlContract.outputMessage.sentTo = MapConverter.
|
||||
getStubSideValues(contract.outputMessage.sentTo)
|
||||
yamlContract.outputMessage.headers = (contract.outputMessage?.headers as Headers)?.
|
||||
asStubSideMap()
|
||||
yamlContract.outputMessage.body = MapConverter.getStubSideValues(
|
||||
contract.outputMessage?.body)
|
||||
contract.outputMessage?.bodyMatchers?.matchers()?.each { BodyMatcher matcher ->
|
||||
@@ -103,11 +105,16 @@ class ContractsToYaml {
|
||||
ContentType contentType = evaluateContentType(contract.input?.messageHeaders,
|
||||
contract.input?.messageBody)
|
||||
yamlContract.input = new YamlContract.Input()
|
||||
yamlContract.input.assertThat = MapConverter.getTestSideValues(contract.input?.assertThat?.toString())
|
||||
yamlContract.input.triggeredBy = MapConverter.getTestSideValues(contract.input?.triggeredBy?.toString())
|
||||
yamlContract.input.messageHeaders = (contract.input?.messageHeaders as Headers)?.asTestSideMap()
|
||||
yamlContract.input.messageBody = MapConverter.getTestSideValues(contract.input?.messageBody)
|
||||
yamlContract.input.messageFrom = MapConverter.getTestSideValues(contract.input?.messageFrom)
|
||||
yamlContract.input.assertThat = MapConverter.
|
||||
getTestSideValues(contract.input?.assertThat?.toString())
|
||||
yamlContract.input.triggeredBy = MapConverter.
|
||||
getTestSideValues(contract.input?.triggeredBy?.toString())
|
||||
yamlContract.input.messageHeaders = (contract.input?.messageHeaders as Headers)?.
|
||||
asTestSideMap()
|
||||
yamlContract.input.messageBody = MapConverter.
|
||||
getTestSideValues(contract.input?.messageBody)
|
||||
yamlContract.input.messageFrom = MapConverter.
|
||||
getTestSideValues(contract.input?.messageFrom)
|
||||
contract.input?.bodyMatchers?.matchers()?.each { BodyMatcher matcher ->
|
||||
yamlContract.input.matchers.body << new YamlContract.BodyStubMatcher(
|
||||
path: matcher.path(),
|
||||
@@ -139,15 +146,21 @@ class ContractsToYaml {
|
||||
request.cookies = (contract.request?.cookies as Cookies)?.asTestSideMap()
|
||||
Object body = contract.request?.body?.serverValue
|
||||
if (body instanceof FromFileProperty) {
|
||||
if (body.isByte()) request.bodyFromFileAsBytes = body.fileName()
|
||||
if (body.isString()) request.bodyFromFile = body.fileName()
|
||||
} else {
|
||||
if (body.isByte()) {
|
||||
request.bodyFromFileAsBytes = body.fileName()
|
||||
}
|
||||
if (body.isString()) {
|
||||
request.bodyFromFile = body.fileName()
|
||||
}
|
||||
}
|
||||
else {
|
||||
request.body = MapConverter.getTestSideValues(contract.request?.body)
|
||||
}
|
||||
Multipart multipart = contract.request.multipart
|
||||
if (multipart) {
|
||||
request.multipart = new YamlContract.Multipart()
|
||||
Map<String, Object> map = (Map<String, Object>) MapConverter.getTestSideValues(multipart)
|
||||
Map<String, Object> map = (Map<String, Object>) MapConverter.
|
||||
getTestSideValues(multipart)
|
||||
map.each { String key, Object value ->
|
||||
if (value instanceof NamedProperty) {
|
||||
Object fileName = value.name?.serverValue
|
||||
@@ -162,7 +175,8 @@ class ContractsToYaml {
|
||||
fileNameCommand: fileName instanceof ExecutionProperty ? fileName.toString() : null,
|
||||
fileContentCommand: fileContent instanceof ExecutionProperty ? fileContent.toString() : null,
|
||||
contentTypeCommand: contentType instanceof ExecutionProperty ? contentType.toString() : null)
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
request.multipart.params.put(key, value != null ? value.toString() : null)
|
||||
}
|
||||
}
|
||||
@@ -178,18 +192,19 @@ class ContractsToYaml {
|
||||
)
|
||||
}
|
||||
Object url = contract.request.url?.clientValue
|
||||
request.matchers.url = url instanceof RegexProperty ?
|
||||
request.matchers.url = url instanceof RegexProperty ?
|
||||
new YamlContract.KeyValueMatcher(regex: url.pattern()) :
|
||||
url instanceof ExecutionProperty ?
|
||||
new YamlContract.KeyValueMatcher(command: url.toString()) : null
|
||||
Object urlPath = contract.request.urlPath?.clientValue
|
||||
request.matchers.url = urlPath instanceof RegexProperty ?
|
||||
request.matchers.url = urlPath instanceof RegexProperty ?
|
||||
new YamlContract.KeyValueMatcher(regex: urlPath.pattern()) :
|
||||
urlPath instanceof ExecutionProperty ?
|
||||
new YamlContract.KeyValueMatcher(command: urlPath.toString()) : null
|
||||
if (multipart) {
|
||||
request.matchers.multipart = new YamlContract.MultipartStubMatcher()
|
||||
Map<String, Object> map = (Map<String, Object>) MapConverter.getStubSideValues(multipart)
|
||||
Map<String, Object> map = (Map<String, Object>) MapConverter.
|
||||
getStubSideValues(multipart)
|
||||
map.each { String key, Object value ->
|
||||
if (value instanceof NamedProperty) {
|
||||
Object fileName = value.name?.clientValue
|
||||
@@ -205,13 +220,15 @@ class ContractsToYaml {
|
||||
contentType: valueMatcher(contentType),
|
||||
)
|
||||
}
|
||||
} else if (value instanceof RegexProperty || value instanceof Pattern) {
|
||||
}
|
||||
else if (value instanceof RegexProperty || value instanceof Pattern) {
|
||||
RegexProperty property = new RegexProperty(value)
|
||||
request.matchers.multipart.params.add(new YamlContract.KeyValueMatcher(
|
||||
key: key,
|
||||
regex: property.pattern(),
|
||||
regexType: regexType(property.clazz())
|
||||
))
|
||||
request.matchers.multipart.params.
|
||||
add(new YamlContract.KeyValueMatcher(
|
||||
key: key,
|
||||
regex: property.pattern(),
|
||||
regexType: regexType(property.clazz())
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -232,12 +249,14 @@ class ContractsToYaml {
|
||||
}
|
||||
|
||||
protected YamlContract.ValueMatcher valueMatcher(Object o) {
|
||||
return o instanceof RegexProperty ? new YamlContract.ValueMatcher(regex: o.pattern()) : null
|
||||
return o instanceof RegexProperty ? new YamlContract.ValueMatcher(regex: o.
|
||||
pattern()) : null
|
||||
}
|
||||
|
||||
protected void setInputBodyMatchers(DslProperty body, List<YamlContract.BodyStubMatcher> bodyMatchers) {
|
||||
def testSideValues = MapConverter.getTestSideValues(body)
|
||||
JsonPaths paths = new JsonToJsonPathsConverter().transformToJsonPathWithStubsSideValues(body)
|
||||
JsonPaths paths = new JsonToJsonPathsConverter().
|
||||
transformToJsonPathWithStubsSideValues(body)
|
||||
paths?.findAll { it.valueBeforeChecking() instanceof Pattern }?.each {
|
||||
Object element = JsonToJsonPathsConverter.readElement(testSideValues, it.keyBeforeChecking())
|
||||
bodyMatchers << new YamlContract.BodyStubMatcher(
|
||||
@@ -254,28 +273,29 @@ class ContractsToYaml {
|
||||
}
|
||||
|
||||
protected RegexType regexType(Class clazz) {
|
||||
switch(clazz) {
|
||||
case Boolean:
|
||||
return RegexType.as_boolean
|
||||
case Long:
|
||||
return RegexType.as_long
|
||||
case Short:
|
||||
return RegexType.as_short
|
||||
case Integer:
|
||||
return RegexType.as_integer
|
||||
case Float:
|
||||
return RegexType.as_float
|
||||
case Double:
|
||||
return RegexType.as_double
|
||||
default:
|
||||
return RegexType.as_string
|
||||
switch (clazz) {
|
||||
case Boolean:
|
||||
return RegexType.as_boolean
|
||||
case Long:
|
||||
return RegexType.as_long
|
||||
case Short:
|
||||
return RegexType.as_short
|
||||
case Integer:
|
||||
return RegexType.as_integer
|
||||
case Float:
|
||||
return RegexType.as_float
|
||||
case Double:
|
||||
return RegexType.as_double
|
||||
default:
|
||||
return RegexType.as_string
|
||||
}
|
||||
}
|
||||
|
||||
protected void setOutputBodyMatchers(DslProperty body,
|
||||
List<YamlContract.BodyTestMatcher> bodyMatchers) {
|
||||
List<YamlContract.BodyTestMatcher> bodyMatchers) {
|
||||
def testSideValues = MapConverter.getTestSideValues(body)
|
||||
JsonPaths paths = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(body)
|
||||
JsonPaths paths = new JsonToJsonPathsConverter().
|
||||
transformToJsonPathWithTestsSideValues(body)
|
||||
paths?.findAll { it.valueBeforeChecking() instanceof Pattern }?.each {
|
||||
Object element = JsonToJsonPathsConverter.readElement(testSideValues, it.keyBeforeChecking())
|
||||
bodyMatchers << new YamlContract.BodyTestMatcher(
|
||||
@@ -311,9 +331,14 @@ class ContractsToYaml {
|
||||
response.cookies = (contract.response?.cookies as Cookies)?.asStubSideMap()
|
||||
Object body = contract.response?.body?.clientValue
|
||||
if (body instanceof FromFileProperty) {
|
||||
if (body.isByte()) response.bodyFromFileAsBytes = body.fileName()
|
||||
if (body.isString()) response.bodyFromFile = body.fileName()
|
||||
} else {
|
||||
if (body.isByte()) {
|
||||
response.bodyFromFileAsBytes = body.fileName()
|
||||
}
|
||||
if (body.isString()) {
|
||||
response.bodyFromFile = body.fileName()
|
||||
}
|
||||
}
|
||||
else {
|
||||
response.body = MapConverter.getStubSideValues(contract.response?.body)
|
||||
}
|
||||
contract.response?.bodyMatchers?.matchers()?.each { BodyMatcher matcher ->
|
||||
@@ -356,12 +381,14 @@ class ContractsToYaml {
|
||||
regex: property.pattern(),
|
||||
regexType: regexType(property.clazz())
|
||||
)
|
||||
} else if (value instanceof ExecutionProperty) {
|
||||
}
|
||||
else if (value instanceof ExecutionProperty) {
|
||||
headerMatchers << new YamlContract.TestHeaderMatcher(
|
||||
key: key,
|
||||
command: value.executionCommand,
|
||||
)
|
||||
} else if (value instanceof NotToEscapePattern) {
|
||||
}
|
||||
else if (value instanceof NotToEscapePattern) {
|
||||
headerMatchers << new YamlContract.TestHeaderMatcher(
|
||||
key: key,
|
||||
regex: ((Pattern) value.serverValue).pattern(),
|
||||
@@ -372,39 +399,39 @@ class ContractsToYaml {
|
||||
|
||||
protected YamlContract.TestMatcherType testMatcherType(MatchingType matchingType) {
|
||||
switch (matchingType) {
|
||||
case MatchingType.EQUALITY:
|
||||
return YamlContract.TestMatcherType.by_equality
|
||||
case MatchingType.TYPE:
|
||||
return YamlContract.TestMatcherType.by_type
|
||||
case MatchingType.COMMAND:
|
||||
return YamlContract.TestMatcherType.by_command
|
||||
case MatchingType.DATE:
|
||||
return YamlContract.TestMatcherType.by_date
|
||||
case MatchingType.TIME:
|
||||
return YamlContract.TestMatcherType.by_time
|
||||
case MatchingType.TIMESTAMP:
|
||||
return YamlContract.TestMatcherType.by_timestamp
|
||||
case MatchingType.REGEX:
|
||||
return YamlContract.TestMatcherType.by_regex
|
||||
case MatchingType.EQUALITY:
|
||||
return YamlContract.TestMatcherType.by_equality
|
||||
case MatchingType.TYPE:
|
||||
return YamlContract.TestMatcherType.by_type
|
||||
case MatchingType.COMMAND:
|
||||
return YamlContract.TestMatcherType.by_command
|
||||
case MatchingType.DATE:
|
||||
return YamlContract.TestMatcherType.by_date
|
||||
case MatchingType.TIME:
|
||||
return YamlContract.TestMatcherType.by_time
|
||||
case MatchingType.TIMESTAMP:
|
||||
return YamlContract.TestMatcherType.by_timestamp
|
||||
case MatchingType.REGEX:
|
||||
return YamlContract.TestMatcherType.by_regex
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
protected YamlContract.StubMatcherType stubMatcherType(MatchingType matchingType) {
|
||||
switch (matchingType) {
|
||||
case MatchingType.EQUALITY:
|
||||
return YamlContract.StubMatcherType.by_equality
|
||||
case MatchingType.TYPE:
|
||||
case MatchingType.COMMAND:
|
||||
throw new UnsupportedOperationException("No type for client side")
|
||||
case MatchingType.DATE:
|
||||
return YamlContract.StubMatcherType.by_date
|
||||
case MatchingType.TIME:
|
||||
return YamlContract.StubMatcherType.by_time
|
||||
case MatchingType.TIMESTAMP:
|
||||
return YamlContract.StubMatcherType.by_timestamp
|
||||
case MatchingType.REGEX:
|
||||
return YamlContract.StubMatcherType.by_regex
|
||||
case MatchingType.EQUALITY:
|
||||
return YamlContract.StubMatcherType.by_equality
|
||||
case MatchingType.TYPE:
|
||||
case MatchingType.COMMAND:
|
||||
throw new UnsupportedOperationException("No type for client side")
|
||||
case MatchingType.DATE:
|
||||
return YamlContract.StubMatcherType.by_date
|
||||
case MatchingType.TIME:
|
||||
return YamlContract.StubMatcherType.by_time
|
||||
case MatchingType.TIMESTAMP:
|
||||
return YamlContract.StubMatcherType.by_timestamp
|
||||
case MatchingType.REGEX:
|
||||
return YamlContract.StubMatcherType.by_regex
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.converter
|
||||
|
||||
import java.nio.file.Files
|
||||
@@ -9,6 +25,7 @@ import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.spec.ContractConverter
|
||||
import org.springframework.cloud.contract.verifier.util.ContractVerifierDslConverter
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader
|
||||
|
||||
/**
|
||||
* Converts contracts to YAML for the given folder
|
||||
*
|
||||
@@ -31,11 +48,19 @@ class ToYamlConverter {
|
||||
// target/copied_contracts/contracts/foo/baz/bar.groovy
|
||||
Collection<Contract> collection = converter.convertFrom(file)
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Converted file [" + file + "] to collection of [" + collection.size() + "] contracts")
|
||||
log.debug("Converted file [" + file + "] to collection of ["
|
||||
+ collection.
|
||||
size()
|
||||
+ "] contracts")
|
||||
}
|
||||
List<YamlContract> yamls = yamlContractConverter.convertTo(collection)
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Converted collection of [" + collection.size() + "] contracts to [" + yamls.size() + "] YAML contracts")
|
||||
log.debug("Converted collection of ["
|
||||
+ collection.
|
||||
size()
|
||||
+ "] contracts to ["
|
||||
+ yamls.size()
|
||||
+ "] YAML contracts")
|
||||
}
|
||||
// rm target/copied_contracts/contracts/foo/baz/bar.groovy
|
||||
file.delete()
|
||||
@@ -103,4 +128,4 @@ class GroovyContractConverter implements ContractConverter<Collection<Contract>>
|
||||
Collection<Contract> convertTo(Collection<Contract> contract) {
|
||||
return contract
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.converter
|
||||
@@ -22,9 +22,8 @@ import groovy.transform.ToString
|
||||
|
||||
/**
|
||||
* YAML representation of a {@link org.springframework.cloud.contract.spec.Contract}
|
||||
*
|
||||
* @since 1.2.1
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
* @since 1.2.1* @author Marcin Grzejszczak
|
||||
* @author Tim Ysewyn
|
||||
*/
|
||||
@CompileStatic
|
||||
@@ -270,4 +269,4 @@ class YamlContract {
|
||||
public String assertThat
|
||||
public TestMatchers matchers = new TestMatchers()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,31 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.converter
|
||||
|
||||
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper
|
||||
import groovy.transform.CompileStatic
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.spec.ContractConverter
|
||||
|
||||
/**
|
||||
* Simple converter from and to a {@link YamlContract} to a collection of {@link Contract}
|
||||
*
|
||||
* @since 1.2.1
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.2.1* @author Marcin Grzejszczak
|
||||
* @author Tim Ysewyn
|
||||
*/
|
||||
@CompileStatic
|
||||
@@ -54,7 +55,7 @@ class YamlContractConverter implements ContractConverter<List<YamlContract>> {
|
||||
@Override
|
||||
Map<String, byte[]> store(List<YamlContract> contracts) {
|
||||
return contracts.collectEntries {
|
||||
return [(name(it)) :
|
||||
return [(name(it)):
|
||||
this.mapper.writeValueAsString(it).bytes]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.converter
|
||||
@@ -54,11 +54,13 @@ class YamlToContracts {
|
||||
ClassLoader classLoader = YamlContractConverter.getClassLoader()
|
||||
YAMLMapper mapper = new YAMLMapper()
|
||||
try {
|
||||
Iterable<Object> iterables = new Yaml().loadAll(Files.newInputStream(contractFile.toPath()))
|
||||
Iterable<Object> iterables = new Yaml().
|
||||
loadAll(Files.newInputStream(contractFile.toPath()))
|
||||
Collection<Contract> contracts = []
|
||||
int counter = 0
|
||||
for (Object document : iterables) {
|
||||
List<Contract> processedYaml = processYaml(counter, document, mapper, classLoader, contractFile)
|
||||
List<Contract> processedYaml =
|
||||
processYaml(counter, document, mapper, classLoader, contractFile)
|
||||
contracts.addAll(processedYaml)
|
||||
counter = counter + 1
|
||||
}
|
||||
@@ -72,23 +74,33 @@ class YamlToContracts {
|
||||
}
|
||||
catch (Exception e1) {
|
||||
throw new IllegalStateException("Exception occurred while processing the file [" + contractFile + "]", e1)
|
||||
} finally {
|
||||
}
|
||||
finally {
|
||||
Thread.currentThread().setContextClassLoader(classLoader)
|
||||
}
|
||||
}
|
||||
|
||||
protected List<Contract> processYaml(int counter, Object document, ObjectMapper mapper, ClassLoader classLoader, File contractFile) {
|
||||
List<YamlContract> yamlContracts = convert(mapper, document)
|
||||
Thread.currentThread().setContextClassLoader(updatedClassLoader(contractFile.getParentFile(), classLoader))
|
||||
Thread.currentThread().setContextClassLoader(
|
||||
updatedClassLoader(contractFile.getParentFile(), classLoader))
|
||||
List<Contract> contracts = []
|
||||
for (YamlContract yamlContract : yamlContracts) {
|
||||
Contract contract = Contract.make {
|
||||
if (yamlContract.description) description(yamlContract.description)
|
||||
if (yamlContract.label) label(yamlContract.label)
|
||||
if (yamlContract.description) {
|
||||
description(yamlContract.description)
|
||||
}
|
||||
if (yamlContract.label) {
|
||||
label(yamlContract.label)
|
||||
}
|
||||
name(StringUtils.hasText(yamlContract.name) ? yamlContract.name
|
||||
: NamesUtil.defaultContractName(contractFile, yamlContracts, counter))
|
||||
if (yamlContract.priority) priority(yamlContract.priority)
|
||||
if (yamlContract.ignored) ignored()
|
||||
: NamesUtil.defaultContractName(contractFile, yamlContracts, counter))
|
||||
if (yamlContract.priority) {
|
||||
priority(yamlContract.priority)
|
||||
}
|
||||
if (yamlContract.ignored) {
|
||||
ignored()
|
||||
}
|
||||
if (yamlContract.request?.method) {
|
||||
request {
|
||||
method(yamlContract.request?.method)
|
||||
@@ -96,125 +108,156 @@ class YamlToContracts {
|
||||
url(urlValue(yamlContract.request?.url, yamlContract.request?.matchers?.url)) {
|
||||
if (yamlContract.request.queryParameters) {
|
||||
queryParameters {
|
||||
yamlContract.request.queryParameters.each { String key, Object value ->
|
||||
if (value instanceof List) {
|
||||
((List) value).each {
|
||||
parameter(key, it)
|
||||
yamlContract.request.queryParameters.
|
||||
each { String key, Object value ->
|
||||
if (value instanceof List) {
|
||||
((List) value).each {
|
||||
parameter(key, it)
|
||||
}
|
||||
}
|
||||
else {
|
||||
parameter(key, value)
|
||||
}
|
||||
} else {
|
||||
parameter(key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (yamlContract.request?.urlPath) {
|
||||
urlPath(urlValue(yamlContract.request?.urlPath, yamlContract.request?.matchers?.url)) {
|
||||
urlPath(
|
||||
urlValue(yamlContract.request?.urlPath, yamlContract.request?.matchers?.url)) {
|
||||
if (yamlContract.request.queryParameters) {
|
||||
queryParameters {
|
||||
yamlContract.request.queryParameters.each { String key, Object value ->
|
||||
if (value instanceof List) {
|
||||
((List) value).each {
|
||||
parameter(key, queryParamValue(yamlContract, key, it))
|
||||
yamlContract.request.queryParameters.
|
||||
each { String key, Object value ->
|
||||
if (value instanceof List) {
|
||||
((List) value).each {
|
||||
parameter(key,
|
||||
queryParamValue(yamlContract, key, it))
|
||||
}
|
||||
}
|
||||
else {
|
||||
parameter(key,
|
||||
queryParamValue(yamlContract, key, value))
|
||||
}
|
||||
} else {
|
||||
parameter(key, queryParamValue(yamlContract, key, value))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (yamlContract.request?.headers) {
|
||||
headers {
|
||||
yamlContract.request.headers.each { String key, Object value ->
|
||||
List<YamlContract.KeyValueMatcher> matchers =
|
||||
yamlContract.request.matchers.headers.findAll { it.key == key }
|
||||
matchers.each { YamlContract.KeyValueMatcher matcher ->
|
||||
if (value instanceof List) {
|
||||
((List) value).each {
|
||||
header(key, clientValue(it, matcher, key).clientValue)
|
||||
yamlContract.request.headers.
|
||||
each { String key, Object value ->
|
||||
List<YamlContract.KeyValueMatcher> matchers =
|
||||
yamlContract.request.matchers.headers.
|
||||
findAll { it.key == key }
|
||||
matchers.
|
||||
each { YamlContract.KeyValueMatcher matcher ->
|
||||
if (value instanceof List) {
|
||||
((List) value).each {
|
||||
header(key,
|
||||
clientValue(it, matcher, key).clientValue)
|
||||
}
|
||||
}
|
||||
else {
|
||||
header(key, new DslProperty(
|
||||
clientValue(value, matcher, key).clientValue,
|
||||
serverValue(value, matcher)))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
header(key, new DslProperty(clientValue(value, matcher, key).clientValue,
|
||||
serverValue(value, matcher)))
|
||||
if (!matchers) {
|
||||
header(key, value)
|
||||
}
|
||||
}
|
||||
if (!matchers) {
|
||||
header(key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (yamlContract.request?.cookies) {
|
||||
cookies {
|
||||
yamlContract.request?.cookies?.each { String key, Object value ->
|
||||
YamlContract.KeyValueMatcher matcher = yamlContract.request.matchers.cookies.find { it.key == key }
|
||||
cookie(key, clientValue(value, matcher, key))
|
||||
}
|
||||
yamlContract.request?.cookies?.
|
||||
each { String key, Object value ->
|
||||
YamlContract.KeyValueMatcher matcher = yamlContract.request.matchers.cookies.
|
||||
find { it.key == key }
|
||||
cookie(key, clientValue(value, matcher, key))
|
||||
}
|
||||
}
|
||||
}
|
||||
if (yamlContract.request.body != null) body(yamlContract.request.body)
|
||||
if (yamlContract.request.bodyFromFile != null) body(file(yamlContract.request.bodyFromFile))
|
||||
if (yamlContract.request.bodyFromFileAsBytes != null) body(fileAsBytes(yamlContract.request.bodyFromFileAsBytes))
|
||||
if (yamlContract.request.body != null) {
|
||||
body(yamlContract.request.body)
|
||||
}
|
||||
if (yamlContract.request.bodyFromFile != null) {
|
||||
body(file(yamlContract.request.bodyFromFile))
|
||||
}
|
||||
if (yamlContract.request.bodyFromFileAsBytes != null) {
|
||||
body(fileAsBytes(yamlContract.request.bodyFromFileAsBytes))
|
||||
}
|
||||
if (yamlContract.request.multipart) {
|
||||
Map multipartMap = [:]
|
||||
Map<String, DslProperty> multiPartParams = yamlContract.request
|
||||
.multipart.params.collectEntries { String paramKey, String paramValue ->
|
||||
YamlContract.KeyValueMatcher matcher = yamlContract.request.matchers
|
||||
.multipart.params.
|
||||
collectEntries { String paramKey, String paramValue ->
|
||||
YamlContract.KeyValueMatcher matcher = yamlContract.request.matchers
|
||||
.multipart.params.find {
|
||||
it.key == paramKey
|
||||
}
|
||||
Object value = paramValue
|
||||
if (matcher) {
|
||||
value = matcher.regex ? Pattern.compile(matcher.regex) :
|
||||
it.key == paramKey
|
||||
}
|
||||
Object value = paramValue
|
||||
if (matcher) {
|
||||
value = matcher.regex ? Pattern.
|
||||
compile(matcher.regex) :
|
||||
predefinedToPattern(matcher.predefined)
|
||||
}
|
||||
return [(paramKey), new DslProperty<>(value, paramValue)]
|
||||
} as Map<String, DslProperty>
|
||||
}
|
||||
return [(paramKey), new DslProperty<>(value, paramValue)]
|
||||
} as Map<String, DslProperty>
|
||||
multipartMap.putAll(multiPartParams)
|
||||
yamlContract.request.multipart.named.each { YamlContract.Named namedParam ->
|
||||
YamlContract.MultipartNamedStubMatcher matcher = yamlContract.request.matchers.multipart.named.find {
|
||||
it.paramName == namedParam.paramName
|
||||
}
|
||||
Object fileNameValue = namedParam.fileName
|
||||
Object fileContentValue = namedParam.fileContent
|
||||
String fileContentAsBytes = namedParam.fileContentAsBytes
|
||||
String fileContentFromFileAsBytes = namedParam.fileContentFromFileAsBytes
|
||||
String contentTypeCommand = namedParam.contentTypeCommand
|
||||
String fileContentCommand = namedParam.fileContentCommand
|
||||
String fileNameCommand = namedParam.fileNameCommand
|
||||
Object contentTypeValue = namedParam.contentType
|
||||
if (matcher && matcher.fileName) {
|
||||
fileNameValue = matcher.fileName.regex ? Pattern.compile(matcher.fileName.regex) :
|
||||
yamlContract.request.multipart.named.
|
||||
each { YamlContract.Named namedParam ->
|
||||
YamlContract.MultipartNamedStubMatcher matcher = yamlContract.request.matchers.multipart.named.
|
||||
find {
|
||||
it.paramName == namedParam.paramName
|
||||
}
|
||||
Object fileNameValue = namedParam.fileName
|
||||
Object fileContentValue = namedParam.fileContent
|
||||
String fileContentAsBytes = namedParam.fileContentAsBytes
|
||||
String fileContentFromFileAsBytes = namedParam.fileContentFromFileAsBytes
|
||||
String contentTypeCommand = namedParam.contentTypeCommand
|
||||
String fileContentCommand = namedParam.fileContentCommand
|
||||
String fileNameCommand = namedParam.fileNameCommand
|
||||
Object contentTypeValue = namedParam.contentType
|
||||
if (matcher && matcher.fileName) {
|
||||
fileNameValue = matcher.fileName.regex ? Pattern.
|
||||
compile(matcher.fileName.regex) :
|
||||
predefinedToPattern(matcher.fileName.predefined)
|
||||
}
|
||||
if (matcher && matcher.fileContent) {
|
||||
fileContentValue = matcher.fileContent.regex ? Pattern.compile(matcher.fileContent.regex) :
|
||||
}
|
||||
if (matcher && matcher.fileContent) {
|
||||
fileContentValue = matcher.fileContent.regex ? Pattern.
|
||||
compile(matcher.fileContent.regex) :
|
||||
predefinedToPattern(matcher.fileContent.predefined)
|
||||
}
|
||||
if (matcher && matcher.contentType) {
|
||||
contentTypeValue = matcher.contentType.regex ? Pattern.compile(matcher.contentType.regex) :
|
||||
}
|
||||
if (matcher && matcher.contentType) {
|
||||
contentTypeValue = matcher.contentType.regex ? Pattern.
|
||||
compile(matcher.contentType.regex) :
|
||||
predefinedToPattern(matcher.contentType.predefined)
|
||||
}
|
||||
multipartMap.put(namedParam.paramName, new NamedProperty(
|
||||
new DslProperty<>(fileNameValue, fileNameCommand ? new ExecutionProperty(fileNameCommand)
|
||||
}
|
||||
multipartMap.
|
||||
put(namedParam.paramName, new NamedProperty(
|
||||
new DslProperty<>(fileNameValue, fileNameCommand ? new ExecutionProperty(fileNameCommand)
|
||||
: namedParam.fileName),
|
||||
new DslProperty<>(fileContentValue, namedParam.fileContent ? namedParam.fileContent : fileContentFromFileAsBytes ? fileAsBytes(namedParam.fileContentFromFileAsBytes) : fileContentAsBytes ? fileContentAsBytes.bytes : new ExecutionProperty(fileContentCommand)),
|
||||
new DslProperty(contentTypeValue, contentTypeCommand ? new ExecutionProperty(contentTypeCommand)
|
||||
new DslProperty<>(fileContentValue, namedParam.fileContent ? namedParam.fileContent : fileContentFromFileAsBytes ?
|
||||
fileAsBytes(namedParam.fileContentFromFileAsBytes) : fileContentAsBytes ? fileContentAsBytes.bytes : new ExecutionProperty(fileContentCommand)),
|
||||
new DslProperty(contentTypeValue, contentTypeCommand ? new ExecutionProperty(contentTypeCommand)
|
||||
: namedParam.contentType)))
|
||||
}
|
||||
}
|
||||
multipart(multipartMap)
|
||||
}
|
||||
bodyMatchers {
|
||||
yamlContract.request.matchers?.body?.each { YamlContract.BodyStubMatcher matcher ->
|
||||
ContentType contentType =
|
||||
yamlContract.request.matchers?.body?.
|
||||
each { YamlContract.BodyStubMatcher matcher ->
|
||||
ContentType contentType =
|
||||
evaluateContentType(
|
||||
yamlHeadersToContractHeaders(yamlContract.request?.headers),
|
||||
yamlContract.request?.body)
|
||||
MatchingTypeValue value = null
|
||||
switch (matcher.type) {
|
||||
yamlHeadersToContractHeaders(yamlContract.request?.headers),
|
||||
yamlContract.request?.body)
|
||||
MatchingTypeValue value = null
|
||||
switch (matcher.type) {
|
||||
case YamlContract.StubMatcherType.by_date:
|
||||
value = byDate()
|
||||
break
|
||||
@@ -227,7 +270,9 @@ class YamlToContracts {
|
||||
case YamlContract.StubMatcherType.by_regex:
|
||||
String regex = matcher.value
|
||||
if (matcher.predefined) {
|
||||
regex = predefinedToPattern(matcher.predefined).pattern()
|
||||
regex =
|
||||
predefinedToPattern(matcher.predefined).
|
||||
pattern()
|
||||
}
|
||||
value = byRegex(regex)
|
||||
break
|
||||
@@ -236,8 +281,12 @@ class YamlToContracts {
|
||||
break
|
||||
case YamlContract.StubMatcherType.by_type:
|
||||
value = byType {
|
||||
if (matcher.minOccurrence != null) minOccurrence(matcher.minOccurrence)
|
||||
if (matcher.maxOccurrence != null) maxOccurrence(matcher.maxOccurrence)
|
||||
if (matcher.minOccurrence != null) {
|
||||
minOccurrence(matcher.minOccurrence)
|
||||
}
|
||||
if (matcher.maxOccurrence != null) {
|
||||
maxOccurrence(matcher.maxOccurrence)
|
||||
}
|
||||
}
|
||||
break
|
||||
case YamlContract.StubMatcherType.by_null:
|
||||
@@ -245,68 +294,87 @@ class YamlToContracts {
|
||||
break
|
||||
default:
|
||||
throw new UnsupportedOperationException("The type [" + matcher.type + "] is unsupported. Hint: If you're using <predefined> remember to pass <type: by_regex>")
|
||||
}
|
||||
if (value) {
|
||||
if (XML == contentType) {
|
||||
xPath(matcher.path, value)
|
||||
}
|
||||
else {
|
||||
jsonPath(matcher.path, value)
|
||||
if (value) {
|
||||
if (XML == contentType) {
|
||||
xPath(matcher.path, value)
|
||||
}
|
||||
else {
|
||||
jsonPath(matcher.path, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
response {
|
||||
status(yamlContract.response.status)
|
||||
headers {
|
||||
yamlContract.response?.headers?.each { String key, Object value ->
|
||||
YamlContract.TestHeaderMatcher matcher = yamlContract.response.matchers.headers.find { it.key == key }
|
||||
if (value instanceof List) {
|
||||
((List) value).each {
|
||||
Object serverValue = serverValue(it, matcher, key)
|
||||
header(key, new DslProperty(it, serverValue))
|
||||
yamlContract.response?.headers?.
|
||||
each { String key, Object value ->
|
||||
YamlContract.TestHeaderMatcher matcher = yamlContract.response.matchers.headers.
|
||||
find { it.key == key }
|
||||
if (value instanceof List) {
|
||||
((List) value).each {
|
||||
Object serverValue =
|
||||
serverValue(it, matcher, key)
|
||||
header(key, new DslProperty(it, serverValue))
|
||||
}
|
||||
}
|
||||
else {
|
||||
Object serverValue =
|
||||
serverValue(value, matcher, key)
|
||||
header(key, new DslProperty(value, serverValue))
|
||||
}
|
||||
} else {
|
||||
Object serverValue = serverValue(value, matcher, key)
|
||||
header(key, new DslProperty(value, serverValue))
|
||||
}
|
||||
}
|
||||
}
|
||||
if (yamlContract.response?.cookies) {
|
||||
cookies {
|
||||
yamlContract.response?.cookies?.each { String key, Object value ->
|
||||
YamlContract.TestCookieMatcher matcher = yamlContract.response.matchers.cookies.find { it.key == key }
|
||||
DslProperty cookieValue = serverCookieValue(value, matcher, key)
|
||||
cookie(key, cookieValue)
|
||||
}
|
||||
yamlContract.response?.cookies?.
|
||||
each { String key, Object value ->
|
||||
YamlContract.TestCookieMatcher matcher = yamlContract.response.matchers.cookies.
|
||||
find { it.key == key }
|
||||
DslProperty cookieValue =
|
||||
serverCookieValue(value, matcher, key)
|
||||
cookie(key, cookieValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (yamlContract.response.body != null) {
|
||||
YamlContract.BodyTestMatcher bodyTestMatcher = yamlContract.response?.matchers?.body?.find {
|
||||
it.path == null && (it.type == YamlContract.TestMatcherType.by_regex ||
|
||||
it.type == YamlContract.TestMatcherType.by_command)
|
||||
}
|
||||
}
|
||||
if (bodyTestMatcher) {
|
||||
body(new DslProperty(yamlContract.response.body,
|
||||
bodyTestMatcher.type == YamlContract.TestMatcherType.by_regex ?
|
||||
Pattern.compile(bodyTestMatcher.value) : new ExecutionProperty(bodyTestMatcher.value)))
|
||||
} else {
|
||||
bodyTestMatcher.type == YamlContract.TestMatcherType.by_regex ?
|
||||
Pattern.
|
||||
compile(bodyTestMatcher.value) : new ExecutionProperty(bodyTestMatcher.value)))
|
||||
}
|
||||
else {
|
||||
body(yamlContract.response.body)
|
||||
}
|
||||
}
|
||||
if (yamlContract.response.bodyFromFile) body(file(yamlContract.response.bodyFromFile))
|
||||
if (yamlContract.response.bodyFromFileAsBytes) body(fileAsBytes(yamlContract.response.bodyFromFileAsBytes))
|
||||
if (yamlContract.response.async) async()
|
||||
if (yamlContract.response.fixedDelayMilliseconds) fixedDelayMilliseconds(yamlContract.response.fixedDelayMilliseconds)
|
||||
if (yamlContract.response.bodyFromFile) {
|
||||
body(file(yamlContract.response.bodyFromFile))
|
||||
}
|
||||
if (yamlContract.response.bodyFromFileAsBytes) {
|
||||
body(fileAsBytes(yamlContract.response.bodyFromFileAsBytes))
|
||||
}
|
||||
if (yamlContract.response.async) {
|
||||
async()
|
||||
}
|
||||
if (yamlContract.response.fixedDelayMilliseconds) {
|
||||
fixedDelayMilliseconds(yamlContract.response.fixedDelayMilliseconds)
|
||||
}
|
||||
bodyMatchers {
|
||||
yamlContract.response?.matchers?.body?.each { YamlContract.BodyTestMatcher testMatcher ->
|
||||
ContentType contentType =
|
||||
yamlContract.response?.matchers?.body?.
|
||||
each { YamlContract.BodyTestMatcher testMatcher ->
|
||||
ContentType contentType =
|
||||
evaluateContentType(
|
||||
yamlHeadersToContractHeaders(yamlContract.response?.headers),
|
||||
yamlContract.response?.body)
|
||||
MatchingTypeValue value = null
|
||||
switch (testMatcher.type) {
|
||||
yamlHeadersToContractHeaders(yamlContract.response?.headers),
|
||||
yamlContract.response?.body)
|
||||
MatchingTypeValue value = null
|
||||
switch (testMatcher.type) {
|
||||
case YamlContract.TestMatcherType.by_date:
|
||||
value = byDate()
|
||||
break
|
||||
@@ -319,7 +387,9 @@ class YamlToContracts {
|
||||
case YamlContract.TestMatcherType.by_regex:
|
||||
String regex = testMatcher.value
|
||||
if (testMatcher.predefined) {
|
||||
regex = predefinedToPattern(testMatcher.predefined).pattern()
|
||||
regex =
|
||||
predefinedToPattern(testMatcher.predefined).
|
||||
pattern()
|
||||
}
|
||||
value = byRegex(regex)
|
||||
break
|
||||
@@ -328,8 +398,12 @@ class YamlToContracts {
|
||||
break
|
||||
case YamlContract.TestMatcherType.by_type:
|
||||
value = byType() {
|
||||
if (testMatcher.minOccurrence != null) minOccurrence(testMatcher.minOccurrence)
|
||||
if (testMatcher.maxOccurrence != null) maxOccurrence(testMatcher.maxOccurrence)
|
||||
if (testMatcher.minOccurrence != null) {
|
||||
minOccurrence(testMatcher.minOccurrence)
|
||||
}
|
||||
if (testMatcher.maxOccurrence != null) {
|
||||
maxOccurrence(testMatcher.maxOccurrence)
|
||||
}
|
||||
}
|
||||
break
|
||||
case YamlContract.TestMatcherType.by_command:
|
||||
@@ -340,41 +414,57 @@ class YamlToContracts {
|
||||
break
|
||||
default:
|
||||
throw new UnsupportedOperationException("The type [" + testMatcher.type + "] is unsupported. Hint: If you're using <predefined> remember to pass <type: by_regex>")
|
||||
}
|
||||
if (testMatcher.path) {
|
||||
if (XML == contentType) {
|
||||
xPath(testMatcher.path, value)
|
||||
}
|
||||
else {
|
||||
jsonPath(testMatcher.path, value)
|
||||
if (testMatcher.path) {
|
||||
if (XML == contentType) {
|
||||
xPath(testMatcher.path, value)
|
||||
}
|
||||
else {
|
||||
jsonPath(testMatcher.path, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (yamlContract.input) {
|
||||
input {
|
||||
if (yamlContract.input.messageFrom) messageFrom(yamlContract.input.messageFrom)
|
||||
if (yamlContract.input.assertThat) assertThat(yamlContract.input.assertThat)
|
||||
if (yamlContract.input.triggeredBy) triggeredBy(yamlContract.input.triggeredBy)
|
||||
messageHeaders {
|
||||
yamlContract.input?.messageHeaders?.each { String key, Object value ->
|
||||
YamlContract.KeyValueMatcher matcher = yamlContract.input.matchers?.headers?.find { it.key == key }
|
||||
header(key, clientValue(value, matcher, key))
|
||||
}
|
||||
if (yamlContract.input.messageFrom) {
|
||||
messageFrom(yamlContract.input.messageFrom)
|
||||
}
|
||||
if (yamlContract.input.assertThat) {
|
||||
assertThat(yamlContract.input.assertThat)
|
||||
}
|
||||
if (yamlContract.input.triggeredBy) {
|
||||
triggeredBy(yamlContract.input.triggeredBy)
|
||||
}
|
||||
messageHeaders {
|
||||
yamlContract.input?.messageHeaders?.
|
||||
each { String key, Object value ->
|
||||
YamlContract.KeyValueMatcher matcher = yamlContract.input.matchers?.headers?.
|
||||
find { it.key == key }
|
||||
header(key, clientValue(value, matcher, key))
|
||||
}
|
||||
}
|
||||
if (yamlContract.input.messageBody) {
|
||||
messageBody(yamlContract.input.messageBody)
|
||||
}
|
||||
if (yamlContract.input.messageBodyFromFile) {
|
||||
messageBody(file(yamlContract.input.messageBodyFromFile))
|
||||
}
|
||||
if (yamlContract.input.messageBodyFromFileAsBytes) {
|
||||
messageBody(
|
||||
fileAsBytes(yamlContract.input.messageBodyFromFileAsBytes))
|
||||
}
|
||||
if (yamlContract.input.messageBody) messageBody(yamlContract.input.messageBody)
|
||||
if (yamlContract.input.messageBodyFromFile) messageBody(file(yamlContract.input.messageBodyFromFile))
|
||||
if (yamlContract.input.messageBodyFromFileAsBytes) messageBody(fileAsBytes(yamlContract.input.messageBodyFromFileAsBytes))
|
||||
bodyMatchers {
|
||||
yamlContract.input.matchers.body?.each { YamlContract.BodyStubMatcher matcher ->
|
||||
ContentType contentType =
|
||||
yamlContract.input.matchers.body?.
|
||||
each { YamlContract.BodyStubMatcher matcher ->
|
||||
ContentType contentType =
|
||||
evaluateContentType(
|
||||
yamlHeadersToContractHeaders(yamlContract.input?.messageHeaders),
|
||||
yamlContract.input?.messageBody)
|
||||
MatchingTypeValue value = null
|
||||
switch (matcher.type) {
|
||||
yamlHeadersToContractHeaders(yamlContract.input?.messageHeaders),
|
||||
yamlContract.input?.messageBody)
|
||||
MatchingTypeValue value = null
|
||||
switch (matcher.type) {
|
||||
case YamlContract.StubMatcherType.by_date:
|
||||
value = byDate()
|
||||
break
|
||||
@@ -387,7 +477,9 @@ class YamlToContracts {
|
||||
case YamlContract.StubMatcherType.by_regex:
|
||||
String regex = matcher.value
|
||||
if (matcher.predefined) {
|
||||
regex = predefinedToPattern(matcher.predefined).pattern()
|
||||
regex =
|
||||
predefinedToPattern(matcher.predefined).
|
||||
pattern()
|
||||
}
|
||||
value = byRegex(regex)
|
||||
break
|
||||
@@ -396,41 +488,53 @@ class YamlToContracts {
|
||||
break
|
||||
default:
|
||||
throw new UnsupportedOperationException("The type [" + matcher.type + "] is unsupported. Hint: If you're using <predefined> remember to pass <type: by_regex>")
|
||||
}
|
||||
if (XML == contentType) {
|
||||
xPath(matcher.path, value)
|
||||
}
|
||||
else {
|
||||
jsonPath(matcher.path, value)
|
||||
}
|
||||
}
|
||||
if (XML == contentType) {
|
||||
xPath(matcher.path, value)
|
||||
}
|
||||
else {
|
||||
jsonPath(matcher.path, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
YamlContract.OutputMessage outputMsg = yamlContract.outputMessage
|
||||
if (outputMsg) {
|
||||
outputMessage {
|
||||
if (outputMsg.assertThat) assertThat(outputMsg.assertThat)
|
||||
if (outputMsg.sentTo) sentTo(outputMsg.sentTo)
|
||||
if (outputMsg.assertThat) {
|
||||
assertThat(outputMsg.assertThat)
|
||||
}
|
||||
if (outputMsg.sentTo) {
|
||||
sentTo(outputMsg.sentTo)
|
||||
}
|
||||
headers {
|
||||
outputMsg.headers?.each { String key, Object value ->
|
||||
YamlContract.TestHeaderMatcher matcher = outputMsg.matchers?.headers?.find { it.key == key }
|
||||
YamlContract.TestHeaderMatcher matcher = outputMsg.matchers?.headers?.
|
||||
find { it.key == key }
|
||||
Object serverValue = serverValue(value, matcher, key)
|
||||
header(key, new DslProperty(value, serverValue))
|
||||
}
|
||||
}
|
||||
if (outputMsg.body) body(outputMsg.body)
|
||||
if (outputMsg.bodyFromFile) body(file(outputMsg.bodyFromFile))
|
||||
if (outputMsg.bodyFromFileAsBytes) body(fileAsBytes(outputMsg.bodyFromFileAsBytes))
|
||||
if (outputMsg.body) {
|
||||
body(outputMsg.body)
|
||||
}
|
||||
if (outputMsg.bodyFromFile) {
|
||||
body(file(outputMsg.bodyFromFile))
|
||||
}
|
||||
if (outputMsg.bodyFromFileAsBytes) {
|
||||
body(fileAsBytes(outputMsg.bodyFromFileAsBytes))
|
||||
}
|
||||
if (outputMsg.matchers) {
|
||||
bodyMatchers {
|
||||
yamlContract.outputMessage?.matchers?.body?.each { YamlContract.BodyTestMatcher testMatcher ->
|
||||
ContentType contentType =
|
||||
yamlContract.outputMessage?.matchers?.body?.
|
||||
each { YamlContract.BodyTestMatcher testMatcher ->
|
||||
ContentType contentType =
|
||||
evaluateContentType(
|
||||
yamlHeadersToContractHeaders(yamlContract.outputMessage?.headers),
|
||||
yamlContract.outputMessage?.body)
|
||||
MatchingTypeValue value = null
|
||||
switch (testMatcher.type) {
|
||||
yamlHeadersToContractHeaders(yamlContract.outputMessage?.headers),
|
||||
yamlContract.outputMessage?.body)
|
||||
MatchingTypeValue value = null
|
||||
switch (testMatcher.type) {
|
||||
case YamlContract.TestMatcherType.by_date:
|
||||
value = byDate()
|
||||
break
|
||||
@@ -443,7 +547,9 @@ class YamlToContracts {
|
||||
case YamlContract.TestMatcherType.by_regex:
|
||||
String regex = testMatcher.value
|
||||
if (testMatcher.predefined) {
|
||||
regex = predefinedToPattern(testMatcher.predefined).pattern()
|
||||
regex =
|
||||
predefinedToPattern(testMatcher.predefined).
|
||||
pattern()
|
||||
}
|
||||
value = byRegex(regex)
|
||||
break
|
||||
@@ -452,8 +558,12 @@ class YamlToContracts {
|
||||
break
|
||||
case YamlContract.TestMatcherType.by_type:
|
||||
value = byType() {
|
||||
if (testMatcher.minOccurrence != null) minOccurrence(testMatcher.minOccurrence)
|
||||
if (testMatcher.maxOccurrence != null) maxOccurrence(testMatcher.maxOccurrence)
|
||||
if (testMatcher.minOccurrence != null) {
|
||||
minOccurrence(testMatcher.minOccurrence)
|
||||
}
|
||||
if (testMatcher.maxOccurrence != null) {
|
||||
maxOccurrence(testMatcher.maxOccurrence)
|
||||
}
|
||||
}
|
||||
break
|
||||
case YamlContract.TestMatcherType.by_command:
|
||||
@@ -464,14 +574,14 @@ class YamlToContracts {
|
||||
break
|
||||
default:
|
||||
throw new UnsupportedOperationException("The type [" + testMatcher.type + "] is unsupported. Hint: If you're using <predefined> remember to pass <type: by_regex>")
|
||||
}
|
||||
if (XML == contentType) {
|
||||
xPath(testMatcher.path, value)
|
||||
}
|
||||
else {
|
||||
jsonPath(testMatcher.path, value)
|
||||
}
|
||||
}
|
||||
if (XML == contentType) {
|
||||
xPath(testMatcher.path, value)
|
||||
}
|
||||
else {
|
||||
jsonPath(testMatcher.path, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -484,8 +594,8 @@ class YamlToContracts {
|
||||
|
||||
private Headers yamlHeadersToContractHeaders(Map<String, Object> headers) {
|
||||
Set<Header> convertedHeaders = headers.keySet().stream()
|
||||
.map({ new Header(it, headers.get(it)) })
|
||||
.collect(toSet())
|
||||
.map({ new Header(it, headers.get(it)) })
|
||||
.collect(toSet())
|
||||
Headers contractHeaders = new Headers()
|
||||
contractHeaders.headers(convertedHeaders)
|
||||
return contractHeaders
|
||||
@@ -497,7 +607,8 @@ class YamlToContracts {
|
||||
return new DslProperty<Object>(url, new ExecutionProperty(urlMatcher.command))
|
||||
}
|
||||
return new DslProperty(urlMatcher.regex ? Pattern.compile(urlMatcher.regex) :
|
||||
urlMatcher.predefined ? predefinedToPattern(urlMatcher.predefined) : url, url)
|
||||
urlMatcher.predefined ?
|
||||
predefinedToPattern(urlMatcher.predefined) : url, url)
|
||||
}
|
||||
return new DslProperty(url)
|
||||
}
|
||||
@@ -505,7 +616,8 @@ class YamlToContracts {
|
||||
protected List<YamlContract> convert(ObjectMapper mapper, Object o) {
|
||||
try {
|
||||
return Arrays.asList(mapper.convertValue(o, YamlContract[].class))
|
||||
} catch(IllegalArgumentException e) {
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
return Collections.singletonList(mapper.convertValue(o, YamlContract.class))
|
||||
}
|
||||
}
|
||||
@@ -516,11 +628,13 @@ class YamlToContracts {
|
||||
serverValue = Pattern.compile(matcher.regex)
|
||||
Pattern pattern = (Pattern) serverValue
|
||||
assertPatternMatched(pattern, value, key)
|
||||
} else if (matcher?.predefined) {
|
||||
}
|
||||
else if (matcher?.predefined) {
|
||||
Pattern pattern = predefinedToPattern(matcher.predefined)
|
||||
serverValue = pattern
|
||||
assertPatternMatched(pattern, value, key)
|
||||
} else if (matcher?.command) {
|
||||
}
|
||||
else if (matcher?.command) {
|
||||
serverValue = new ExecutionProperty(matcher.command)
|
||||
}
|
||||
return serverValue
|
||||
@@ -532,11 +646,13 @@ class YamlToContracts {
|
||||
serverValue = Pattern.compile(matcher.regex)
|
||||
Pattern pattern = (Pattern) serverValue
|
||||
assertPatternMatched(pattern, value, key)
|
||||
} else if (matcher?.predefined) {
|
||||
}
|
||||
else if (matcher?.predefined) {
|
||||
Pattern pattern = predefinedToPattern(matcher.predefined)
|
||||
serverValue = pattern
|
||||
assertPatternMatched(pattern, value, key)
|
||||
} else if (matcher?.command) {
|
||||
}
|
||||
else if (matcher?.command) {
|
||||
return new DslProperty(new ExecutionProperty(matcher.command), value)
|
||||
}
|
||||
return new DslProperty(value, serverValue)
|
||||
@@ -548,11 +664,13 @@ class YamlToContracts {
|
||||
clientValue = Pattern.compile(matcher.regex)
|
||||
Pattern pattern = (Pattern) clientValue
|
||||
assertPatternMatched(pattern, value, key)
|
||||
} else if (matcher?.predefined) {
|
||||
}
|
||||
else if (matcher?.predefined) {
|
||||
Pattern pattern = predefinedToPattern(matcher.predefined)
|
||||
clientValue = pattern
|
||||
assertPatternMatched(pattern, value, key)
|
||||
} else if (matcher?.command) {
|
||||
}
|
||||
else if (matcher?.command) {
|
||||
return new DslProperty(value, new ExecutionProperty(matcher.command))
|
||||
}
|
||||
return new DslProperty(clientValue, value)
|
||||
@@ -561,27 +679,29 @@ class YamlToContracts {
|
||||
protected Object queryParamValue(YamlContract yamlContract, String key, Object value) {
|
||||
Request request = new Request()
|
||||
YamlContract.QueryParameterMatcher matcher = yamlContract.request.
|
||||
matchers.queryParameters.find { it.key == key}
|
||||
matchers.queryParameters.find { it.key == key }
|
||||
if (!matcher) {
|
||||
return value
|
||||
}
|
||||
switch (matcher.type) {
|
||||
case YamlContract.MatchingType.equal_to:
|
||||
return new DslProperty(request.equalTo(matcher.value), value)
|
||||
case YamlContract.MatchingType.containing:
|
||||
return new DslProperty(request.containing(matcher.value), value)
|
||||
case YamlContract.MatchingType.matching:
|
||||
return new DslProperty(request.matching(matcher.value), value)
|
||||
case YamlContract.MatchingType.not_matching:
|
||||
return new DslProperty(request.notMatching(matcher.value), value)
|
||||
case YamlContract.MatchingType.equal_to_json:
|
||||
return new DslProperty(request.equalToJson(matcher.value), value)
|
||||
case YamlContract.MatchingType.equal_to_xml:
|
||||
return new DslProperty(request.equalToXml(matcher.value), value)
|
||||
case YamlContract.MatchingType.absent:
|
||||
return new DslProperty(request.absent(), null)
|
||||
default:
|
||||
throw new UnsupportedOperationException("The provided matching type [" + matcher + "] is unsupported. Use on of " + YamlContract.MatchingType.values())
|
||||
case YamlContract.MatchingType.equal_to:
|
||||
return new DslProperty(request.equalTo(matcher.value), value)
|
||||
case YamlContract.MatchingType.containing:
|
||||
return new DslProperty(request.containing(matcher.value), value)
|
||||
case YamlContract.MatchingType.matching:
|
||||
return new DslProperty(request.matching(matcher.value), value)
|
||||
case YamlContract.MatchingType.not_matching:
|
||||
return new DslProperty(request.notMatching(matcher.value), value)
|
||||
case YamlContract.MatchingType.equal_to_json:
|
||||
return new DslProperty(request.equalToJson(matcher.value), value)
|
||||
case YamlContract.MatchingType.equal_to_xml:
|
||||
return new DslProperty(request.equalToXml(matcher.value), value)
|
||||
case YamlContract.MatchingType.absent:
|
||||
return new DslProperty(request.absent(), null)
|
||||
default:
|
||||
throw new UnsupportedOperationException("The provided matching type [" + matcher + "] is unsupported. Use on of "
|
||||
+ YamlContract.MatchingType.
|
||||
values())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -591,55 +711,61 @@ class YamlToContracts {
|
||||
return new ExecutionProperty(matcher.command)
|
||||
}
|
||||
return serverValue instanceof DslProperty ?
|
||||
((DslProperty) serverValue).serverValue : serverValue
|
||||
((DslProperty) serverValue).serverValue : serverValue
|
||||
}
|
||||
|
||||
private void assertPatternMatched(Pattern pattern, value, String key) {
|
||||
boolean matches = pattern.matcher(value.toString()).matches()
|
||||
if (!matches) throw new IllegalStateException("Broken headers! A header with " +
|
||||
if (!matches) {
|
||||
throw new IllegalStateException("Broken headers! A header with "
|
||||
+
|
||||
"key [${key}] with value [${value}] is not matched by regex [${pattern.pattern()}]")
|
||||
}
|
||||
}
|
||||
|
||||
protected Pattern predefinedToPattern(YamlContract.PredefinedRegex predefinedRegex) {
|
||||
RegexPatterns patterns = new RegexPatterns()
|
||||
switch (predefinedRegex) {
|
||||
case YamlContract.PredefinedRegex.only_alpha_unicode:
|
||||
return patterns.onlyAlphaUnicode().pattern
|
||||
case YamlContract.PredefinedRegex.number:
|
||||
return patterns.number().pattern
|
||||
case YamlContract.PredefinedRegex.any_double:
|
||||
return patterns.aDouble().pattern
|
||||
case YamlContract.PredefinedRegex.any_boolean:
|
||||
return patterns.anyBoolean().pattern
|
||||
case YamlContract.PredefinedRegex.ip_address:
|
||||
return patterns.ipAddress().pattern
|
||||
case YamlContract.PredefinedRegex.hostname:
|
||||
return patterns.hostname().pattern
|
||||
case YamlContract.PredefinedRegex.email:
|
||||
return patterns.email().pattern
|
||||
case YamlContract.PredefinedRegex.url:
|
||||
return patterns.url().pattern
|
||||
case YamlContract.PredefinedRegex.uuid:
|
||||
return patterns.uuid().pattern
|
||||
case YamlContract.PredefinedRegex.iso_date:
|
||||
return patterns.isoDate().pattern
|
||||
case YamlContract.PredefinedRegex.iso_date_time:
|
||||
return patterns.isoDateTime().pattern
|
||||
case YamlContract.PredefinedRegex.iso_time:
|
||||
return patterns.isoTime().pattern
|
||||
case YamlContract.PredefinedRegex.iso_8601_with_offset:
|
||||
return patterns.iso8601WithOffset().pattern
|
||||
case YamlContract.PredefinedRegex.non_empty:
|
||||
return patterns.nonEmpty().pattern
|
||||
case YamlContract.PredefinedRegex.non_blank:
|
||||
return patterns.nonBlank().pattern
|
||||
default:
|
||||
throw new UnsupportedOperationException("The predefined regex [" + predefinedRegex + "] is unsupported. Use on of " + YamlContract.PredefinedRegex.values())
|
||||
case YamlContract.PredefinedRegex.only_alpha_unicode:
|
||||
return patterns.onlyAlphaUnicode().pattern
|
||||
case YamlContract.PredefinedRegex.number:
|
||||
return patterns.number().pattern
|
||||
case YamlContract.PredefinedRegex.any_double:
|
||||
return patterns.aDouble().pattern
|
||||
case YamlContract.PredefinedRegex.any_boolean:
|
||||
return patterns.anyBoolean().pattern
|
||||
case YamlContract.PredefinedRegex.ip_address:
|
||||
return patterns.ipAddress().pattern
|
||||
case YamlContract.PredefinedRegex.hostname:
|
||||
return patterns.hostname().pattern
|
||||
case YamlContract.PredefinedRegex.email:
|
||||
return patterns.email().pattern
|
||||
case YamlContract.PredefinedRegex.url:
|
||||
return patterns.url().pattern
|
||||
case YamlContract.PredefinedRegex.uuid:
|
||||
return patterns.uuid().pattern
|
||||
case YamlContract.PredefinedRegex.iso_date:
|
||||
return patterns.isoDate().pattern
|
||||
case YamlContract.PredefinedRegex.iso_date_time:
|
||||
return patterns.isoDateTime().pattern
|
||||
case YamlContract.PredefinedRegex.iso_time:
|
||||
return patterns.isoTime().pattern
|
||||
case YamlContract.PredefinedRegex.iso_8601_with_offset:
|
||||
return patterns.iso8601WithOffset().pattern
|
||||
case YamlContract.PredefinedRegex.non_empty:
|
||||
return patterns.nonEmpty().pattern
|
||||
case YamlContract.PredefinedRegex.non_blank:
|
||||
return patterns.nonBlank().pattern
|
||||
default:
|
||||
throw new UnsupportedOperationException("The predefined regex [" + predefinedRegex + "] is unsupported. Use on of "
|
||||
+ YamlContract.PredefinedRegex.
|
||||
values())
|
||||
}
|
||||
}
|
||||
|
||||
protected String file(String relativePath) {
|
||||
URL resource = Thread.currentThread().getContextClassLoader().getResource(relativePath)
|
||||
URL resource = Thread.currentThread().getContextClassLoader().
|
||||
getResource(relativePath)
|
||||
if (resource == null) {
|
||||
throw new IllegalStateException("File [${relativePath}] is not present")
|
||||
}
|
||||
@@ -648,7 +774,7 @@ class YamlToContracts {
|
||||
|
||||
protected static ClassLoader updatedClassLoader(File rootFolder, ClassLoader classLoader) {
|
||||
ClassLoader urlCl = URLClassLoader
|
||||
.newInstance([rootFolder.toURI().toURL()] as URL[], classLoader)
|
||||
.newInstance([rootFolder.toURI().toURL()] as URL[], classLoader)
|
||||
Thread.currentThread().setContextClassLoader(urlCl)
|
||||
return urlCl
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.dsl.wiremock
|
||||
@@ -71,9 +71,9 @@ abstract class BaseWireMockStubStrategy {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the stub side values from the object
|
||||
* @return the stub side values from the object
|
||||
*/
|
||||
protected getStubSideValue(Object object) {
|
||||
protected Object getStubSideValue(Object object) {
|
||||
return MapConverter.getStubSideValues(object)
|
||||
}
|
||||
|
||||
@@ -139,7 +139,9 @@ abstract class BaseWireMockStubStrategy {
|
||||
return it
|
||||
}
|
||||
return "${WRAPPER}${it}${WRAPPER}"
|
||||
} else if (it instanceof String && processor.containsTemplateEntry(it) &&
|
||||
}
|
||||
else if (it instanceof String && processor.containsTemplateEntry(it)
|
||||
&&
|
||||
template.escapedBody() == it) {
|
||||
return template.escapedBody()
|
||||
}
|
||||
@@ -155,7 +157,8 @@ abstract class BaseWireMockStubStrategy {
|
||||
list.each {
|
||||
if (it instanceof Map) {
|
||||
result += MapConverter.getStubSideValues(it)
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
result += parseBody(it, contentType)
|
||||
}
|
||||
}
|
||||
@@ -166,7 +169,8 @@ abstract class BaseWireMockStubStrategy {
|
||||
* For the given {@link ContentType} returns the String version of the body
|
||||
*/
|
||||
String parseBody(GString value, ContentType contentType) {
|
||||
Object processedValue = extractValue(value, contentType, { Object o -> o instanceof DslProperty ? o.clientValue : o })
|
||||
Object processedValue =
|
||||
extractValue(value, contentType, { Object o -> o instanceof DslProperty ? o.clientValue : o })
|
||||
if (processedValue instanceof GString) {
|
||||
return parseBody(processedValue.toString(), contentType)
|
||||
}
|
||||
@@ -185,7 +189,8 @@ abstract class BaseWireMockStubStrategy {
|
||||
Map convertedMap = MapConverter.transformValues(value) {
|
||||
it instanceof GString ? it.toString() : it
|
||||
} as Map
|
||||
String jsonOutput = new JSONObject(new JsonBuilder(convertedMap).toString()).toString()
|
||||
String jsonOutput = new JSONObject(new JsonBuilder(convertedMap).toString()).
|
||||
toString()
|
||||
return jsonOutput.replaceAll("\\\\\\\\\\\\", "\\\\")
|
||||
}
|
||||
return new JsonBuilder(value).toString()
|
||||
@@ -205,4 +210,4 @@ abstract class BaseWireMockStubStrategy {
|
||||
}
|
||||
return contentType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.dsl.wiremock
|
||||
|
||||
import com.github.tomakehurst.wiremock.extension.responsetemplating.ResponseTemplateTransformer
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.dsl.wiremock;
|
||||
|
||||
import java.util.List;
|
||||
@@ -5,12 +21,14 @@ import java.util.List;
|
||||
import com.github.tomakehurst.wiremock.extension.Extension;
|
||||
|
||||
/**
|
||||
* Contract that describes a list of {@link Extension} extensions
|
||||
* that should be applied to the response
|
||||
* Contract that describes a list of {@link Extension} extensions that should be applied
|
||||
* to the response.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public interface WireMockExtensions {
|
||||
|
||||
List<Extension> extensions();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.dsl.wiremock
|
||||
@@ -89,7 +89,7 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
|
||||
|
||||
@PackageScope
|
||||
RequestPattern buildClientRequestContent() {
|
||||
if(!request) {
|
||||
if (!request) {
|
||||
return null
|
||||
}
|
||||
RequestPatternBuilder requestPatternBuilder = appendMethodAndUrl()
|
||||
@@ -102,10 +102,11 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
|
||||
}
|
||||
|
||||
private RequestPatternBuilder appendMethodAndUrl() {
|
||||
if(!request.method) {
|
||||
if (!request.method) {
|
||||
return null
|
||||
}
|
||||
RequestMethod requestMethod = RequestMethod.fromString(request.method.clientValue?.toString())
|
||||
RequestMethod requestMethod = RequestMethod.
|
||||
fromString(request.method.clientValue?.toString())
|
||||
UrlPattern urlPattern = urlPattern()
|
||||
return RequestPatternBuilder.newRequestPattern(requestMethod, urlPattern)
|
||||
}
|
||||
@@ -117,20 +118,28 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
|
||||
MatchingStrategy matchingStrategy = getMatchingStrategyFromBody(request.body)
|
||||
if (contentType == ContentType.JSON) {
|
||||
def originalBody = matchingStrategy?.clientValue
|
||||
def body = JsonToJsonPathsConverter.removeMatchingJsonPaths(originalBody, request.bodyMatchers)
|
||||
JsonPaths values = JsonToJsonPathsConverter.transformToJsonPathWithStubsSideValuesAndNoArraySizeCheck(body)
|
||||
if ((values.empty && !request.bodyMatchers?.hasMatchers()) || onlySizeAssertionsArePresent(values)) {
|
||||
def body = JsonToJsonPathsConverter.
|
||||
removeMatchingJsonPaths(originalBody, request.bodyMatchers)
|
||||
JsonPaths values = JsonToJsonPathsConverter.
|
||||
transformToJsonPathWithStubsSideValuesAndNoArraySizeCheck(body)
|
||||
if ((values.empty && !request.bodyMatchers?.hasMatchers())
|
||||
||
|
||||
onlySizeAssertionsArePresent(values)) {
|
||||
requestPattern.withRequestBody(WireMock.equalToJson(JsonOutput.toJson(
|
||||
getMatchingStrategy(request.body.clientValue).clientValue),
|
||||
false, false))
|
||||
} else {
|
||||
values.findAll{ !it.assertsSize() }.each {
|
||||
requestPattern.withRequestBody(WireMock.matchingJsonPath(it.jsonPath().replace("\\\\", "\\")))
|
||||
}
|
||||
else {
|
||||
values.findAll { !it.assertsSize() }.each {
|
||||
requestPattern.withRequestBody(WireMock.
|
||||
matchingJsonPath(it.jsonPath().replace("\\\\", "\\")))
|
||||
}
|
||||
}
|
||||
request.bodyMatchers?.matchers()?.each {
|
||||
String newPath = JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(it, originalBody)
|
||||
requestPattern.withRequestBody(WireMock.matchingJsonPath(newPath.replace("\\\\", "\\")))
|
||||
String newPath = JsonToJsonPathsConverter.
|
||||
convertJsonPathAndRegexToAJsonPath(it, originalBody)
|
||||
requestPattern.withRequestBody(WireMock.
|
||||
matchingJsonPath(newPath.replace("\\\\", "\\")))
|
||||
}
|
||||
}
|
||||
else if (contentType == ContentType.XML) {
|
||||
@@ -145,10 +154,12 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
|
||||
request.bodyMatchers?.matchers()?.each {
|
||||
addWireMockStubMatchingSection(it, requestPattern, originalBody)
|
||||
}
|
||||
} else if (containsPattern(request?.body)) {
|
||||
}
|
||||
else if (containsPattern(request?.body)) {
|
||||
requestPattern.withRequestBody(
|
||||
convertToValuePattern(appendBodyRegexpMatchPattern(request.body)))
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
requestBodyGuessedFromMatchingStrategy(requestPattern)
|
||||
}
|
||||
}
|
||||
@@ -159,8 +170,8 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
|
||||
}
|
||||
|
||||
private static void addWireMockStubMatchingSection(BodyMatcher matcher,
|
||||
RequestPatternBuilder requestPattern,
|
||||
Object body) {
|
||||
RequestPatternBuilder requestPattern,
|
||||
Object body) {
|
||||
Set<MatchingType> matchingTypesUnsupportedForRequest = [NULL, COMMAND, TYPE] as Set
|
||||
if (!matcher instanceof PathBodyMatcher) {
|
||||
throw new IllegalArgumentException("Only jsonPath and XPath matchers can be processed.")
|
||||
@@ -184,7 +195,8 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
|
||||
}
|
||||
|
||||
private boolean onlySizeAssertionsArePresent(JsonPaths values) {
|
||||
return !values.empty && !request.bodyMatchers?.hasMatchers() && values.every { it.assertsSize() }
|
||||
return !values.empty && !request.bodyMatchers?.hasMatchers() && values.
|
||||
every { it.assertsSize() }
|
||||
}
|
||||
|
||||
private void appendMultipart(RequestPatternBuilder requestPattern) {
|
||||
@@ -192,13 +204,16 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
|
||||
return
|
||||
}
|
||||
if (request.multipart.clientValue instanceof Map) {
|
||||
List<StringValuePattern> multipartPatterns = (request.multipart.clientValue as Map).collect {
|
||||
(it.value instanceof NamedProperty
|
||||
? WireMock.matching(RegexPatterns.multipartFile(it.key, (it.value as NamedProperty).name.clientValue,
|
||||
(it.value as NamedProperty).value.clientValue,
|
||||
(it.value as NamedProperty).contentType?.clientValue))
|
||||
: WireMock.matching(RegexPatterns.multipartParam(it.key, it.value)) )
|
||||
}
|
||||
List<StringValuePattern> multipartPatterns = (request.multipart.clientValue as Map).
|
||||
collect {
|
||||
(it.value instanceof NamedProperty
|
||||
? WireMock.matching(RegexPatterns.
|
||||
multipartFile(it.key, (it.value as NamedProperty).name.clientValue,
|
||||
(it.value as NamedProperty).value.clientValue,
|
||||
(it.value as NamedProperty).contentType?.clientValue))
|
||||
: WireMock.
|
||||
matching(RegexPatterns.multipartParam(it.key, it.value)))
|
||||
}
|
||||
multipartPatterns.each {
|
||||
requestPattern.withRequestBody(it)
|
||||
}
|
||||
@@ -206,7 +221,7 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
|
||||
}
|
||||
|
||||
private void appendHeaders(RequestPatternBuilder requestPattern) {
|
||||
if(!request.headers) {
|
||||
if (!request.headers) {
|
||||
return
|
||||
}
|
||||
request.headers.entries.each {
|
||||
@@ -216,7 +231,7 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
|
||||
}
|
||||
|
||||
private void appendCookies(RequestPatternBuilder requestPattern) {
|
||||
if(!request.cookies) {
|
||||
if (!request.cookies) {
|
||||
return
|
||||
}
|
||||
request.cookies.entries.each {
|
||||
@@ -228,13 +243,16 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
|
||||
private UrlPattern urlPattern() {
|
||||
Object urlPath = urlPathOrUrlIfQueryPresent()
|
||||
if (urlPath) {
|
||||
if(urlPath instanceof Pattern || urlPath instanceof RegexProperty) {
|
||||
return WireMock.urlPathMatching(getStubSideValue(new RegexProperty(urlPath).pattern()) as String)
|
||||
} else {
|
||||
return WireMock.urlPathEqualTo(getStubSideValue(urlPath.toString()) as String)
|
||||
if (urlPath instanceof Pattern || urlPath instanceof RegexProperty) {
|
||||
return WireMock.urlPathMatching(
|
||||
getStubSideValue(new RegexProperty(urlPath).pattern()) as String)
|
||||
}
|
||||
else {
|
||||
return WireMock.
|
||||
urlPathEqualTo(getStubSideValue(urlPath.toString()) as String)
|
||||
}
|
||||
}
|
||||
if(!request.url) {
|
||||
if (!request.url) {
|
||||
throw new IllegalStateException("URL is required!")
|
||||
}
|
||||
Object url = getUrlIfGstring(request?.url?.clientValue)
|
||||
@@ -264,7 +282,8 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
|
||||
}) {
|
||||
String string = getStubSideValue(clientSide).toString()
|
||||
return new RegexProperty(Pattern.compile(string))
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return getStubSideValue(clientSide).toString()
|
||||
}
|
||||
}
|
||||
@@ -282,29 +301,31 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
|
||||
@TypeChecked(TypeCheckingMode.SKIP)
|
||||
private ContentPattern convertToValuePattern(Object object) {
|
||||
switch (object) {
|
||||
case Pattern:
|
||||
case RegexProperty:
|
||||
return WireMock.matching(new RegexProperty(object).pattern())
|
||||
case OptionalProperty:
|
||||
OptionalProperty value = object as OptionalProperty
|
||||
return WireMock.matching(value.optionalPattern())
|
||||
case MatchingStrategy:
|
||||
MatchingStrategy value = object as MatchingStrategy
|
||||
switch (value.type) {
|
||||
case MatchingStrategy.Type.NOT_MATCHING:
|
||||
return WireMock.notMatching(value.clientValue.toString())
|
||||
case MatchingStrategy.Type.ABSENT:
|
||||
return WireMock.absent()
|
||||
default:
|
||||
try {
|
||||
return WireMock."${value.type.name}"(clientBody(value.clientValue, contentType))
|
||||
} catch (Throwable t) {
|
||||
log.error("Exception occurred while trying to call WireMock.${value.type.name}(${value.clientValue})", t)
|
||||
throw t
|
||||
}
|
||||
}
|
||||
case Pattern:
|
||||
case RegexProperty:
|
||||
return WireMock.matching(new RegexProperty(object).pattern())
|
||||
case OptionalProperty:
|
||||
OptionalProperty value = object as OptionalProperty
|
||||
return WireMock.matching(value.optionalPattern())
|
||||
case MatchingStrategy:
|
||||
MatchingStrategy value = object as MatchingStrategy
|
||||
switch (value.type) {
|
||||
case MatchingStrategy.Type.NOT_MATCHING:
|
||||
return WireMock.notMatching(value.clientValue.toString())
|
||||
case MatchingStrategy.Type.ABSENT:
|
||||
return WireMock.absent()
|
||||
default:
|
||||
return WireMock.equalTo(object.toString())
|
||||
try {
|
||||
return WireMock."${value.type.name}"(
|
||||
clientBody(value.clientValue, contentType))
|
||||
}
|
||||
catch (Throwable t) {
|
||||
log.error("Exception occurred while trying to call WireMock.${value.type.name}(${value.clientValue})", t)
|
||||
throw t
|
||||
}
|
||||
}
|
||||
default:
|
||||
return WireMock.equalTo(object.toString())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,9 +334,11 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
|
||||
if (bodyValue instanceof Map) {
|
||||
// [a:3, b:4] == "a=3&b=4"
|
||||
return ((Map) bodyValue).collect {
|
||||
StringEscapeUtils.unescapeJavaScript(it.key.toString() + "=" + it.value)
|
||||
StringEscapeUtils.
|
||||
unescapeJavaScript(it.key.toString() + "=" + it.value)
|
||||
}.join("&")
|
||||
} else if (bodyValue instanceof List) {
|
||||
}
|
||||
else if (bodyValue instanceof List) {
|
||||
// ["a=3", "b=4"] == "a=3&b=4"
|
||||
return ((List) bodyValue).collect {
|
||||
StringEscapeUtils.unescapeJavaScript(it.toString())
|
||||
@@ -329,7 +352,7 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
|
||||
}
|
||||
|
||||
private MatchingStrategy getMatchingStrategyFromBody(Body body) {
|
||||
if(!body) {
|
||||
if (!body) {
|
||||
return null
|
||||
}
|
||||
return getMatchingStrategy(body.clientValue)
|
||||
@@ -338,6 +361,7 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
|
||||
private MatchingStrategy getMatchingStrategy(MatchingStrategy matchingStrategy) {
|
||||
return getMatchingStrategyIncludingContentType(matchingStrategy)
|
||||
}
|
||||
|
||||
private MatchingStrategy getMatchingStrategy(GString gString) {
|
||||
if (!gString) {
|
||||
return new MatchingStrategy("", MatchingStrategy.Type.EQUAL_TO)
|
||||
@@ -369,7 +393,8 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
|
||||
private MatchingStrategy getMatchingStrategyIncludingContentType(MatchingStrategy matchingStrategy) {
|
||||
MatchingStrategy.Type type = matchingStrategy.type
|
||||
Object value = matchingStrategy.clientValue
|
||||
ContentType contentType = ContentUtils.recognizeContentTypeFromMatchingStrategy(type)
|
||||
ContentType contentType = ContentUtils.
|
||||
recognizeContentTypeFromMatchingStrategy(type)
|
||||
if (contentType == ContentType.UNKNOWN && type == MatchingStrategy.Type.EQUAL_TO) {
|
||||
contentType = ContentUtils.recognizeContentTypeFromContent(value)
|
||||
type = getEqualsTypeFromContentType(contentType)
|
||||
@@ -379,12 +404,14 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
|
||||
|
||||
private MatchingStrategy appendBodyRegexpMatchPattern(Object value, ContentType contentType) {
|
||||
switch (contentType) {
|
||||
case ContentType.JSON:
|
||||
return new MatchingStrategy(buildJSONRegexpMatch(value), MatchingStrategy.Type.MATCHING)
|
||||
case ContentType.UNKNOWN:
|
||||
return new MatchingStrategy(buildGStringRegexpForStubSide(value), MatchingStrategy.Type.MATCHING)
|
||||
case ContentType.XML:
|
||||
throw new IllegalStateException("XML pattern matching is not implemented yet")
|
||||
case ContentType.JSON:
|
||||
return new MatchingStrategy(
|
||||
buildJSONRegexpMatch(value), MatchingStrategy.Type.MATCHING)
|
||||
case ContentType.UNKNOWN:
|
||||
return new MatchingStrategy(
|
||||
buildGStringRegexpForStubSide(value), MatchingStrategy.Type.MATCHING)
|
||||
case ContentType.XML:
|
||||
throw new IllegalStateException("XML pattern matching is not implemented yet")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.dsl.wiremock
|
||||
@@ -55,7 +55,7 @@ class WireMockResponseStubStrategy extends BaseWireMockStubStrategy {
|
||||
|
||||
@PackageScope
|
||||
ResponseDefinition buildClientResponseContent() {
|
||||
if(!response) {
|
||||
if (!response) {
|
||||
return null
|
||||
}
|
||||
ResponseDefinitionBuilder builder = new ResponseDefinitionBuilder()
|
||||
@@ -68,12 +68,13 @@ class WireMockResponseStubStrategy extends BaseWireMockStubStrategy {
|
||||
}
|
||||
|
||||
private String[] responseTransformerNames() {
|
||||
List<WireMockExtensions> wireMockExtensions = SpringFactoriesLoader.loadFactories(WireMockExtensions, null)
|
||||
List<WireMockExtensions> wireMockExtensions = SpringFactoriesLoader.
|
||||
loadFactories(WireMockExtensions, null)
|
||||
if (wireMockExtensions) {
|
||||
return ((List<Extension>) wireMockExtensions
|
||||
.collect { WireMockExtensions extension -> extension.extensions() }
|
||||
.collect { WireMockExtensions extension -> extension.extensions() }
|
||||
.flatten())
|
||||
.collect { Extension e -> e.getName()} as String[]
|
||||
.collect { Extension e -> e.getName() } as String[]
|
||||
}
|
||||
return [new DefaultResponseTransformer().getName()] as String[]
|
||||
}
|
||||
@@ -81,7 +82,8 @@ class WireMockResponseStubStrategy extends BaseWireMockStubStrategy {
|
||||
private void appendHeaders(ResponseDefinitionBuilder builder) {
|
||||
if (response.headers) {
|
||||
builder.withHeaders(new HttpHeaders(response.headers.entries?.collect {
|
||||
new HttpHeader(it.name, MapConverter.getStubSideValues(it.clientValue).toString())
|
||||
new HttpHeader(it.name, MapConverter.getStubSideValues(it.clientValue).
|
||||
toString())
|
||||
}))
|
||||
}
|
||||
}
|
||||
@@ -92,9 +94,11 @@ class WireMockResponseStubStrategy extends BaseWireMockStubStrategy {
|
||||
ContentType contentType = evaluateContentType(response.headers, body)
|
||||
if (body instanceof byte[]) {
|
||||
builder.withBody(body)
|
||||
} else if (body instanceof FromFileProperty && body.isByte()) {
|
||||
}
|
||||
else if (body instanceof FromFileProperty && body.isByte()) {
|
||||
builder.withBody(body.asBytes())
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
builder.withBody(parseBody(body, contentType))
|
||||
}
|
||||
}
|
||||
@@ -107,5 +111,4 @@ class WireMockResponseStubStrategy extends BaseWireMockStubStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.dsl.wiremock;
|
||||
|
||||
import com.github.tomakehurst.wiremock.stubbing.StubMapping;
|
||||
@@ -5,8 +21,14 @@ import com.github.tomakehurst.wiremock.stubbing.StubMapping;
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
public class WireMockStubMapping {
|
||||
public final class WireMockStubMapping {
|
||||
|
||||
private WireMockStubMapping() {
|
||||
throw new IllegalStateException("Can't instantiate a utility class");
|
||||
}
|
||||
|
||||
public static StubMapping buildFrom(String mappingDefinition) {
|
||||
return StubMapping.buildFrom(mappingDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.dsl.wiremock
|
||||
@@ -22,6 +22,7 @@ import com.github.tomakehurst.wiremock.stubbing.StubMapping
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.verifier.file.ContractMetadata
|
||||
|
||||
/**
|
||||
* Converts a {@link ContractMetadata} into a WireMock stub
|
||||
*
|
||||
@@ -54,7 +55,8 @@ class WireMockStubStrategy {
|
||||
StubMapping stubMapping = new StubMapping()
|
||||
|
||||
RequestPattern request = wireMockRequestStubStrategy.buildClientRequestContent()
|
||||
ResponseDefinition response = wireMockResponseStubStrategy.buildClientResponseContent()
|
||||
ResponseDefinition response = wireMockResponseStubStrategy.
|
||||
buildClientResponseContent()
|
||||
if (priority) {
|
||||
stubMapping.priority = priority
|
||||
}
|
||||
@@ -79,4 +81,4 @@ class WireMockStubStrategy {
|
||||
}
|
||||
return StubMapping.buildJsonStringFor(stubMapping)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2018-2019 the original author or authors.
|
||||
* Copyright 2018-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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.dsl.wiremock
|
||||
@@ -35,8 +35,8 @@ class XPathBodyMatcherToWireMockValuePatternConverter {
|
||||
|
||||
static StringValuePattern mapToPattern(MatchingType type, String value) {
|
||||
switch (type) {
|
||||
case EQUALITY: return WireMock.equalTo(value)
|
||||
default: return WireMock.matching(value)
|
||||
case EQUALITY: return WireMock.equalTo(value)
|
||||
default: return WireMock.matching(value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.file
|
||||
@@ -32,6 +32,7 @@ import org.springframework.cloud.contract.spec.ContractConverter
|
||||
import org.springframework.cloud.contract.verifier.converter.YamlContractConverter
|
||||
import org.springframework.cloud.contract.verifier.util.ContractVerifierDslConverter
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader
|
||||
|
||||
/**
|
||||
* Scans the provided file path for the DSLs. There's a possibility to provide
|
||||
* inclusion and exclusion filters.
|
||||
@@ -46,10 +47,12 @@ class ContractFileScanner {
|
||||
|
||||
private static final String OS_NAME = System.getProperty("os.name")
|
||||
private static final String OS_NAME_WINDOWS_PREFIX = "Windows"
|
||||
protected static final boolean IS_OS_WINDOWS = getOSMatchesName(OS_NAME_WINDOWS_PREFIX)
|
||||
protected static final boolean IS_OS_WINDOWS =
|
||||
getOSMatchesName(OS_NAME_WINDOWS_PREFIX)
|
||||
|
||||
private static final String MATCH_PREFIX = "glob:"
|
||||
private static final Pattern SCENARIO_STEP_FILENAME_PATTERN = Pattern.compile("[0-9]+_.*")
|
||||
private static final Pattern SCENARIO_STEP_FILENAME_PATTERN = Pattern.
|
||||
compile("[0-9]+_.*")
|
||||
private final File baseDir
|
||||
private final Set<PathMatcher> excludeMatchers
|
||||
private final Set<PathMatcher> ignoreMatchers
|
||||
@@ -57,8 +60,8 @@ class ContractFileScanner {
|
||||
private final String includeMatcher
|
||||
|
||||
ContractFileScanner(File baseDir, Set<String> excluded, Set<String> ignored,
|
||||
Set<String> included = [],
|
||||
String includeMatcher = "") {
|
||||
Set<String> included = [],
|
||||
String includeMatcher = "") {
|
||||
this.baseDir = baseDir
|
||||
this.excludeMatchers = processPatterns(excluded ?: [] as Set<String>)
|
||||
this.ignoreMatchers = processPatterns(ignored ?: [] as Set<String>)
|
||||
@@ -81,7 +84,7 @@ class ContractFileScanner {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns for a map of paths for which a list of matching contracts has been found
|
||||
* @return for a map of paths for which a list of matching contracts has been found
|
||||
*/
|
||||
ListMultimap<Path, ContractMetadata> findContracts() {
|
||||
ListMultimap<Path, ContractMetadata> result = ArrayListMultimap.create()
|
||||
@@ -108,20 +111,25 @@ class ContractFileScanner {
|
||||
boolean excluded = matchesPattern(file, excludeMatchers)
|
||||
if (!excluded) {
|
||||
boolean contractFile = isContractFile(file)
|
||||
boolean included = includeMatcher ? file.absolutePath.matches(includeMatcher) : true
|
||||
included = includeMatchers ? matchesPattern(file, includeMatchers) : included
|
||||
boolean included = includeMatcher ? file.absolutePath.
|
||||
matches(includeMatcher) : true
|
||||
included = includeMatchers ?
|
||||
matchesPattern(file, includeMatchers) : included
|
||||
if (contractFile && included) {
|
||||
addContractToTestGeneration(result, files, file, i, ContractVerifierDslConverter.convertAsCollection(baseDir, file))
|
||||
addContractToTestGeneration(result, files, file, i, ContractVerifierDslConverter.
|
||||
convertAsCollection(baseDir, file))
|
||||
}
|
||||
if (!contractFile && included) {
|
||||
addContractToTestGeneration(converters, result, files, file, i)
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
appendRecursively(file, result)
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("File [$file] is ignored. Is a contract file? [$contractFile]. Should be included by pattern? [$included]")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("File [$file] is ignored. Should be excluded? [$excluded]")
|
||||
}
|
||||
@@ -140,7 +148,7 @@ class ContractFileScanner {
|
||||
}
|
||||
|
||||
private void addContractToTestGeneration(List<ContractConverter> converters, ListMultimap<Path, ContractMetadata> result,
|
||||
File[] files, File file, int index) {
|
||||
File[] files, File file, int index) {
|
||||
boolean converted = false
|
||||
if (!file.isDirectory()) {
|
||||
for (ContractConverter converter : converters) {
|
||||
@@ -167,20 +175,22 @@ class ContractFileScanner {
|
||||
}
|
||||
try {
|
||||
return converter.convertFrom(file)
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException("Failed to convert file [" + file + "]", e)
|
||||
}
|
||||
}
|
||||
|
||||
private void addContractToTestGeneration(ListMultimap<Path, ContractMetadata> result, File[] files, File file,
|
||||
int index, Collection<Contract> convertedContract) {
|
||||
int index, Collection<Contract> convertedContract) {
|
||||
Path path = file.toPath()
|
||||
Integer order = null
|
||||
if (hasScenarioFilenamePattern(path)) {
|
||||
order = index
|
||||
}
|
||||
Path parent = file.parentFile.toPath()
|
||||
ContractMetadata metadata = new ContractMetadata(path, matchesPattern(file, ignoreMatchers),
|
||||
ContractMetadata metadata = new ContractMetadata(path,
|
||||
matchesPattern(file, ignoreMatchers),
|
||||
files.size(), order, convertedContract)
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Creating a contract entry for path [" + path + "] and metadata [" + metadata + "]")
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.file
|
||||
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
|
||||
/**
|
||||
* Scans the provided file path for the DSLs. There's a possibility to provide
|
||||
* inclusion and exclusion filters.
|
||||
@@ -62,10 +63,10 @@ class ContractFileScannerBuilder {
|
||||
|
||||
ContractFileScanner build() {
|
||||
return new ContractFileScanner(this.baseDir,
|
||||
this.excluded,
|
||||
this.ignored,
|
||||
this.included,
|
||||
this.includeMatcher)
|
||||
this.excluded,
|
||||
this.ignored,
|
||||
this.included,
|
||||
this.includeMatcher)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,28 +1,29 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.file
|
||||
|
||||
import java.nio.file.Path
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.ToString
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.verifier.util.ContractVerifierDslConverter
|
||||
|
||||
import java.nio.file.Path
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
|
||||
/**
|
||||
* Contains metadata for a particular file with a DSL
|
||||
*
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.template
|
||||
|
||||
import java.util.regex.Matcher
|
||||
@@ -23,12 +39,16 @@ import org.springframework.cloud.contract.verifier.builder.handlebars.Handlebars
|
||||
@CompileStatic
|
||||
class HandlebarsTemplateProcessor implements TemplateProcessor, ContractTemplate {
|
||||
|
||||
private static final Pattern ESCAPED_LEGACY_JSON_PATH_PATTERN = Pattern.compile("^.*\\{\\{\\{jsonpath this '(.*)'}}}.*\$")
|
||||
private static final Pattern ESCAPED_JSON_PATH_PATTERN = Pattern.compile("^.*\\{\\{\\{jsonPath request.body '(.*)'}}}.*\$")
|
||||
private static final Pattern LEGACY_JSON_PATH_PATTERN = Pattern.compile("^.*\\{\\{jsonpath this '(.*)'}}.*\$")
|
||||
private static final Pattern JSON_PATH_PATTERN = Pattern.compile("^.*\\{\\{jsonPath request.body '(.*)'}}.*\$")
|
||||
private static final Pattern ESCAPED_LEGACY_JSON_PATH_PATTERN = Pattern.
|
||||
compile("^.*\\{\\{\\{jsonpath this '(.*)'}}}.*\$")
|
||||
private static final Pattern ESCAPED_JSON_PATH_PATTERN = Pattern.
|
||||
compile("^.*\\{\\{\\{jsonPath request.body '(.*)'}}}.*\$")
|
||||
private static final Pattern LEGACY_JSON_PATH_PATTERN = Pattern.
|
||||
compile("^.*\\{\\{jsonpath this '(.*)'}}.*\$")
|
||||
private static final Pattern JSON_PATH_PATTERN = Pattern.
|
||||
compile("^.*\\{\\{jsonPath request.body '(.*)'}}.*\$")
|
||||
private static final List<Pattern> PATTERNS = [ESCAPED_LEGACY_JSON_PATH_PATTERN,
|
||||
ESCAPED_JSON_PATH_PATTERN, LEGACY_JSON_PATH_PATTERN, JSON_PATH_PATTERN]
|
||||
ESCAPED_JSON_PATH_PATTERN, LEGACY_JSON_PATH_PATTERN, JSON_PATH_PATTERN]
|
||||
private static final String LEGACY_JSON_PATH_TEMPLATE_NAME = HandlebarsJsonPathHelper.NAME
|
||||
private static final String JSON_PATH_TEMPLATE_NAME = WireMockHelpers.jsonPath.name()
|
||||
|
||||
@@ -36,7 +56,8 @@ class HandlebarsTemplateProcessor implements TemplateProcessor, ContractTemplate
|
||||
|
||||
@Override
|
||||
String transform(Request request, String testContents) {
|
||||
TestSideRequestTemplateModel templateModel = TestSideRequestTemplateModel.from(request)
|
||||
TestSideRequestTemplateModel templateModel = TestSideRequestTemplateModel.
|
||||
from(request)
|
||||
Map<String, TestSideRequestTemplateModel> model = [(HandlebarsJsonPathHelper.REQUEST_MODEL_NAME): templateModel]
|
||||
Template bodyTemplate = uncheckedCompileTemplate(testContents)
|
||||
return templatedResponseBody(model, bodyTemplate)
|
||||
@@ -44,16 +65,18 @@ class HandlebarsTemplateProcessor implements TemplateProcessor, ContractTemplate
|
||||
|
||||
@Override
|
||||
boolean containsTemplateEntry(String line) {
|
||||
return (line.contains(contractTemplate.openingTemplate()) && line.contains(contractTemplate.closingTemplate())) ||
|
||||
(line.contains(contractTemplate.escapedOpeningTemplate()) && line.contains(contractTemplate.escapedClosingTemplate()))
|
||||
return (line.contains(contractTemplate.openingTemplate())
|
||||
&& line.contains(contractTemplate.closingTemplate())) ||
|
||||
(line.contains(contractTemplate.escapedOpeningTemplate()) &&
|
||||
line.contains(contractTemplate.escapedClosingTemplate()))
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean containsJsonPathTemplateEntry(String line) {
|
||||
return line.contains(openingTemplate() + LEGACY_JSON_PATH_TEMPLATE_NAME) ||
|
||||
line.contains(openingTemplate() + JSON_PATH_TEMPLATE_NAME) ||
|
||||
line.contains(escapedOpeningTemplate() + LEGACY_JSON_PATH_TEMPLATE_NAME) ||
|
||||
line.contains(escapedOpeningTemplate() + JSON_PATH_TEMPLATE_NAME)
|
||||
line.contains(openingTemplate() + JSON_PATH_TEMPLATE_NAME) ||
|
||||
line.contains(escapedOpeningTemplate() + LEGACY_JSON_PATH_TEMPLATE_NAME) ||
|
||||
line.contains(escapedOpeningTemplate() + JSON_PATH_TEMPLATE_NAME)
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -70,14 +93,15 @@ class HandlebarsTemplateProcessor implements TemplateProcessor, ContractTemplate
|
||||
return ""
|
||||
}
|
||||
|
||||
private String templatedResponseBody(Map< String, TestSideRequestTemplateModel> model, Template bodyTemplate) {
|
||||
private String templatedResponseBody(Map<String, TestSideRequestTemplateModel> model, Template bodyTemplate) {
|
||||
return uncheckedApplyTemplate(bodyTemplate, model)
|
||||
}
|
||||
|
||||
private String uncheckedApplyTemplate(Template template, Object context) {
|
||||
try {
|
||||
return template.apply(context)
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e)
|
||||
}
|
||||
}
|
||||
@@ -85,15 +109,18 @@ class HandlebarsTemplateProcessor implements TemplateProcessor, ContractTemplate
|
||||
private Template uncheckedCompileTemplate(String content) {
|
||||
try {
|
||||
Handlebars handlebars = new Handlebars()
|
||||
handlebars.registerHelper(HandlebarsJsonPathHelper.NAME, new HandlebarsJsonPathHelper())
|
||||
handlebars.registerHelper(WireMockHelpers.jsonPath.name(), new HandlebarsJsonPathHelper())
|
||||
handlebars.
|
||||
registerHelper(HandlebarsJsonPathHelper.NAME, new HandlebarsJsonPathHelper())
|
||||
handlebars.registerHelper(WireMockHelpers.jsonPath.
|
||||
name(), new HandlebarsJsonPathHelper())
|
||||
WireMockHelpers.values()
|
||||
.findAll { it != WireMockHelpers.jsonPath}
|
||||
.each { WireMockHelpers helper ->
|
||||
.findAll { it != WireMockHelpers.jsonPath }
|
||||
.each { WireMockHelpers helper ->
|
||||
handlebars.registerHelper(helper.name(), helper)
|
||||
}
|
||||
return handlebars.compileInline(content)
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.template
|
||||
|
||||
import org.springframework.cloud.contract.spec.internal.Request
|
||||
@@ -19,24 +35,24 @@ interface TemplateProcessor {
|
||||
String transform(Request request, String testContents)
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the current line contains template related entry. E.g. for Handlebars
|
||||
* @return {@code true} if the current line contains template related entry. E.g. for Handlebars
|
||||
* if a line contains {{{...}}} then it's considered to contain template related entry
|
||||
*/
|
||||
boolean containsTemplateEntry(String line)
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the current line contains template related entry for json path processing.
|
||||
* @return {@code true} if the current line contains template related entry for json path processing.
|
||||
* E.g. for Handlebars if a line contains {{{jsonpath ...}}} or {{{jsonPath ...}}} then
|
||||
* it's considered to contain template related entry for json path processing
|
||||
*/
|
||||
boolean containsJsonPathTemplateEntry(String line)
|
||||
|
||||
/**
|
||||
* Returns the json path entry from the current line that contains template related entry for json path processing.
|
||||
* @return the json path entry from the current line that contains template related entry for json path processing.
|
||||
* E.g. for Handlebars if a line contains {{{jsonpath this '$.a.b.c'}}} or {{{jsonPath request.body ...}}} then
|
||||
* the te method would return {@code $.a.b.c}. Returns empty string if there's no matching
|
||||
* json path entry
|
||||
*/
|
||||
String jsonPathFromTemplateEntry(String line)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.util
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.util
|
||||
@@ -27,6 +27,7 @@ import org.springframework.cloud.contract.spec.internal.DslProperty
|
||||
import org.springframework.cloud.contract.spec.internal.RegexProperty
|
||||
|
||||
import static ContentUtils.extractValue
|
||||
|
||||
/**
|
||||
* Class that constructs a String from a body. The body can be a GString
|
||||
* or a map.
|
||||
@@ -41,7 +42,7 @@ class BodyExtractor {
|
||||
private BodyExtractor() {}
|
||||
|
||||
/**
|
||||
* Returns the string representation of the body for the server side.
|
||||
* @return the string representation of the body for the server side.
|
||||
* That means that all the interpolations etc. will be resolved for the
|
||||
* server side.
|
||||
*/
|
||||
@@ -53,7 +54,7 @@ class BodyExtractor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string representation of the body for the client side.
|
||||
* @return the string representation of the body for the client side.
|
||||
* That means that all the interpolations etc. will be resolved for the
|
||||
* client side.
|
||||
*/
|
||||
@@ -70,9 +71,13 @@ class BodyExtractor {
|
||||
|
||||
static Object extractServerValueFromBody(bodyValue) {
|
||||
if (bodyValue instanceof GString) {
|
||||
bodyValue = extractValue(bodyValue, { DslProperty dslProperty -> dslProperty.serverValue })
|
||||
} else {
|
||||
bodyValue = MapConverter.transformValues(bodyValue, { it instanceof DslProperty ? it.serverValue : it })
|
||||
bodyValue =
|
||||
extractValue(bodyValue, { DslProperty dslProperty -> dslProperty.serverValue })
|
||||
}
|
||||
else {
|
||||
bodyValue = MapConverter.transformValues(bodyValue, {
|
||||
it instanceof DslProperty ? it.serverValue : it
|
||||
})
|
||||
}
|
||||
return bodyValue
|
||||
}
|
||||
@@ -80,9 +85,11 @@ class BodyExtractor {
|
||||
static Object extractClientValueFromBody(bodyValue) {
|
||||
if (bodyValue instanceof GString) {
|
||||
return extractValue(bodyValue, { DslProperty dslProperty -> dslProperty.clientValue })
|
||||
} else if (bodyValue instanceof DslProperty) {
|
||||
}
|
||||
else if (bodyValue instanceof DslProperty) {
|
||||
return extractClientValueFromBody(bodyValue.clientValue)
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return MapConverter.transformValues(bodyValue, {
|
||||
Object prop = it instanceof DslProperty ? it.clientValue : it
|
||||
if (prop instanceof CanBeDynamic || prop instanceof Pattern) {
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.util
|
||||
@@ -33,4 +33,4 @@ enum ContentType {
|
||||
ContentType(String mimeType) {
|
||||
this.mimeType = mimeType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.util
|
||||
@@ -50,8 +50,8 @@ import static org.springframework.cloud.contract.verifier.util.ContentType.UNKNO
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @author Konstantin Shevchuk
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@CompileStatic
|
||||
class ContentUtils {
|
||||
@@ -66,9 +66,12 @@ class ContentUtils {
|
||||
it instanceof DslProperty ? it.serverValue : it
|
||||
}
|
||||
|
||||
private static final Pattern TEMPORARY_PATTERN_HOLDER = Pattern.compile('.*REGEXP>>(.*)<<.*')
|
||||
private static final Pattern TEMPORARY_EXECUTION_PATTERN_HOLDER = Pattern.compile('["]?EXECUTION>>(.*)<<["]?')
|
||||
private static final Pattern TEMPORARY_OPTIONAL_PATTERN_HOLDER = Pattern.compile('OPTIONAL>>(.*)<<')
|
||||
private static final Pattern TEMPORARY_PATTERN_HOLDER = Pattern.
|
||||
compile('.*REGEXP>>(.*)<<.*')
|
||||
private static final Pattern TEMPORARY_EXECUTION_PATTERN_HOLDER = Pattern.
|
||||
compile('["]?EXECUTION>>(.*)<<["]?')
|
||||
private static final Pattern TEMPORARY_OPTIONAL_PATTERN_HOLDER = Pattern.
|
||||
compile('OPTIONAL>>(.*)<<')
|
||||
private static final String JSON_VALUE_PATTERN_FOR_REGEX = 'REGEXP>>%s<<'
|
||||
private static final String JSON_VALUE_PATTERN_FOR_OPTIONAL = 'OPTIONAL>>%s<<'
|
||||
private static final String JSON_VALUE_PATTERN_FOR_EXECUTION = '"EXECUTION>>%s<<"'
|
||||
@@ -86,7 +89,7 @@ class ContentUtils {
|
||||
* @return JSON structure with replaced client / server side parts
|
||||
*/
|
||||
static Object extractValue(GString bodyAsValue, ContentType contentType, Closure valueProvider) {
|
||||
if (bodyAsValue.isEmpty()){
|
||||
if (bodyAsValue.isEmpty()) {
|
||||
return bodyAsValue
|
||||
}
|
||||
if (contentType == ContentType.TEXT || contentType == ContentType.FORM) {
|
||||
@@ -102,12 +105,14 @@ class ContentUtils {
|
||||
try {
|
||||
log.trace("No content type provided so trying to parse as JSON")
|
||||
return extractValueForJSON(bodyAsValue, valueProvider)
|
||||
} catch(JsonException e) {
|
||||
}
|
||||
catch (JsonException e) {
|
||||
// Not a JSON format
|
||||
log.trace("Failed to parse as JSON - trying to parse as XML", e)
|
||||
try {
|
||||
return extractValueForXML(bodyAsValue, valueProvider)
|
||||
} catch (Exception exception) {
|
||||
}
|
||||
catch (Exception exception) {
|
||||
log.trace("No content type provided and failed to parse as XML - returning the value back to the user", exception)
|
||||
return extractValueForGString(bodyAsValue, valueProvider)
|
||||
}
|
||||
@@ -118,11 +123,14 @@ class ContentUtils {
|
||||
try {
|
||||
extractValueForJSON(bodyAsValue, GET_STUB_SIDE)
|
||||
return JSON
|
||||
} catch(JsonException e) {
|
||||
}
|
||||
catch (JsonException e) {
|
||||
try {
|
||||
getXmlSlurperWithDefaultErrorHandler().parseText(extractValueForXML(bodyAsValue, GET_STUB_SIDE).toString())
|
||||
getXmlSlurperWithDefaultErrorHandler()
|
||||
.parseText(extractValueForXML(bodyAsValue, GET_STUB_SIDE).toString())
|
||||
return ContentType.XML
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
extractValueForGString(bodyAsValue, GET_STUB_SIDE)
|
||||
return UNKNOWN
|
||||
}
|
||||
@@ -133,11 +141,14 @@ class ContentUtils {
|
||||
try {
|
||||
new JsonSlurper().parseText(bodyAsValue)
|
||||
return JSON
|
||||
} catch(JsonException e) {
|
||||
}
|
||||
catch (JsonException e) {
|
||||
try {
|
||||
getXmlSlurperWithDefaultErrorHandler().parseText(bodyAsValue)
|
||||
getXmlSlurperWithDefaultErrorHandler()
|
||||
.parseText(bodyAsValue)
|
||||
return ContentType.XML
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
return UNKNOWN
|
||||
}
|
||||
}
|
||||
@@ -146,15 +157,20 @@ class ContentUtils {
|
||||
static ContentType getClientContentType(Object bodyAsValue) {
|
||||
if (bodyAsValue instanceof GString) {
|
||||
return getClientContentType((GString) bodyAsValue)
|
||||
} else if (bodyAsValue instanceof String) {
|
||||
}
|
||||
else if (bodyAsValue instanceof String) {
|
||||
return getClientContentType((String) bodyAsValue)
|
||||
} else if (bodyAsValue instanceof Map) {
|
||||
}
|
||||
else if (bodyAsValue instanceof Map) {
|
||||
return getClientContentType((Map) bodyAsValue)
|
||||
} else if (bodyAsValue instanceof List) {
|
||||
}
|
||||
else if (bodyAsValue instanceof List) {
|
||||
return getClientContentType((List) bodyAsValue)
|
||||
} else if (bodyAsValue instanceof MatchingStrategy) {
|
||||
}
|
||||
else if (bodyAsValue instanceof MatchingStrategy) {
|
||||
return UNKNOWN
|
||||
} else if (bodyAsValue instanceof FromFileProperty) {
|
||||
}
|
||||
else if (bodyAsValue instanceof FromFileProperty) {
|
||||
return UNKNOWN
|
||||
}
|
||||
return tryToGuessContentType(bodyAsValue)
|
||||
@@ -187,7 +203,8 @@ class ContentUtils {
|
||||
try {
|
||||
JsonOutput.toJson(bodyAsValue)
|
||||
return JSON
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
return UNKNOWN
|
||||
}
|
||||
}
|
||||
@@ -196,14 +213,17 @@ class ContentUtils {
|
||||
try {
|
||||
JsonOutput.toJson(bodyAsValue)
|
||||
return JSON
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
return UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
static GStringImpl extractValueForGString(GString bodyAsValue, Closure valueProvider) {
|
||||
return new GStringImpl(
|
||||
bodyAsValue.values.collect { it instanceof DslProperty ? valueProvider(it) : it } as String[],
|
||||
bodyAsValue.values.collect {
|
||||
it instanceof DslProperty ? valueProvider(it) : it
|
||||
} as String[],
|
||||
bodyAsValue.strings.clone() as String[]
|
||||
)
|
||||
}
|
||||
@@ -222,31 +242,38 @@ class ContentUtils {
|
||||
|
||||
private static Object extractValueForJSON(GString bodyAsValue, Closure valueProvider) {
|
||||
GString transformedString = new GStringImpl(
|
||||
bodyAsValue.values.collect { transformJSONStringValue(it, valueProvider) } as String[],
|
||||
bodyAsValue.values.
|
||||
collect { transformJSONStringValue(it, valueProvider) } as String[],
|
||||
bodyAsValue.strings.clone() as String[]
|
||||
)
|
||||
def parsedJson = new JsonSlurper().parseText(transformedString.toString().replace('\\', '\\\\'))
|
||||
def parsedJson = new JsonSlurper().
|
||||
parseText(transformedString.toString().replace('\\', '\\\\'))
|
||||
return convertAllTemporaryRegexPlaceholdersBackToPatterns(parsedJson)
|
||||
}
|
||||
|
||||
private static GStringImpl extractValueForXML(GString bodyAsValue, Closure valueProvider) {
|
||||
GStringImpl impl = new GStringImpl(
|
||||
bodyAsValue.values.collect { transformXMLStringValue(it, valueProvider) } as String[],
|
||||
bodyAsValue.values.
|
||||
collect { transformXMLStringValue(it, valueProvider) } as String[],
|
||||
bodyAsValue.strings.clone() as String[]
|
||||
)
|
||||
// try to convert it to XML
|
||||
getXmlSlurperWithDefaultErrorHandler().parseText(impl.toString())
|
||||
getXmlSlurperWithDefaultErrorHandler()
|
||||
.parseText(impl.toString())
|
||||
return impl
|
||||
}
|
||||
|
||||
protected static Object transformJSONStringValue(Object obj, Closure valueProvider) {
|
||||
if (obj instanceof DslProperty) {
|
||||
return transformJSONStringValue((DslProperty) obj, valueProvider)
|
||||
} else if (obj instanceof Pattern) {
|
||||
}
|
||||
else if (obj instanceof Pattern) {
|
||||
return transformJSONStringValue((Pattern) obj, valueProvider)
|
||||
} else if (obj instanceof OptionalProperty) {
|
||||
}
|
||||
else if (obj instanceof OptionalProperty) {
|
||||
return transformJSONStringValue((OptionalProperty) obj, valueProvider)
|
||||
} else if (obj instanceof ExecutionProperty) {
|
||||
}
|
||||
else if (obj instanceof ExecutionProperty) {
|
||||
return transformJSONStringValue((ExecutionProperty) obj, valueProvider)
|
||||
}
|
||||
return obj
|
||||
@@ -329,7 +356,8 @@ class ContentUtils {
|
||||
if (matcher.matches()) {
|
||||
return Pattern.compile(patternFromMatchingGroup(matcher))
|
||||
}
|
||||
Matcher executionMatcher = TEMPORARY_EXECUTION_PATTERN_HOLDER.matcher(string.trim())
|
||||
Matcher executionMatcher = TEMPORARY_EXECUTION_PATTERN_HOLDER.
|
||||
matcher(string.trim())
|
||||
if (executionMatcher.matches()) {
|
||||
return new ExecutionProperty(patternFromMatchingGroup(executionMatcher))
|
||||
}
|
||||
@@ -347,8 +375,10 @@ class ContentUtils {
|
||||
}
|
||||
|
||||
static ContentType recognizeContentTypeFromHeader(Headers headers, Closure<Object> closure) {
|
||||
Header header = headers?.entries?.find { it.name == "Content-Type" ||
|
||||
it.name == "contentType" }
|
||||
Header header = headers?.entries?.find {
|
||||
it.name == "Content-Type" ||
|
||||
it.name == "contentType"
|
||||
}
|
||||
String content = closure(header)?.toString()
|
||||
if (content?.contains("json")) {
|
||||
return JSON
|
||||
@@ -375,10 +405,10 @@ class ContentUtils {
|
||||
|
||||
static MatchingStrategy.Type getEqualsTypeFromContentType(ContentType contentType) {
|
||||
switch (contentType) {
|
||||
case JSON:
|
||||
return MatchingStrategy.Type.EQUAL_TO_JSON
|
||||
case ContentType.XML:
|
||||
return MatchingStrategy.Type.EQUAL_TO_XML
|
||||
case JSON:
|
||||
return MatchingStrategy.Type.EQUAL_TO_JSON
|
||||
case ContentType.XML:
|
||||
return MatchingStrategy.Type.EQUAL_TO_XML
|
||||
}
|
||||
return MatchingStrategy.Type.EQUAL_TO
|
||||
}
|
||||
@@ -409,7 +439,8 @@ class ContentUtils {
|
||||
try {
|
||||
new JsonSlurper().parseText(string)
|
||||
return JSON
|
||||
} catch (Exception ignored){
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
if (isXmlType("$string")) {
|
||||
return ContentType.XML
|
||||
}
|
||||
@@ -424,15 +455,20 @@ class ContentUtils {
|
||||
static ContentType recognizeContentTypeFromContent(Object object) {
|
||||
if (object instanceof GString) {
|
||||
return recognizeContentTypeFromContent((GString) object)
|
||||
} else if (object instanceof Map) {
|
||||
}
|
||||
else if (object instanceof Map) {
|
||||
return recognizeContentTypeFromContent((Map) object)
|
||||
} else if (object instanceof byte[]) {
|
||||
}
|
||||
else if (object instanceof byte[]) {
|
||||
return recognizeContentTypeFromContent((byte[]) object)
|
||||
} else if (object instanceof List) {
|
||||
}
|
||||
else if (object instanceof List) {
|
||||
return recognizeContentTypeFromContent((List) object)
|
||||
} else if (object instanceof String) {
|
||||
}
|
||||
else if (object instanceof String) {
|
||||
return recognizeContentTypeFromContent((String) object)
|
||||
} else if (object instanceof Number) {
|
||||
}
|
||||
else if (object instanceof Number) {
|
||||
return recognizeContentTypeFromContent((Number) object)
|
||||
}
|
||||
return UNKNOWN
|
||||
@@ -444,14 +480,16 @@ class ContentUtils {
|
||||
}
|
||||
GString stringWithoutValues = new GStringImpl(
|
||||
gstring.values.collect({
|
||||
it instanceof String || it instanceof GString ? it.toString() : escapeJson(it.toString())
|
||||
it instanceof String || it instanceof GString ? it.toString() :
|
||||
escapeJson(it.toString())
|
||||
}) as Object[],
|
||||
gstring.strings.clone() as String[]
|
||||
)
|
||||
try {
|
||||
new JsonSlurper().parseText(stringWithoutValues.toString())
|
||||
return true
|
||||
} catch (JsonException e) {
|
||||
}
|
||||
catch (JsonException e) {
|
||||
// Not JSON
|
||||
}
|
||||
return false
|
||||
@@ -460,14 +498,17 @@ class ContentUtils {
|
||||
static boolean isXmlType(GString gString) {
|
||||
GString stringWithoutValues = new GStringImpl(
|
||||
gString.values.collect({
|
||||
it instanceof String || it instanceof GString ? it.toString() : escapeXml11(it.toString())
|
||||
it instanceof String || it instanceof GString ? it.toString() :
|
||||
escapeXml11(it.toString())
|
||||
}) as Object[],
|
||||
gString.strings.clone() as String[]
|
||||
)
|
||||
try {
|
||||
getXmlSlurperWithDefaultErrorHandler().parseText(stringWithoutValues.toString())
|
||||
getXmlSlurperWithDefaultErrorHandler()
|
||||
.parseText(stringWithoutValues.toString())
|
||||
return true
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
// Not XML
|
||||
}
|
||||
return false
|
||||
@@ -475,10 +516,10 @@ class ContentUtils {
|
||||
|
||||
static ContentType recognizeContentTypeFromMatchingStrategy(MatchingStrategy.Type type) {
|
||||
switch (type) {
|
||||
case MatchingStrategy.Type.EQUAL_TO_XML:
|
||||
return ContentType.XML
|
||||
case MatchingStrategy.Type.EQUAL_TO_JSON:
|
||||
return JSON
|
||||
case MatchingStrategy.Type.EQUAL_TO_XML:
|
||||
return ContentType.XML
|
||||
case MatchingStrategy.Type.EQUAL_TO_JSON:
|
||||
return JSON
|
||||
}
|
||||
return UNKNOWN
|
||||
}
|
||||
@@ -486,18 +527,26 @@ class ContentUtils {
|
||||
static String getGroovyMultipartFileParameterContent(String propertyName, NamedProperty propertyValue,
|
||||
Closure<String> bytesFromFile) {
|
||||
return "'$propertyName', ${namedPropertyName(propertyValue, "'")}, " +
|
||||
"${groovyNamedPropertyValue(propertyValue, "'", bytesFromFile)}" + namedContentTypeNameIfPresent(propertyValue, "'")
|
||||
"${groovyNamedPropertyValue(propertyValue, "'", bytesFromFile)}" +
|
||||
namedContentTypeNameIfPresent(propertyValue, "'")
|
||||
}
|
||||
|
||||
static String getJavaMultipartFileParameterContent(String propertyName, NamedProperty propertyValue,
|
||||
Closure<String> bytesFromFile) {
|
||||
return """"${escapeJava(propertyName)}", ${namedPropertyName(propertyValue, '"')}, """ +
|
||||
"""${javaNamedPropertyValue(propertyValue, '"', bytesFromFile)}${namedContentTypeNameIfPresent(propertyValue, '"')}"""
|
||||
return """"${escapeJava(propertyName)}", ${
|
||||
namedPropertyName(propertyValue, '"')
|
||||
}, """ +
|
||||
"""${
|
||||
javaNamedPropertyValue(propertyValue, '"', bytesFromFile)
|
||||
}${
|
||||
namedContentTypeNameIfPresent(propertyValue, '"')
|
||||
}"""
|
||||
}
|
||||
|
||||
static String namedPropertyName(NamedProperty property, String quote) {
|
||||
return property.name.serverValue instanceof ExecutionProperty ?
|
||||
property.name.serverValue.toString() : quote + escapeJava(property.name.serverValue.toString()) + quote
|
||||
property.name.serverValue.toString() : quote +
|
||||
escapeJava(property.name.serverValue.toString()) + quote
|
||||
}
|
||||
|
||||
static String namedContentTypeNameIfPresent(NamedProperty property, String quote) {
|
||||
@@ -505,40 +554,46 @@ class ContentUtils {
|
||||
return ""
|
||||
}
|
||||
String contentType = property.contentType.serverValue instanceof ExecutionProperty ?
|
||||
property.contentType.serverValue.toString() : quote + escapeJava(property.contentType.serverValue.toString()) + quote
|
||||
property.contentType.serverValue.toString() : quote +
|
||||
escapeJava(property.contentType.serverValue.toString()) + quote
|
||||
return ", " + contentType
|
||||
}
|
||||
|
||||
static String groovyNamedPropertyValue(NamedProperty property, String quote, Closure<String> bytesFromFile) {
|
||||
if (property.value.serverValue instanceof ExecutionProperty) {
|
||||
return property.value.serverValue.toString()
|
||||
} else if (property.value.serverValue instanceof byte[]) {
|
||||
}
|
||||
else if (property.value.serverValue instanceof byte[]) {
|
||||
byte[] bytes = (byte[]) property.value.serverValue
|
||||
return "[" + bytes.collect { it }.join(", ") + "] as byte[]"
|
||||
} else if (property.value.serverValue instanceof FromFileProperty) {
|
||||
}
|
||||
else if (property.value.serverValue instanceof FromFileProperty) {
|
||||
FromFileProperty fromFileProperty = (FromFileProperty) property.value.serverValue
|
||||
if (fromFileProperty.isByte()) {
|
||||
return bytesFromFile(fromFileProperty)
|
||||
}
|
||||
return "[" + fromFileProperty.asBytes().collect { it }.join(", ") + "] as byte[]"
|
||||
}
|
||||
return quote + escapeJava(property.value.serverValue.toString()) + quote + ".bytes"
|
||||
return quote +
|
||||
escapeJava(property.value.serverValue.toString()) + quote + ".bytes"
|
||||
}
|
||||
|
||||
static String javaNamedPropertyValue(NamedProperty property, String quote, Closure<String> bytesFromFile) {
|
||||
if (property.value.serverValue instanceof ExecutionProperty) {
|
||||
return property.value.serverValue.toString()
|
||||
} else if (property.value.serverValue instanceof byte[]) {
|
||||
}
|
||||
else if (property.value.serverValue instanceof byte[]) {
|
||||
byte[] bytes = (byte[]) property.value.serverValue
|
||||
return "new byte[] {" + bytes.collect { it }.join(", ") + "}"
|
||||
} else if (property.value.serverValue instanceof FromFileProperty) {
|
||||
}
|
||||
else if (property.value.serverValue instanceof FromFileProperty) {
|
||||
FromFileProperty fromFileProperty = (FromFileProperty) property.value.serverValue
|
||||
if (fromFileProperty.isByte()) {
|
||||
return bytesFromFile(fromFileProperty)
|
||||
}
|
||||
return "new byte[] {" + fromFileProperty.asBytes().collect { it }.join(", ") + "}"
|
||||
}
|
||||
return quote + escapeJava(property.value.serverValue.toString()) + quote + ".getBytes()"
|
||||
return quote + escapeJava(property.value.serverValue.toString()) + quote + ".getBytes()"
|
||||
}
|
||||
|
||||
static ContentType evaluateContentType(Headers contractHeaders, Object body) {
|
||||
@@ -548,6 +603,7 @@ class ContentUtils {
|
||||
}
|
||||
return contentType
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link XmlSlurper} with default error handler.
|
||||
*
|
||||
|
||||
@@ -1,27 +1,20 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.util
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import org.apache.commons.logging.Log
|
||||
import org.apache.commons.logging.LogFactory
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.spec.ContractConverter
|
||||
import org.springframework.cloud.contract.verifier.converter.YamlContractConverter
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader
|
||||
package org.springframework.cloud.contract.verifier.util
|
||||
|
||||
import java.nio.file.FileVisitResult
|
||||
import java.nio.file.Files
|
||||
@@ -31,6 +24,15 @@ import java.nio.file.SimpleFileVisitor
|
||||
import java.nio.file.attribute.BasicFileAttributes
|
||||
import java.util.function.Predicate
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import org.apache.commons.logging.Log
|
||||
import org.apache.commons.logging.LogFactory
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.spec.ContractConverter
|
||||
import org.springframework.cloud.contract.verifier.converter.YamlContractConverter
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader
|
||||
|
||||
/**
|
||||
* Scans through the given directory and converts all files for
|
||||
* contract definitions.
|
||||
@@ -82,8 +84,8 @@ final class ContractScanner {
|
||||
if (isContractDescriptor(file)) {
|
||||
contractDescriptors
|
||||
.addAll(ContractVerifierDslConverter
|
||||
.convertAsCollection(
|
||||
file.getParentFile(), file))
|
||||
.convertAsCollection(
|
||||
file.getParentFile(), file))
|
||||
}
|
||||
else if (converter != null
|
||||
&& converter.isAccepted(file)) {
|
||||
@@ -91,10 +93,10 @@ final class ContractScanner {
|
||||
.addAll(converter.convertFrom(file))
|
||||
}
|
||||
else if (YamlContractConverter.INSTANCE
|
||||
.isAccepted(file)) {
|
||||
.isAccepted(file)) {
|
||||
contractDescriptors
|
||||
.addAll(YamlContractConverter.INSTANCE
|
||||
.convertFrom(file))
|
||||
.convertFrom(file))
|
||||
}
|
||||
}
|
||||
return super.visitFile(path, attrs)
|
||||
@@ -120,4 +122,4 @@ final class ContractScanner {
|
||||
private static boolean isContractDescriptor(File file) {
|
||||
return file.isFile() && file.getName().endsWith(".groovy")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.util
|
||||
@@ -19,6 +19,7 @@ package org.springframework.cloud.contract.verifier.util
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.util.logging.Commons
|
||||
import org.codehaus.groovy.control.CompilerConfiguration
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.util.StringUtils
|
||||
|
||||
@@ -43,9 +44,11 @@ class ContractVerifierDslConverter {
|
||||
try {
|
||||
Object object = groovyShell().evaluate(dsl)
|
||||
return listOfContracts(object)
|
||||
} catch (DslParseException e) {
|
||||
}
|
||||
catch (DslParseException e) {
|
||||
throw e
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("Exception occurred while trying to evaluate the contract", e)
|
||||
throw new DslParseException(e)
|
||||
}
|
||||
@@ -57,12 +60,15 @@ class ContractVerifierDslConverter {
|
||||
ClassLoader urlCl = updatedClassLoader(rootFolder, classLoader)
|
||||
Object object = groovyShell(urlCl, rootFolder).evaluate(dsl)
|
||||
return listOfContracts(object)
|
||||
} catch (DslParseException e) {
|
||||
}
|
||||
catch (DslParseException e) {
|
||||
throw e
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("Exception occurred while trying to evaluate the contract", e)
|
||||
throw new DslParseException(e)
|
||||
} finally {
|
||||
}
|
||||
finally {
|
||||
Thread.currentThread().setContextClassLoader(classLoader)
|
||||
}
|
||||
}
|
||||
@@ -77,12 +83,15 @@ class ContractVerifierDslConverter {
|
||||
ClassLoader urlCl = updatedClassLoader(rootFolder, classLoader)
|
||||
Object object = groovyShell(urlCl, rootFolder).evaluate(dsl)
|
||||
return listOfContracts(dsl, object)
|
||||
} catch (DslParseException e) {
|
||||
}
|
||||
catch (DslParseException e) {
|
||||
throw e
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("Exception occurred while trying to evaluate the contract at path [${dsl.path}]", e)
|
||||
throw new DslParseException(e)
|
||||
} finally {
|
||||
}
|
||||
finally {
|
||||
Thread.currentThread().setContextClassLoader(classLoader)
|
||||
}
|
||||
}
|
||||
@@ -107,7 +116,8 @@ class ContractVerifierDslConverter {
|
||||
private static Collection<Contract> listOfContracts(object) {
|
||||
if (object instanceof Collection) {
|
||||
return object as Collection<Contract>
|
||||
} else if (!object instanceof Contract) {
|
||||
}
|
||||
else if (!object instanceof Contract) {
|
||||
throw new DslParseException("Contract is not returning a Contract or list of Contracts")
|
||||
}
|
||||
return [object] as Collection<Contract>
|
||||
@@ -116,7 +126,8 @@ class ContractVerifierDslConverter {
|
||||
private static Collection<Contract> listOfContracts(File file, Object object) {
|
||||
if (object instanceof Collection) {
|
||||
return withName(file, object as Collection<Contract>)
|
||||
} else if (!object instanceof Contract) {
|
||||
}
|
||||
else if (!object instanceof Contract) {
|
||||
throw new DslParseException("Contract is not returning a Contract or list of Contracts")
|
||||
}
|
||||
return withName(file, [object] as Collection<Contract>)
|
||||
@@ -138,7 +149,6 @@ class ContractVerifierDslConverter {
|
||||
}
|
||||
|
||||
private static boolean relatedToScenarios(File file, Contract contract) {
|
||||
return contract.name?.matches(SCENARIO_MATCHER) ||
|
||||
file.name.matches(SCENARIO_MATCHER)
|
||||
return contract.name?.matches(SCENARIO_MATCHER) || file.name.matches(SCENARIO_MATCHER)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.util;
|
||||
@@ -25,33 +25,36 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link MethodBufferingJsonVerifiable} that contains a list
|
||||
* of String method commands that need to be executed to assert JSONs.
|
||||
* Implementation of the {@link MethodBufferingJsonVerifiable} that contains a list of
|
||||
* String method commands that need to be executed to assert JSONs.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
|
||||
private static final Log log = LogFactory.getLog(DelegatingJsonVerifiable.class);
|
||||
|
||||
private static final Pattern FIELD_PATTERN = Pattern.compile("\\.field\\((\")?(.)+(\")?\\)");
|
||||
private static final Pattern ARRAY_PATTERN = Pattern.compile("\\.array\\((\")?(.)+(\")?\\)");
|
||||
private static final Pattern FIELD_PATTERN = Pattern
|
||||
.compile("\\.field\\((\")?(.)+(\")?\\)");
|
||||
|
||||
private static final Pattern ARRAY_PATTERN = Pattern
|
||||
.compile("\\.array\\((\")?(.)+(\")?\\)");
|
||||
|
||||
final JsonVerifiable delegate;
|
||||
|
||||
final LinkedList<String> methodsBuffer;
|
||||
|
||||
final Object valueToCheck;
|
||||
|
||||
DelegatingJsonVerifiable(JsonVerifiable delegate,
|
||||
LinkedList<String> methodsBuffer, Object valueToCheck) {
|
||||
DelegatingJsonVerifiable(JsonVerifiable delegate, LinkedList<String> methodsBuffer,
|
||||
Object valueToCheck) {
|
||||
this.delegate = delegate;
|
||||
this.methodsBuffer = new LinkedList<>(methodsBuffer);
|
||||
this.valueToCheck = valueToCheck;
|
||||
}
|
||||
|
||||
DelegatingJsonVerifiable(JsonVerifiable delegate,
|
||||
LinkedList<String> methodsBuffer) {
|
||||
DelegatingJsonVerifiable(JsonVerifiable delegate, LinkedList<String> methodsBuffer) {
|
||||
this.delegate = delegate;
|
||||
this.methodsBuffer = new LinkedList<>(methodsBuffer);
|
||||
this.valueToCheck = null;
|
||||
@@ -69,13 +72,12 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
}
|
||||
|
||||
private static String wrapValueWithQuotes(Object value) {
|
||||
return value instanceof String ?
|
||||
"\"" + stringWithEscapedQuotes(value) + "\"" :
|
||||
value.toString();
|
||||
return value instanceof String ? "\"" + stringWithEscapedQuotes(value) + "\""
|
||||
: value.toString();
|
||||
}
|
||||
|
||||
private void appendMethodWithValue(String methodName, Object value) {
|
||||
this.methodsBuffer.offer("." + methodName + "(" + value + ")");
|
||||
this.methodsBuffer.offer("." + methodName + "(" + value + ")");
|
||||
}
|
||||
|
||||
private void appendMethodWithQuotedValue(String methodName, Object value) {
|
||||
@@ -84,8 +86,9 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
|
||||
@Override
|
||||
public MethodBufferingJsonVerifiable contains(Object value) {
|
||||
DelegatingJsonVerifiable verifiable = new FinishedDelegatingJsonVerifiable(this.delegate.jsonPath(),
|
||||
this.delegate.contains(value), this.methodsBuffer);
|
||||
DelegatingJsonVerifiable verifiable = new FinishedDelegatingJsonVerifiable(
|
||||
this.delegate.jsonPath(), this.delegate.contains(value),
|
||||
this.methodsBuffer);
|
||||
verifiable.appendMethodWithQuotedValue("contains", value);
|
||||
if (isAssertingAValueInArray()) {
|
||||
verifiable.methodsBuffer.offer(".value()");
|
||||
@@ -95,12 +98,15 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
|
||||
@Override
|
||||
public MethodBufferingJsonVerifiable field(Object value) {
|
||||
Object valueToPut = value instanceof ShouldTraverse ? ((ShouldTraverse) value).value : value;
|
||||
Object valueToPut = value instanceof ShouldTraverse
|
||||
? ((ShouldTraverse) value).value : value;
|
||||
Object wrappedValue = wrapInBrackets(valueToPut);
|
||||
DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.field(wrappedValue), this.methodsBuffer, value);
|
||||
DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(
|
||||
this.delegate.field(wrappedValue), this.methodsBuffer, value);
|
||||
if (this.delegate.isIteratingOverArray() && !(value instanceof ShouldTraverse)) {
|
||||
verifiable.appendMethodWithQuotedValue("contains", wrappedValue);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
verifiable.appendMethodWithQuotedValue("field", wrappedValue);
|
||||
}
|
||||
return verifiable;
|
||||
@@ -118,7 +124,8 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
@Override
|
||||
public MethodBufferingJsonVerifiable array(Object value) {
|
||||
Object valueToPut = wrapInBrackets(value);
|
||||
DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.array(valueToPut), this.methodsBuffer, value);
|
||||
DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(
|
||||
this.delegate.array(valueToPut), this.methodsBuffer, value);
|
||||
verifiable.appendMethodWithQuotedValue("array", valueToPut);
|
||||
return verifiable;
|
||||
}
|
||||
@@ -126,28 +133,32 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
@Override
|
||||
public MethodBufferingJsonVerifiable arrayField(Object value) {
|
||||
Object valueToPut = wrapInBrackets(value);
|
||||
DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.field(valueToPut).arrayField(), this.methodsBuffer, value);
|
||||
DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(
|
||||
this.delegate.field(valueToPut).arrayField(), this.methodsBuffer, value);
|
||||
verifiable.appendMethodWithQuotedValue("array", valueToPut);
|
||||
return verifiable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodBufferingJsonVerifiable arrayField() {
|
||||
DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.arrayField(), this.methodsBuffer);
|
||||
DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(
|
||||
this.delegate.arrayField(), this.methodsBuffer);
|
||||
verifiable.methodsBuffer.offer(".arrayField()");
|
||||
return verifiable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodBufferingJsonVerifiable array() {
|
||||
DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.array(), this.methodsBuffer);
|
||||
DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(
|
||||
this.delegate.array(), this.methodsBuffer);
|
||||
verifiable.methodsBuffer.offer(".array()");
|
||||
return verifiable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonVerifiable elementWithIndex(int i) {
|
||||
DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.elementWithIndex(i), this.methodsBuffer);
|
||||
DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(
|
||||
this.delegate.elementWithIndex(i), this.methodsBuffer);
|
||||
this.methodsBuffer.offer(".elementWithIndex(" + i + ")");
|
||||
return verifiable;
|
||||
}
|
||||
@@ -159,15 +170,22 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
|
||||
@Override
|
||||
public MethodBufferingJsonVerifiable isEqualTo(String value) {
|
||||
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.jsonPath(),
|
||||
this.delegate.isEqualTo(value), this.methodsBuffer, value);
|
||||
if (this.delegate.isAssertingAValueInArray() && readyToCheck.methodsBuffer.peekLast().equals(".arrayField()")) {
|
||||
readyToCheck.appendMethodWithQuotedValue("isEqualTo", escapedHackedJavaText(value));
|
||||
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(
|
||||
this.delegate.jsonPath(), this.delegate.isEqualTo(value),
|
||||
this.methodsBuffer, value);
|
||||
if (this.delegate.isAssertingAValueInArray()
|
||||
&& readyToCheck.methodsBuffer.peekLast().equals(".arrayField()")) {
|
||||
readyToCheck.appendMethodWithQuotedValue("isEqualTo",
|
||||
escapedHackedJavaText(value));
|
||||
readyToCheck.methodsBuffer.offer(".value()");
|
||||
} else if (this.delegate.isAssertingAValueInArray() && !readyToCheck.methodsBuffer.peekLast().contains("array")) {
|
||||
}
|
||||
else if (this.delegate.isAssertingAValueInArray()
|
||||
&& !readyToCheck.methodsBuffer.peekLast().contains("array")) {
|
||||
readyToCheck.methodsBuffer.offer(".value()");
|
||||
} else {
|
||||
readyToCheck.appendMethodWithQuotedValue("isEqualTo", escapedHackedJavaText(value));
|
||||
}
|
||||
else {
|
||||
readyToCheck.appendMethodWithQuotedValue("isEqualTo",
|
||||
escapedHackedJavaText(value));
|
||||
}
|
||||
return readyToCheck;
|
||||
}
|
||||
@@ -182,21 +200,26 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
|
||||
@Override
|
||||
public MethodBufferingJsonVerifiable isEqualTo(Number value) {
|
||||
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.jsonPath(),
|
||||
this.delegate.isEqualTo(value), this.methodsBuffer, value);
|
||||
// related to #271 - the problem is with asserting arrays of maps vs arrays of primitives
|
||||
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(
|
||||
this.delegate.jsonPath(), this.delegate.isEqualTo(value),
|
||||
this.methodsBuffer, value);
|
||||
// related to #271 - the problem is with asserting arrays of maps vs arrays of
|
||||
// primitives
|
||||
String last = readyToCheck.methodsBuffer.peekLast();
|
||||
boolean containsAMatcher = containsAnyMatcher(last);
|
||||
if (this.delegate.isAssertingAValueInArray() && containsAMatcher) {
|
||||
readyToCheck.methodsBuffer.offer(".value()");
|
||||
} else {
|
||||
readyToCheck.appendMethodWithValue("isEqualTo", value instanceof Long ? String.valueOf(value).concat("L") : String.valueOf(value));
|
||||
}
|
||||
else {
|
||||
readyToCheck.appendMethodWithValue("isEqualTo", value instanceof Long
|
||||
? String.valueOf(value).concat("L") : String.valueOf(value));
|
||||
}
|
||||
return readyToCheck;
|
||||
}
|
||||
|
||||
private boolean containsAnyMatcher(String string) {
|
||||
return string.contains("isEqualTo") || string.contains("matches") || string.contains("isNull");
|
||||
return string.contains("isEqualTo") || string.contains("matches")
|
||||
|| string.contains("isNull");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -207,17 +230,20 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
return readyToCheck;
|
||||
}
|
||||
|
||||
@Override public MethodBufferingJsonVerifiable isEmpty() {
|
||||
@Override
|
||||
public MethodBufferingJsonVerifiable isEmpty() {
|
||||
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(
|
||||
this.delegate.jsonPath(), this.delegate.isEmpty(), this.methodsBuffer);
|
||||
readyToCheck.methodsBuffer.offer(".isEmpty()");
|
||||
return readyToCheck;
|
||||
}
|
||||
|
||||
@Override public MethodBufferingJsonVerifiable isInstanceOf(Class clazz)
|
||||
@Override
|
||||
public MethodBufferingJsonVerifiable isInstanceOf(Class clazz)
|
||||
throws IllegalStateException {
|
||||
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(
|
||||
this.delegate.jsonPath(), this.delegate.isInstanceOf(clazz), this.methodsBuffer);
|
||||
this.delegate.jsonPath(), this.delegate.isInstanceOf(clazz),
|
||||
this.methodsBuffer);
|
||||
readyToCheck.methodsBuffer.offer(".isInstanceOf(" + clazz.getName() + ")");
|
||||
return readyToCheck;
|
||||
}
|
||||
@@ -225,13 +251,16 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
@Override
|
||||
public MethodBufferingJsonVerifiable matches(String value) {
|
||||
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(
|
||||
this.delegate.jsonPath(), this.delegate.matches(value), this.methodsBuffer,
|
||||
compilePattern(value));
|
||||
this.delegate.jsonPath(), this.delegate.matches(value),
|
||||
this.methodsBuffer, compilePattern(value));
|
||||
if (this.delegate.isAssertingAValueInArray()) {
|
||||
readyToCheck.appendMethodWithQuotedValue("matches", escapedHackedJavaText(value));
|
||||
readyToCheck.appendMethodWithQuotedValue("matches",
|
||||
escapedHackedJavaText(value));
|
||||
readyToCheck.methodsBuffer.offer(".value()");
|
||||
} else {
|
||||
readyToCheck.appendMethodWithQuotedValue("matches", escapedHackedJavaText(value));
|
||||
}
|
||||
else {
|
||||
readyToCheck.appendMethodWithQuotedValue("matches",
|
||||
escapedHackedJavaText(value));
|
||||
}
|
||||
return readyToCheck;
|
||||
}
|
||||
@@ -239,30 +268,36 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
private Object compilePattern(String value) {
|
||||
try {
|
||||
return Pattern.compile(value);
|
||||
} catch (Exception e) {
|
||||
log.warn("Exception occurred while trying to compile the pattern [" + value + "]. Will return the value explicitly. Hopefully, you know what you're doing...");
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.warn("Exception occurred while trying to compile the pattern [" + value
|
||||
+ "]. Will return the value explicitly. Hopefully, you know what you're doing...");
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We need to escape the pattern in order for the produced text to be compilable.
|
||||
* The problem is that sometimes we get quotes that already escaped. If we escape them
|
||||
* we get code that doesn't compile. That's why we're doing this hack to unescape
|
||||
* an double escaped text. Related to https://github.com/spring-cloud/spring-cloud-contract/issues/169
|
||||
* We need to escape the pattern in order for the produced text to be compilable. The
|
||||
* problem is that sometimes we get quotes that already escaped. If we escape them we
|
||||
* get code that doesn't compile. That's why we're doing this hack to unescape an
|
||||
* double escaped text. Related to
|
||||
* https://github.com/spring-cloud/spring-cloud-contract/issues/169
|
||||
* @param value text to escape
|
||||
* @return escaped text with lower number of escaped backslashes
|
||||
*/
|
||||
private String escapedHackedJavaText(String value) {
|
||||
return StringEscapeUtils.escapeJava(value)
|
||||
.replace("\\\"", "\"");
|
||||
return StringEscapeUtils.escapeJava(value).replace("\\\"", "\"");
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodBufferingJsonVerifiable isEqualTo(Boolean value) {
|
||||
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(
|
||||
this.delegate.jsonPath(), this.delegate.isEqualTo(value), this.methodsBuffer, value);
|
||||
this.delegate.jsonPath(), this.delegate.isEqualTo(value),
|
||||
this.methodsBuffer, value);
|
||||
if (this.delegate.isAssertingAValueInArray()) {
|
||||
readyToCheck.methodsBuffer.offer(".value()");
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
readyToCheck.appendMethodWithValue("isEqualTo", String.valueOf(value));
|
||||
}
|
||||
return readyToCheck;
|
||||
@@ -273,11 +308,13 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
return new FinishedDelegatingJsonVerifiable(this.delegate, this.methodsBuffer);
|
||||
}
|
||||
|
||||
@Override public String keyBeforeChecking() {
|
||||
@Override
|
||||
public String keyBeforeChecking() {
|
||||
return this.delegate.jsonPath();
|
||||
}
|
||||
|
||||
@Override public Object valueBeforeChecking() {
|
||||
@Override
|
||||
public Object valueBeforeChecking() {
|
||||
return this.valueToCheck;
|
||||
}
|
||||
|
||||
@@ -294,7 +331,8 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
@Override
|
||||
public boolean assertsConcreteValue() {
|
||||
for (String s : this.methodsBuffer) {
|
||||
if (FIELD_PATTERN.matcher(s).matches()|| ARRAY_PATTERN.matcher(s).matches()) {
|
||||
if (FIELD_PATTERN.matcher(s).matches()
|
||||
|| ARRAY_PATTERN.matcher(s).matches()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -319,7 +357,8 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
@Override
|
||||
public JsonVerifiable hasSize(int size) {
|
||||
FinishedDelegatingJsonVerifiable verifiable = new FinishedDelegatingJsonVerifiable(
|
||||
this.delegate.jsonPath(), this.delegate.hasSize(size), this.methodsBuffer);
|
||||
this.delegate.jsonPath(), this.delegate.hasSize(size),
|
||||
this.methodsBuffer);
|
||||
verifiable.methodsBuffer.offer(".hasSize(" + size + ")");
|
||||
return verifiable;
|
||||
}
|
||||
@@ -363,10 +402,12 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
if (this == o) {
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
DelegatingJsonVerifiable that = (DelegatingJsonVerifiable) o;
|
||||
return this.methodsBuffer.toString().equals(that.methodsBuffer.toString());
|
||||
}
|
||||
@@ -379,14 +420,13 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DelegatingJsonVerifiable{" +
|
||||
"delegate=\n" + this.delegate +
|
||||
", methodsBuffer=" + this.methodsBuffer +
|
||||
'}';
|
||||
return "DelegatingJsonVerifiable{" + "delegate=\n" + this.delegate
|
||||
+ ", methodsBuffer=" + this.methodsBuffer + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T read(Class<T> aClass) {
|
||||
return this.delegate.read(aClass);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.util
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.util;
|
||||
@@ -21,11 +21,10 @@ import java.util.LinkedList;
|
||||
import com.toomuchcoding.jsonassert.JsonVerifiable;
|
||||
|
||||
/**
|
||||
* Helper class that represents a finished assertion of a JSON.
|
||||
* Contains a list of all necessary method calls to assert the JSON.
|
||||
* Helper class that represents a finished assertion of a JSON. Contains a list of all
|
||||
* necessary method calls to assert the JSON.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class FinishedDelegatingJsonVerifiable extends DelegatingJsonVerifiable {
|
||||
@@ -50,7 +49,9 @@ class FinishedDelegatingJsonVerifiable extends DelegatingJsonVerifiable {
|
||||
this.keyBeforeChecking = delegate.jsonPath();
|
||||
}
|
||||
|
||||
@Override public String keyBeforeChecking() {
|
||||
@Override
|
||||
public String keyBeforeChecking() {
|
||||
return this.keyBeforeChecking;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.util
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.verifier.util
|
||||
@@ -35,6 +34,7 @@ import org.springframework.cloud.contract.spec.internal.OptionalProperty
|
||||
import org.springframework.cloud.contract.spec.internal.RegexProperty
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
import org.springframework.util.SerializationUtils
|
||||
|
||||
/**
|
||||
* I would like to apologize to anyone who is reading this class. Since JSON is a hectic structure
|
||||
* this class is also hectic. The idea is to traverse the JSON structure and build a set of
|
||||
@@ -55,6 +55,7 @@ class JsonToJsonPathsConverter {
|
||||
private static final Boolean SERVER_SIDE = false
|
||||
private static final Boolean CLIENT_SIDE = true
|
||||
private static final String ANY_ARRAY_NOTATION_IN_JSONPATH = "[*]"
|
||||
private static final String DESCENDANT_OPERATOR = ".."
|
||||
|
||||
private final ContractVerifierConfigProperties configProperties
|
||||
|
||||
@@ -87,9 +88,10 @@ class JsonToJsonPathsConverter {
|
||||
def entry = entry(context, matcher.path())
|
||||
if (entry != null) {
|
||||
context.delete(matcher.path())
|
||||
removeTrailingContainers(matcher, context)
|
||||
removeTrailingContainers(matcher.path(), context)
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Exception occurred while trying to delete path [${matcher.path()}]", e)
|
||||
}
|
||||
@@ -102,7 +104,8 @@ class JsonToJsonPathsConverter {
|
||||
private static def entry(DocumentContext context, String path) {
|
||||
try {
|
||||
return context.read(path)
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Exception occurred while trying to retrieve element via path [${path}]", ex)
|
||||
}
|
||||
@@ -131,21 +134,34 @@ class JsonToJsonPathsConverter {
|
||||
* remove that trailing collection. All in all it's better to use the Groovy based notation for
|
||||
* defining body...
|
||||
*/
|
||||
private static void removeTrailingContainers(BodyMatcher matcher, DocumentContext context) {
|
||||
String pathWithoutAnyArray = matcher.path().contains(ANY_ARRAY_NOTATION_IN_JSONPATH) ? matcher.path().substring(0, matcher.path().lastIndexOf(ANY_ARRAY_NOTATION_IN_JSONPATH)) : matcher.path()
|
||||
private static boolean removeTrailingContainers(String matcherPath, DocumentContext context) {
|
||||
boolean containsArray = matcherPath.contains(ANY_ARRAY_NOTATION_IN_JSONPATH)
|
||||
String pathWithoutAnyArray = containsArray ? matcherPath.substring(0, matcherPath.
|
||||
lastIndexOf(ANY_ARRAY_NOTATION_IN_JSONPATH)) : matcherPath
|
||||
def object = entry(context, pathWithoutAnyArray)
|
||||
// object got removed and it was the only element
|
||||
// let's get its parent and see if it contains an empty element
|
||||
if (isIterable(object) && containsOnlyEmptyElements(object)) {
|
||||
if (isIterable(object)
|
||||
&&
|
||||
containsOnlyEmptyElements(object)
|
||||
&& isNotRootArray(matcherPath)) {
|
||||
String pathToDelete = pathToDelete(pathWithoutAnyArray)
|
||||
context.delete(pathToDelete)
|
||||
} else {
|
||||
String lastParent = matcher.path().substring(0, matcher.path().lastIndexOf("."))
|
||||
return pathToDelete.contains(DESCENDANT_OPERATOR) ? false :
|
||||
removeTrailingContainers(pathToDelete, context)
|
||||
}
|
||||
else {
|
||||
String lastParent = matcherPath.substring(0, matcherPath.lastIndexOf("."))
|
||||
def lastParentObject = context.read(lastParent)
|
||||
if (isIterable(lastParentObject) && containsOnlyEmptyElements(lastParentObject)) {
|
||||
if (isIterable(lastParentObject)
|
||||
&&
|
||||
containsOnlyEmptyElements(lastParentObject)
|
||||
&& isNotRoot(lastParent)) {
|
||||
context.delete(lastParent)
|
||||
return removeTrailingContainers(lastParent, context)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private static boolean isIterable(Object object) {
|
||||
@@ -157,11 +173,22 @@ class JsonToJsonPathsConverter {
|
||||
return pathWithoutAnyArray == '$' ? '$[*]' : pathWithoutAnyArray
|
||||
}
|
||||
|
||||
private static boolean isNotRoot(String path) {
|
||||
// we can't remove root
|
||||
return path != '$'
|
||||
}
|
||||
|
||||
private static boolean isNotRootArray(String path) {
|
||||
// we can't remove root
|
||||
return path != '$[*]'
|
||||
}
|
||||
|
||||
private static boolean containsOnlyEmptyElements(Object object) {
|
||||
return object.every {
|
||||
if (it instanceof Map) {
|
||||
return it.isEmpty()
|
||||
} else if (it instanceof List) {
|
||||
}
|
||||
else if (it instanceof List) {
|
||||
return it.isEmpty()
|
||||
}
|
||||
return false
|
||||
@@ -184,7 +211,8 @@ class JsonToJsonPathsConverter {
|
||||
static String convertJsonPathAndRegexToAJsonPath(BodyMatcher bodyMatcher, def body = null) {
|
||||
String path = bodyMatcher.path()
|
||||
Object value = bodyMatcher.value()
|
||||
if (value == null && bodyMatcher.matchingType() != MatchingType.EQUALITY &&
|
||||
if (value == null && bodyMatcher.matchingType() != MatchingType.EQUALITY
|
||||
&&
|
||||
bodyMatcher.matchingType() != MatchingType.TYPE) {
|
||||
return path
|
||||
}
|
||||
@@ -227,13 +255,16 @@ class JsonToJsonPathsConverter {
|
||||
convertedBody = MapConverter.transformValues(body) {
|
||||
return generatedValueIfNeeded(it)
|
||||
}
|
||||
Object retrievedValue = JsonPath.parse(convertedBody).read(bodyMatcher.path())
|
||||
Object retrievedValue = JsonPath.parse(convertedBody).
|
||||
read(bodyMatcher.path())
|
||||
String wrappedValue = retrievedValue instanceof Number ? retrievedValue : "'${retrievedValue.toString()}'"
|
||||
return "${propertyName} == ${wrappedValue}"
|
||||
} catch (PathNotFoundException e) {
|
||||
}
|
||||
catch (PathNotFoundException e) {
|
||||
throw new IllegalStateException("Value [${bodyMatcher.path()}] not found in JSON [${JsonOutput.toJson(convertedBody)}]", e)
|
||||
}
|
||||
} else if (bodyMatcher.matchingType() == MatchingType.TYPE) {
|
||||
}
|
||||
else if (bodyMatcher.matchingType() == MatchingType.TYPE) {
|
||||
Integer min = bodyMatcher.minTypeOccurrence()
|
||||
Integer max = bodyMatcher.maxTypeOccurrence()
|
||||
String result = ""
|
||||
@@ -245,7 +276,8 @@ class JsonToJsonPathsConverter {
|
||||
result = result ? "${result} && ${maxResult}" : maxResult
|
||||
}
|
||||
return result
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
String convertedValue = value.toString().replace('/', '\\\\/')
|
||||
return "${propertyName} =~ /(${convertedValue})/"
|
||||
}
|
||||
@@ -269,23 +301,25 @@ class JsonToJsonPathsConverter {
|
||||
|
||||
private JsonPaths transformToJsonPathWithValues(def json, boolean clientSide,
|
||||
Closure parsingClosure = MapConverter.JSON_PARSING_CLOSURE) {
|
||||
if(!json) {
|
||||
if (!json) {
|
||||
return new JsonPaths()
|
||||
}
|
||||
JsonPaths pathsAndValues = [] as Set
|
||||
Object convertedJson = MapConverter.getClientOrServerSideValues(json, clientSide, parsingClosure)
|
||||
Object convertedJson = MapConverter.
|
||||
getClientOrServerSideValues(json, clientSide, parsingClosure)
|
||||
Object jsonWithPatterns = ContentUtils.
|
||||
convertDslPropsToTemporaryRegexPatterns(convertedJson, parsingClosure)
|
||||
MethodBufferingJsonVerifiable methodBufferingJsonPathVerifiable =
|
||||
new DelegatingJsonVerifiable(JsonAssertion.assertThat(JsonOutput.toJson(jsonWithPatterns))
|
||||
.withoutThrowingException())
|
||||
new DelegatingJsonVerifiable(JsonAssertion.
|
||||
assertThat(JsonOutput.toJson(jsonWithPatterns))
|
||||
.withoutThrowingException())
|
||||
traverseRecursivelyForKey(jsonWithPatterns, methodBufferingJsonPathVerifiable,
|
||||
{ MethodBufferingJsonVerifiable key, Object value ->
|
||||
if (value instanceof ExecutionProperty || !(key instanceof FinishedDelegatingJsonVerifiable)) {
|
||||
return
|
||||
}
|
||||
pathsAndValues.add(key)
|
||||
}, parsingClosure)
|
||||
{ MethodBufferingJsonVerifiable key, Object value ->
|
||||
if (value instanceof ExecutionProperty || !(key instanceof FinishedDelegatingJsonVerifiable)) {
|
||||
return
|
||||
}
|
||||
pathsAndValues.add(key)
|
||||
}, parsingClosure)
|
||||
return pathsAndValues
|
||||
}
|
||||
|
||||
@@ -298,48 +332,68 @@ class JsonToJsonPathsConverter {
|
||||
if (json instanceof Map) {
|
||||
return convertWithKey(parentType, key, json, closure, parsingClosure)
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
return runClosure(closure, key, value)
|
||||
}
|
||||
} else if (isAnEntryWithNonCollectionLikeValue(value)) {
|
||||
}
|
||||
else if (isAnEntryWithNonCollectionLikeValue(value)) {
|
||||
return convertWithKey(List, key, value as Map, closure, parsingClosure)
|
||||
} else if (isAnEntryWithoutNestedStructures(value)) {
|
||||
}
|
||||
else if (isAnEntryWithoutNestedStructures(value)) {
|
||||
return convertWithKey(List, key, value as Map, closure, parsingClosure)
|
||||
} else if (value instanceof Map && !value.isEmpty()) {
|
||||
}
|
||||
else if (value instanceof Map && !value.isEmpty()) {
|
||||
return convertWithKey(Map, key, value as Map, closure, parsingClosure)
|
||||
} else if (value instanceof Map && value.isEmpty()) {
|
||||
}
|
||||
else if (value instanceof Map && value.isEmpty()) {
|
||||
return runClosure(closure, key.isEmpty(), value)
|
||||
// JSON with a list of primitives ["a", "b", "c"] in root issue #266
|
||||
} else if (key.isIteratingOverNamelessArray() && value instanceof List && listContainsOnlyPrimitives(value)) {
|
||||
}
|
||||
else if (key.isIteratingOverNamelessArray() && value instanceof List
|
||||
&&
|
||||
listContainsOnlyPrimitives(value)) {
|
||||
addSizeVerificationForListWithPrimitives(key, closure, value)
|
||||
value.each {
|
||||
traverseRecursively(Object, key.arrayField().contains(ContentUtils.returnParsedObject(it)),
|
||||
traverseRecursively(Object, key.arrayField().
|
||||
contains(ContentUtils.returnParsedObject(it)),
|
||||
ContentUtils.returnParsedObject(it), closure, parsingClosure)
|
||||
}
|
||||
// JSON containing list of primitives { "partners":[ { "role":"AGENT", "payment_methods":[ "BANK", "CASH" ] } ]
|
||||
} else if (value instanceof List && listContainsOnlyPrimitives(value)) {
|
||||
// JSON containing list of primitives { "partners":[ { "role":"AGENT", "payment_methods":[ "BANK", "CASH" ] } ]
|
||||
}
|
||||
else if (value instanceof List && listContainsOnlyPrimitives(value)) {
|
||||
addSizeVerificationForListWithPrimitives(key, closure, value)
|
||||
value.each {
|
||||
traverseRecursively(Object, valueToAsserter(key.arrayField(), ContentUtils.returnParsedObject(it)),
|
||||
traverseRecursively(Object,
|
||||
valueToAsserter(key.arrayField(), ContentUtils.
|
||||
returnParsedObject(it)),
|
||||
ContentUtils.returnParsedObject(it), closure, parsingClosure)
|
||||
}
|
||||
} else if (value instanceof List && !value.empty) {
|
||||
MethodBufferingJsonVerifiable jsonPathVerifiable = createAsserterFromList(key, value)
|
||||
}
|
||||
else if (value instanceof List && !value.empty) {
|
||||
MethodBufferingJsonVerifiable jsonPathVerifiable =
|
||||
createAsserterFromList(key, value)
|
||||
addSizeVerificationForListWithPrimitives(key, closure, value)
|
||||
value.each { def element ->
|
||||
traverseRecursively(List, createAsserterFromListElement(jsonPathVerifiable, ContentUtils.returnParsedObject(element)),
|
||||
traverseRecursively(List,
|
||||
createAsserterFromListElement(jsonPathVerifiable, ContentUtils.
|
||||
returnParsedObject(element)),
|
||||
ContentUtils.returnParsedObject(element), closure, parsingClosure)
|
||||
}
|
||||
return value
|
||||
} else if (value instanceof List && value.empty) {
|
||||
}
|
||||
else if (value instanceof List && value.empty) {
|
||||
return runClosure(closure, key, value)
|
||||
} else if (key.isIteratingOverArray()) {
|
||||
traverseRecursively(Object, key.arrayField().contains(ContentUtils.returnParsedObject(value)),
|
||||
}
|
||||
else if (key.isIteratingOverArray()) {
|
||||
traverseRecursively(Object, key.arrayField().
|
||||
contains(ContentUtils.returnParsedObject(value)),
|
||||
ContentUtils.returnParsedObject(value), closure, parsingClosure)
|
||||
}
|
||||
try {
|
||||
return runClosure(closure, key, value)
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
return value
|
||||
}
|
||||
}
|
||||
@@ -348,12 +402,15 @@ class JsonToJsonPathsConverter {
|
||||
private void addSizeVerificationForListWithPrimitives(MethodBufferingJsonVerifiable key, Closure closure, List value) {
|
||||
String systemPropValue = System.getProperty(SIZE_ASSERTION_SYSTEM_PROP)
|
||||
Boolean configPropValue = configProperties.assertJsonSize
|
||||
if ((systemPropValue != null && Boolean.parseBoolean(systemPropValue)) ||
|
||||
if ((systemPropValue != null && Boolean.parseBoolean(systemPropValue))
|
||||
||
|
||||
configPropValue && listContainsOnlyPrimitives(value)) {
|
||||
addArraySizeCheck(key, value, closure)
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Turning off the incubating feature of JSON array check. " +
|
||||
log.debug("Turning off the incubating feature of JSON array check. "
|
||||
+
|
||||
"System property [$systemPropValue]. Config property [$configPropValue]")
|
||||
}
|
||||
return
|
||||
@@ -379,13 +436,16 @@ class JsonToJsonPathsConverter {
|
||||
private MethodBufferingJsonVerifiable createAsserterFromList(MethodBufferingJsonVerifiable key, List value) {
|
||||
if (key.isIteratingOverNamelessArray()) {
|
||||
return key.array()
|
||||
} else if (key.isIteratingOverArray() && isAnEntryWithLists(value)) {
|
||||
if (!value.every { listContainsOnlyPrimitives(it as List)} ) {
|
||||
}
|
||||
else if (key.isIteratingOverArray() && isAnEntryWithLists(value)) {
|
||||
if (!value.every { listContainsOnlyPrimitives(it as List) }) {
|
||||
return key.array()
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return key.iterationPassingArray()
|
||||
}
|
||||
} else if (key.isIteratingOverArray()) {
|
||||
}
|
||||
else if (key.isIteratingOverArray()) {
|
||||
return key.iterationPassingArray()
|
||||
}
|
||||
return key
|
||||
@@ -398,7 +458,8 @@ class JsonToJsonPathsConverter {
|
||||
return jsonPathVerifiable.matches((object as Pattern).pattern())
|
||||
}
|
||||
return jsonPathVerifiable.contains(object)
|
||||
} else if (element instanceof List) {
|
||||
}
|
||||
else if (element instanceof List) {
|
||||
if (listContainsOnlyPrimitives(element)) {
|
||||
return jsonPathVerifiable.array()
|
||||
}
|
||||
@@ -407,7 +468,9 @@ class JsonToJsonPathsConverter {
|
||||
}
|
||||
|
||||
private def runClosure(Closure closure, MethodBufferingJsonVerifiable key, def value) {
|
||||
if (key.isAssertingAValueInArray() && !(value instanceof List || value instanceof Map)) {
|
||||
if (key.
|
||||
isAssertingAValueInArray()
|
||||
&& !(value instanceof List || value instanceof Map)) {
|
||||
return closure(valueToAsserter(key, value), value)
|
||||
}
|
||||
return closure(key, value)
|
||||
@@ -465,10 +528,12 @@ class JsonToJsonPathsConverter {
|
||||
Object entrykey, value ->
|
||||
def convertedValue = ContentUtils.returnParsedObject(value)
|
||||
[entrykey, traverseRecursively(parentType,
|
||||
convertedValue instanceof List ? list(convertedValue, entrykey, parentKey) :
|
||||
convertedValue instanceof Map ? parentKey.field(new ShouldTraverse(entrykey)) :
|
||||
valueToAsserter(parentKey.field(entrykey), convertedValue)
|
||||
, convertedValue, closureToExecute, parsingClosure)]
|
||||
convertedValue instanceof List ?
|
||||
list(convertedValue, entrykey, parentKey) :
|
||||
convertedValue instanceof Map ? parentKey.
|
||||
field(new ShouldTraverse(entrykey)) :
|
||||
valueToAsserter(parentKey.field(entrykey), convertedValue)
|
||||
, convertedValue, closureToExecute, parsingClosure)]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,11 +558,15 @@ class JsonToJsonPathsConverter {
|
||||
}
|
||||
if (convertedValue instanceof Pattern) {
|
||||
return key.matches((convertedValue as Pattern).pattern())
|
||||
} else if (convertedValue instanceof OptionalProperty) {
|
||||
}
|
||||
else if (convertedValue instanceof OptionalProperty) {
|
||||
return key.matches((convertedValue as OptionalProperty).optionalPattern())
|
||||
} else if (convertedValue instanceof GString) {
|
||||
return key.matches(RegexpBuilders.buildGStringRegexpForTestSide(convertedValue))
|
||||
} else if (convertedValue instanceof ExecutionProperty) {
|
||||
}
|
||||
else if (convertedValue instanceof GString) {
|
||||
return key.
|
||||
matches(RegexpBuilders.buildGStringRegexpForTestSide(convertedValue))
|
||||
}
|
||||
else if (convertedValue instanceof ExecutionProperty) {
|
||||
return key
|
||||
}
|
||||
return key.isEqualTo(convertedValue)
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.verifier.util
|
||||
@@ -53,7 +52,7 @@ class MapConverter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object with client side values of {@link org.springframework.cloud.contract.spec.internal.DslProperty}
|
||||
* @return the object with client side values of {@link org.springframework.cloud.contract.spec.internal.DslProperty}
|
||||
*/
|
||||
static def transformToClientValues(def value) {
|
||||
return transformValues(value) {
|
||||
@@ -65,7 +64,7 @@ class MapConverter {
|
||||
* Iterates over the structure of the object and executes the closure
|
||||
* on each element of that structure.
|
||||
*
|
||||
* Returns the transformed structure
|
||||
* @return the transformed structure
|
||||
*/
|
||||
static def transformValues(def value, Closure closure,
|
||||
Closure parsingClosure = JSON_PARSING_CLOSURE) {
|
||||
@@ -74,15 +73,19 @@ class MapConverter {
|
||||
def json = parsingClosure(value)
|
||||
if (json instanceof Map) {
|
||||
return convert(json, closure, parsingClosure)
|
||||
} else if (json instanceof List) {
|
||||
}
|
||||
else if (json instanceof List) {
|
||||
return transformValues(json, closure, parsingClosure)
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
}
|
||||
return extractValue(value, closure)
|
||||
} else if (value instanceof Map) {
|
||||
}
|
||||
else if (value instanceof Map) {
|
||||
return convert(value as Map, closure, parsingClosure)
|
||||
} else if (value instanceof List) {
|
||||
}
|
||||
else if (value instanceof List) {
|
||||
return value.collect({ transformValues(it, closure, parsingClosure) })
|
||||
}
|
||||
return transformValue(closure, value, parsingClosure)
|
||||
@@ -93,7 +96,7 @@ class MapConverter {
|
||||
* method access exception will occur at runtime.
|
||||
*/
|
||||
protected static Object transformValue(Closure closure, Object value, Closure parsingClosure) {
|
||||
return extractValue(value, { Object val->
|
||||
return extractValue(value, { Object val ->
|
||||
Object newValue = closure(val)
|
||||
if (newValue instanceof Map || newValue instanceof List || newValue instanceof String && value) {
|
||||
return transformValues(newValue, closure, parsingClosure)
|
||||
@@ -105,7 +108,8 @@ class MapConverter {
|
||||
private static extractValue(Object value, Closure closure) {
|
||||
try {
|
||||
return closure(value)
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
return value
|
||||
}
|
||||
}
|
||||
@@ -129,11 +133,15 @@ class MapConverter {
|
||||
return clientSide ?
|
||||
getClientOrServerSideValues(dslProperty.clientValue, clientSide, parsingClosure) :
|
||||
getClientOrServerSideValues(dslProperty.serverValue, clientSide, parsingClosure)
|
||||
} else if (it instanceof GString) {
|
||||
ContentType type = new MapConverter().templateProcessor.containsJsonPathTemplateEntry(
|
||||
ContentUtils.extractValueForGString(it, ContentUtils.GET_TEST_SIDE).toString()
|
||||
) ? ContentType.TEXT : null
|
||||
return ContentUtils.extractValue(it , type, {
|
||||
}
|
||||
else if (it instanceof GString) {
|
||||
ContentType type = new MapConverter().templateProcessor.
|
||||
containsJsonPathTemplateEntry(
|
||||
ContentUtils.
|
||||
extractValueForGString(it, ContentUtils.GET_TEST_SIDE).
|
||||
toString()
|
||||
) ? ContentType.TEXT : null
|
||||
return ContentUtils.extractValue(it, type, {
|
||||
if (it instanceof DslProperty) {
|
||||
return clientSide ?
|
||||
getClientOrServerSideValues((it as DslProperty).clientValue, clientSide, parsingClosure) :
|
||||
@@ -141,7 +149,8 @@ class MapConverter {
|
||||
}
|
||||
return it
|
||||
})
|
||||
} else if (it instanceof FromFileProperty) {
|
||||
}
|
||||
else if (it instanceof FromFileProperty) {
|
||||
return it.isByte() ? it.asBytes() : it.asString()
|
||||
}
|
||||
return it
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.util;
|
||||
|
||||
/**
|
||||
* Contract for classes that buffer method executions
|
||||
* Contract for classes that buffer method executions.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface MethodBuffering {
|
||||
|
||||
String method();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.util;
|
||||
@@ -19,15 +19,14 @@ package org.springframework.cloud.contract.verifier.util;
|
||||
import com.toomuchcoding.jsonassert.JsonVerifiable;
|
||||
|
||||
/**
|
||||
* A wrapper over {@link JsonVerifiable} that allows to store the method
|
||||
* name in order to print it out in the generated test
|
||||
* A wrapper over {@link JsonVerifiable} that allows to store the method name in order to
|
||||
* print it out in the generated test.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface MethodBufferingJsonVerifiable
|
||||
extends JsonVerifiable, MethodBuffering {
|
||||
public interface MethodBufferingJsonVerifiable extends JsonVerifiable, MethodBuffering {
|
||||
|
||||
@Override
|
||||
MethodBufferingJsonVerifiable contains(Object value);
|
||||
|
||||
@@ -81,4 +80,5 @@ public interface MethodBufferingJsonVerifiable
|
||||
boolean assertsSize();
|
||||
|
||||
boolean assertsConcreteValue();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.util
|
||||
@@ -33,7 +33,7 @@ class NamesUtil {
|
||||
|
||||
/**
|
||||
* Returns the first element before the last separator presence.
|
||||
* Returns empty string if separator is not found.
|
||||
* @return empty string if separator is not found.
|
||||
*/
|
||||
static String beforeLast(String string, String separator) {
|
||||
if (string?.indexOf(separator) > -1) {
|
||||
@@ -44,7 +44,7 @@ class NamesUtil {
|
||||
|
||||
/**
|
||||
* Returns the first element after the last separator presence
|
||||
* Returns the provided string if separator is not found.
|
||||
* @return the provided string if separator is not found.
|
||||
*/
|
||||
static String afterLast(String string, String separator) {
|
||||
if (hasSeparator(string, separator)) {
|
||||
@@ -62,28 +62,26 @@ class NamesUtil {
|
||||
|
||||
/**
|
||||
* Returns the first element after the last dot presence
|
||||
* Returns the provided string if separator is not found.
|
||||
* @return the provided string if separator is not found.
|
||||
*/
|
||||
static String afterLastDot(String string) {
|
||||
return afterLast(string, '.')
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if has a dot
|
||||
* @return {@code true} if has a dot
|
||||
*/
|
||||
static boolean hasDot(String string) {
|
||||
return hasSeparator(string, '.')
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default contract name, resolved from file name, taking
|
||||
* into consideration also the index of contract (for multiple contracts
|
||||
* stored in a single file).
|
||||
*
|
||||
* @param file - file with contracts
|
||||
* @param contracts - collection of contracts
|
||||
* @param counter - given contract index
|
||||
* @return
|
||||
* @return the default contract name, resolved from file name, taking
|
||||
* * into consideration also the index of contract (for multiple contracts
|
||||
* * stored in a single file).
|
||||
*/
|
||||
static String defaultContractName(File file, Collection contracts, int counter) {
|
||||
String tillExtension = file.name.substring(0, file.name.lastIndexOf("."))
|
||||
@@ -114,7 +112,7 @@ class NamesUtil {
|
||||
|
||||
/**
|
||||
* Returns the whole string to the last present dot.
|
||||
* Returns input string if there is no dot
|
||||
* @return input string if there is no dot
|
||||
*/
|
||||
static String toLastDot(String string) {
|
||||
if (string?.indexOf('.') > -1) {
|
||||
@@ -170,7 +168,8 @@ class NamesUtil {
|
||||
String name = dir.toFile().getName()
|
||||
String convertedName = directoryToPackage(name)
|
||||
if (name != convertedName) {
|
||||
this.filesToRename.addFirst(new FileAndNewName(dir.toFile(), convertedName))
|
||||
this.filesToRename.
|
||||
addFirst(new FileAndNewName(dir.toFile(), convertedName))
|
||||
}
|
||||
return FileVisitResult.CONTINUE
|
||||
}
|
||||
@@ -203,7 +202,7 @@ class NamesUtil {
|
||||
* Converts illegal characters in method names to underscores
|
||||
*/
|
||||
static String convertIllegalMethodNameChars(String methodName) {
|
||||
String result = methodName.replaceAll('^[^a-zA-Z_$0-9]', '_')
|
||||
String result = methodName.replaceAll('^[^a-zA-Z_$0-9]', '_')
|
||||
return result.replaceAll('[^a-zA-Z_$0-9]', '_')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,32 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.util
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
import groovy.transform.TypeChecked
|
||||
import org.codehaus.groovy.runtime.GStringImpl
|
||||
|
||||
import org.springframework.cloud.contract.spec.internal.DslProperty
|
||||
import org.springframework.cloud.contract.spec.util.RegexpUtils
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
import static org.apache.commons.text.StringEscapeUtils.escapeJson
|
||||
import static ContentType.*
|
||||
import static ContentUtils.extractValue
|
||||
import static org.apache.commons.text.StringEscapeUtils.escapeJson
|
||||
import static org.springframework.cloud.contract.verifier.util.ContentType.JSON
|
||||
|
||||
/**
|
||||
* Useful utility methods to work with regular expressions
|
||||
@@ -106,7 +107,8 @@ class RegexpBuilders {
|
||||
private final static String WS = /\s*/
|
||||
|
||||
static String buildJSONRegexpMatch(GString gString) {
|
||||
return buildJSONRegexpMatch(extractValue(gString, JSON, { DslProperty dslProperty -> dslProperty.clientValue }))
|
||||
return buildJSONRegexpMatch(
|
||||
extractValue(gString, JSON, { DslProperty dslProperty -> dslProperty.clientValue }))
|
||||
}
|
||||
|
||||
static String buildJSONRegexpMatch(Map jsonMap) {
|
||||
@@ -121,7 +123,8 @@ class RegexpBuilders {
|
||||
* Converts the map into String representation of regular expressions
|
||||
*/
|
||||
static String buildJSONRegexpMatch(Map.Entry<String, Object> entry) {
|
||||
return buildJSONRegexpMatchString(escapeJson(entry.key)) + ":" + buildJSONRegexpMatch(entry.value)
|
||||
return buildJSONRegexpMatchString(escapeJson(entry.key)) + ":" +
|
||||
buildJSONRegexpMatch(entry.value)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,33 +1,34 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.util;
|
||||
|
||||
/**
|
||||
* Utility class that wraps an object that should be traversed
|
||||
* when building a list of methods to execute in the generated test.
|
||||
* Utility class that wraps an object that should be traversed when building a list of
|
||||
* methods to execute in the generated test.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class ShouldTraverse {
|
||||
|
||||
final Object value;
|
||||
|
||||
ShouldTraverse(Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,28 +1,30 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.util
|
||||
|
||||
import java.nio.file.Files
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import org.apache.commons.logging.Log
|
||||
import org.apache.commons.logging.LogFactory
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.spec.ContractConverter
|
||||
|
||||
import java.nio.file.Files
|
||||
|
||||
/**
|
||||
* Allows conversion of Contract files to files.
|
||||
*
|
||||
@@ -69,10 +71,12 @@ final class ToFileContractsTransformer {
|
||||
log.info("Input path [" + path + "]")
|
||||
log.info("FQN of the converter [" + fqn + "]")
|
||||
log.info("Output path [" + outputPath + "]")
|
||||
Collection<Contract> contracts = ContractScanner.collectContractDescriptors(new File(path))
|
||||
Collection<Contract> contracts = ContractScanner.
|
||||
collectContractDescriptors(new File(path))
|
||||
log.info("Found [" + contracts.size() + "] contract definition")
|
||||
Class<?> name = Class.forName(fqn)
|
||||
ContractConverter<Collection> contractConverter = (ContractConverter) name.newInstance()
|
||||
ContractConverter<Collection> contractConverter = (ContractConverter) name.
|
||||
newInstance()
|
||||
Collection converted = contractConverter.convertTo(contracts)
|
||||
log.info("Successfully converted contracts definitions")
|
||||
Map<String, byte[]> stored = contractConverter.store(converted)
|
||||
@@ -85,11 +89,17 @@ final class ToFileContractsTransformer {
|
||||
for (Map.Entry<String, byte[]> entry : entries) {
|
||||
File outputFile = new File(outputFolder, entry.getKey())
|
||||
Files.write(outputFile.toPath(), entry.getValue())
|
||||
log.info("[" + i + "/" + entries.size() + "] Successfully stored [" + outputFile.getName() + "]")
|
||||
log.info("[" + i + "/"
|
||||
+ entries.
|
||||
size()
|
||||
+ "] Successfully stored ["
|
||||
+ outputFile.getName()
|
||||
+ "]")
|
||||
files.add(outputFile)
|
||||
}
|
||||
return files
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException(ex)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2018-2019 the original author or authors.
|
||||
* Copyright 2018-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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.util.xml
|
||||
@@ -63,9 +63,9 @@ class XmlToXPathsConverter {
|
||||
static Object removeMatchingXPaths(Object body, BodyMatchers bodyMatchers) {
|
||||
XPath xPath = XPathFactory.newInstance().newXPath()
|
||||
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance()
|
||||
.newDocumentBuilder()
|
||||
.newDocumentBuilder()
|
||||
Document parsedXml = documentBuilder
|
||||
.parse(new InputSource(new StringReader(body as String)))
|
||||
.parse(new InputSource(new StringReader(body as String)))
|
||||
bodyMatchers?.matchers()?.each({
|
||||
Node node = xPath.evaluate(it.path(), parsedXml.documentElement, NODE) as Node
|
||||
removeNode(node)
|
||||
@@ -88,9 +88,9 @@ class XmlToXPathsConverter {
|
||||
private static String getNodeValue(String path, Object body) {
|
||||
XPath xPath = XPathFactory.newInstance().newXPath()
|
||||
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance()
|
||||
.newDocumentBuilder()
|
||||
.newDocumentBuilder()
|
||||
Document parsedXml = documentBuilder.
|
||||
parse(new InputSource(new StringReader(body as String)))
|
||||
parse(new InputSource(new StringReader(body as String)))
|
||||
return xPath.evaluate(path, parsedXml.documentElement)
|
||||
}
|
||||
|
||||
@@ -99,7 +99,9 @@ class XmlToXPathsConverter {
|
||||
if (isValueNode(node as Node)) {
|
||||
node.getParentNode().removeChild(node)
|
||||
}
|
||||
else removeNode(node.getParentNode())
|
||||
else {
|
||||
removeNode(node.getParentNode())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,10 +128,10 @@ class XmlToXPathsConverter {
|
||||
|
||||
static List<BodyMatcher> mapToMatchers(Object xml) {
|
||||
DocumentBuilder documentBuilder = DocumentBuilderFactory
|
||||
.newInstance()
|
||||
.newDocumentBuilder()
|
||||
.newInstance()
|
||||
.newDocumentBuilder()
|
||||
Document parsedXml = documentBuilder
|
||||
.parse(new InputSource(new StringReader(xml as String)))
|
||||
.parse(new InputSource(new StringReader(xml as String)))
|
||||
List<List<Node>> valueNodes = getValueNodesWithParents(parsedXml)
|
||||
List<BodyMatcher> matchers = []
|
||||
List<NodePath> valueNodePaths = transformListEntries(valueNodes)
|
||||
@@ -148,12 +150,12 @@ class XmlToXPathsConverter {
|
||||
nodeLists.each { nodeList ->
|
||||
List<Node> parentNodesList = nodeList.subList(1, nodeList.size())
|
||||
int elementIndex = pathOccurrenceCounters.stream()
|
||||
.map({ it })
|
||||
.filter({
|
||||
.map({ it })
|
||||
.filter({
|
||||
nodeNames(it.path) == nodeNames(parentNodesList)
|
||||
}).findFirst()
|
||||
.map({ ++it.counter })
|
||||
.orElseGet({
|
||||
.map({ ++it.counter })
|
||||
.orElseGet({
|
||||
PathOccurrenceCounter pathCounter = new PathOccurrenceCounter(parentNodesList)
|
||||
pathOccurrenceCounters << pathCounter
|
||||
return pathCounter.counter
|
||||
@@ -165,8 +167,8 @@ class XmlToXPathsConverter {
|
||||
|
||||
private static List<String> nodeNames(List<Node> nodes) {
|
||||
return nodes.stream()
|
||||
.map({ it.getNodeName() })
|
||||
.collect(toList())
|
||||
.map({ it.getNodeName() })
|
||||
.collect(toList())
|
||||
}
|
||||
|
||||
static String buildXPath(List<Node> nodes, int index = 1) {
|
||||
@@ -237,8 +239,8 @@ class XmlToXPathsConverter {
|
||||
@CompileDynamic
|
||||
private static List<Node> getNodeCollectionElements(def nodeCollection) {
|
||||
return IntStream.range(0, nodeCollection.getLength())
|
||||
.mapToObj({ nodeCollection.item(it) as Node })
|
||||
.collect(toList())
|
||||
.mapToObj({ nodeCollection.item(it) as Node })
|
||||
.collect(toList())
|
||||
}
|
||||
|
||||
private static List<Node> withParents(Node node) {
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.assertion;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -7,8 +23,9 @@ import java.util.Map;
|
||||
import org.assertj.core.api.IterableAssert;
|
||||
|
||||
/**
|
||||
* Extension to {@link Iterable} assertions
|
||||
* Extension to {@link Iterable} assertions.
|
||||
*
|
||||
* @param <ELEMENT> type to assert
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@@ -23,7 +40,7 @@ public class CollectionAssert<ELEMENT> extends IterableAssert<ELEMENT> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts all elements of the collection whether they match a regular expression
|
||||
* Asserts all elements of the collection whether they match a regular expression.
|
||||
* @param regex - regular expression to check against
|
||||
* @return this
|
||||
*/
|
||||
@@ -48,7 +65,7 @@ public class CollectionAssert<ELEMENT> extends IterableAssert<ELEMENT> {
|
||||
|
||||
/**
|
||||
* Flattens the collection and checks whether size is greater than or equal to the
|
||||
* provided value
|
||||
* provided value.
|
||||
* @param size - the flattened collection should have size greater than or equal to
|
||||
* this value
|
||||
* @return this
|
||||
@@ -65,7 +82,7 @@ public class CollectionAssert<ELEMENT> extends IterableAssert<ELEMENT> {
|
||||
|
||||
/**
|
||||
* Flattens the collection and checks whether size is less than or equal to the
|
||||
* provided value
|
||||
* provided value.
|
||||
* @param size - the flattened collection should have size less than or equal to this
|
||||
* value
|
||||
* @return this
|
||||
@@ -81,7 +98,7 @@ public class CollectionAssert<ELEMENT> extends IterableAssert<ELEMENT> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattens the collection and checks whether size is between the provided value
|
||||
* Flattens the collection and checks whether size is between the provided value.
|
||||
* @param lowerBound - the flattened collection should have size greater than or equal
|
||||
* to this value
|
||||
* @param higherBound - the flattened collection should have size less than or equal
|
||||
@@ -99,7 +116,7 @@ public class CollectionAssert<ELEMENT> extends IterableAssert<ELEMENT> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether size is greater than or equal to the provided value
|
||||
* Checks whether size is greater than or equal to the provided value.
|
||||
* @param size - the collection should have size greater than or equal to this value
|
||||
* @return this
|
||||
*/
|
||||
@@ -114,7 +131,7 @@ public class CollectionAssert<ELEMENT> extends IterableAssert<ELEMENT> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether size is less than or equal to the provided value
|
||||
* Checks whether size is less than or equal to the provided value.
|
||||
* @param size - the collection should have size less than or equal to this value
|
||||
* @return this
|
||||
*/
|
||||
@@ -129,7 +146,7 @@ public class CollectionAssert<ELEMENT> extends IterableAssert<ELEMENT> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether size is between the provided value
|
||||
* Checks whether size is between the provided value.
|
||||
* @param lowerBound - the collection should have size greater than or equal to this
|
||||
* value
|
||||
* @param higherBound - the collection should have size less than or equal to this
|
||||
|
||||
@@ -1,9 +1,25 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.assertion;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
|
||||
/**
|
||||
* Assertions used by the generated tests
|
||||
* Assertions used by the generated tests.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.1.0
|
||||
@@ -12,6 +28,7 @@ public class SpringCloudContractAssertions extends Assertions {
|
||||
|
||||
/**
|
||||
* Creates a new instance of <code>{@link CollectionAssert}</code>.
|
||||
* @param <ELEMENT> type to assert
|
||||
* @param actual the actual value.
|
||||
* @return the created assertion object.
|
||||
*/
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.messaging;
|
||||
@@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit;
|
||||
* Destination is relevant to the underlying implementation. Might be a channel, queue,
|
||||
* topic etc.
|
||||
*
|
||||
* @param <M> message type
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@@ -32,24 +33,35 @@ public interface MessageVerifier<M> {
|
||||
|
||||
/**
|
||||
* Sends the message to the given destination.
|
||||
* @param message to send
|
||||
* @param destination destination to which the message will be sent
|
||||
*/
|
||||
void send(M message, String destination);
|
||||
|
||||
/**
|
||||
* Sends the given payload with headers, to the given destination.
|
||||
* @param <T> payload type
|
||||
* @param payload payload to send
|
||||
* @param headers headers to send
|
||||
* @param destination destination to which the message will be sent
|
||||
*/
|
||||
<T> void send(T payload, Map<String, Object> headers, String destination);
|
||||
|
||||
/**
|
||||
* Receives the message from the given destination. You can provide the timeout for
|
||||
* receiving that message.
|
||||
* @param destination destination from which the message will be received
|
||||
* @param timeout timeout to wait for the message
|
||||
* @param timeUnit param to define the unit of timeout
|
||||
* @return received message
|
||||
*/
|
||||
M receive(String destination, long timeout, TimeUnit timeUnit);
|
||||
|
||||
/**
|
||||
* Receives the message from the given destination. A default timeout will be applied.
|
||||
* @param destination destination from which the message will be received
|
||||
* @return received message
|
||||
*/
|
||||
M receive(String destination);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.messaging.amqp;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.amqp.core.Binding;
|
||||
@@ -43,9 +41,11 @@ import org.springframework.cloud.contract.verifier.messaging.stream.ContractVeri
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
/**
|
||||
* Configuration setting up {@link MessageVerifier} for use with plain
|
||||
* spring-rabbit/spring-amqp
|
||||
* spring-rabbit/spring-amqp.
|
||||
*
|
||||
* @author Mathias Düsterhöft
|
||||
* @since 1.0.2
|
||||
@@ -91,7 +91,7 @@ class ContractVerifierHelper extends ContractVerifierMessaging<Message> {
|
||||
|
||||
private final MessageConverter messageConverter;
|
||||
|
||||
public ContractVerifierHelper(MessageVerifier<Message> exchange,
|
||||
ContractVerifierHelper(MessageVerifier<Message> exchange,
|
||||
MessageConverter messageConverter) {
|
||||
super(exchange);
|
||||
this.messageConverter = messageConverter;
|
||||
@@ -101,7 +101,8 @@ class ContractVerifierHelper extends ContractVerifierMessaging<Message> {
|
||||
protected ContractVerifierMessage convert(Message message) {
|
||||
MessagingMessageConverter messageConverter = new MessagingMessageConverter(
|
||||
this.messageConverter, new SimpleAmqpHeaderMapper());
|
||||
org.springframework.messaging.Message<?> messagingMessage = (org.springframework.messaging.Message<?>) messageConverter
|
||||
org.springframework.messaging.Message<?> messagingMessage;
|
||||
messagingMessage = (org.springframework.messaging.Message<?>) messageConverter
|
||||
.fromMessage(message);
|
||||
return new ContractVerifierMessage(messagingMessage.getPayload(),
|
||||
messagingMessage.getHeaders());
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.messaging.amqp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -12,13 +28,13 @@ import org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistry;
|
||||
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
|
||||
|
||||
/**
|
||||
* Abstraction hiding details of the different sources of message listeners
|
||||
* Abstraction hiding details of the different sources of message listeners.
|
||||
*
|
||||
* Needed because
|
||||
* {@link org.springframework.amqp.rabbit.annotation.RabbitListenerAnnotationBeanPostProcessor}
|
||||
* adds the listeners to the {@link RabbitListenerEndpointRegistry} so that the registry
|
||||
* is empty when wired into an auto configuration class so we wrap it in the accessor to
|
||||
* access the listeners late at runtime
|
||||
* access the listeners late at runtime.
|
||||
*
|
||||
* @author Mathias Düsterhöft
|
||||
* @since 1.0.2
|
||||
|
||||
@@ -1,12 +1,28 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.verifier.messaging.amqp;
|
||||
|
||||
import com.rabbitmq.client.AMQP;
|
||||
import com.rabbitmq.client.Channel;
|
||||
import com.rabbitmq.client.Connection;
|
||||
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
|
||||
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.messaging.amqp;
|
||||
@@ -24,6 +24,7 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.core.MessageListener;
|
||||
import org.springframework.amqp.core.MessagePropertiesBuilder;
|
||||
@@ -86,18 +87,17 @@ public class SpringAmqpStubMessages implements MessageVerifier<Message> {
|
||||
public <T> void send(T payload, Map<String, Object> headers, String destination) {
|
||||
Message message = org.springframework.amqp.core.MessageBuilder
|
||||
.withBody(((String) payload).getBytes())
|
||||
.andProperties(
|
||||
MessagePropertiesBuilder.newInstance()
|
||||
.setContentType(header(headers, "contentType"))
|
||||
.copyHeaders(headers).build())
|
||||
.andProperties(MessagePropertiesBuilder.newInstance()
|
||||
.setContentType(header(headers, "contentType"))
|
||||
.copyHeaders(headers).build())
|
||||
.build();
|
||||
if (headers != null && headers.containsKey(DEFAULT_CLASSID_FIELD_NAME)) {
|
||||
message.getMessageProperties().setHeader(DEFAULT_CLASSID_FIELD_NAME,
|
||||
headers.get(DEFAULT_CLASSID_FIELD_NAME));
|
||||
}
|
||||
if (headers != null && headers.containsKey(AmqpHeaders.RECEIVED_ROUTING_KEY)) {
|
||||
message.getMessageProperties()
|
||||
.setReceivedRoutingKey(header(headers, AmqpHeaders.RECEIVED_ROUTING_KEY));
|
||||
message.getMessageProperties().setReceivedRoutingKey(
|
||||
header(headers, AmqpHeaders.RECEIVED_ROUTING_KEY));
|
||||
}
|
||||
send(message, destination);
|
||||
}
|
||||
@@ -109,7 +109,8 @@ public class SpringAmqpStubMessages implements MessageVerifier<Message> {
|
||||
Object value = headers.get(headerName);
|
||||
if (value instanceof String) {
|
||||
return (String) value;
|
||||
} else if (value instanceof Iterable) {
|
||||
}
|
||||
else if (value instanceof Iterable) {
|
||||
Iterable values = ((Iterable) value);
|
||||
return values.iterator().hasNext() ? (String) values.iterator().next() : "";
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.messaging.camel;
|
||||
@@ -27,6 +27,7 @@ import org.apache.camel.ProducerTemplate;
|
||||
import org.apache.camel.impl.DefaultExchange;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.contract.verifier.messaging.MessageVerifier;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -37,10 +38,10 @@ import org.springframework.stereotype.Component;
|
||||
@Component
|
||||
public class CamelStubMessages implements MessageVerifier<Message> {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(
|
||||
CamelStubMessages.class);
|
||||
private static final Logger log = LoggerFactory.getLogger(CamelStubMessages.class);
|
||||
|
||||
private final CamelContext context;
|
||||
|
||||
private final ContractVerifierCamelMessageBuilder builder;
|
||||
|
||||
@Autowired
|
||||
@@ -56,9 +57,10 @@ public class CamelStubMessages implements MessageVerifier<Message> {
|
||||
Exchange exchange = new DefaultExchange(this.context);
|
||||
exchange.setIn(message);
|
||||
producerTemplate.send(destination, exchange);
|
||||
} catch (Exception e) {
|
||||
log.error("Exception occurred while trying to send a message [" + message + "] " +
|
||||
"to a channel with name [" + destination + "]", e);
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("Exception occurred while trying to send a message [" + message
|
||||
+ "] " + "to a channel with name [" + destination + "]", e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@@ -72,11 +74,13 @@ public class CamelStubMessages implements MessageVerifier<Message> {
|
||||
public Message receive(String destination, long timeout, TimeUnit timeUnit) {
|
||||
try {
|
||||
ConsumerTemplate consumerTemplate = this.context.createConsumerTemplate();
|
||||
Exchange exchange = consumerTemplate.receive(destination, timeUnit.toMillis(timeout));
|
||||
Exchange exchange = consumerTemplate.receive(destination,
|
||||
timeUnit.toMillis(timeout));
|
||||
return exchange.getIn();
|
||||
} catch (Exception e) {
|
||||
log.error("Exception occurred while trying to read a message from " +
|
||||
" a channel with name [" + destination + "]", e);
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("Exception occurred while trying to read a message from "
|
||||
+ " a channel with name [" + destination + "]", e);
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.messaging.camel;
|
||||
@@ -19,13 +19,18 @@ package org.springframework.cloud.contract.verifier.messaging.camel;
|
||||
import org.apache.camel.CamelContext;
|
||||
import org.apache.camel.Message;
|
||||
import org.apache.camel.spring.boot.CamelAutoConfiguration;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.condition.*;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.cloud.contract.verifier.messaging.MessageVerifier;
|
||||
import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage;
|
||||
import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging;
|
||||
import org.springframework.cloud.contract.verifier.messaging.noop.NoOpContractVerifierAutoConfiguration;
|
||||
import org.springframework.context.annotation.*;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
@@ -33,14 +38,13 @@ import org.springframework.context.annotation.*;
|
||||
@Configuration
|
||||
@ConditionalOnClass(Message.class)
|
||||
@Import(CamelAutoConfiguration.class)
|
||||
@ConditionalOnProperty(name="stubrunner.camel.enabled", havingValue="true", matchIfMissing = true)
|
||||
@ConditionalOnProperty(name = "stubrunner.camel.enabled", havingValue = "true", matchIfMissing = true)
|
||||
@AutoConfigureBefore(NoOpContractVerifierAutoConfiguration.class)
|
||||
public class ContractVerifierCamelConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
MessageVerifier<Message> contractVerifierMessageExchange(
|
||||
CamelContext camelContext) {
|
||||
MessageVerifier<Message> contractVerifierMessageExchange(CamelContext camelContext) {
|
||||
return new CamelStubMessages(camelContext);
|
||||
}
|
||||
|
||||
@@ -50,12 +54,12 @@ public class ContractVerifierCamelConfiguration {
|
||||
MessageVerifier<Message> exchange) {
|
||||
return new ContractVerifierCamelHelper(exchange);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ContractVerifierCamelHelper extends ContractVerifierMessaging<Message> {
|
||||
|
||||
public ContractVerifierCamelHelper(
|
||||
MessageVerifier<Message> exchange) {
|
||||
ContractVerifierCamelHelper(MessageVerifier<Message> exchange) {
|
||||
super(exchange);
|
||||
}
|
||||
|
||||
@@ -63,4 +67,5 @@ class ContractVerifierCamelHelper extends ContractVerifierMessaging<Message> {
|
||||
protected ContractVerifierMessage convert(Message receive) {
|
||||
return new ContractVerifierMessage(receive.getBody(), receive.getHeaders());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.messaging.camel;
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.messaging.integration;
|
||||
@@ -57,7 +57,7 @@ public class ContractVerifierIntegrationConfiguration {
|
||||
|
||||
class ContractVerifierHelper extends ContractVerifierMessaging<Message<?>> {
|
||||
|
||||
public ContractVerifierHelper(MessageVerifier<Message<?>> exchange) {
|
||||
ContractVerifierHelper(MessageVerifier<Message<?>> exchange) {
|
||||
super(exchange);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.messaging.integration;
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.messaging.integration;
|
||||
@@ -21,6 +21,7 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.contract.verifier.messaging.MessageVerifier;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
@@ -54,19 +54,20 @@ public class ContractVerifierMessage {
|
||||
if (this.payload instanceof byte[]) {
|
||||
return (byte[]) this.payload;
|
||||
}
|
||||
throw new IllegalStateException("Payload [" + this.payload.getClass() + "]" + "is not instance of byte[]");
|
||||
throw new IllegalStateException("Payload [" + this.payload.getClass() + "]"
|
||||
+ "is not instance of byte[]");
|
||||
}
|
||||
|
||||
public Map<String, Object> getHeaders() {
|
||||
return this.headers;
|
||||
}
|
||||
|
||||
public Object getHeader(String name) {
|
||||
return this.headers.get(name);
|
||||
}
|
||||
|
||||
public void setHeaders(Map<String, Object> headers) {
|
||||
this.headers = headers;
|
||||
}
|
||||
|
||||
public Object getHeader(String name) {
|
||||
return this.headers.get(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,8 +21,12 @@ import java.util.Map;
|
||||
import org.springframework.cloud.contract.verifier.messaging.MessageVerifier;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* Wrapper around messaging. Abstracts all message related operations like sending,
|
||||
* converting and receiving. Delegates the actual work to an implementation of a
|
||||
* {@link MessageVerifier}.
|
||||
*
|
||||
* @param <M> message type
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class ContractVerifierMessaging<M> {
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.messaging.internal;
|
||||
@@ -50,9 +50,11 @@ public class ContractVerifierObjectMapper {
|
||||
public byte[] writeValueAsBytes(Object payload) throws JsonProcessingException {
|
||||
if (payload instanceof String) {
|
||||
return payload.toString().getBytes();
|
||||
} else if (payload instanceof byte[]) {
|
||||
}
|
||||
else if (payload instanceof byte[]) {
|
||||
return (byte[]) payload;
|
||||
}
|
||||
return this.objectMapper.writeValueAsBytes(payload);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.messaging.noop;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
@@ -26,10 +28,8 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* Verifier auto configuration containing default beans for messaging
|
||||
* Verifier auto configuration containing default beans for messaging.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.messaging.noop;
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.messaging.stream;
|
||||
@@ -59,7 +59,7 @@ public class ContractVerifierStreamAutoConfiguration {
|
||||
|
||||
class ContractVerifierHelper extends ContractVerifierMessaging<Message<?>> {
|
||||
|
||||
public ContractVerifierHelper(MessageVerifier<Message<?>> exchange) {
|
||||
ContractVerifierHelper(MessageVerifier<Message<?>> exchange) {
|
||||
super(exchange);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.messaging.stream;
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.messaging.stream;
|
||||
@@ -22,6 +22,7 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.messaging.MessageVerifier;
|
||||
import org.springframework.cloud.stream.config.BindingProperties;
|
||||
import org.springframework.cloud.stream.config.BindingServiceProperties;
|
||||
@@ -31,6 +32,12 @@ import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
enum DefaultChannels {
|
||||
|
||||
INPUT, OUTPUT
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
@@ -140,9 +147,3 @@ public class StreamStubMessages implements MessageVerifier<Message<?>> {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum DefaultChannels {
|
||||
|
||||
INPUT, OUTPUT
|
||||
|
||||
}
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://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.
|
||||
* 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.verifier.messaging.util;
|
||||
@@ -22,16 +22,26 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Helper class that allows to build headers in a nice way
|
||||
* Helper class that allows to build headers in a nice way.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
public class ContractVerifierMessagingUtil {
|
||||
public final class ContractVerifierMessagingUtil {
|
||||
|
||||
private ContractVerifierMessagingUtil() {
|
||||
throw new IllegalStateException("Can't instantiate a utility class");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a builder for headers
|
||||
*/
|
||||
public static ContractVerifierHeaders headers() {
|
||||
return new ContractVerifierHeaders();
|
||||
}
|
||||
|
||||
/**
|
||||
* A map with a fluent interface. Thanks to this, the generated tests look much nicer.
|
||||
*/
|
||||
public static class ContractVerifierHeaders implements Map<String, Object> {
|
||||
|
||||
private final Map<String, Object> delegate = new HashMap<>();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user