├── core ├── README.md ├── support │ ├── README.md │ └── src │ │ └── main │ │ ├── java │ │ └── au │ │ │ └── com │ │ │ └── dius │ │ │ └── pact │ │ │ └── core │ │ │ └── support │ │ │ └── NonNullApi.java │ │ └── kotlin │ │ └── au │ │ └── com │ │ └── dius │ │ └── pact │ │ ├── core │ │ └── support │ │ │ ├── expressions │ │ │ └── ValueResolver.kt │ │ │ └── Utils.kt │ │ └── com │ │ └── github │ │ └── michaelbull │ │ └── result │ │ └── On.kt ├── matchers │ ├── README.md │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── au │ │ │ └── com │ │ │ └── dius │ │ │ └── pact │ │ │ └── core │ │ │ └── matchers │ │ │ └── BodyMatcher.kt │ │ └── test │ │ └── groovy │ │ └── au │ │ └── com │ │ └── dius │ │ └── pact │ │ └── core │ │ └── matchers │ │ └── ResponseMatchingSpec.groovy ├── pact-broker │ ├── README.md │ └── src │ │ └── main │ │ └── kotlin │ │ └── au │ │ └── com │ │ └── dius │ │ └── pact │ │ └── core │ │ └── pactbroker │ │ └── PactBrokerConsumer.kt └── model │ ├── src │ ├── test │ │ └── groovy │ │ │ └── au │ │ │ └── com │ │ │ └── dius │ │ │ └── pact │ │ │ └── core │ │ │ └── model │ │ │ ├── generators │ │ │ └── test │ │ │ │ ├── pkg1 │ │ │ │ └── Pkg1Generator.groovy │ │ │ │ ├── pkg2 │ │ │ │ └── Pkg2Generator.groovy │ │ │ │ └── pkg3 │ │ │ │ └── Pkg3Generator.groovy │ │ │ └── BasePactSpec.groovy │ └── main │ │ └── kotlin │ │ └── au │ │ └── com │ │ └── dius │ │ └── pact │ │ └── core │ │ └── model │ │ ├── PactSpecVersion.kt │ │ └── annotations │ │ └── PactFolder.kt │ └── README.md ├── consumer ├── README.md ├── pact-jvm-consumer-junit │ └── src │ │ ├── test │ │ ├── resources │ │ │ └── keystore │ │ │ │ ├── pact-jvm-512.jks │ │ │ │ └── pact-jvm-other.jks │ │ ├── groovy │ │ │ └── au │ │ │ │ └── com │ │ │ │ └── dius │ │ │ │ └── pact │ │ │ │ └── consumer │ │ │ │ └── junit │ │ │ │ └── formpost │ │ │ │ └── Animal.groovy │ │ └── java │ │ │ └── au │ │ │ └── com │ │ │ └── dius │ │ │ └── pact │ │ │ └── consumer │ │ │ └── events │ │ │ └── EventRequest.java │ │ └── main │ │ └── java │ │ └── au │ │ └── com │ │ └── dius │ │ └── pact │ │ └── consumer │ │ └── junit │ │ └── PactVerifications.java ├── pact-jvm-consumer-java8 │ ├── src │ │ ├── main │ │ │ └── java │ │ │ │ └── io │ │ │ │ └── pactfoundation │ │ │ │ └── consumer │ │ │ │ └── dsl │ │ │ │ └── package-info.java │ │ └── test │ │ │ └── kotlin │ │ │ └── io │ │ │ └── pactfoundation │ │ │ └── consumer │ │ │ └── dsl │ │ │ └── ExtensionsTest.kt │ └── build.gradle ├── pact-jvm-consumer │ └── src │ │ └── main │ │ ├── kotlin │ │ └── au │ │ │ └── com │ │ │ └── dius │ │ │ └── pact │ │ │ └── consumer │ │ │ ├── PactTestExecutionContext.kt │ │ │ ├── Headers.kt │ │ │ ├── PactMismatchesException.kt │ │ │ └── dsl │ │ │ └── Dsl.kt │ │ └── java │ │ └── au │ │ └── com │ │ └── dius │ │ └── pact │ │ └── consumer │ │ └── InvalidMatcherException.java └── pact-jvm-consumer-groovy │ └── src │ └── main │ └── groovy │ └── au │ └── com │ └── dius │ └── pact │ └── consumer │ └── groovy │ ├── AndMatcher.groovy │ ├── LikeMatcher.groovy │ ├── OrMatcher.groovy │ ├── GeneratedValue.groovy │ ├── InvalidMatcherException.groovy │ ├── NullMatcher.groovy │ ├── EqualsMatcher.groovy │ ├── IncludeMatcher.groovy │ ├── EachLikeMatcher.groovy │ ├── ValuesMatcher.groovy │ ├── Matcher.groovy │ ├── MaxLikeMatcher.groovy │ ├── MinLikeMatcher.groovy │ ├── MinMaxLikeMatcher.groovy │ └── BaseBuilder.groovy ├── provider ├── README.md ├── pact-jvm-provider-sbt │ └── project │ │ ├── build.properties │ │ └── plugins.sbt ├── pact-jvm-provider-scalasupport │ ├── README.md │ └── src │ │ ├── test │ │ └── resources │ │ │ ├── pact-config-invalid.json │ │ │ ├── pact-config-no-statechange-url.json │ │ │ └── pact-config.json │ │ └── main │ │ └── scala │ │ └── au │ │ └── com │ │ └── dius │ │ └── pact │ │ └── provider │ │ ├── ServiceInvokeRequest.scala │ │ └── EnterStateRequest.scala ├── pact-jvm-provider │ └── src │ │ ├── test │ │ ├── resources │ │ │ └── dropwizard │ │ │ │ └── test-config.yaml │ │ ├── groovy │ │ │ └── au │ │ │ │ └── com │ │ │ │ └── dius │ │ │ │ └── pact │ │ │ │ └── provider │ │ │ │ ├── readme │ │ │ │ └── dropwizard │ │ │ │ │ ├── DropwizardConfiguration.groovy │ │ │ │ │ └── TestDropwizardApplication.groovy │ │ │ │ └── TestVerifyResponseByInvokingProviderMethodsClass.groovy │ │ └── scala │ │ │ └── au │ │ │ └── com │ │ │ └── dius │ │ │ └── pact │ │ │ └── provider │ │ │ └── GroovyScalaUtils.scala │ │ └── main │ │ ├── java │ │ └── au │ │ │ └── com │ │ │ └── dius │ │ │ └── pact │ │ │ └── provider │ │ │ └── junit │ │ │ ├── StateChangeAction.java │ │ │ └── loader │ │ │ └── NoPactsFoundException.java │ │ └── kotlin │ │ └── au │ │ └── com │ │ └── dius │ │ └── pact │ │ └── provider │ │ └── junit │ │ ├── target │ │ └── TestTarget.kt │ │ └── Consumer.kt ├── pact-jvm-provider-gradle │ └── src │ │ ├── main │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── gradle-plugins │ │ │ │ └── au.com.dius.pact.properties │ │ └── groovy │ │ │ └── au │ │ │ └── com │ │ │ └── dius │ │ │ └── pact │ │ │ └── provider │ │ │ └── gradle │ │ │ └── StateChangeUrl.groovy │ │ └── test │ │ └── resources │ │ └── pacts │ │ ├── bar_pact.json │ │ └── foo_pact.json ├── pact-jvm-provider-junit │ └── src │ │ ├── test │ │ ├── resources │ │ │ ├── articles.json │ │ │ └── logback.groovy │ │ ├── java │ │ │ └── au │ │ │ │ └── com │ │ │ │ └── dius │ │ │ │ └── pact │ │ │ │ └── provider │ │ │ │ └── junit │ │ │ │ └── Git.java │ │ └── groovy │ │ │ └── au │ │ │ └── com │ │ │ └── dius │ │ │ └── pact │ │ │ └── provider │ │ │ └── junit │ │ │ └── JUnitProviderTestSupportSpec.groovy │ │ └── main │ │ └── kotlin │ │ └── au │ │ └── com │ │ └── dius │ │ └── pact │ │ └── provider │ │ └── junit │ │ └── target │ │ └── TestClassAwareTarget.kt ├── pact-jvm-provider-scalatest │ ├── README.md │ ├── build.gradle │ └── src │ │ └── main │ │ └── scala │ │ └── au │ │ └── com │ │ └── dius │ │ └── pact │ │ └── provider │ │ └── scalatest │ │ └── Tags.scala ├── pact-jvm-provider-lein │ └── src │ │ ├── test │ │ └── clojure │ │ │ └── leiningen │ │ │ └── pact_verify_test.clj │ │ └── main │ │ └── resources │ │ └── META-INF │ │ └── leiningen │ │ └── au.com.dius │ │ └── pact-jvm-provider-lein_2.11 │ │ └── project.clj ├── pact-jvm-provider-junit5 │ └── src │ │ └── test │ │ └── resources │ │ └── logback.groovy ├── pact-jvm-provider-spring │ └── src │ │ ├── test │ │ └── java │ │ │ └── au │ │ │ └── com │ │ │ └── dius │ │ │ └── pact │ │ │ └── provider │ │ │ └── spring │ │ │ ├── BookType.java │ │ │ ├── BookNotFoundException.java │ │ │ └── BookValidationException.java │ │ └── main │ │ └── kotlin │ │ └── au │ │ └── com │ │ └── dius │ │ └── pact │ │ └── provider │ │ └── spring │ │ └── target │ │ └── SpringBootHttpTarget.kt ├── pact-jvm-provider-specs2 │ ├── README.md │ └── src │ │ └── test │ │ ├── resources │ │ └── exampleSpec.json │ │ └── scala │ │ └── au │ │ └── com │ │ └── dius │ │ └── pact │ │ └── provider │ │ └── specs2 │ │ └── ExampleProviderSpec.scala └── pact-jvm-provider-maven │ └── src │ └── main │ └── groovy │ └── au │ └── com │ └── dius │ └── pact │ └── provider │ └── maven │ ├── PactBroker.groovy │ ├── PactBrokerAuth.groovy │ └── Provider.groovy ├── pact-specification-test ├── src │ ├── test │ │ ├── resources │ │ │ └── log4j.properties │ │ └── groovy │ │ │ └── specification │ │ │ └── RequestSpecificationV3Spec.groovy │ └── main │ │ └── resources │ │ ├── v2 │ │ ├── response │ │ │ ├── status │ │ │ │ ├── matches.json │ │ │ │ └── different status.json │ │ │ ├── headers │ │ │ │ ├── empty headers.json │ │ │ │ ├── unexpected header found.json │ │ │ │ ├── header name is different case.json │ │ │ │ ├── header value is different case.json │ │ │ │ ├── matches.json │ │ │ │ ├── whitespace after comma different.json │ │ │ │ ├── order of comma separated header values different.json │ │ │ │ └── matches with regex.json │ │ │ └── body │ │ │ │ ├── missing body found when empty expected.json │ │ │ │ ├── empty body no content type.json │ │ │ │ ├── null body no content type.json │ │ │ │ ├── empty body.json │ │ │ │ ├── null body.json │ │ │ │ ├── no body no content type xml.json │ │ │ │ ├── plain text that matches.json │ │ │ │ ├── missing body xml.json │ │ │ │ ├── plain text that does not match.json │ │ │ │ ├── no body no content type.json │ │ │ │ ├── missing body no content type.json │ │ │ │ ├── missing body.json │ │ │ │ ├── missing key.json │ │ │ │ ├── different value found at key xml.json │ │ │ │ ├── different value found at key.json │ │ │ │ ├── missing key xml.json │ │ │ │ ├── not null found at key when null expected.json │ │ │ │ ├── null found at key where not null expected.json │ │ │ │ ├── missing index.json │ │ │ │ ├── unexpected key with non-empty value xml.json │ │ │ │ ├── number found at key when string expected.json │ │ │ │ ├── string found at key when number expected.json │ │ │ │ ├── unexpected key with empty value xml.json │ │ │ │ ├── keys out of order match.json │ │ │ │ ├── property name is different case xml.json │ │ │ │ ├── property name is different case.json │ │ │ │ ├── unexpected key with not null value.json │ │ │ │ ├── array in different order.json │ │ │ │ ├── different value found at index.json │ │ │ │ ├── non empty body found when empty expected.json │ │ │ │ ├── unexpected key with null value.json │ │ │ │ └── unexpected index with not null value.json │ │ └── request │ │ │ ├── method │ │ │ ├── matches.json │ │ │ ├── different method.json │ │ │ └── method is different case.json │ │ │ ├── headers │ │ │ ├── empty headers.json │ │ │ ├── unexpected header found.json │ │ │ ├── header name is different case.json │ │ │ ├── header value is different case.json │ │ │ ├── matches.json │ │ │ └── whitespace after comma different.json │ │ │ ├── path │ │ │ ├── matches.json │ │ │ ├── incorrect path.json │ │ │ ├── empty path found when forward slash expected.json │ │ │ ├── forward slash found when empty path expected.json │ │ │ ├── missing trailing slash in path.json │ │ │ └── unexpected trailing slash in path.json │ │ │ ├── body │ │ │ ├── missing body found when empty expected.json │ │ │ ├── empty body no content type.json │ │ │ ├── null body no content type.json │ │ │ ├── empty body.json │ │ │ ├── null body.json │ │ │ ├── no body no content type.json │ │ │ ├── no body no content type xml.json │ │ │ ├── missing body no content type.json │ │ │ ├── no body xml.json │ │ │ ├── no body.json │ │ │ ├── plain text that matches.json │ │ │ ├── missing body.json │ │ │ └── plain text that does not match.json │ │ │ └── query │ │ │ ├── matches.json │ │ │ ├── trailing ampersand.json │ │ │ ├── different order.json │ │ │ ├── different params.json │ │ │ ├── missing params.json │ │ │ ├── unexpected param.json │ │ │ ├── matches with equals in the query value.json │ │ │ ├── same parameter different values.json │ │ │ ├── same parameter multiple times in different order.json │ │ │ └── same parameter multiple times.json │ │ ├── v3 │ │ ├── response │ │ │ ├── status │ │ │ │ ├── matches.json │ │ │ │ └── different status.json │ │ │ ├── headers │ │ │ │ ├── empty headers.json │ │ │ │ ├── unexpected header found.json │ │ │ │ ├── header name is different case.json │ │ │ │ ├── header value is different case.json │ │ │ │ ├── matches.json │ │ │ │ ├── whitespace after comma different.json │ │ │ │ ├── matches content type with charset.json │ │ │ │ ├── content type parameters do not match.json │ │ │ │ ├── order of comma separated header values different.json │ │ │ │ └── matches content type with parameters in different order.json │ │ │ └── body │ │ │ │ ├── missing body found when empty expected.json │ │ │ │ ├── empty body no content type.json │ │ │ │ ├── null body no content type.json │ │ │ │ ├── plain text missing body.json │ │ │ │ ├── empty body.json │ │ │ │ ├── null body.json │ │ │ │ ├── plain text empty body.json │ │ │ │ ├── no body no content type xml.json │ │ │ │ ├── plain text that matches.json │ │ │ │ ├── missing body xml.json │ │ │ │ ├── plain text that does not match.json │ │ │ │ ├── no body no content type.json │ │ │ │ ├── missing body no content type.json │ │ │ │ ├── missing body.json │ │ │ │ ├── missing key.json │ │ │ │ ├── different value found at key xml.json │ │ │ │ ├── different value found at key.json │ │ │ │ ├── missing key xml.json │ │ │ │ ├── not null found at key when null expected.json │ │ │ │ ├── null found at key where not null expected.json │ │ │ │ ├── missing index.json │ │ │ │ ├── unexpected key with non-empty value xml.json │ │ │ │ ├── number found at key when string expected.json │ │ │ │ ├── string found at key when number expected.json │ │ │ │ ├── unexpected key with empty value xml.json │ │ │ │ ├── keys out of order match.json │ │ │ │ ├── property name is different case xml.json │ │ │ │ ├── property name is different case.json │ │ │ │ ├── unexpected key with not null value.json │ │ │ │ ├── array in different order.json │ │ │ │ ├── non empty body found when empty expected.json │ │ │ │ ├── different value found at index.json │ │ │ │ ├── unexpected key with null value.json │ │ │ │ └── unexpected index with not null value.json │ │ ├── request │ │ │ ├── method │ │ │ │ ├── matches.json │ │ │ │ ├── different method.json │ │ │ │ └── method is different case.json │ │ │ ├── headers │ │ │ │ ├── empty headers.json │ │ │ │ ├── unexpected header found.json │ │ │ │ ├── header name is different case.json │ │ │ │ ├── header value is different case.json │ │ │ │ ├── matches.json │ │ │ │ ├── whitespace after comma different.json │ │ │ │ └── matches content type with charset.json │ │ │ ├── path │ │ │ │ ├── matches.json │ │ │ │ ├── incorrect path.json │ │ │ │ ├── empty path found when forward slash expected.json │ │ │ │ ├── forward slash found when empty path expected.json │ │ │ │ ├── missing trailing slash in path.json │ │ │ │ └── unexpected trailing slash in path.json │ │ │ ├── body │ │ │ │ ├── missing body found when empty expected.json │ │ │ │ ├── empty body no content type.json │ │ │ │ ├── null body no content type.json │ │ │ │ ├── empty body.json │ │ │ │ ├── null body.json │ │ │ │ ├── no body no content type.json │ │ │ │ ├── no body no content type xml.json │ │ │ │ ├── missing body no content type.json │ │ │ │ ├── no body xml.json │ │ │ │ ├── no body.json │ │ │ │ ├── plain text that matches.json │ │ │ │ ├── missing body.json │ │ │ │ └── plain text that does not match.json │ │ │ └── query │ │ │ │ ├── matches.json │ │ │ │ ├── different order.json │ │ │ │ ├── different params.json │ │ │ │ └── same parameter different values.json │ │ └── message │ │ │ └── body │ │ │ ├── no body no content type.json │ │ │ ├── no body.json │ │ │ ├── missing key.json │ │ │ └── not null found at key when null expected.json │ │ ├── v1 │ │ ├── response │ │ │ ├── status │ │ │ │ ├── matches.json │ │ │ │ └── different status.json │ │ │ ├── headers │ │ │ │ ├── empty headers.json │ │ │ │ ├── unexpected header found.json │ │ │ │ ├── header name is different case.json │ │ │ │ ├── header value is different case.json │ │ │ │ ├── matches.json │ │ │ │ ├── whitespace after comma different.json │ │ │ │ └── order of comma separated header values different.json │ │ │ └── body │ │ │ │ ├── plain text that matches.json │ │ │ │ ├── plain text that does not match.json │ │ │ │ ├── missing key.json │ │ │ │ ├── not null found at key when null expected.json │ │ │ │ ├── different value found at key.json │ │ │ │ ├── null found at key where not null expected.json │ │ │ │ ├── missing index.json │ │ │ │ ├── number found at key when string expected.json │ │ │ │ ├── string found at key when number expected.json │ │ │ │ ├── array in different order.json │ │ │ │ ├── different value found at index.json │ │ │ │ ├── keys out of order match.json │ │ │ │ ├── objects in array first matches.json │ │ │ │ ├── property name is different case.json │ │ │ │ ├── unexpected key with not null value.json │ │ │ │ ├── unexpected key with null value.json │ │ │ │ ├── unexpected index with not null value.json │ │ │ │ ├── objects in array second matches.json │ │ │ │ ├── unexpected index with null value.json │ │ │ │ ├── string found in array when number expected.json │ │ │ │ ├── null found in array when not null expected.json │ │ │ │ ├── number found in array when string expected.json │ │ │ │ ├── objects in array no matches.json │ │ │ │ ├── not null found in array when null expected.json │ │ │ │ └── matches.json │ │ └── request │ │ │ ├── method │ │ │ ├── matches.json │ │ │ ├── different method.json │ │ │ └── method is different case.json │ │ │ ├── headers │ │ │ ├── empty headers.json │ │ │ ├── unexpected header found.json │ │ │ ├── header name is different case.json │ │ │ ├── header value is different case.json │ │ │ ├── matches.json │ │ │ └── whitespace after comma different.json │ │ │ ├── path │ │ │ ├── matches.json │ │ │ ├── incorrect path.json │ │ │ ├── empty path found when forward slash expected.json │ │ │ ├── forward slash found when empty path expected.json │ │ │ ├── missing trailing slash in path.json │ │ │ └── unexpected trailing slash in path.json │ │ │ ├── query │ │ │ ├── matches.json │ │ │ ├── different param values.json │ │ │ ├── matches with equals in the query value.json │ │ │ ├── different param order.json │ │ │ └── trailing amperand.json │ │ │ └── body │ │ │ ├── plain text that matches.json │ │ │ └── plain text that does not match.json │ │ └── v1.1 │ │ ├── response │ │ ├── headers │ │ │ ├── empty headers.json │ │ │ ├── unexpected header found.json │ │ │ ├── header name is different case.json │ │ │ ├── header value is different case.json │ │ │ ├── matches.json │ │ │ ├── whitespace after comma different.json │ │ │ └── order of comma separated header values different.json │ │ ├── status │ │ │ ├── matches.json │ │ │ └── different status.json │ │ └── body │ │ │ ├── missing body found when empty expected.json │ │ │ ├── empty body no content type.json │ │ │ ├── null body no content type.json │ │ │ ├── empty body.json │ │ │ ├── null body.json │ │ │ ├── plain text that matches.json │ │ │ ├── plain text that does not match.json │ │ │ ├── missing body no content type.json │ │ │ ├── missing key.json │ │ │ ├── not null found at key when null expected.json │ │ │ ├── different value found at key.json │ │ │ ├── null found at key where not null expected.json │ │ │ ├── missing index.json │ │ │ ├── missing body.json │ │ │ ├── number found at key when string expected.json │ │ │ ├── string found at key when number expected.json │ │ │ ├── array in different order.json │ │ │ ├── different value found at index.json │ │ │ ├── keys out of order match.json │ │ │ ├── property name is different case.json │ │ │ ├── unexpected key with not null value.json │ │ │ ├── objects in array first matches.json │ │ │ ├── unexpected key with null value.json │ │ │ ├── unexpected index with not null value.json │ │ │ ├── objects in array second matches.json │ │ │ ├── unexpected index with null value.json │ │ │ ├── string found in array when number expected.json │ │ │ ├── null found in array when not null expected.json │ │ │ ├── number found in array when string expected.json │ │ │ ├── objects in array no matches.json │ │ │ ├── not null found in array when null expected.json │ │ │ ├── matches.json │ │ │ └── non empty body found when empty expected.json │ │ └── request │ │ ├── method │ │ ├── matches.json │ │ ├── different method.json │ │ └── method is different case.json │ │ ├── headers │ │ ├── empty headers.json │ │ ├── unexpected header found.json │ │ ├── header name is different case.json │ │ ├── header value is different case.json │ │ ├── matches.json │ │ └── whitespace after comma different.json │ │ ├── path │ │ ├── matches.json │ │ ├── incorrect path.json │ │ ├── empty path found when forward slash expected.json │ │ ├── forward slash found when empty path expected.json │ │ ├── missing trailing slash in path.json │ │ └── unexpected trailing slash in path.json │ │ ├── body │ │ ├── missing body found when empty expected.json │ │ ├── empty body no content type.json │ │ ├── null body no content type.json │ │ ├── empty body.json │ │ ├── null body.json │ │ ├── missing body no content type.json │ │ ├── missing body.json │ │ ├── plain text that matches.json │ │ └── plain text that does not match.json │ │ └── query │ │ ├── matches.json │ │ ├── trailing ampersand.json │ │ ├── different order.json │ │ ├── different params.json │ │ ├── missing params.json │ │ ├── unexpected param.json │ │ ├── matches with equals in the query value.json │ │ ├── same parameter different values.json │ │ ├── same parameter multiple times in different order.json │ │ └── same parameter multiple times.json ├── README.md └── build.gradle ├── pact-publish └── README.md ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .github └── FUNDING.yml ├── pact-jvm-server └── src │ ├── test │ └── resources │ │ └── keystore │ │ └── pact-jvm-512.jks │ └── main │ └── scala │ └── au │ └── com │ └── dius │ └── pact │ └── server │ ├── package.scala │ └── ResponseUtils.scala ├── appveyor.yml └── gradle.properties /core/README.md: -------------------------------------------------------------------------------- 1 | Core Pact-JVM Modules 2 | ===================== 3 | -------------------------------------------------------------------------------- /consumer/README.md: -------------------------------------------------------------------------------- 1 | Consumer Pact-JVM Modules 2 | ========================= 3 | -------------------------------------------------------------------------------- /provider/README.md: -------------------------------------------------------------------------------- 1 | Provider Pact-JVM Modules 2 | ========================= 3 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-sbt/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.0.3 2 | -------------------------------------------------------------------------------- /pact-specification-test/src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | logger.level=DEBUG 2 | 3 | -------------------------------------------------------------------------------- /core/support/README.md: -------------------------------------------------------------------------------- 1 | # pact-jvm-support 2 | 3 | Support module with common utilities 4 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-scalasupport/README.md: -------------------------------------------------------------------------------- 1 | Scala Support classes 2 | ===================== 3 | -------------------------------------------------------------------------------- /pact-publish/README.md: -------------------------------------------------------------------------------- 1 | # Pact Publish 2 | 3 | Module for generating and publishing pacts to the pact broker 4 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-sbt/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.0") 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nitro/pact-jvm/master/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /core/matchers/README.md: -------------------------------------------------------------------------------- 1 | Pact JVM Matchers 2 | ================= 3 | 4 | Implements matchers for pact requests and responses. 5 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | open_collective: pact-foundation 4 | custom: ['https://pactflow.io'] 5 | -------------------------------------------------------------------------------- /core/pact-broker/README.md: -------------------------------------------------------------------------------- 1 | Pact Broker Client 2 | ================== 3 | 4 | This module contains the client classes for interacting with a pact broker. 5 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider/src/test/resources/dropwizard/test-config.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | type: simple 3 | connector: 4 | type: http 5 | port: 8080 6 | -------------------------------------------------------------------------------- /pact-jvm-server/src/test/resources/keystore/pact-jvm-512.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nitro/pact-jvm/master/pact-jvm-server/src/test/resources/keystore/pact-jvm-512.jks -------------------------------------------------------------------------------- /provider/pact-jvm-provider-gradle/src/main/resources/META-INF/gradle-plugins/au.com.dius.pact.properties: -------------------------------------------------------------------------------- 1 | implementation-class=au.com.dius.pact.provider.gradle.PactPlugin 2 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-junit/src/test/resources/keystore/pact-jvm-512.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nitro/pact-jvm/master/consumer/pact-jvm-consumer-junit/src/test/resources/keystore/pact-jvm-512.jks -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-java8/src/main/java/io/pactfoundation/consumer/dsl/package-info.java: -------------------------------------------------------------------------------- 1 | @NonNullApi 2 | package io.pactfoundation.consumer.dsl; 3 | 4 | import au.com.dius.pact.core.support.NonNullApi; 5 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-junit/src/test/resources/keystore/pact-jvm-other.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nitro/pact-jvm/master/consumer/pact-jvm-consumer-junit/src/test/resources/keystore/pact-jvm-other.jks -------------------------------------------------------------------------------- /core/model/src/test/groovy/au/com/dius/pact/core/model/generators/test/pkg1/Pkg1Generator.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.core.model.generators.test.pkg1 2 | 3 | @SuppressWarnings('EmptyClass') 4 | class Pkg1Generator { 5 | } 6 | -------------------------------------------------------------------------------- /core/model/src/test/groovy/au/com/dius/pact/core/model/generators/test/pkg2/Pkg2Generator.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.core.model.generators.test.pkg2 2 | 3 | @SuppressWarnings('EmptyClass') 4 | class Pkg2Generator { 5 | } 6 | -------------------------------------------------------------------------------- /core/model/src/test/groovy/au/com/dius/pact/core/model/generators/test/pkg3/Pkg3Generator.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.core.model.generators.test.pkg3 2 | 3 | @SuppressWarnings('EmptyClass') 4 | class Pkg3Generator { 5 | } 6 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider/src/main/java/au/com/dius/pact/provider/junit/StateChangeAction.java: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider.junit; 2 | 3 | public enum StateChangeAction { 4 | 5 | SETUP, 6 | 7 | TEARDOWN; 8 | } 9 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer/src/main/kotlin/au/com/dius/pact/consumer/PactTestExecutionContext.kt: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer 2 | 3 | data class PactTestExecutionContext(var pactFolder: String = PactConsumerConfig.pactDirectory) 4 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-gradle/src/test/resources/pacts/bar_pact.json: -------------------------------------------------------------------------------- 1 | { 2 | "provider" : { 3 | "name" : "Provider" 4 | }, 5 | "consumer" : { 6 | "name" : "Bar Consumer" 7 | }, 8 | "interactions" : [] 9 | } -------------------------------------------------------------------------------- /provider/pact-jvm-provider-gradle/src/test/resources/pacts/foo_pact.json: -------------------------------------------------------------------------------- 1 | { 2 | "provider" : { 3 | "name" : "Provider" 4 | }, 5 | "consumer" : { 6 | "name" : "Foo Consumer" 7 | }, 8 | "interactions" : [] 9 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/status/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Status matches", 4 | "expected" : { 5 | "status" : 202 6 | }, 7 | "actual" : { 8 | "status" : 202 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/status/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Status matches", 4 | "expected" : { 5 | "status" : 202 6 | }, 7 | "actual" : { 8 | "status" : 202 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer/src/main/kotlin/au/com/dius/pact/consumer/Headers.kt: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer 2 | 3 | object Headers { 4 | const val MULTIPART_HEADER_REGEX = "multipart/form-data;(\\s*charset=[^;]*;)?\\s*boundary=.*" 5 | } 6 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/status/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Status matches", 4 | "expected" : { 5 | "status" : 202 6 | }, 7 | "actual" : { 8 | "status" : 202 9 | } 10 | } -------------------------------------------------------------------------------- /provider/pact-jvm-provider-scalasupport/src/test/resources/pact-config-invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "stateChangeUrl": { 3 | "protocol": "http", 4 | "host": "localhost", 5 | "port": 8888, 6 | "path": "/enterState" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-scalasupport/src/test/resources/pact-config-no-statechange-url.json: -------------------------------------------------------------------------------- 1 | { 2 | "providerRoot": { 3 | "protocol": "http", 4 | "host": "localhost", 5 | "port": 8888, 6 | "path": "" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/headers/empty headers.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Empty headers match", 4 | "expected" : { 5 | "headers": {} 6 | }, 7 | "actual": { 8 | "headers": {} 9 | } 10 | } -------------------------------------------------------------------------------- /provider/pact-jvm-provider-junit/src/test/resources/articles.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "articles": [ 4 | { 5 | "variants": { 6 | "1234": { 7 | "description": "sample description" 8 | } 9 | } 10 | } 11 | ] 12 | } -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer/src/main/kotlin/au/com/dius/pact/consumer/PactMismatchesException.kt: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer 2 | 3 | class PactMismatchesException(private val mismatches: PactVerificationResult) : AssertionError(mismatches.getDescription()) 4 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/headers/empty headers.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Empty headers match", 4 | "expected" : { 5 | "headers": {} 6 | 7 | }, 8 | "actual": { 9 | "headers": {} 10 | } 11 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/headers/empty headers.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Empty headers match", 4 | "expected" : { 5 | "headers": {} 6 | 7 | }, 8 | "actual": { 9 | "headers": {} 10 | } 11 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/status/different status.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Status is incorrect", 4 | "expected" : { 5 | "status" : 202 6 | }, 7 | "actual" : { 8 | "status" : 400 9 | } 10 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/headers/empty headers.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Empty headers match", 4 | "expected" : { 5 | "headers": {} 6 | 7 | }, 8 | "actual": { 9 | "headers": {} 10 | } 11 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/status/different status.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Status is incorrect", 4 | "expected": { 5 | "status": 202 6 | }, 7 | "actual": { 8 | "status": 400 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/status/different status.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Status is incorrect", 4 | "expected": { 5 | "status": 202 6 | }, 7 | "actual": { 8 | "status": 400 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-groovy/src/main/groovy/au/com/dius/pact/consumer/groovy/AndMatcher.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer.groovy 2 | 3 | /** 4 | * Matches if all provided matches match 5 | */ 6 | class AndMatcher extends Matcher { 7 | def matchers 8 | } 9 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/status/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Status matches", 4 | "expected": { 5 | "status": 202 6 | }, 7 | "actual": { 8 | "status": 202 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-groovy/src/main/groovy/au/com/dius/pact/consumer/groovy/LikeMatcher.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer.groovy 2 | 3 | /** 4 | * Base class for like matchers 5 | */ 6 | class LikeMatcher extends Matcher { 7 | Integer numberExamples = 1 8 | } 9 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-groovy/src/main/groovy/au/com/dius/pact/consumer/groovy/OrMatcher.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer.groovy 2 | 3 | /** 4 | * Matcher that matches if any provided matcher matches 5 | */ 6 | class OrMatcher extends Matcher { 7 | def matchers 8 | } 9 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider/src/test/groovy/au/com/dius/pact/provider/readme/dropwizard/DropwizardConfiguration.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider.readme.dropwizard 2 | 3 | import io.dropwizard.Configuration 4 | 5 | class DropwizardConfiguration extends Configuration { 6 | } 7 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/status/different status.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Status is incorrect", 4 | "expected": { 5 | "status": 202 6 | }, 7 | "actual": { 8 | "status": 400 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /pact-jvm-server/src/main/scala/au/com/dius/pact/server/package.scala: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact 2 | 3 | import au.com.dius.pact.core.model.RequestResponseInteraction 4 | 5 | package object server { 6 | type ServerState = Map[String, StatefulMockProvider[RequestResponseInteraction]] 7 | } 8 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/missing body found when empty expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Missing body found, when an empty body was expected", 4 | "expected" : { 5 | "body": null 6 | }, 7 | "actual": { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/missing body found when empty expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Missing body found, when an empty body was expected", 4 | "expected" : { 5 | "body": null 6 | }, 7 | "actual": { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/missing body found when empty expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Missing body found, when an empty body was expected", 4 | "expected" : { 5 | "body": null 6 | }, 7 | "actual": { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer/src/main/java/au/com/dius/pact/consumer/InvalidMatcherException.java: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer; 2 | 3 | public class InvalidMatcherException extends RuntimeException { 4 | 5 | public InvalidMatcherException(String message) { 6 | super(message); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-java8/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | api project(path: ":consumer:pact-jvm-consumer", configuration: 'default') 3 | 4 | testRuntime "org.junit.vintage:junit-vintage-engine:${project.junit5Version}" 5 | testRuntime "ch.qos.logback:logback-classic:${project.logbackVersion}" 6 | } 7 | -------------------------------------------------------------------------------- /pact-jvm-server/src/main/scala/au/com/dius/pact/server/ResponseUtils.scala: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.server 2 | 3 | import scala.collection.JavaConverters._ 4 | 5 | object ResponseUtils { 6 | val CrossSiteHeaders = Map[String, java.util.List[String]]("Access-Control-Allow-Origin" -> List("*").asJava) 7 | } 8 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/headers/unexpected header found.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Extra headers allowed", 4 | "expected" : { 5 | "headers": {} 6 | }, 7 | "actual": { 8 | "headers": { 9 | "Accept": "alligators" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/headers/unexpected header found.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Extra headers allowed", 4 | "expected" : { 5 | "headers": {} 6 | }, 7 | "actual": { 8 | "headers": { 9 | "Accept": "alligators" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/headers/unexpected header found.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Extra headers allowed", 4 | "expected" : { 5 | "headers": {} 6 | }, 7 | "actual": { 8 | "headers": { 9 | "Accept": "alligators" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/headers/unexpected header found.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Extra headers allowed", 4 | "expected" : { 5 | "headers": {} 6 | }, 7 | "actual": { 8 | "headers": { 9 | "Accept": "alligators" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-junit/src/test/groovy/au/com/dius/pact/consumer/junit/formpost/Animal.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer.junit.formpost 2 | 3 | import groovy.transform.Canonical 4 | 5 | @Canonical 6 | class Animal { 7 | String animalType 8 | String name 9 | List feedingLog = [] 10 | } 11 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer/src/main/kotlin/au/com/dius/pact/consumer/dsl/Dsl.kt: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer.dsl 2 | 3 | object Dsl { 4 | /** 5 | * Creates a builder to define the matchers on an array of JSON primitives 6 | */ 7 | @JvmStatic 8 | fun arrayOfPrimitives() = ArrayOfPrimitivesBuilder() 9 | } 10 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/empty body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Empty body, no content-type", 4 | "expected" : { 5 | "body": "" 6 | }, 7 | "actual": { 8 | "headers": {"Content-Type": "application/json"}, 9 | "body": "" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/empty body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Empty body, no content-type", 4 | "expected" : { 5 | "body": "" 6 | }, 7 | "actual": { 8 | "headers": {"Content-Type": "application/json"}, 9 | "body": "" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/null body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "NULL body, no content-type", 4 | "expected" : { 5 | "body": null 6 | }, 7 | "actual": { 8 | "headers": {"Content-Type": "application/json"}, 9 | "body": null 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/empty body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Empty body, no content-type", 4 | "expected" : { 5 | "body": "" 6 | }, 7 | "actual": { 8 | "headers": {"Content-Type": "application/json"}, 9 | "body": "" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/null body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "NULL body, no content-type", 4 | "expected" : { 5 | "body": null 6 | }, 7 | "actual": { 8 | "headers": {"Content-Type": "application/json"}, 9 | "body": null 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/plain text missing body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Plain text that matches", 4 | "expected" : { 5 | "headers": { "Content-Type": "text/plain" }, 6 | }, 7 | "actual": { 8 | "headers": { "Content-Type": "text/plain" } 9 | 10 | } 11 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/null body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "NULL body, no content-type", 4 | "expected" : { 5 | "body": null 6 | }, 7 | "actual": { 8 | "headers": {"Content-Type": "application/json"}, 9 | "body": null 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider/src/test/scala/au/com/dius/pact/provider/GroovyScalaUtils.scala: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider 2 | 3 | import _root_.org.apache.http.HttpRequest 4 | 5 | object GroovyScalaUtils { 6 | 7 | def testRequestFilter = (httpRequest: HttpRequest) => httpRequest.addHeader("Scala", "Was Called") 8 | 9 | } 10 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # fix lineendings in Windows 2 | init: 3 | - git config --global core.autocrlf input 4 | 5 | build: false 6 | 7 | build_script: 8 | - set JAVA_HOME=C:\Program Files\Java\jdk11 9 | - java -version 10 | - gradlew --version 11 | - gradlew --stacktrace --no-daemon -i check -x :consumer:pact-jvm-consumer-junit:clojureTest 12 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-scalatest/README.md: -------------------------------------------------------------------------------- 1 | pact-jvm-provider-scalatest 2 | ======================== 3 | 4 | Provides an extension to scalatest to validate pact files against a running provider. See 5 | [examples](src/test/scala/au/com/dius/pact/provider/scalatest) 6 | for details. 7 | 8 | *Note:* The Pact ProviderSpec requires scalatest 2.2.x 9 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-groovy/src/main/groovy/au/com/dius/pact/consumer/groovy/GeneratedValue.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer.groovy 2 | 3 | import groovy.transform.Canonical 4 | 5 | /** 6 | * Marker class for generated values 7 | */ 8 | @Canonical 9 | class GeneratedValue { 10 | String expression 11 | def exampleValue 12 | } 13 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/empty body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Empty body", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": "" 7 | }, 8 | "actual": { 9 | "headers": {"Content-Type": "application/json"}, 10 | "body": "" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/empty body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Empty body", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": "" 7 | }, 8 | "actual": { 9 | "headers": {"Content-Type": "application/json"}, 10 | "body": "" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/null body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "NULL body", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": null 7 | }, 8 | "actual": { 9 | "headers": {"Content-Type": "application/json"}, 10 | "body": null 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/empty body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Empty body", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": "" 7 | }, 8 | "actual": { 9 | "headers": {"Content-Type": "application/json"}, 10 | "body": "" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/null body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "NULL body", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": null 7 | }, 8 | "actual": { 9 | "headers": {"Content-Type": "application/json"}, 10 | "body": null 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/null body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "NULL body", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": null 7 | }, 8 | "actual": { 9 | "headers": {"Content-Type": "application/json"}, 10 | "body": null 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-lein/src/test/clojure/leiningen/pact_verify_test.clj: -------------------------------------------------------------------------------- 1 | (ns leiningen.pact-verify-test 2 | (:require [clojure.test :refer :all] 3 | [leiningen.pact-verify :as pact-verify])) 4 | 5 | (deftest fails-if-there-is-no-pact-definition-in-project 6 | (is (thrown? RuntimeException 7 | (pact-verify/pact-verify {})))) 8 | 9 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/headers/header name is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Header name is case insensitive", 4 | "expected" : { 5 | "headers": { 6 | "Accept": "alligators" 7 | } 8 | }, 9 | "actual": { 10 | "headers": { 11 | "ACCEPT": "alligators" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/headers/header name is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Header name is case insensitive", 4 | "expected" : { 5 | "headers": { 6 | "Accept": "alligators" 7 | } 8 | }, 9 | "actual": { 10 | "headers": { 11 | "ACCEPT": "alligators" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/headers/header name is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Header name is case insensitive", 4 | "expected" : { 5 | "headers": { 6 | "Accept": "alligators" 7 | } 8 | }, 9 | "actual": { 10 | "headers": { 11 | "ACCEPT": "alligators" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/plain text empty body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Plain text that matches", 4 | "expected" : { 5 | "headers": { "Content-Type": "text/plain" }, 6 | "body": "" 7 | }, 8 | "actual": { 9 | "headers": { "Content-Type": "text/plain" }, 10 | "body": "" 11 | 12 | } 13 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/headers/header name is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Header name is case insensitive", 4 | "expected" : { 5 | "headers": { 6 | "Accept": "alligators" 7 | } 8 | }, 9 | "actual": { 10 | "headers": { 11 | "ACCEPT": "alligators" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /provider/pact-jvm-provider-junit/src/test/resources/logback.groovy: -------------------------------------------------------------------------------- 1 | import ch.qos.logback.classic.encoder.PatternLayoutEncoder 2 | 3 | appender("STDOUT", ConsoleAppender) { 4 | encoder(PatternLayoutEncoder) { 5 | pattern = "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" 6 | } 7 | } 8 | logger("org.eclipse", INFO) 9 | root(DEBUG, ["STDOUT"]) 10 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-junit5/src/test/resources/logback.groovy: -------------------------------------------------------------------------------- 1 | import ch.qos.logback.classic.encoder.PatternLayoutEncoder 2 | 3 | appender("STDOUT", ConsoleAppender) { 4 | encoder(PatternLayoutEncoder) { 5 | pattern = "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" 6 | } 7 | } 8 | logger("org.eclipse", INFO) 9 | root(DEBUG, ["STDOUT"]) 10 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/headers/header value is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Headers values are case sensitive", 4 | "expected" : { 5 | "headers": { 6 | "Accept": "alligators" 7 | } 8 | }, 9 | "actual": { 10 | "headers": { 11 | "Accept": "Alligators" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/headers/header value is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Headers values are case sensitive", 4 | "expected" : { 5 | "headers": { 6 | "Accept": "alligators" 7 | } 8 | }, 9 | "actual": { 10 | "headers": { 11 | "Accept": "Alligators" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/headers/header value is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Headers values are case sensitive", 4 | "expected" : { 5 | "headers": { 6 | "Accept": "alligators" 7 | } 8 | }, 9 | "actual": { 10 | "headers": { 11 | "Accept": "Alligators" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/headers/header value is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Headers values are case sensitive", 4 | "expected" : { 5 | "headers": { 6 | "Accept": "alligators" 7 | } 8 | }, 9 | "actual": { 10 | "headers": { 11 | "Accept": "Alligators" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /core/pact-broker/src/main/kotlin/au/com/dius/pact/core/pactbroker/PactBrokerConsumer.kt: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.core.pactbroker 2 | 3 | data class PactBrokerConsumer @JvmOverloads constructor ( 4 | val name: String, 5 | val source: String, 6 | val pactBrokerUrl: String, 7 | val pactFileAuthentication: List = listOf(), 8 | val tag: String? = null 9 | ) 10 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/no body no content type xml.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "XML No body, no content-type", 4 | "expected" : { 5 | }, 6 | "actual": { 7 | "headers": {"Content-Type": "application/xml"}, 8 | "body": "" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/no body no content type xml.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "XML No body, no content-type", 4 | "expected" : { 5 | }, 6 | "actual": { 7 | "headers": {"Content-Type": "application/xml"}, 8 | "body": "" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-groovy/src/main/groovy/au/com/dius/pact/consumer/groovy/InvalidMatcherException.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer.groovy 2 | 3 | /** 4 | * Exception for handling invalid matchers 5 | */ 6 | class InvalidMatcherException extends RuntimeException { 7 | 8 | InvalidMatcherException(String message) { 9 | super(message) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/method/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Methods match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/", 13 | "query": "", 14 | "headers": {} 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/method/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Methods match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/", 13 | "query": "", 14 | "headers": {} 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/method/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Methods match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": {}, 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/", 13 | "query": {}, 14 | "headers": {} 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /provider/pact-jvm-provider-spring/src/test/java/au/com/dius/pact/provider/spring/BookType.java: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider.spring; 2 | 3 | public class BookType { 4 | 5 | private final String type; 6 | 7 | public BookType(String type) { 8 | this.type = type; 9 | } 10 | 11 | public String getType() { 12 | return type; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/method/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Methods match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/", 13 | "query": "", 14 | "headers": {} 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/message/body/no body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "No body, no content-type", 4 | "expected": {}, 5 | "actual": { 6 | "metaData": { 7 | "contentType": "application/json" 8 | }, 9 | "contents": { 10 | "alligator": { 11 | "age": 3 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-specs2/README.md: -------------------------------------------------------------------------------- 1 | pact-jvm-provider-specs2 2 | ======================== 3 | 4 | Provides an extension to Specs2 Specification to validate a pact file against a running provider. See 5 | [ExampleProviderSpec.scala](src/test/scala/au/com/dius/pact/provider/specs2/ExampleProviderSpec.scala) 6 | for an example. 7 | 8 | *Note:* The Pact ProviderSpec requires spec2 3.x 9 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-scalasupport/src/main/scala/au/com/dius/pact/provider/ServiceInvokeRequest.scala: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider 2 | 3 | import au.com.dius.pact.core.model.Request 4 | 5 | object ServiceInvokeRequest { 6 | def apply(url: String, request: Request): Request = { 7 | val r = request.copy 8 | r.setPath(s"$url${request.getPath}") 9 | r 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/method/different method.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Methods is incorrect", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "GET", 12 | "path": "/", 13 | "query": "", 14 | "headers": {} 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/headers/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Headers match", 4 | "expected" : { 5 | "headers": { 6 | "Accept": "alligators", 7 | "Content-Type": "hippos" 8 | } 9 | }, 10 | "actual": { 11 | "headers": { 12 | "Content-Type": "hippos", 13 | "Accept": "alligators" 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/method/different method.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Methods is incorrect", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "GET", 12 | "path": "/", 13 | "query": "", 14 | "headers": {} 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/plain text that matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Plain text that matches", 4 | "expected" : { 5 | "headers": { "Content-Type": "text/plain" }, 6 | "body": "alligator named mary" 7 | }, 8 | "actual": { 9 | "headers": { "Content-Type": "text/plain" }, 10 | "body": "alligator named mary" 11 | } 12 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/headers/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Headers match", 4 | "expected" : { 5 | "headers": { 6 | "Accept": "alligators", 7 | "Content-Type": "hippos" 8 | } 9 | }, 10 | "actual": { 11 | "headers": { 12 | "Content-Type": "hippos", 13 | "Accept": "alligators" 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/method/different method.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Methods is incorrect", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "GET", 12 | "path": "/", 13 | "query": "", 14 | "headers": {} 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/plain text that matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Plain text that matches", 4 | "expected" : { 5 | "headers": { "Content-Type": "text/plain" }, 6 | "body": "alligator named mary" 7 | }, 8 | "actual": { 9 | "headers": { "Content-Type": "text/plain" }, 10 | "body": "alligator named mary" 11 | } 12 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/headers/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Headers match", 4 | "expected" : { 5 | "headers": { 6 | "Accept": "alligators", 7 | "Content-Type": "hippos" 8 | } 9 | }, 10 | "actual": { 11 | "headers": { 12 | "Content-Type": "hippos", 13 | "Accept": "alligators" 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/method/different method.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Methods is incorrect", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": {}, 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "GET", 12 | "path": "/", 13 | "query": {}, 14 | "headers": {} 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/plain text that matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Plain text that matches", 4 | "expected" : { 5 | "headers": { "Content-Type": "text/plain" }, 6 | "body": "alligator named mary" 7 | }, 8 | "actual": { 9 | "headers": { "Content-Type": "text/plain" }, 10 | "body": "alligator named mary" 11 | } 12 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/headers/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Headers match", 4 | "expected" : { 5 | "headers": { 6 | "Accept": "alligators", 7 | "Content-Type": "hippos" 8 | } 9 | }, 10 | "actual": { 11 | "headers": { 12 | "Content-Type": "hippos", 13 | "Accept": "alligators" 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/headers/empty headers.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Empty headers match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": "", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/path", 14 | "query": "", 15 | "headers": {} 16 | } 17 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/plain text that matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Plain text that matches", 4 | "expected" : { 5 | "headers": { "Content-Type": "text/plain" }, 6 | "body": "alligator named mary" 7 | }, 8 | "actual": { 9 | "headers": { "Content-Type": "text/plain" }, 10 | "body": "alligator named mary" 11 | } 12 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/headers/empty headers.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Empty headers match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": "", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/path", 14 | "query": "", 15 | "headers": {} 16 | } 17 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/headers/empty headers.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Empty headers match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": "", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/path", 14 | "query": "", 15 | "headers": {} 16 | } 17 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/missing body xml.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "XML Missing body", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/xml"} 6 | }, 7 | "actual": { 8 | "headers": {"Content-Type": "application/xml"}, 9 | "body": "" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/headers/empty headers.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Empty headers match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": {}, 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/path", 14 | "query": {}, 15 | "headers": {} 16 | } 17 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/path/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Paths match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path/to/something", 7 | "query": {}, 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/path/to/something", 13 | "query": {}, 14 | "headers": {} 15 | } 16 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/missing body xml.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "XML Missing body", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/xml"} 6 | }, 7 | "actual": { 8 | "headers": {"Content-Type": "application/xml"}, 9 | "body": "" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-maven/src/main/groovy/au/com/dius/pact/provider/maven/PactBroker.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider.maven 2 | 3 | import groovy.transform.Canonical 4 | 5 | /** 6 | * Bean to configure a pact broker to query 7 | */ 8 | @Canonical 9 | class PactBroker { 10 | URL url 11 | List tags = [] 12 | PactBrokerAuth authentication 13 | String serverId 14 | } 15 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-scalasupport/src/test/resources/pact-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "providerRoot": { 3 | "protocol": "http", 4 | "host": "localhost", 5 | "port": 8888, 6 | "path": "" 7 | }, 8 | "stateChangeUrl": { 9 | "protocol": "http", 10 | "host": "localhost", 11 | "port": 8888, 12 | "path": "/enterState" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/headers/whitespace after comma different.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Whitespace between comma separated headers does not matter", 4 | "expected" : { 5 | "headers": { 6 | "Accept": "alligators,hippos" 7 | } 8 | }, 9 | "actual": { 10 | "headers": { 11 | "Accept": "alligators, hippos" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/headers/whitespace after comma different.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Whitespace between comma separated headers does not matter", 4 | "expected" : { 5 | "headers": { 6 | "Accept": "alligators,hippos" 7 | } 8 | }, 9 | "actual": { 10 | "headers": { 11 | "Accept": "alligators, hippos" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/headers/whitespace after comma different.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Whitespace between comma separated headers does not matter", 4 | "expected" : { 5 | "headers": { 6 | "Accept": "alligators,hippos" 7 | } 8 | }, 9 | "actual": { 10 | "headers": { 11 | "Accept": "alligators, hippos" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/headers/whitespace after comma different.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Whitespace between comma separated headers does not matter", 4 | "expected" : { 5 | "headers": { 6 | "Accept": "alligators,hippos" 7 | } 8 | }, 9 | "actual": { 10 | "headers": { 11 | "Accept": "alligators, hippos" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/method/method is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Methods case does not matter", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "post", 12 | "path": "/", 13 | "query": "", 14 | "headers": {} 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/method/method is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Methods case does not matter", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "post", 12 | "path": "/", 13 | "query": "", 14 | "headers": {} 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/plain text that does not match.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Plain text that does not match", 4 | "expected" : { 5 | "headers": { "Content-Type": "text/plain" }, 6 | "body": "alligator named mary" 7 | }, 8 | "actual": { 9 | "headers": { "Content-Type": "text/plain" }, 10 | "body": "alligator named fred" 11 | } 12 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/method/method is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Methods case does not matter", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "post", 12 | "path": "/", 13 | "query": "", 14 | "headers": {} 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/plain text that does not match.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Plain text that does not match", 4 | "expected" : { 5 | "headers": { "Content-Type": "text/plain" }, 6 | "body": "alligator named mary" 7 | }, 8 | "actual": { 9 | "headers": { "Content-Type": "text/plain" }, 10 | "body": "alligator named fred" 11 | } 12 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/method/method is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Methods case does not matter", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": {}, 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "post", 12 | "path": "/", 13 | "query": {}, 14 | "headers": {} 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/plain text that does not match.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Plain text that does not match", 4 | "expected" : { 5 | "headers": { "Content-Type": "text/plain" }, 6 | "body": "alligator named mary" 7 | }, 8 | "actual": { 9 | "headers": { "Content-Type": "text/plain" }, 10 | "body": "alligator named fred" 11 | } 12 | } -------------------------------------------------------------------------------- /provider/pact-jvm-provider-gradle/src/main/groovy/au/com/dius/pact/provider/gradle/StateChangeUrl.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider.gradle 2 | 3 | /** 4 | * Config for stage change URL 5 | */ 6 | class StateChangeUrl { 7 | 8 | boolean enabled = false 9 | String protocol = 'http' 10 | String host = 'localhost' 11 | Integer port = 8080 12 | String path = '/enterState' 13 | 14 | } 15 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/path/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Paths match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path/to/something", 7 | "query": "", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/path/to/something", 14 | "query": "", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/plain text that does not match.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Plain text that does not match", 4 | "expected" : { 5 | "headers": { "Content-Type": "text/plain" }, 6 | "body": "alligator named mary" 7 | }, 8 | "actual": { 9 | "headers": { "Content-Type": "text/plain" }, 10 | "body": "alligator named fred" 11 | } 12 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/path/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Paths match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path/to/something", 7 | "query": "", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/path/to/something", 14 | "query": "", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/path/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Paths match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path/to/something", 7 | "query": "", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/path/to/something", 14 | "query": "", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/body/missing body found when empty expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Missing body found, when an empty body was expected", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "body": null 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/", 13 | "query": "" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/body/missing body found when empty expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Missing body found, when an empty body was expected", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "body": null 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/", 13 | "query": "" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/body/missing body found when empty expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Missing body found, when an empty body was expected", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": {}, 8 | "body": null 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/", 13 | "query": {} 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/path/incorrect path.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Paths do not match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path/to/something", 7 | "query": {}, 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/path/to/something/else", 13 | "query": {}, 14 | "headers": {} 15 | } 16 | } -------------------------------------------------------------------------------- /core/model/README.md: -------------------------------------------------------------------------------- 1 | Pact model 2 | ========== 3 | 4 | The model project is responsible for providing: 5 | * a model to represent pacts 6 | * serialization and deserialization 7 | * comparison between two parts of the pact model 8 | * conversion between the pact model and whatever third party libraries used by the pact-consumer and pact-provider requires 9 | 10 | You should never need to include this project directly 11 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-scalasupport/src/main/scala/au/com/dius/pact/provider/EnterStateRequest.scala: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider 2 | 3 | import au.com.dius.pact.core.model.{OptionalBody, Request} 4 | 5 | object EnterStateRequest { 6 | def apply(url: String, state: String): Request = { 7 | new Request("POST", url, null, null, OptionalBody.body(("{\"state\": \"" + state + "\"}").getBytes), null) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-groovy/src/main/groovy/au/com/dius/pact/consumer/groovy/NullMatcher.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer.groovy 2 | 3 | import au.com.dius.pact.core.model.matchingrules.MatchingRule 4 | 5 | /** 6 | * Matcher to match null values 7 | */ 8 | class NullMatcher extends Matcher { 9 | MatchingRule getMatcher() { 10 | au.com.dius.pact.core.model.matchingrules.NullMatcher.INSTANCE 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-maven/src/main/groovy/au/com/dius/pact/provider/maven/PactBrokerAuth.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider.maven 2 | 3 | import groovy.transform.Canonical 4 | 5 | /** 6 | * Authentication for the pact broker, defaulting to Basic Authentication 7 | */ 8 | @Canonical 9 | class PactBrokerAuth { 10 | String scheme = 'basic' 11 | String token 12 | String username 13 | String password 14 | } 15 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/path/incorrect path.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Paths do not match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path/to/something", 7 | "query": "", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/path/to/something/else", 14 | "query": "", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/path/incorrect path.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Paths do not match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path/to/something", 7 | "query": "", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/path/to/something/else", 14 | "query": "", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/path/incorrect path.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Paths do not match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path/to/something", 7 | "query": "", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/path/to/something/else", 14 | "query": "", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/path/empty path found when forward slash expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Empty path found when forward slash expected", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": {}, 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "", 13 | "query": {}, 14 | "headers": {} 15 | } 16 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/path/forward slash found when empty path expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Foward slash found when empty path expected", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "", 7 | "query": {}, 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/", 13 | "query": {}, 14 | "headers": {} 15 | } 16 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/headers/matches content type with charset.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Headers match when the actual includes additional parameters", 4 | "expected" : { 5 | "headers": { 6 | "Content-Type": "application/json" 7 | } 8 | }, 9 | "actual": { 10 | "headers": { 11 | "Content-Type": "application/json; charset=UTF-8" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider/src/test/groovy/au/com/dius/pact/provider/TestVerifyResponseByInvokingProviderMethodsClass.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider 2 | 3 | import org.apache.commons.lang3.NotImplementedException 4 | 5 | class TestVerifyResponseByInvokingProviderMethodsClass { 6 | @PactVerifyProvider('verifyResponseByInvokingProviderMethods Test Message') 7 | String method() { throw new NotImplementedException('Boom!') } 8 | } 9 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-groovy/src/main/groovy/au/com/dius/pact/consumer/groovy/EqualsMatcher.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer.groovy 2 | 3 | import au.com.dius.pact.core.model.matchingrules.MatchingRule 4 | 5 | /** 6 | * Matcher to match using equality 7 | */ 8 | class EqualsMatcher extends Matcher { 9 | MatchingRule getMatcher() { 10 | au.com.dius.pact.core.model.matchingrules.EqualsMatcher.INSTANCE 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-groovy/src/main/groovy/au/com/dius/pact/consumer/groovy/IncludeMatcher.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer.groovy 2 | 3 | import au.com.dius.pact.core.model.matchingrules.MatchingRule 4 | 5 | /** 6 | * Matcher for string inclusion 7 | */ 8 | class IncludeMatcher extends Matcher { 9 | MatchingRule getMatcher() { 10 | new au.com.dius.pact.core.model.matchingrules.IncludeMatcher(value) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/no body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "No body, no content-type", 4 | "expected" : { 5 | }, 6 | "actual": { 7 | "headers": {"Content-Type": "application/json"}, 8 | "body": { 9 | "alligator":{ 10 | "feet": 4, 11 | "name": "Mary", 12 | "favouriteColours": ["red","blue"] 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/message/body/no body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Missing body", 4 | "expected": { 5 | "metaData": { 6 | "contentType": "application/json" 7 | } 8 | }, 9 | "actual": { 10 | "metaData": { 11 | "contentType": "application/json" 12 | }, 13 | "contents": { 14 | "alligator": { 15 | "age": 3 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/no body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "No body, no content-type", 4 | "expected" : { 5 | }, 6 | "actual": { 7 | "headers": {"Content-Type": "application/json"}, 8 | "body": { 9 | "alligator":{ 10 | "feet": 4, 11 | "name": "Mary", 12 | "favouriteColours": ["red","blue"] 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-junit/src/test/java/au/com/dius/pact/consumer/events/EventRequest.java: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer.events; 2 | 3 | public class EventRequest { 4 | private String someField; 5 | 6 | //for jackson 7 | private EventRequest(){} 8 | 9 | public EventRequest(String someField) { 10 | this.someField = someField; 11 | } 12 | 13 | public String getSomeField() { 14 | return someField; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/query/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Queries are the same", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "alligator=Mary&hippo=John", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "alligator=Mary&hippo=John", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/query/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Queries are the same", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "alligator=Mary&hippo=John", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "alligator=Mary&hippo=John", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/query/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Queries are the same", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "alligator=Mary&hippo=John", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "alligator=Mary&hippo=John", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /provider/pact-jvm-provider-junit/src/test/java/au/com/dius/pact/provider/junit/Git.java: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider.junit; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.TYPE) 10 | public @interface Git { 11 | String value(); 12 | } 13 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-scalatest/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'scala' 3 | } 4 | 5 | dependencies { 6 | compile project(path: ":provider:pact-jvm-provider", configuration: 'default'), 7 | project(path: ":provider:pact-jvm-provider-scalasupport_2.12", configuration: 'default'), 8 | "org.scalatest:scalatest_2.12:${project.scalaTestVersion}" 9 | 10 | testCompile project(":consumer:pact-jvm-consumer") 11 | } 12 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-spring/src/test/java/au/com/dius/pact/provider/spring/BookNotFoundException.java: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider.spring; 2 | 3 | import java.util.UUID; 4 | 5 | /** 6 | * Created by raceconditions on 5/17/17. 7 | */ 8 | public class BookNotFoundException extends Exception { 9 | public BookNotFoundException(UUID id) { 10 | super(String.format("No book with ID: %s", id.toString())); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/headers/unexpected header found.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Extra headers allowed", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": "", 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/path", 13 | "query": "", 14 | "headers": { 15 | "Accept": "alligators" 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/path/empty path found when forward slash expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Empty path found when forward slash expected", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "", 14 | "query": "", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/path/forward slash found when empty path expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Foward slash found when empty path expected", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "", 7 | "query": "", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/", 14 | "query": "", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/headers/unexpected header found.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Extra headers allowed", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": "", 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/path", 13 | "query": "", 14 | "headers": { 15 | "Accept": "alligators" 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/path/empty path found when forward slash expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Empty path found when forward slash expected", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "", 14 | "query": "", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/path/forward slash found when empty path expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Foward slash found when empty path expected", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "", 7 | "query": "", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/", 14 | "query": "", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/headers/unexpected header found.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Extra headers allowed", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": "", 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/path", 13 | "query": "", 14 | "headers": { 15 | "Accept": "alligators" 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/path/empty path found when forward slash expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Empty path found when forward slash expected", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "", 14 | "query": "", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/path/forward slash found when empty path expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Foward slash found when empty path expected", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "", 7 | "query": "", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/", 14 | "query": "", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/missing body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Missing body, no content-type", 4 | "expected" : { 5 | }, 6 | "actual": { 7 | "headers": {"Content-Type": "application/json"}, 8 | "body": { 9 | "alligator":{ 10 | "feet": 4, 11 | "name": "Mary", 12 | "favouriteColours": ["red","blue"] 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/headers/unexpected header found.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Extra headers allowed", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": {}, 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/path", 13 | "query": {}, 14 | "headers": { 15 | "Accept": "alligators" 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/missing body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Missing body, no content-type", 4 | "expected" : { 5 | }, 6 | "actual": { 7 | "headers": {"Content-Type": "application/json"}, 8 | "body": { 9 | "alligator":{ 10 | "feet": 4, 11 | "name": "Mary", 12 | "favouriteColours": ["red","blue"] 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/headers/content type parameters do not match.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Headers don't match when the parameters are different", 4 | "expected" : { 5 | "headers": { 6 | "Content-Type": "application/json; charset=UTF-16" 7 | } 8 | }, 9 | "actual": { 10 | "headers": { 11 | "Content-Type": "application/json; charset=UTF-8" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-scalatest/src/main/scala/au/com/dius/pact/provider/scalatest/Tags.scala: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider.scalatest 2 | 3 | import org.scalatest.Tag 4 | 5 | object Tags { 6 | 7 | /** 8 | * Provider pact tests are annotated with this tag by default. Can be excluded or included in the build process. 9 | */ 10 | object ProviderTest extends Tag("au.com.dius.pact.provider.scalatest.Tags.ProviderTest") 11 | 12 | } 13 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-groovy/src/main/groovy/au/com/dius/pact/consumer/groovy/EachLikeMatcher.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer.groovy 2 | 3 | import au.com.dius.pact.core.model.matchingrules.MatchingRule 4 | 5 | /** 6 | * Each like matcher for arrays 7 | */ 8 | class EachLikeMatcher extends LikeMatcher { 9 | 10 | MatchingRule getMatcher() { 11 | au.com.dius.pact.core.model.matchingrules.TypeMatcher.INSTANCE 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /core/support/src/main/java/au/com/dius/pact/core/support/NonNullApi.java: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.core.support; 2 | 3 | import javax.annotation.Nonnull; 4 | import javax.annotation.meta.TypeQualifierDefault; 5 | import java.lang.annotation.ElementType; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(ElementType.PACKAGE) 9 | @Nonnull 10 | @TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER}) 11 | public @interface NonNullApi { 12 | } 13 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/missing body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Missing body, no content-type", 4 | "expected" : { 5 | }, 6 | "actual": { 7 | "headers": {"Content-Type": "application/json"}, 8 | "body": { 9 | "alligator":{ 10 | "feet": 4, 11 | "name": "Mary", 12 | "favouriteColours": ["red","blue"] 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/headers/order of comma separated header values different.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Comma separated headers out of order, order can matter http://tools.ietf.org/html/rfc2616", 4 | "expected" : { 5 | "headers": { 6 | "Accept": "alligators, hippos" 7 | } 8 | }, 9 | "actual": { 10 | "headers": { 11 | "Accept": "hippos, alligators" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/headers/order of comma separated header values different.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Comma separated headers out of order, order can matter http://tools.ietf.org/html/rfc2616", 4 | "expected" : { 5 | "headers": { 6 | "Accept": "alligators, hippos" 7 | } 8 | }, 9 | "actual": { 10 | "headers": { 11 | "Accept": "hippos, alligators" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/headers/order of comma separated header values different.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Comma separated headers out of order, order can matter http://tools.ietf.org/html/rfc2616", 4 | "expected" : { 5 | "headers": { 6 | "Accept": "alligators, hippos" 7 | } 8 | }, 9 | "actual": { 10 | "headers": { 11 | "Accept": "hippos, alligators" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/headers/order of comma separated header values different.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Comma separated headers out of order, order can matter http://tools.ietf.org/html/rfc2616", 4 | "expected" : { 5 | "headers": { 6 | "Accept": "alligators, hippos" 7 | } 8 | }, 9 | "actual": { 10 | "headers": { 11 | "Accept": "hippos, alligators" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-groovy/src/main/groovy/au/com/dius/pact/consumer/groovy/ValuesMatcher.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer.groovy 2 | 3 | import au.com.dius.pact.core.model.matchingrules.MatchingRule 4 | 5 | /** 6 | * Matcher for validating the values in a map 7 | */ 8 | class ValuesMatcher extends Matcher { 9 | 10 | MatchingRule getMatcher() { 11 | au.com.dius.pact.core.model.matchingrules.ValuesMatcher.INSTANCE 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/body/empty body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Empty body, no content-type", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "body": "" 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/", 13 | "query": "", 14 | "headers": {"Content-Type": "application/json"}, 15 | "body": "" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/missing key.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Missing key alligator name", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary", 9 | "age": 3 10 | } 11 | } 12 | }, 13 | "actual": { 14 | "headers": {}, 15 | "body": { 16 | "alligator": { 17 | "age": 3 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/not null found at key when null expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Name should be null", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "name": null 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "name": "Fred" 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/missing key.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Missing key alligator name", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary", 9 | "age": 3 10 | } 11 | } 12 | }, 13 | "actual": { 14 | "headers": {}, 15 | "body": { 16 | "alligator": { 17 | "age": 3 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/not null found at key when null expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Name should be null", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "name": null 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "name": "Fred" 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/body/empty body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Empty body, no content-type", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "body": "" 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/", 13 | "query": "", 14 | "headers": {"Content-Type": "application/json"}, 15 | "body": "" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/body/null body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "NULL body, no content-type", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "body": null 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/", 13 | "query": "", 14 | "headers": {"Content-Type": "application/json"}, 15 | "body": null 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/body/empty body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Empty body, no content-type", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": {}, 8 | "body": "" 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/", 13 | "query": {}, 14 | "headers": {"Content-Type": "application/json"}, 15 | "body": "" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/body/null body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "NULL body, no content-type", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": {}, 8 | "body": null 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/", 13 | "query": {}, 14 | "headers": {"Content-Type": "application/json"}, 15 | "body": null 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-junit/src/main/kotlin/au/com/dius/pact/provider/junit/target/TestClassAwareTarget.kt: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider.junit.target 2 | 3 | import org.junit.runners.model.TestClass 4 | 5 | /** 6 | * Interface to target implementations that require more information from the test class (like annotated methods) 7 | */ 8 | interface TestClassAwareTarget : Target { 9 | fun setTestClass(testClass: TestClass, testTarget: Any) 10 | } 11 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-lein/src/main/resources/META-INF/leiningen/au.com.dius/pact-jvm-provider-lein_2.11/project.clj: -------------------------------------------------------------------------------- 1 | (defproject pact-jvm-provider-lein "${project.version}" 2 | :description "Lein plugin for Pact verification" 3 | :url "https://github.com/DiUS/pact-jvm" 4 | :license {:name "Apache License" 5 | :url "https://github.com/DiUS/pact-jvm/blob/master/LICENSE"} 6 | :eval-in-leiningen true) -------------------------------------------------------------------------------- /core/matchers/src/main/kotlin/au/com/dius/pact/core/matchers/BodyMatcher.kt: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.core.matchers 2 | 3 | import au.com.dius.pact.core.model.OptionalBody 4 | import au.com.dius.pact.core.model.matchingrules.MatchingRules 5 | 6 | interface BodyMatcher { 7 | fun matchBody( 8 | expected: OptionalBody, 9 | actual: OptionalBody, 10 | allowUnexpectedKeys: Boolean, 11 | matchingRules: MatchingRules 12 | ): List 13 | } 14 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/body/null body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "NULL body, no content-type", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "body": null 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/", 13 | "query": "", 14 | "headers": {"Content-Type": "application/json"}, 15 | "body": null 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/different value found at key.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Incorrect value at alligator name", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "name": "Fred" 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/null found at key where not null expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Name should not be null", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "name": null 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/different value found at key.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Incorrect value at alligator name", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "name": "Fred" 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/null found at key where not null expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Name should not be null", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "name": null 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/README.md: -------------------------------------------------------------------------------- 1 | Pact Specification 2 | ================== 3 | 4 | The [Pact Specification](https://github.com/bethesque/pact_specification) is a robust set of tests on the pact matching 5 | code aimed at ensuring pact library implementations across different languages have the same matching behaviour. 6 | 7 | Without adhering to these specifications there would be room for subtle issues to arise between consumers and providers 8 | using different libraries. 9 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/query/trailing ampersand.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Trailing amperands can be ignored", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "alligator=Mary&hippo=John", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "alligator=Mary&hippo=John&", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/query/trailing ampersand.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Trailing amperands can be ignored", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "alligator=Mary&hippo=John", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "alligator=Mary&hippo=John&", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/missing index.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Missing favorite colour", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteColours": ["red","blue"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator": { 16 | "favouriteColours": ["red"] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/missing index.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Missing favorite colour", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteColours": ["red","blue"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator": { 16 | "favouriteColours": ["red"] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/missing body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Missing body", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"} 6 | }, 7 | "actual": { 8 | "headers": {"Content-Type": "application/json"}, 9 | "body": { 10 | "alligator":{ 11 | "feet": 4, 12 | "name": "Mary", 13 | "favouriteColours": ["red","blue"] 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/path/missing trailing slash in path.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Path is missing trailing slash, trailing slashes can matter", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path/to/something/", 7 | "query": {}, 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/path/to/something", 13 | "query": {}, 14 | "headers": {} 15 | } 16 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/missing body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Missing body", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"} 6 | }, 7 | "actual": { 8 | "headers": {"Content-Type": "application/json"}, 9 | "body": { 10 | "alligator":{ 11 | "feet": 4, 12 | "name": "Mary", 13 | "favouriteColours": ["red","blue"] 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-spring/src/test/java/au/com/dius/pact/provider/spring/BookValidationException.java: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider.spring; 2 | 3 | import java.util.UUID; 4 | 5 | /** 6 | * Created by raceconditions on 5/17/17. 7 | */ 8 | public class BookValidationException extends Exception { 9 | public BookValidationException(Book book) { 10 | super(String.format("Could not create book with ID: %s", book.getId().toString())); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider/src/test/groovy/au/com/dius/pact/provider/readme/dropwizard/TestDropwizardApplication.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider.readme.dropwizard 2 | 3 | import io.dropwizard.Application 4 | import io.dropwizard.setup.Environment 5 | 6 | class TestDropwizardApplication extends Application { 7 | @Override 8 | void run(DropwizardConfiguration configuration, Environment environment) throws Exception { 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | groovyVersion=2.5.7 2 | kotlinVersion=1.3.50 3 | httpBuilderVersion=0.7.1 4 | commonsLang3Version=3.4 5 | httpClientVersion=4.5.5 6 | scalaVersion=2.12.8 7 | specs2Version=4.5.1 8 | scalaTestVersion=3.0.7 9 | jansiVersion=1.17.1 10 | slf4jVersion=1.7.26 11 | logbackVersion=1.2.3 12 | junitVersion=4.12 13 | jsonVersion=20160212 14 | nettyVersion=4.1.30.Final 15 | mavenPluginPluginVersion=3.5 16 | guavaVersion=18.0 17 | junit5Version=5.4.1 18 | gsonVersion=2.8.5 19 | -------------------------------------------------------------------------------- /pact-specification-test/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | dependencies { 3 | testCompile project(":core:pact-jvm-core-matchers"), 4 | project(":provider:pact-jvm-provider") 5 | testCompile "ch.qos.logback:logback-core:${project.logbackVersion}", 6 | "ch.qos.logback:logback-classic:${project.logbackVersion}" 7 | testRuntime "org.junit.vintage:junit-vintage-engine:${project.junit5Version}" 8 | testCompile "org.codehaus.groovy:groovy-json:${project.groovyVersion}" 9 | } 10 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/query/different order.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Queries are the same but in different key order", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "alligator=Mary&hippo=John", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "hippo=John&alligator=Mary", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/missing body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Missing body", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"} 6 | }, 7 | "actual": { 8 | "headers": {"Content-Type": "application/json"}, 9 | "body": { 10 | "alligator":{ 11 | "feet": 4, 12 | "name": "Mary", 13 | "favouriteColours": ["red","blue"] 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/query/different order.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Queries are the same but in different key order", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "alligator=Mary&hippo=John", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "hippo=John&alligator=Mary", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/path/unexpected trailing slash in path.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Path has unexpected trailing slash, trailing slashes can matter", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path/to/something", 7 | "query": {}, 8 | "headers": {} 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/path/to/something/", 13 | "query": {}, 14 | "headers": {} 15 | } 16 | } -------------------------------------------------------------------------------- /provider/pact-jvm-provider-junit/src/test/groovy/au/com/dius/pact/provider/junit/JUnitProviderTestSupportSpec.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider.junit 2 | 3 | import spock.lang.Specification 4 | 5 | class JUnitProviderTestSupportSpec extends Specification { 6 | 7 | def 'exceptionMessage should handle an exception with a null message'() { 8 | expect: 9 | JUnitProviderTestSupport.exceptionMessage(new NullPointerException(), 5) == 'null\n' 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-groovy/src/main/groovy/au/com/dius/pact/consumer/groovy/Matcher.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer.groovy 2 | 3 | import au.com.dius.pact.core.model.generators.Generator 4 | import au.com.dius.pact.core.model.matchingrules.MatchingRule 5 | import groovy.transform.Canonical 6 | 7 | /** 8 | * Base class for matchers 9 | */ 10 | @Canonical 11 | class Matcher { 12 | def value 13 | MatchingRule matcher = null 14 | Generator generator = null 15 | } 16 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-junit/src/main/java/au/com/dius/pact/consumer/junit/PactVerifications.java: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer.junit; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.METHOD) 10 | public @interface PactVerifications { 11 | PactVerification[] value(); 12 | } 13 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/body/empty body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Empty body", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": {"Content-Type": "application/json"}, 9 | "body": "" 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/", 14 | "query": "", 15 | "headers": {"Content-Type": "application/json"}, 16 | "body": "" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/path/missing trailing slash in path.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Path is missing trailing slash, trailing slashes can matter", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path/to/something/", 7 | "query": "", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/path/to/something", 14 | "query": "", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/number found at key when string expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Number of feet expected to be string but was number", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "feet": "4" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "feet": 4 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/string found at key when number expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Number of feet expected to be number but was string", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "feet": 4 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "feet": "4" 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/body/empty body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Empty body", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": {"Content-Type": "application/json"}, 9 | "body": "" 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/", 14 | "query": "", 15 | "headers": {"Content-Type": "application/json"}, 16 | "body": "" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/body/null body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "NULL body", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": {"Content-Type": "application/json"}, 9 | "body": null 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/", 14 | "query": "", 15 | "headers": {"Content-Type": "application/json"}, 16 | "body": null 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/path/missing trailing slash in path.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Path is missing trailing slash, trailing slashes can matter", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path/to/something/", 7 | "query": "", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/path/to/something", 14 | "query": "", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/body/empty body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Empty body", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": {}, 8 | "headers": {"Content-Type": "application/json"}, 9 | "body": "" 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/", 14 | "query": {}, 15 | "headers": {"Content-Type": "application/json"}, 16 | "body": "" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/body/null body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "NULL body", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": {}, 8 | "headers": {"Content-Type": "application/json"}, 9 | "body": null 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/", 14 | "query": {}, 15 | "headers": {"Content-Type": "application/json"}, 16 | "body": null 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/body/null body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "NULL body", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": {"Content-Type": "application/json"}, 9 | "body": null 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/", 14 | "query": "", 15 | "headers": {"Content-Type": "application/json"}, 16 | "body": null 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/path/missing trailing slash in path.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Path is missing trailing slash, trailing slashes can matter", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path/to/something/", 7 | "query": "", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/path/to/something", 14 | "query": "", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/number found at key when string expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Number of feet expected to be string but was number", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "feet": "4" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "feet": 4 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/string found at key when number expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Number of feet expected to be number but was string", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "feet": 4 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "feet": "4" 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/query/different params.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Queries are not the same - hippo is Fred instead of John", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "alligator=Mary&hippo=John", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "alligator=Mary&hippo=Fred", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/path/unexpected trailing slash in path.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Path has unexpected trailing slash, trailing slashes can matter", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path/to/something", 7 | "query": "", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/path/to/something/", 14 | "query": "", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/query/different params.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Queries are not the same - hippo is Fred instead of John", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "alligator=Mary&hippo=John", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "alligator=Mary&hippo=Fred", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/path/unexpected trailing slash in path.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Path has unexpected trailing slash, trailing slashes can matter", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path/to/something", 7 | "query": "", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/path/to/something/", 14 | "query": "", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/query/different param values.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Queries are not the same - hippo is Fred instead of John", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "alligator=Mary&hippo=John", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "alligator=Mary&hippo=Fred", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/path/unexpected trailing slash in path.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Path has unexpected trailing slash, trailing slashes can matter", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path/to/something", 7 | "query": "", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/path/to/something/", 14 | "query": "", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/array in different order.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Favourite colours in wrong order", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteColours": ["red","blue"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteColours": ["blue", "red"] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/different value found at index.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Incorrect favourite colour", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteColours": ["red","blue"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteColours": ["red","taupe"] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/keys out of order match.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Favourite number and favourite colours out of order", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "favouriteNumber": 7, 8 | "favouriteColours": ["red","blue"] 9 | } 10 | }, 11 | "actual": { 12 | "headers": {}, 13 | "body": { 14 | "favouriteColours": ["red","blue"], 15 | "favouriteNumber": 7 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/property name is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Property names on objects are case sensitive", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "FavouriteColour": "red" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "favouritecolour": "red" 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/unexpected key with not null value.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Unexpected phone number", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "name": "Mary", 17 | "phoneNumber": "12345678" 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/array in different order.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Favourite colours in wrong order", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteColours": ["red","blue"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteColours": ["blue", "red"] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/different value found at index.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Incorrect favourite colour", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteColours": ["red","blue"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteColours": ["red","taupe"] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/keys out of order match.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Favourite number and favourite colours out of order", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "favouriteNumber": 7, 8 | "favouriteColours": ["red","blue"] 9 | } 10 | }, 11 | "actual": { 12 | "headers": {}, 13 | "body": { 14 | "favouriteColours": ["red","blue"], 15 | "favouriteNumber": 7 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/objects in array first matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Properties match but unexpected element recieved", 4 | "expected" : { 5 | "headers": {}, 6 | "body": [ 7 | {"favouriteColor": "red"} 8 | ] 9 | }, 10 | "actual": { 11 | "headers": {}, 12 | "body": [ 13 | {"favouriteColor": "red", 14 | "favouriteNumber": 2}, 15 | {"favouriteColor": "blue", 16 | "favouriteNumber": 2} 17 | ] 18 | } 19 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/property name is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Property names on objects are case sensitive", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "FavouriteColour": "red" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "favouritecolour": "red" 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/unexpected key with not null value.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Unexpected phone number", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "name": "Mary", 17 | "phoneNumber": "12345678" 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/query/missing params.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Queries are not the same - elephant is missing", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "alligator=Mary&hippo=Fred&elephant=missing", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "alligator=Mary&hippo=Fred", 15 | "headers": {} 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /core/model/src/main/kotlin/au/com/dius/pact/core/model/PactSpecVersion.kt: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.core.model 2 | 3 | /** 4 | * Pact Specification Version 5 | */ 6 | @Suppress("EnumNaming") 7 | enum class PactSpecVersion { 8 | UNSPECIFIED, V1, V1_1, V2, V3; 9 | 10 | companion object { 11 | @JvmStatic 12 | fun fromInt(version: Int): PactSpecVersion { 13 | return when (version) { 14 | 1 -> V1 15 | 2 -> V2 16 | else -> V3 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/query/missing params.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Queries are not the same - elephant is missing", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "alligator=Mary&hippo=Fred&elephant=missing", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "alligator=Mary&hippo=Fred", 15 | "headers": {} 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/objects in array first matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Properties match but unexpected element recieved", 4 | "expected" : { 5 | "headers": {}, 6 | "body": [ 7 | {"favouriteColor": "red"} 8 | ] 9 | }, 10 | "actual": { 11 | "headers": {}, 12 | "body": [ 13 | {"favouriteColor": "red", 14 | "favouriteNumber": 2}, 15 | {"favouriteColor": "blue", 16 | "favouriteNumber": 2} 17 | ] 18 | } 19 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/unexpected key with null value.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Unexpected phone number with null value", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "name": "Mary", 17 | "phoneNumber": null 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/unexpected key with null value.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Unexpected phone number with null value", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "name": "Mary", 17 | "phoneNumber": null 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/body/no body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "No body, no content-type", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "" 8 | }, 9 | "actual": { 10 | "method": "POST", 11 | "path": "/", 12 | "query": "", 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator": { 16 | "age": 3 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/body/no body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "No body, no content-type", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": {} 8 | }, 9 | "actual": { 10 | "method": "POST", 11 | "path": "/", 12 | "query": {}, 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator": { 16 | "age": 3 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-groovy/src/main/groovy/au/com/dius/pact/consumer/groovy/MaxLikeMatcher.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer.groovy 2 | 3 | import au.com.dius.pact.core.model.matchingrules.MatchingRule 4 | import au.com.dius.pact.core.model.matchingrules.MaxTypeMatcher 5 | 6 | /** 7 | * Like matcher with a maximum size 8 | */ 9 | class MaxLikeMatcher extends LikeMatcher { 10 | 11 | Integer max 12 | 13 | MatchingRule getMatcher() { 14 | new MaxTypeMatcher(max) 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/headers/header name is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Header name is case insensitive", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": "", 8 | "headers": { 9 | "Accept": "alligators" 10 | } 11 | }, 12 | "actual": { 13 | "method": "POST", 14 | "path": "/path", 15 | "query": "", 16 | "headers": { 17 | "ACCEPT": "alligators" 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/headers/header name is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Header name is case insensitive", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": "", 8 | "headers": { 9 | "Accept": "alligators" 10 | } 11 | }, 12 | "actual": { 13 | "method": "POST", 14 | "path": "/path", 15 | "query": "", 16 | "headers": { 17 | "ACCEPT": "alligators" 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/headers/header value is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Headers values are case sensitive", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": "", 8 | "headers": { 9 | "Accept": "alligators" 10 | } 11 | }, 12 | "actual": { 13 | "method": "POST", 14 | "path": "/path", 15 | "query": "", 16 | "headers": { 17 | "Accept": "Alligators" 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/body/no body no content type xml.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "XML No body, no content-type", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "" 8 | }, 9 | "actual": { 10 | "method": "POST", 11 | "path": "/", 12 | "query": "", 13 | "headers": {"Content-Type": "application/xml"}, 14 | "body": "" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/headers/header name is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Header name is case insensitive", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": "", 8 | "headers": { 9 | "Accept": "alligators" 10 | } 11 | }, 12 | "actual": { 13 | "method": "POST", 14 | "path": "/path", 15 | "query": "", 16 | "headers": { 17 | "ACCEPT": "alligators" 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/headers/header value is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Headers values are case sensitive", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": "", 8 | "headers": { 9 | "Accept": "alligators" 10 | } 11 | }, 12 | "actual": { 13 | "method": "POST", 14 | "path": "/path", 15 | "query": "", 16 | "headers": { 17 | "Accept": "Alligators" 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/query/unexpected param.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Queries are not the same - elephant is not expected", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "alligator=Mary&hippo=John", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "alligator=Mary&hippo=John&elephant=unexpected", 15 | "headers": {} 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/body/no body no content type xml.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "XML No body, no content-type", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": {} 8 | }, 9 | "actual": { 10 | "method": "POST", 11 | "path": "/", 12 | "query": {}, 13 | "headers": {"Content-Type": "application/xml"}, 14 | "body": "" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/headers/header name is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Header name is case insensitive", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": {}, 8 | "headers": { 9 | "Accept": "alligators" 10 | } 11 | }, 12 | "actual": { 13 | "method": "POST", 14 | "path": "/path", 15 | "query": {}, 16 | "headers": { 17 | "ACCEPT": "alligators" 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/headers/header value is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Headers values are case sensitive", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": {}, 8 | "headers": { 9 | "Accept": "alligators" 10 | } 11 | }, 12 | "actual": { 13 | "method": "POST", 14 | "path": "/path", 15 | "query": {}, 16 | "headers": { 17 | "Accept": "Alligators" 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-groovy/src/main/groovy/au/com/dius/pact/consumer/groovy/MinLikeMatcher.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer.groovy 2 | 3 | import au.com.dius.pact.core.model.matchingrules.MatchingRule 4 | import au.com.dius.pact.core.model.matchingrules.MinTypeMatcher 5 | 6 | /** 7 | * Like matcher with a minimum size 8 | */ 9 | class MinLikeMatcher extends LikeMatcher { 10 | 11 | Integer min = 0 12 | 13 | MatchingRule getMatcher() { 14 | new MinTypeMatcher(min) 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/body/missing body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Missing body, no content-type", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "" 8 | }, 9 | "actual": { 10 | "method": "POST", 11 | "path": "/", 12 | "query": "", 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator": { 16 | "age": 3 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/headers/header value is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Headers values are case sensitive", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": "", 8 | "headers": { 9 | "Accept": "alligators" 10 | } 11 | }, 12 | "actual": { 13 | "method": "POST", 14 | "path": "/path", 15 | "query": "", 16 | "headers": { 17 | "Accept": "Alligators" 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/query/unexpected param.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Queries are not the same - elephant is not expected", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "alligator=Mary&hippo=John", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "alligator=Mary&hippo=John&elephant=unexpected", 15 | "headers": {} 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/unexpected index with not null value.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Unexpected favourite colour", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteColours": ["red","blue"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteColours": ["red","blue","taupe"] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/unexpected index with not null value.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Unexpected favourite colour", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteColours": ["red","blue"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteColours": ["red","blue","taupe"] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/body/missing body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Missing body, no content-type", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "" 8 | }, 9 | "actual": { 10 | "method": "POST", 11 | "path": "/", 12 | "query": "", 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator": { 16 | "age": 3 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/body/missing body no content type.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Missing body, no content-type", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": {} 8 | }, 9 | "actual": { 10 | "method": "POST", 11 | "path": "/", 12 | "query": {}, 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator": { 16 | "age": 3 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/query/matches with equals in the query value.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Queries are equivalent", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "options=delete.topic.enable=true&broker=1", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "options=delete.topic.enable%3Dtrue&broker=1", 15 | "headers": {} 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/query/matches with equals in the query value.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Queries are equivalent", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "options=delete.topic.enable=true&broker=1", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "options=delete.topic.enable%3Dtrue&broker=1", 15 | "headers": {} 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/objects in array second matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Property of second object matches, but unexpected element recieved", 4 | "expected" : { 5 | "headers": {}, 6 | "body": [ 7 | {"favouriteColor": "red"} 8 | ] 9 | }, 10 | "actual": { 11 | "headers": {}, 12 | "body": [ 13 | {"favouriteColor": "blue", 14 | "favouriteNumber": 4}, 15 | {"favouriteColor": "red", 16 | "favouriteNumber": 2} 17 | ] 18 | } 19 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/query/matches with equals in the query value.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Queries are equivalent", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "options=delete.topic.enable=true&broker=1", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "options=delete.topic.enable%3Dtrue&broker=1", 15 | "headers": {} 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/objects in array second matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Property of second object matches, but unexpected element recieved", 4 | "expected" : { 5 | "headers": {}, 6 | "body": [ 7 | {"favouriteColor": "red"} 8 | ] 9 | }, 10 | "actual": { 11 | "headers": {}, 12 | "body": [ 13 | {"favouriteColor": "blue", 14 | "favouriteNumber": 4}, 15 | {"favouriteColor": "red", 16 | "favouriteNumber": 2} 17 | ] 18 | } 19 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/unexpected index with null value.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Unexpected favourite colour with null value", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteColours": ["red","blue"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteColours": ["red","blue", null] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/unexpected index with null value.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Unexpected favourite colour with null value", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteColours": ["red","blue"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteColours": ["red","blue", null] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/missing key.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Missing key alligator name", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary", 9 | "age": 3 10 | } 11 | } 12 | }, 13 | "actual": { 14 | "headers": {"Content-Type": "application/json"}, 15 | "body": { 16 | "alligator": { 17 | "age": 3 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/missing key.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Missing key alligator name", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary", 9 | "age": 3 10 | } 11 | } 12 | }, 13 | "actual": { 14 | "headers": {"Content-Type": "application/json"}, 15 | "body": { 16 | "alligator": { 17 | "age": 3 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /provider/pact-jvm-provider-maven/src/main/groovy/au/com/dius/pact/provider/maven/Provider.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider.maven 2 | 3 | import au.com.dius.pact.provider.ProviderInfo 4 | import groovy.transform.ToString 5 | 6 | /** 7 | * Provider Info 8 | */ 9 | @ToString(includeSuperProperties = true) 10 | class Provider extends ProviderInfo { 11 | def requestFilter 12 | File pactFileDirectory 13 | URL pactBrokerUrl 14 | PactBroker pactBroker 15 | List pactFileDirectories = [] 16 | } 17 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/string found in array when number expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Favourite Numbers expected to be numbers, but 2 is a string", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteNumbers": [1,2,3] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteNumbers": [1,"2",3] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/different value found at key xml.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "XML Incorrect value at alligator name", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/xml"}, 6 | "body": "" 7 | }, 8 | "actual": { 9 | "headers": {"Content-Type": "application/xml"}, 10 | "body": "" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/different value found at key.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Incorrect value at alligator name", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "name": "Fred" 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/missing key xml.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "XML Missing key alligator name", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/xml"}, 6 | "body": "" 7 | }, 8 | "actual": { 9 | "headers": {"Content-Type": "application/xml"}, 10 | "body": "" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/not null found at key when null expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Name should be null", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "name": null 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "name": "Fred" 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/query/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Queries are the same", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": { 8 | "alligator": ["Mary"], 9 | "hippo": ["John"] 10 | }, 11 | "headers": {} 12 | }, 13 | "actual": { 14 | "method": "GET", 15 | "path": "/path", 16 | "query": { 17 | "alligator": ["Mary"], 18 | "hippo": ["John"] 19 | }, 20 | "headers": {} 21 | } 22 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/different value found at key xml.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "XML Incorrect value at alligator name", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/xml"}, 6 | "body": "" 7 | }, 8 | "actual": { 9 | "headers": {"Content-Type": "application/xml"}, 10 | "body": "" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/different value found at key.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Incorrect value at alligator name", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "name": "Fred" 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/missing key xml.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "XML Missing key alligator name", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/xml"}, 6 | "body": "" 7 | }, 8 | "actual": { 9 | "headers": {"Content-Type": "application/xml"}, 10 | "body": "" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/not null found at key when null expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Name should be null", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "name": null 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "name": "Fred" 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-groovy/src/main/groovy/au/com/dius/pact/consumer/groovy/MinMaxLikeMatcher.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer.groovy 2 | 3 | import au.com.dius.pact.core.model.matchingrules.MatchingRule 4 | import au.com.dius.pact.core.model.matchingrules.MinMaxTypeMatcher 5 | 6 | /** 7 | * Like Matcher with a minimum and maximum size 8 | */ 9 | class MinMaxLikeMatcher extends LikeMatcher { 10 | Integer min, max 11 | 12 | MatchingRule getMatcher() { 13 | new MinMaxTypeMatcher(min, max) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /core/model/src/test/groovy/au/com/dius/pact/core/model/BasePactSpec.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.core.model 2 | 3 | import au.com.dius.pact.core.support.Json 4 | import spock.lang.Specification 5 | 6 | class BasePactSpec extends Specification { 7 | 8 | def 'metadata should use the metadata from the pact file as a base'() { 9 | expect: 10 | BasePact.metaData(Json.INSTANCE.toJson([a: 'A']), PactSpecVersion.V3) == 11 | [a: 'A', pactSpecification: [version: '3.0.0'], 'pact-jvm': [version: '']] 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/string found in array when number expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Favourite Numbers expected to be numbers, but 2 is a string", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteNumbers": [1,2,3] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteNumbers": [1,"2",3] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/body/plain text that matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Plain text that matches", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": { "Content-Type": "text/plain" }, 9 | "body": "alligator named mary" 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/", 14 | "query": "", 15 | "headers": { "Content-Type": "text/plain" }, 16 | "body": "alligator named mary" 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/null found in array when not null expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Favourite numbers expected to be strings found a null", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteNumbers": ["1","2","3"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteNumbers": ["1",null,"3"] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/number found in array when string expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Favourite numbers expected to be strings found a number", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteNumbers": ["1","2","3"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteNumbers": ["1",2,"3"] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/objects in array no matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Array of objects, properties match on incorrect objects", 4 | "expected" : { 5 | "headers": {}, 6 | "body": [ 7 | {"favouriteColor": "red"}, 8 | {"favouriteNumber": 2} 9 | ] 10 | }, 11 | "actual": { 12 | "headers": {}, 13 | "body": [ 14 | {"favouriteColor": "blue", 15 | "favouriteNumber": 4}, 16 | {"favouriteColor": "red", 17 | "favouriteNumber": 2} 18 | ] 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/body/no body xml.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "XML Missing body", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": {"Content-Type": "application/xml"} 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/", 13 | "query": "", 14 | "headers": {"Content-Type": "application/xml"}, 15 | "body": "" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/body/no body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Missing body", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": {"Content-Type": "application/json"} 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/", 13 | "query": "", 14 | "headers": {"Content-Type": "application/json"}, 15 | "body": { 16 | "alligator": { 17 | "age": 3 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/body/plain text that matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Plain text that matches", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": { "Content-Type": "text/plain" }, 9 | "body": "alligator named mary" 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/", 14 | "query": "", 15 | "headers": { "Content-Type": "text/plain" }, 16 | "body": "alligator named mary" 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/null found at key where not null expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Name should not be null", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "name": null 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/headers/matches with regex.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Headers match with regex", 4 | "expected" : { 5 | "headers": { 6 | "Accept": "alligators", 7 | "Content-Type": "hippos" 8 | }, 9 | "matchingRules": { 10 | "$.headers.Accept": {"match": "regex", "regex": "\\w+"} 11 | } 12 | }, 13 | "actual": { 14 | "headers": { 15 | "Content-Type": "hippos", 16 | "Accept": "godzilla" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/body/no body xml.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "XML Missing body", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": {}, 8 | "headers": {"Content-Type": "application/xml"} 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/", 13 | "query": {}, 14 | "headers": {"Content-Type": "application/xml"}, 15 | "body": "" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/body/no body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Missing body", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": {}, 8 | "headers": {"Content-Type": "application/json"} 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/", 13 | "query": {}, 14 | "headers": {"Content-Type": "application/json"}, 15 | "body": { 16 | "alligator": { 17 | "age": 3 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/body/plain text that matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Plain text that matches", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": {}, 8 | "headers": { "Content-Type": "text/plain" }, 9 | "body": "alligator named mary" 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/", 14 | "query": {}, 15 | "headers": { "Content-Type": "text/plain" }, 16 | "body": "alligator named mary" 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/null found at key where not null expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Name should not be null", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "name": null 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /provider/pact-jvm-provider/src/main/kotlin/au/com/dius/pact/provider/junit/target/TestTarget.kt: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider.junit.target 2 | 3 | import java.lang.annotation.Inherited 4 | 5 | /** 6 | * Mark [au.com.dius.pact.provider.junit.target.Target] for contract tests 7 | * 8 | * @see au.com.dius.pact.provider.junit.target.Target 9 | * 10 | * @see HttpTarget 11 | */ 12 | @Retention(AnnotationRetention.RUNTIME) 13 | @kotlin.annotation.Target(AnnotationTarget.FIELD) 14 | @Inherited 15 | annotation class TestTarget 16 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-java8/src/test/kotlin/io/pactfoundation/consumer/dsl/ExtensionsTest.kt: -------------------------------------------------------------------------------- 1 | package io.pactfoundation.consumer.dsl 2 | 3 | import org.junit.jupiter.api.Test 4 | 5 | class ExtensionsTest { 6 | @Test 7 | fun `can use LambdaDslJsonArray#newObject`() { 8 | newJsonArray { newObject { stringType("foo") } } 9 | } 10 | 11 | @Test 12 | fun `can use LambdaDslObject#newObject`() { 13 | newJsonObject { 14 | newObject("object") { 15 | stringType("field") 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /core/matchers/src/test/groovy/au/com/dius/pact/core/matchers/ResponseMatchingSpec.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.core.matchers 2 | 3 | import spock.lang.Specification 4 | 5 | class ResponseMatchingSpec extends Specification { 6 | 7 | def 'response matching - match statuses'() { 8 | expect: 9 | Matching.INSTANCE.matchStatus(200, 200) == null 10 | } 11 | 12 | def 'response matching - mismatch statuses'() { 13 | expect: 14 | Matching.INSTANCE.matchStatus(200, 300) == new StatusMismatch(200, 300) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/body/missing body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Missing body", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": {"Content-Type": "application/json"} 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/", 13 | "query": "", 14 | "headers": {"Content-Type": "application/json"}, 15 | "body": { 16 | "alligator": { 17 | "age": 3 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/body/plain text that matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Plain text that matches", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": { "Content-Type": "text/plain" }, 9 | "body": "alligator named mary" 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/", 14 | "query": "", 15 | "headers": { "Content-Type": "text/plain" }, 16 | "body": "alligator named mary" 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/null found in array when not null expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Favourite numbers expected to be strings found a null", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteNumbers": ["1","2","3"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteNumbers": ["1",null,"3"] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/number found in array when string expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Favourite numbers expected to be strings found a number", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteNumbers": ["1","2","3"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteNumbers": ["1",2,"3"] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/objects in array no matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Array of objects, properties match on incorrect objects", 4 | "expected" : { 5 | "headers": {}, 6 | "body": [ 7 | {"favouriteColor": "red"}, 8 | {"favouriteNumber": 2} 9 | ] 10 | }, 11 | "actual": { 12 | "headers": {}, 13 | "body": [ 14 | {"favouriteColor": "blue", 15 | "favouriteNumber": 4}, 16 | {"favouriteColor": "red", 17 | "favouriteNumber": 2} 18 | ] 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/headers/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Headers match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": "", 8 | "headers": { 9 | "Accept": "alligators", 10 | "Content-Type": "hippos" 11 | } 12 | }, 13 | "actual": { 14 | "method": "POST", 15 | "path": "/path", 16 | "query": "", 17 | "headers": { 18 | "Content-Type": "hippos", 19 | "Accept": "alligators" 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/query/different param order.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Query strings are matched using basic string equality, these are not equal. (not supported by pact-jvm)", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "alligator=Mary&hippo=John", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "hippo=John&alligator=Mary", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/query/trailing amperand.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Query strings are matched using basic string equality, these are not equal. (not supported by pact-jvm)", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "alligator=Mary&hippo=John", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "alligator=Mary&hippo=John&", 15 | "headers": {} 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/body/missing body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Missing body", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": {"Content-Type": "application/json"} 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/", 13 | "query": "", 14 | "headers": {"Content-Type": "application/json"}, 15 | "body": { 16 | "alligator": { 17 | "age": 3 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/headers/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Headers match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": "", 8 | "headers": { 9 | "Accept": "alligators", 10 | "Content-Type": "hippos" 11 | } 12 | }, 13 | "actual": { 14 | "method": "POST", 15 | "path": "/path", 16 | "query": "", 17 | "headers": { 18 | "Content-Type": "hippos", 19 | "Accept": "alligators" 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/missing index.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Missing favorite colour", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteColours": ["red","blue"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator": { 16 | "favouriteColours": ["red"] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/body/missing body.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Missing body", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": {}, 8 | "headers": {"Content-Type": "application/json"} 9 | }, 10 | "actual": { 11 | "method": "POST", 12 | "path": "/", 13 | "query": {}, 14 | "headers": {"Content-Type": "application/json"}, 15 | "body": { 16 | "alligator": { 17 | "age": 3 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/headers/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Headers match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": {}, 8 | "headers": { 9 | "Accept": "alligators", 10 | "Content-Type": "hippos" 11 | } 12 | }, 13 | "actual": { 14 | "method": "POST", 15 | "path": "/path", 16 | "query": {}, 17 | "headers": { 18 | "Content-Type": "hippos", 19 | "Accept": "alligators" 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/missing index.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Missing favorite colour", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteColours": ["red","blue"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator": { 16 | "favouriteColours": ["red"] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /provider/pact-jvm-provider/src/main/kotlin/au/com/dius/pact/provider/junit/Consumer.kt: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider.junit 2 | 3 | import java.lang.annotation.Inherited 4 | import kotlin.annotation.Retention 5 | 6 | /** 7 | * Used to pass consumer name to Pact runner 8 | */ 9 | @Retention(AnnotationRetention.RUNTIME) 10 | @Target(AnnotationTarget.CLASS, AnnotationTarget.FILE) 11 | @Inherited 12 | annotation class Consumer( 13 | /** 14 | * @return consumer name for pact test running 15 | */ 16 | val value: String 17 | ) 18 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/headers/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Headers match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": "", 8 | "headers": { 9 | "Accept": "alligators", 10 | "Content-Type": "hippos" 11 | } 12 | }, 13 | "actual": { 14 | "method": "POST", 15 | "path": "/path", 16 | "query": "", 17 | "headers": { 18 | "Content-Type": "hippos", 19 | "Accept": "alligators" 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/not null found in array when null expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Favourite numbers expected to contain null, but not null found", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteNumbers": ["1",null,"3"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteNumbers": ["1","2","3"] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/query/same parameter different values.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Queries are not the same - animals are alligator, hippo versus alligator, elephant", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "animal=alligator&animal=hippo", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "animal=alligator&animal=elephant", 15 | "headers": {} 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/not null found in array when null expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Favourite numbers expected to contain null, but not null found", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteNumbers": ["1",null,"3"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteNumbers": ["1","2","3"] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/body/plain text that does not match.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Plain text that does not match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": { "Content-Type": "text/plain" }, 9 | "body": "alligator named mary" 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/", 14 | "query": "", 15 | "headers": { "Content-Type": "text/plain" }, 16 | "body": "alligator named fred" 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/body/plain text that does not match.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Plain text that does not match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": { "Content-Type": "text/plain" }, 9 | "body": "alligator named mary" 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/", 14 | "query": "", 15 | "headers": { "Content-Type": "text/plain" }, 16 | "body": "alligator named fred" 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/query/same parameter different values.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Queries are not the same - animals are alligator, hippo versus alligator, elephant", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "animal=alligator&animal=hippo", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "animal=alligator&animal=elephant", 15 | "headers": {} 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/unexpected key with non-empty value xml.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "XML Unexpected phone number", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/xml"}, 6 | "body": "" 7 | }, 8 | "actual": { 9 | "headers": {"Content-Type": "application/xml"}, 10 | "body": "" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/body/plain text that does not match.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Plain text that does not match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": {}, 8 | "headers": { "Content-Type": "text/plain" }, 9 | "body": "alligator named mary" 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/", 14 | "query": {}, 15 | "headers": { "Content-Type": "text/plain" }, 16 | "body": "alligator named fred" 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/unexpected key with non-empty value xml.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "XML Unexpected phone number", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/xml"}, 6 | "body": "" 7 | }, 8 | "actual": { 9 | "headers": {"Content-Type": "application/xml"}, 10 | "body": "" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /core/model/src/main/kotlin/au/com/dius/pact/core/model/annotations/PactFolder.kt: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.core.model.annotations 2 | 3 | import java.lang.annotation.Inherited 4 | 5 | /** 6 | * Used to point Pact runner to the directory where the pact files are stored 7 | */ 8 | @Retention(AnnotationRetention.RUNTIME) 9 | @Target(AnnotationTarget.CLASS, AnnotationTarget.FILE) 10 | @Inherited 11 | annotation class PactFolder( 12 | /** 13 | * @return path to subfolder of project resource folder with pacts 14 | */ 15 | val value: String 16 | ) 17 | -------------------------------------------------------------------------------- /core/support/src/main/kotlin/au/com/dius/pact/core/support/expressions/ValueResolver.kt: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.core.support.expressions 2 | 3 | interface ValueResolver { 4 | fun resolveValue(property: String?): String? 5 | fun propertyDefined(property: String): Boolean 6 | } 7 | 8 | data class MapValueResolver(val context: Map) : ValueResolver { 9 | override fun resolveValue(property: String?) = context[property ?: ""].toString() 10 | 11 | override fun propertyDefined(property: String) = context.containsKey(property) 12 | } 13 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/body/plain text that does not match.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Plain text that does not match", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/", 7 | "query": "", 8 | "headers": { "Content-Type": "text/plain" }, 9 | "body": "alligator named mary" 10 | }, 11 | "actual": { 12 | "method": "POST", 13 | "path": "/", 14 | "query": "", 15 | "headers": { "Content-Type": "text/plain" }, 16 | "body": "alligator named fred" 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/headers/whitespace after comma different.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Whitespace between comma separated headers does not matter", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": "", 8 | "headers": { 9 | "Accept": "alligators,hippos" 10 | } 11 | }, 12 | "actual": { 13 | "method": "POST", 14 | "path": "/path", 15 | "query": "", 16 | "headers": { 17 | "Accept": "alligators, hippos" 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/request/headers/whitespace after comma different.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Whitespace between comma separated headers does not matter", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": "", 8 | "headers": { 9 | "Accept": "alligators,hippos" 10 | } 11 | }, 12 | "actual": { 13 | "method": "POST", 14 | "path": "/path", 15 | "query": "", 16 | "headers": { 17 | "Accept": "alligators, hippos" 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/headers/whitespace after comma different.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Whitespace between comma separated headers does not matter", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": "", 8 | "headers": { 9 | "Accept": "alligators,hippos" 10 | } 11 | }, 12 | "actual": { 13 | "method": "POST", 14 | "path": "/path", 15 | "query": "", 16 | "headers": { 17 | "Accept": "alligators, hippos" 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/number found at key when string expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Number of feet expected to be string but was number", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "feet": "4" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "feet": 4 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/string found at key when number expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Number of feet expected to be number but was string", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "feet": 4 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "feet": "4" 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/unexpected key with empty value xml.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "XML Unexpected phone number with empty value", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/xml"}, 6 | "body": "" 7 | }, 8 | "actual": { 9 | "headers": {"Content-Type": "application/xml"}, 10 | "body": "" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/headers/whitespace after comma different.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Whitespace between comma separated headers does not matter", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": {}, 8 | "headers": { 9 | "Accept": "alligators,hippos" 10 | } 11 | }, 12 | "actual": { 13 | "method": "POST", 14 | "path": "/path", 15 | "query": {}, 16 | "headers": { 17 | "Accept": "alligators, hippos" 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/number found at key when string expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Number of feet expected to be string but was number", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "feet": "4" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "feet": 4 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/string found at key when number expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Number of feet expected to be number but was string", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "feet": 4 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "feet": "4" 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/unexpected key with empty value xml.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "XML Unexpected phone number with empty value", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/xml"}, 6 | "body": "" 7 | }, 8 | "actual": { 9 | "headers": {"Content-Type": "application/xml"}, 10 | "body": "" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-spring/src/main/kotlin/au/com/dius/pact/provider/spring/target/SpringBootHttpTarget.kt: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider.spring.target 2 | 3 | import au.com.dius.pact.provider.junit.target.HttpTarget 4 | 5 | /** 6 | * This class sets up an HTTP target configured with the springboot application. Basically, it allows the port 7 | * to be overridden by the interaction runner which looks up the server 8 | * port from the spring context. 9 | */ 10 | class SpringBootHttpTarget(override var port: Int = 0) : HttpTarget(port = port) 11 | -------------------------------------------------------------------------------- /consumer/pact-jvm-consumer-groovy/src/main/groovy/au/com/dius/pact/consumer/groovy/BaseBuilder.groovy: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.consumer.groovy 2 | 3 | /** 4 | * Base class for builders 5 | */ 6 | class BaseBuilder extends Matchers { 7 | public static final List COMPACT_MIME_TYPES = ['application/x-thrift+json'] 8 | 9 | def call(Closure closure) { 10 | build(closure) 11 | } 12 | 13 | def build(Closure closure) { 14 | closure.delegate = this 15 | closure.resolveStrategy = Closure.DELEGATE_FIRST 16 | closure.call() 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/query/same parameter multiple times in different order.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Queries are not the same - values are in different order", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "animal=alligator&animal=hippo&animal=elephant", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "animal=hippo&animal=alligator&animal=elephant", 15 | "headers": {} 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/request/query/same parameter multiple times.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Queries are the same - multiple values are in same order", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "animal=alligator&animal=hippo&animal=elephant&hippo=Fred", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "animal=alligator&hippo=Fred&animal=hippo&animal=elephant", 15 | "headers": {} 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/query/same parameter multiple times in different order.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Queries are not the same - values are in different order", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "animal=alligator&animal=hippo&animal=elephant", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "animal=hippo&animal=alligator&animal=elephant", 15 | "headers": {} 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/request/query/same parameter multiple times.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Queries are the same - multiple values are in same order", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": "animal=alligator&animal=hippo&animal=elephant&hippo=Fred", 8 | "headers": {} 9 | 10 | }, 11 | "actual": { 12 | "method": "GET", 13 | "path": "/path", 14 | "query": "animal=alligator&hippo=Fred&animal=hippo&animal=elephant", 15 | "headers": {} 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/keys out of order match.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Favourite number and favourite colours out of order", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "favouriteNumber": 7, 8 | "favouriteColours": ["red","blue"] 9 | } 10 | }, 11 | "actual": { 12 | "headers": {"Content-Type": "application/json"}, 13 | "body": { 14 | "favouriteColours": ["red","blue"], 15 | "favouriteNumber": 7 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/property name is different case xml.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "XML Property names on objects are case sensitive", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/xml"}, 6 | "body": "" 7 | }, 8 | "actual": { 9 | "headers": {"Content-Type": "application/json"}, 10 | "body": "" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/property name is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Property names on objects are case sensitive", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "FavouriteColour": "red" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "favouritecolour": "red" 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/unexpected key with not null value.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Unexpected phone number", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "name": "Mary", 17 | "phoneNumber": "12345678" 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/keys out of order match.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Favourite number and favourite colours out of order", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "favouriteNumber": 7, 8 | "favouriteColours": ["red","blue"] 9 | } 10 | }, 11 | "actual": { 12 | "headers": {"Content-Type": "application/json"}, 13 | "body": { 14 | "favouriteColours": ["red","blue"], 15 | "favouriteNumber": 7 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/property name is different case xml.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "XML Property names on objects are case sensitive", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/xml"}, 6 | "body": "" 7 | }, 8 | "actual": { 9 | "headers": {"Content-Type": "application/json"}, 10 | "body": "" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/property name is different case.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Property names on objects are case sensitive", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "FavouriteColour": "red" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "favouritecolour": "red" 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/unexpected key with not null value.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Unexpected phone number", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "name": "Mary", 17 | "phoneNumber": "12345678" 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Responses match", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary", 9 | "feet": 4, 10 | "favouriteColours": ["red","blue"] 11 | } 12 | } 13 | }, 14 | "actual": { 15 | "headers": {}, 16 | "body": { 17 | "alligator":{ 18 | "feet": 4, 19 | "name": "Mary", 20 | "favouriteColours": ["red","blue"] 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1.1/response/body/non empty body found when empty expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Non empty body found, when an empty body was expected", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": null 7 | }, 8 | "actual": { 9 | "headers": {"Content-Type": "application/json"}, 10 | "body": { 11 | "alligator":{ 12 | "feet": 4, 13 | "name": "Mary", 14 | "favouriteColours": ["red","blue"] 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v1/response/body/matches.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Responses match", 4 | "expected" : { 5 | "headers": {}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary", 9 | "feet": 4, 10 | "favouriteColours": ["red","blue"] 11 | } 12 | } 13 | }, 14 | "actual": { 15 | "headers": {}, 16 | "body": { 17 | "alligator":{ 18 | "feet": 4, 19 | "name": "Mary", 20 | "favouriteColours": ["red","blue"] 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/array in different order.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Favourite colours in wrong order", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteColours": ["red","blue"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteColours": ["blue", "red"] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/different value found at index.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Incorrect favourite colour", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteColours": ["red","blue"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteColours": ["red","taupe"] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/non empty body found when empty expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Non empty body found, when an empty body was expected", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": null 7 | }, 8 | "actual": { 9 | "headers": {"Content-Type": "application/json"}, 10 | "body": { 11 | "alligator":{ 12 | "feet": 4, 13 | "name": "Mary", 14 | "favouriteColours": ["red","blue"] 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/query/different order.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Queries are the same but in different key order", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": { 8 | "alligator": ["Mary"], 9 | "hippo": ["John"] 10 | }, 11 | "headers": {} 12 | }, 13 | "actual": { 14 | "method": "GET", 15 | "path": "/path", 16 | "query": { 17 | "hippo": ["John"], 18 | "alligator": ["Mary"] 19 | }, 20 | "headers": {} 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/array in different order.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Favourite colours in wrong order", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteColours": ["red","blue"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteColours": ["blue", "red"] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/non empty body found when empty expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Non empty body found, when an empty body was expected", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": null 7 | }, 8 | "actual": { 9 | "headers": {"Content-Type": "application/json"}, 10 | "body": { 11 | "alligator":{ 12 | "feet": 4, 13 | "name": "Mary", 14 | "favouriteColours": ["red","blue"] 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pact-specification-test/src/test/groovy/specification/RequestSpecificationV3Spec.groovy: -------------------------------------------------------------------------------- 1 | package specification 2 | 3 | import au.com.dius.pact.core.matchers.RequestMatching 4 | import spock.lang.Unroll 5 | 6 | class RequestSpecificationV3Spec extends BaseRequestSpec { 7 | 8 | @Unroll 9 | def '#type/#name - #test #matchDesc'() { 10 | expect: 11 | RequestMatching.requestMismatches(expected, actual).isEmpty() == match 12 | 13 | where: 14 | [type, name, test, match, matchDesc, expected, actual] << loadTestCases('/v3/request/') 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-specs2/src/test/resources/exampleSpec.json: -------------------------------------------------------------------------------- 1 | { 2 | "provider" : { 3 | "name" : "test_provider" 4 | }, 5 | "consumer" : { 6 | "name" : "test_consumer" 7 | }, 8 | "interactions" : [ { 9 | "provider_state" : "test state", 10 | "description" : "test interaction", 11 | "request" : { 12 | "method" : "GET", 13 | "path" : "/" 14 | }, 15 | "response" : { 16 | "status" : 200, 17 | "body" : ["All Done"] 18 | } 19 | } ] 20 | } -------------------------------------------------------------------------------- /core/support/src/main/kotlin/au/com/dius/pact/core/support/Utils.kt: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.core.support 2 | 3 | object Utils { 4 | fun extractFromMap(json: Map, vararg s: String): Any? { 5 | return if (s.size == 1) { 6 | json[s.first()] 7 | } else if (json.containsKey(s.first())) { 8 | val map = json[s.first()] 9 | if (map is Map<*, *>) { 10 | extractFromMap(map as Map, *s.drop(1).toTypedArray()) 11 | } else { 12 | null 13 | } 14 | } else { 15 | null 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/unexpected key with null value.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Unexpected phone number with null value", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "name": "Mary", 17 | "phoneNumber": null 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/query/different params.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Queries are not the same - hippo is Fred instead of John", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": { 8 | "alligator": ["Mary"], 9 | "hippo": ["John"] 10 | }, 11 | "headers": {} 12 | }, 13 | "actual": { 14 | "method": "GET", 15 | "path": "/path", 16 | "query": { 17 | "alligator": ["Mary"], 18 | "hippo": ["Fred"] 19 | }, 20 | "headers": {} 21 | } 22 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/different value found at index.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Incorrect favourite colour", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteColours": ["red","blue"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteColours": ["red","taupe"] 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/unexpected key with null value.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Unexpected phone number with null value", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "name": "Mary" 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "name": "Mary", 17 | "phoneNumber": null 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/headers/matches content type with parameters in different order.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Headers match when the content type parameters are in a different order", 4 | "expected" : { 5 | "headers": { 6 | "Content-Type": "Text/x-Okie; charset=iso-8859-1;\n declaration=\"<950118.AEB0@XIson.com>\"" 7 | } 8 | }, 9 | "actual": { 10 | "headers": { 11 | "Content-Type": "Text/x-Okie; declaration=\"<950118.AEB0@XIson.com>\";\n charset=iso-8859-1" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /provider/pact-jvm-provider-specs2/src/test/scala/au/com/dius/pact/provider/specs2/ExampleProviderSpec.scala: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider.specs2 2 | 3 | import org.specs2.execute.Result 4 | import org.junit.runner.RunWith 5 | import org.specs2.runner.JUnitRunner 6 | 7 | @RunWith(classOf[JUnitRunner]) 8 | class ExampleProviderSpec extends ProviderSpec { 9 | def honoursPact = getClass.getClassLoader.getResourceAsStream("exampleSpec.json") 10 | 11 | def inState(state: String, test: (String) => Result): Result = { 12 | TestServer(state).run(test) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /core/support/src/main/kotlin/au/com/dius/pact/com/github/michaelbull/result/On.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is inlined from https://github.com/michaelbull/kotlin-result 3 | */ 4 | package au.com.dius.pact.com.github.michaelbull.result 5 | 6 | /** 7 | * Invokes a [callback] if this [Result] is [Ok]. 8 | */ 9 | inline infix fun Result.onSuccess(callback: (V) -> Unit) = mapBoth(callback, {}) 10 | 11 | /** 12 | * Invokes a [callback] if this [Result] is [Err]. 13 | */ 14 | inline infix fun Result.onFailure(callback: (E) -> Unit) = mapBoth({}, callback) 15 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v2/response/body/unexpected index with not null value.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Unexpected favourite colour", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteColours": ["red","blue"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteColours": ["red","blue","taupe"] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/message/body/missing key.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Missing key alligator name", 4 | "expected": { 5 | "metaData": { 6 | "contentType": "application/json" 7 | }, 8 | "contents": { 9 | "alligator":{ 10 | "name": "Mary", 11 | "age": 3 12 | } 13 | } 14 | }, 15 | "actual": { 16 | "metaData": { 17 | "contentType": "application/json" 18 | }, 19 | "contents": { 20 | "alligator": { 21 | "age": 3 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/response/body/unexpected index with not null value.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Unexpected favourite colour", 4 | "expected" : { 5 | "headers": {"Content-Type": "application/json"}, 6 | "body": { 7 | "alligator":{ 8 | "favouriteColours": ["red","blue"] 9 | } 10 | } 11 | }, 12 | "actual": { 13 | "headers": {"Content-Type": "application/json"}, 14 | "body": { 15 | "alligator":{ 16 | "favouriteColours": ["red","blue","taupe"] 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /provider/pact-jvm-provider/src/main/java/au/com/dius/pact/provider/junit/loader/NoPactsFoundException.java: -------------------------------------------------------------------------------- 1 | package au.com.dius.pact.provider.junit.loader; 2 | 3 | public class NoPactsFoundException extends RuntimeException { 4 | public NoPactsFoundException() { 5 | } 6 | 7 | public NoPactsFoundException(String message) { 8 | super(message); 9 | } 10 | 11 | public NoPactsFoundException(String message, Throwable cause) { 12 | super(message, cause); 13 | } 14 | 15 | public NoPactsFoundException(Throwable cause) { 16 | super(cause); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/message/body/not null found at key when null expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Name should be null", 4 | "expected": { 5 | "metaData": { 6 | "contentType": "application/json" 7 | }, 8 | "contents": { 9 | "alligator":{ 10 | "name": null 11 | } 12 | } 13 | }, 14 | "actual": { 15 | "metaData": { 16 | "contentType": "application/json" 17 | }, 18 | "contents": { 19 | "alligator":{ 20 | "name": "Fred" 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/headers/matches content type with charset.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": true, 3 | "comment": "Headers match when the actual includes additional parameters", 4 | "expected" : { 5 | "method": "POST", 6 | "path": "/path", 7 | "query": {}, 8 | "headers": { 9 | "Content-Type": "application/json" 10 | } 11 | }, 12 | "actual": { 13 | "method": "POST", 14 | "path": "/path", 15 | "query": {}, 16 | "headers": { 17 | "Content-Type": "application/json; charset=UTF-8" 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /pact-specification-test/src/main/resources/v3/request/query/same parameter different values.json: -------------------------------------------------------------------------------- 1 | { 2 | "match": false, 3 | "comment": "Queries are not the same - animals are alligator, hippo versus alligator, elephant", 4 | "expected" : { 5 | "method": "GET", 6 | "path": "/path", 7 | "query": { 8 | "animal": ["alligator", "hippo"] 9 | }, 10 | "headers": {} 11 | }, 12 | "actual": { 13 | "method": "GET", 14 | "path": "/path", 15 | "query": { 16 | "animal": ["alligator", "elephant"] 17 | }, 18 | "headers": {} 19 | } 20 | } 21 | --------------------------------------------------------------------------------