diff --git a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/ContractDsl.kt b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/ContractDsl.kt index 820e8dd12d..6444a69b3a 100644 --- a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/ContractDsl.kt +++ b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/ContractDsl.kt @@ -17,9 +17,13 @@ package org.springframework.cloud.contract.spec import org.springframework.cloud.contract.spec.internal.ContractDslMarker +import org.springframework.cloud.contract.spec.internal.Input import org.springframework.cloud.contract.spec.internal.InputDsl +import org.springframework.cloud.contract.spec.internal.OutputMessage import org.springframework.cloud.contract.spec.internal.OutputMessageDsl +import org.springframework.cloud.contract.spec.internal.Request import org.springframework.cloud.contract.spec.internal.RequestDsl +import org.springframework.cloud.contract.spec.internal.Response import org.springframework.cloud.contract.spec.internal.ResponseDsl /** @@ -28,38 +32,48 @@ import org.springframework.cloud.contract.spec.internal.ResponseDsl @ContractDslMarker class ContractDsl { - val contract = Contract() - companion object { - fun make(block: ContractDsl.() -> Unit): Contract = ContractDsl().apply(block).get() + fun contract(dsl: ContractDsl.() -> Unit): Contract = ContractDsl().apply(dsl).get() } - private fun get(): Contract = contract + var priority: Int? = null + var label: String? = null + var description: String? = null + var name: String? = null + var ignored: Boolean = false + var request: Request? = null + var response: Response? = null + var input: Input? = null + var outputMessage: OutputMessage? = null - infix fun priority(priority: Int) = contract.priority(priority) - - infix fun label(label: String) = contract.label(label) - - infix fun description(description: String) = contract.description(description) - - infix fun name(name: String) = contract.name(name) - - fun ignored() = contract.ignored() - - fun request(block: RequestDsl.() -> Unit) { - contract.request = RequestDsl.make(block) + fun request(request: RequestDsl.() -> Unit) { + this.request = RequestDsl().apply(request).get() } - fun response(block: ResponseDsl.() -> Unit) { - contract.response = ResponseDsl.make(block) + fun response(response: ResponseDsl.() -> Unit) { + this.response = ResponseDsl().apply(response).get() } - fun input(block: InputDsl.() -> Unit) { - contract.input = InputDsl.make(block) + fun input(input: InputDsl.() -> Unit) { + this.input = InputDsl().apply(input).get() } - fun outputMessage(block: OutputMessageDsl.() -> Unit) { - contract.outputMessage = OutputMessageDsl.make(block) + fun outputMessage(outputMessage: OutputMessageDsl.() -> Unit) { + this.outputMessage = OutputMessageDsl().apply(outputMessage).get() + } + + private fun get(): Contract { + val contract = Contract() + priority?.also { contract.priority = priority!! } + label?.also { contract.label = label!! } + description?.also { contract.description = description!! } + name?.also { contract.name = name!! } + contract.ignored = ignored + request?.also { contract.request = request!! } + response?.also { contract.response = response!! } + input?.also { contract.input = input!! } + outputMessage?.also { contract.outputMessage = outputMessage!! } + return contract } } diff --git a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/ContractDslExtensions.kt b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/ContractDslExtensions.kt new file mode 100644 index 0000000000..fc5d9a99c3 --- /dev/null +++ b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/ContractDslExtensions.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.spec + +import org.springframework.cloud.contract.spec.internal.DslProperty +import org.springframework.cloud.contract.spec.internal.QueryParameters +import org.springframework.cloud.contract.spec.internal.Url +import org.springframework.cloud.contract.spec.internal.UrlPath +import java.lang.IllegalStateException +import java.util.stream.Collectors + +/** + * @author Tim Ysewyn + */ +infix fun Url.withQueryParameters(parameters: QueryParameters.() -> Unit): Url { + this.queryParameters = QueryParameters().apply(parameters) + return this +} + +infix fun UrlPath.withQueryParameters(parameters: QueryParameters.() -> Unit): UrlPath { + this.queryParameters = QueryParameters().apply(parameters) + return this +} + +fun Any.toDslProperty(): DslProperty { + return DslProperty(this) +} + +fun Map.toDslProperties(): Map> { + return entries.stream().collect(Collectors.toMap( + { entry -> entry.key }, + { entry -> entry.value.toDslProperty() }, + { t, _ -> throw IllegalStateException(String.format("Duplicate key %s", t)) }, + { LinkedHashMap>() } + )) +} + +fun List.toDslProperties(): List> { + return stream().map(Any::toDslProperty).collect(Collectors.toList()) +} \ No newline at end of file diff --git a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/CommonDsl.kt b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/CommonDsl.kt index 076d95726b..f1a5a5e6ec 100644 --- a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/CommonDsl.kt +++ b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/CommonDsl.kt @@ -16,7 +16,6 @@ package org.springframework.cloud.contract.spec.internal -import org.springframework.cloud.contract.spec.internal.HttpMethods.HttpMethod import java.util.regex.Pattern /** @@ -80,146 +79,6 @@ open class CommonDsl { */ fun test(serverValue: Any) = ServerDslProperty(serverValue) - /* HTTP METHODS */ - - fun GET() = HttpMethod.GET - - fun HEAD() = HttpMethod.HEAD - - fun POST() = HttpMethod.POST - - fun PUT() = HttpMethod.PUT - - fun PATCH() = HttpMethod.PATCH - - fun DELETE() = HttpMethod.DELETE - - fun OPTIONS() = HttpMethod.OPTIONS - - fun TRACE() = HttpMethod.TRACE - - /* HTTP STATUS CODES */ - - fun CONTINUE() = HttpStatus.CONTINUE() - - fun SWITCHING_PROTOCOLS() = HttpStatus.SWITCHING_PROTOCOLS() - - fun PROCESSING() = HttpStatus.PROCESSING() - - fun CHECKPOINT() = HttpStatus.CHECKPOINT() - - fun OK() = HttpStatus.OK() - - fun CREATED() = HttpStatus.CREATED() - - fun ACCEPTED() = HttpStatus.ACCEPTED() - - fun NON_AUTHORITATIVE_INFORMATION() = HttpStatus.NON_AUTHORITATIVE_INFORMATION() - - fun NO_CONTENT() = HttpStatus.NO_CONTENT() - - fun RESET_CONTENT() = HttpStatus.RESET_CONTENT() - - fun PARTIAL_CONTENT() = HttpStatus.PARTIAL_CONTENT() - - fun MULTI_STATUS() = HttpStatus.MULTI_STATUS() - - fun ALREADY_REPORTED() = HttpStatus.ALREADY_REPORTED() - - fun IM_USED() = HttpStatus.IM_USED() - - fun MULTIPLE_CHOICES() = HttpStatus.MULTIPLE_CHOICES() - - fun MOVED_PERMANENTLY() = HttpStatus.MOVED_PERMANENTLY() - - fun FOUND() = HttpStatus.FOUND() - - fun SEE_OTHER() = HttpStatus.SEE_OTHER() - - fun NOT_MODIFIED() = HttpStatus.NOT_MODIFIED() - - fun TEMPORARY_REDIRECT() = HttpStatus.TEMPORARY_REDIRECT() - - fun PERMANENT_REDIRECT() = HttpStatus.PERMANENT_REDIRECT() - - fun BAD_REQUEST() = HttpStatus.BAD_REQUEST() - - fun UNAUTHORIZED() = HttpStatus.UNAUTHORIZED() - - fun PAYMENT_REQUIRED() = HttpStatus.PAYMENT_REQUIRED() - - fun FORBIDDEN() = HttpStatus.FORBIDDEN() - - fun NOT_FOUND() = HttpStatus.NOT_FOUND() - - fun METHOD_NOT_ALLOWED() = HttpStatus.METHOD_NOT_ALLOWED() - - fun NOT_ACCEPTABLE() = HttpStatus.NOT_ACCEPTABLE() - - fun PROXY_AUTHENTICATION_REQUIRED() = HttpStatus.PROXY_AUTHENTICATION_REQUIRED() - - fun REQUEST_TIMEOUT() = HttpStatus.REQUEST_TIMEOUT() - - fun CONFLICT() = HttpStatus.CONFLICT() - - fun GONE() = HttpStatus.GONE() - - fun LENGTH_REQUIRED() = HttpStatus.LENGTH_REQUIRED() - - fun PRECONDITION_FAILED() = HttpStatus.PRECONDITION_FAILED() - - fun PAYLOAD_TOO_LARGE() = HttpStatus.PAYLOAD_TOO_LARGE() - - fun URI_TOO_LONG() = HttpStatus.URI_TOO_LONG() - - fun UNSUPPORTED_MEDIA_TYPE() = HttpStatus.UNSUPPORTED_MEDIA_TYPE() - - fun REQUESTED_RANGE_NOT_SATISFIABLE() = HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE() - - fun EXPECTATION_FAILED() = HttpStatus.EXPECTATION_FAILED() - - fun I_AM_A_TEAPOT() = HttpStatus.I_AM_A_TEAPOT() - - fun UNPROCESSABLE_ENTITY() = HttpStatus.UNPROCESSABLE_ENTITY() - - fun LOCKED() = HttpStatus.LOCKED() - - fun FAILED_DEPENDENCY() = HttpStatus.FAILED_DEPENDENCY() - - fun UPGRADE_REQUIRED() = HttpStatus.UPGRADE_REQUIRED() - - fun PRECONDITION_REQUIRED() = HttpStatus.PRECONDITION_REQUIRED() - - fun TOO_MANY_REQUESTS() = HttpStatus.TOO_MANY_REQUESTS() - - fun REQUEST_HEADER_FIELDS_TOO_LARGE() = HttpStatus.REQUEST_HEADER_FIELDS_TOO_LARGE() - - fun UNAVAILABLE_FOR_LEGAL_REASONS() = HttpStatus.UNAVAILABLE_FOR_LEGAL_REASONS() - - fun INTERNAL_SERVER_ERROR() = HttpStatus.INTERNAL_SERVER_ERROR() - - fun NOT_IMPLEMENTED() = HttpStatus.NOT_IMPLEMENTED() - - fun BAD_GATEWAY() = HttpStatus.BAD_GATEWAY() - - fun SERVICE_UNAVAILABLE() = HttpStatus.SERVICE_UNAVAILABLE() - - fun GATEWAY_TIMEOUT() = HttpStatus.GATEWAY_TIMEOUT() - - fun HTTP_VERSION_NOT_SUPPORTED() = HttpStatus.HTTP_VERSION_NOT_SUPPORTED() - - fun VARIANT_ALSO_NEGOTIATES() = HttpStatus.VARIANT_ALSO_NEGOTIATES() - - fun INSUFFICIENT_STORAGE() = HttpStatus.INSUFFICIENT_STORAGE() - - fun LOOP_DETECTED() = HttpStatus.LOOP_DETECTED() - - fun BANDWIDTH_LIMIT_EXCEEDED() = HttpStatus.BANDWIDTH_LIMIT_EXCEEDED() - - fun NOT_EXTENDED() = HttpStatus.NOT_EXTENDED() - - fun NETWORK_AUTHENTICATION_REQUIRED() = HttpStatus.NETWORK_AUTHENTICATION_REQUIRED() - /* REGEX */ fun regexProperty(value: Any) = RegexProperty(value) diff --git a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/HeadersDsl.kt b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/HeadersDsl.kt new file mode 100644 index 0000000000..910948d1b6 --- /dev/null +++ b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/HeadersDsl.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.spec.internal + +/** + * @author Tim Ysewyn + */ +@ContractDslMarker +class HeadersDsl { + + var accept: String? = null + var contentType: String? = null + + fun header(headerKey: String, headerValue: Any) { + + } + +} diff --git a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/InputDsl.kt b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/InputDsl.kt index 8fe5b60f68..e6009e7d48 100644 --- a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/InputDsl.kt +++ b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/InputDsl.kt @@ -22,68 +22,95 @@ package org.springframework.cloud.contract.spec.internal @ContractDslMarker class InputDsl : CommonDsl(), RegexCreatingProperty { - private val input = Input() + var messageFrom: DslProperty? = null + var triggeredBy: ExecutionProperty? = null + var messageHeaders: Headers? = null + var messageBody: Input.BodyType? = null + var assertThat: ExecutionProperty? = null + var bodyMatchers: BodyMatchers? = null - companion object { - fun make(block: InputDsl.() -> Unit): Input = InputDsl().apply(block).get() + fun messageFrom(messageFrom: String) { + this.messageFrom = DslProperty(messageFrom) } - private fun get(): Input = input - - fun messageFrom(messageFrom: String) = input.messageFrom(messageFrom) - - fun messageFrom(messageFrom: DslProperty) = input.messageFrom(messageFrom) - - fun messageBody(vararg pairs: Pair) = input.messageBody(pairs.toMap()) - - fun messageBody(pair: Pair) = input.messageBody(mapOf(pair)) - - fun messageBody(value: String) = input.messageBody(value) - - fun messageHeaders(block: Headers.() -> Unit) { - input.messageHeaders = Headers().apply(block) + fun messageHeaders(headers: Headers.() -> Unit) { + this.messageHeaders = Headers().apply(headers) } - override fun anyAlphaUnicode(): ClientDslProperty = input.anyAlphaUnicode() + fun triggeredBy(triggeredBy: String) { + this.triggeredBy = ExecutionProperty(triggeredBy) + } - override fun anyAlphaNumeric(): ClientDslProperty = input.anyAlphaNumeric() + fun messageBody(vararg pairs: Pair) { + this.messageBody = Input.BodyType(pairs.toMap()) + } - override fun anyNumber(): ClientDslProperty = input.anyNumber() + fun messageBody(pair: Pair) { + this.messageBody = Input.BodyType(mapOf(pair)) + } - override fun anyInteger(): ClientDslProperty = input.anyInteger() + fun messageBody(value: String) { + this.messageBody = Input.BodyType(value) + } - override fun anyPositiveInt(): ClientDslProperty = input.anyPositiveInt() + fun assertThat(assertThat: String) { + this.assertThat = ExecutionProperty(assertThat) + } - override fun anyDouble(): ClientDslProperty = input.anyDouble() + fun bodyMatchers(bodyMatchers: BodyMatchers.() -> Unit) { + this.bodyMatchers = BodyMatchers().apply(bodyMatchers) + } - override fun anyHex(): ClientDslProperty = input.anyHex() + override fun anyAlphaUnicode(): ClientDslProperty = Input().anyAlphaUnicode() - override fun aBoolean(): ClientDslProperty = input.aBoolean() + override fun anyAlphaNumeric(): ClientDslProperty = Input().anyAlphaNumeric() - override fun anyIpAddress(): ClientDslProperty = input.anyIpAddress() + override fun anyNumber(): ClientDslProperty = Input().anyNumber() - override fun anyHostname(): ClientDslProperty = input.anyHostname() + override fun anyInteger(): ClientDslProperty = Input().anyInteger() - override fun anyEmail(): ClientDslProperty = input.anyEmail() + override fun anyPositiveInt(): ClientDslProperty = Input().anyPositiveInt() - override fun anyUrl(): ClientDslProperty = input.anyUrl() + override fun anyDouble(): ClientDslProperty = Input().anyDouble() - override fun anyHttpsUrl(): ClientDslProperty = input.anyHttpsUrl() + override fun anyHex(): ClientDslProperty = Input().anyHex() - override fun anyUuid(): ClientDslProperty = input.anyUuid() + override fun aBoolean(): ClientDslProperty = Input().aBoolean() - override fun anyDate(): ClientDslProperty = input.anyDate() + override fun anyIpAddress(): ClientDslProperty = Input().anyIpAddress() - override fun anyDateTime(): ClientDslProperty = input.anyDateTime() + override fun anyHostname(): ClientDslProperty = Input().anyHostname() - override fun anyTime(): ClientDslProperty = input.anyTime() + override fun anyEmail(): ClientDslProperty = Input().anyEmail() - override fun anyIso8601WithOffset(): ClientDslProperty = input.anyIso8601WithOffset() + override fun anyUrl(): ClientDslProperty = Input().anyUrl() - override fun anyNonBlankString(): ClientDslProperty = input.anyNonBlankString() + override fun anyHttpsUrl(): ClientDslProperty = Input().anyHttpsUrl() - override fun anyNonEmptyString(): ClientDslProperty = input.anyNonEmptyString() + override fun anyUuid(): ClientDslProperty = Input().anyUuid() - override fun anyOf(vararg values: String?): ClientDslProperty = input.anyOf(*values) + override fun anyDate(): ClientDslProperty = Input().anyDate() + override fun anyDateTime(): ClientDslProperty = Input().anyDateTime() + + override fun anyTime(): ClientDslProperty = Input().anyTime() + + override fun anyIso8601WithOffset(): ClientDslProperty = Input().anyIso8601WithOffset() + + override fun anyNonBlankString(): ClientDslProperty = Input().anyNonBlankString() + + override fun anyNonEmptyString(): ClientDslProperty = Input().anyNonEmptyString() + + override fun anyOf(vararg values: String?): ClientDslProperty = Input().anyOf(*values) + + internal fun get(): Input { + val input = Input() + messageFrom?.also { input.messageFrom = messageFrom!! } + triggeredBy?.also { input.triggeredBy = triggeredBy!! } + messageHeaders?.also { input.messageHeaders = messageHeaders!! } + messageBody?.also { input.messageBody = messageBody!! } + assertThat?.also { input.assertThat = assertThat!! } + bodyMatchers?.also { input.bodyMatchers = bodyMatchers!! } + return input + } } diff --git a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/OutputMessageDsl.kt b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/OutputMessageDsl.kt index 6250947435..72bef50ec6 100644 --- a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/OutputMessageDsl.kt +++ b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/OutputMessageDsl.kt @@ -22,67 +22,81 @@ package org.springframework.cloud.contract.spec.internal @ContractDslMarker class OutputMessageDsl : CommonDsl(), RegexCreatingProperty { - private val outputMessage = OutputMessage() + var sentTo: DslProperty? = null + var headers: Headers? = null + var body: DslProperty? = null + var assertThat: ExecutionProperty? = null + var bodyMatchers: ResponseBodyMatchers? = null - companion object { - fun make(block: OutputMessageDsl.() -> Unit): OutputMessage = OutputMessageDsl().apply(block).get() + fun sentTo(sentTo: String) { + this.sentTo = DslProperty(sentTo) } - private fun get(): OutputMessage = outputMessage - - fun sentTo(value: String) = outputMessage.sentTo(value) - - fun sentTo(value: DslProperty) = outputMessage.sentTo(value) - - fun body(vararg pairs: Pair) = outputMessage.body(pairs.toMap()) - - fun body(pair: Pair) = outputMessage.body(mapOf(pair)) - - fun body(value: String) = outputMessage.body(value) - - fun headers(block: Headers.() -> Unit) { - outputMessage.headers = Headers().apply(block) + fun headers(headers: Headers.() -> Unit) { + this.headers = Headers().apply(headers) } - override fun anyAlphaUnicode(): ServerDslProperty = outputMessage.anyAlphaUnicode() + fun body(body: Any) { + this.body = DslProperty(body) + } - override fun anyAlphaNumeric(): ServerDslProperty = outputMessage.anyAlphaNumeric() + fun assertThat(assertThat: String) { + this.assertThat = ExecutionProperty(assertThat) + } - override fun anyNumber(): ServerDslProperty = outputMessage.anyNumber() + fun bodyMatchers(bodyMatchers: ResponseBodyMatchers.() -> Unit) { + this.bodyMatchers = ResponseBodyMatchers().apply(bodyMatchers) + } - override fun anyInteger(): ServerDslProperty = outputMessage.anyInteger() + override fun anyAlphaUnicode(): ServerDslProperty = OutputMessage().anyAlphaUnicode() - override fun anyPositiveInt(): ServerDslProperty = outputMessage.anyPositiveInt() + override fun anyAlphaNumeric(): ServerDslProperty = OutputMessage().anyAlphaNumeric() - override fun anyDouble(): ServerDslProperty = outputMessage.anyDouble() + override fun anyNumber(): ServerDslProperty = OutputMessage().anyNumber() - override fun anyHex(): ServerDslProperty = outputMessage.anyHex() + override fun anyInteger(): ServerDslProperty = OutputMessage().anyInteger() - override fun aBoolean(): ServerDslProperty = outputMessage.aBoolean() + override fun anyPositiveInt(): ServerDslProperty = OutputMessage().anyPositiveInt() - override fun anyIpAddress(): ServerDslProperty = outputMessage.anyIpAddress() + override fun anyDouble(): ServerDslProperty = OutputMessage().anyDouble() - override fun anyHostname(): ServerDslProperty = outputMessage.anyHostname() + override fun anyHex(): ServerDslProperty = OutputMessage().anyHex() - override fun anyEmail(): ServerDslProperty = outputMessage.anyEmail() + override fun aBoolean(): ServerDslProperty = OutputMessage().aBoolean() - override fun anyUrl(): ServerDslProperty = outputMessage.anyUrl() + override fun anyIpAddress(): ServerDslProperty = OutputMessage().anyIpAddress() - override fun anyHttpsUrl(): ServerDslProperty = outputMessage.anyHttpsUrl() + override fun anyHostname(): ServerDslProperty = OutputMessage().anyHostname() - override fun anyUuid(): ServerDslProperty = outputMessage.anyUuid() + override fun anyEmail(): ServerDslProperty = OutputMessage().anyEmail() - override fun anyDate(): ServerDslProperty = outputMessage.anyDate() + override fun anyUrl(): ServerDslProperty = OutputMessage().anyUrl() - override fun anyDateTime(): ServerDslProperty = outputMessage.anyDateTime() + override fun anyHttpsUrl(): ServerDslProperty = OutputMessage().anyHttpsUrl() - override fun anyTime(): ServerDslProperty = outputMessage.anyTime() + override fun anyUuid(): ServerDslProperty = OutputMessage().anyUuid() - override fun anyIso8601WithOffset(): ServerDslProperty = outputMessage.anyIso8601WithOffset() + override fun anyDate(): ServerDslProperty = OutputMessage().anyDate() - override fun anyNonBlankString(): ServerDslProperty = outputMessage.anyNonBlankString() + override fun anyDateTime(): ServerDslProperty = OutputMessage().anyDateTime() - override fun anyNonEmptyString(): ServerDslProperty = outputMessage.anyNonEmptyString() + override fun anyTime(): ServerDslProperty = OutputMessage().anyTime() - override fun anyOf(vararg values: String?): ServerDslProperty = outputMessage.anyOf(*values) + override fun anyIso8601WithOffset(): ServerDslProperty = OutputMessage().anyIso8601WithOffset() + + override fun anyNonBlankString(): ServerDslProperty = OutputMessage().anyNonBlankString() + + override fun anyNonEmptyString(): ServerDslProperty = OutputMessage().anyNonEmptyString() + + override fun anyOf(vararg values: String?): ServerDslProperty = OutputMessage().anyOf(*values) + + internal fun get(): OutputMessage { + val outputMessage = OutputMessage() + sentTo?.also { outputMessage.sentTo = sentTo } + body?.also { outputMessage.body = body } + headers?.also { outputMessage.headers = headers } + assertThat?.also { outputMessage.assertThat = assertThat } + bodyMatchers?.also { outputMessage.bodyMatchers = bodyMatchers } + return outputMessage + } } diff --git a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/RequestDsl.kt b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/RequestDsl.kt index 0c29bcec45..6e0877fe34 100644 --- a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/RequestDsl.kt +++ b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/RequestDsl.kt @@ -16,109 +16,171 @@ package org.springframework.cloud.contract.spec.internal +import org.springframework.cloud.contract.spec.toDslProperties + /** * @author Tim Ysewyn */ @ContractDslMarker -class RequestDsl : CommonDsl(), RegexCreatingProperty { +open class RequestDsl : CommonDsl(), RegexCreatingProperty { - private val request = Request() + var method: DslProperty? = null + var url: Url? = null + var urlPath: UrlPath? = null + var headers: Headers? = null + var cookies: Cookies? = null + var body: Body? = null + var multipart: Multipart? = null + var bodyMatchers: BodyMatchers? = null - companion object { - fun make(block: RequestDsl.() -> Unit): Request = RequestDsl().apply(block).get() + fun method(method: String) { + this.method = DslProperty(method) } - private fun get(): Request = request - - fun method(value: String) = request.method(value) - - fun method(httpMethod: HttpMethods.HttpMethod) = request.method(httpMethod) - - fun url(url: String) = request.url(url) - - fun url(url: DslProperty) = request.url(url) - - fun urlPath(path: String) = request.urlPath(path) - - fun urlPath(path: DslProperty) = request.urlPath(path) - - fun headers(block: Headers.() -> Unit) { - request.headers = Headers().apply(block) + fun method(method: HttpMethods.HttpMethod) { + this.method(method.toString()) } - fun body(vararg pairs: Pair) = request.body(pairs.toMap()) + fun url(url: String): Url { + return Url(url) + } - fun body(pair: Pair) = request.body(mapOf(pair)) + fun url(url: DslProperty): Url { + return Url(url) + } - fun body(value: String) = request.body(value) + fun urlPath(url: String): UrlPath { + return UrlPath(url) + } + + fun urlPath(url: DslProperty): UrlPath { + return UrlPath(url) + } + + fun headers(headers: Headers.() -> Unit) { + this.headers = Headers().apply(headers) + } + + fun cookies(cookies: Cookies.() -> Unit) { + this.cookies = Cookies().apply(cookies) + } + + fun body(body: Map) { + this.body = Body(body.toDslProperties()) + } + + fun body(vararg body: Pair) { + this.body = Body(body.toMap().toDslProperties()) + } + + fun body(body: Pair) { + this.body = Body(mapOf(body).toDslProperties()) + } + + fun body(body: List) { + this.body = Body(body.toDslProperties()) + } + + fun body(body: DslProperty) { + this.body = Body(body) + } + + fun multipart(multipart: Map) { + this.multipart = Multipart(multipart.toDslProperties()) + } + + fun multipart(multipart: List) { + this.multipart = Multipart(multipart.toDslProperties()) + } + + fun multipart(multipart: DslProperty) { + this.multipart = Multipart(multipart) + } + + fun multipart(multipart: Any) { + this.multipart = Multipart(multipart) + } fun bodyMatchers(block: BodyMatchers.() -> Unit) { - request.bodyMatchers = BodyMatchers().apply(block) + bodyMatchers = BodyMatchers().apply(block) } - fun value(value: DslProperty): DslProperty = request.value(value) + fun value(value: DslProperty): DslProperty = Request().value(value) - fun v(value: DslProperty): DslProperty = request.value(value) + fun v(value: DslProperty): DslProperty = Request().value(value) - fun `$`(value: DslProperty): DslProperty = request.value(value) + fun `$`(value: DslProperty): DslProperty = Request().value(value) - fun value(value: Any): DslProperty = request.value(value) + fun value(value: Any): DslProperty = Request().value(value) - fun v(value: Any): DslProperty = request.value(value) + fun v(value: Any): DslProperty = Request().value(value) - fun `$`(value: Any): DslProperty = request.value(value) + fun `$`(value: Any): DslProperty = Request().value(value) - fun value(client: ClientDslProperty, server: ServerDslProperty): DslProperty = request.value(client, server) + fun value(client: ClientDslProperty, server: ServerDslProperty): DslProperty = Request().value(client, server) - fun v(client: ClientDslProperty, server: ServerDslProperty): DslProperty = request.value(client, server) + fun v(client: ClientDslProperty, server: ServerDslProperty): DslProperty = Request().value(client, server) - fun `$`(client: ClientDslProperty, server: ServerDslProperty): DslProperty = request.value(client, server) + fun `$`(client: ClientDslProperty, server: ServerDslProperty): DslProperty = Request().value(client, server) - fun value(server: ServerDslProperty, client: ClientDslProperty): DslProperty = request.value(client, server) + fun value(server: ServerDslProperty, client: ClientDslProperty): DslProperty = Request().value(client, server) - fun v(server: ServerDslProperty, client: ClientDslProperty): DslProperty = request.value(client, server) + fun v(server: ServerDslProperty, client: ClientDslProperty): DslProperty = Request().value(client, server) - fun `$`(server: ServerDslProperty, client: ClientDslProperty): DslProperty = request.value(client, server) + fun `$`(server: ServerDslProperty, client: ClientDslProperty): DslProperty = Request().value(client, server) - override fun anyAlphaUnicode(): ClientDslProperty = request.anyAlphaUnicode() + override fun anyAlphaUnicode(): ClientDslProperty = Request().anyAlphaUnicode() - override fun anyAlphaNumeric(): ClientDslProperty = request.anyAlphaNumeric() + override fun anyAlphaNumeric(): ClientDslProperty = Request().anyAlphaNumeric() - override fun anyNumber(): ClientDslProperty = request.anyNumber() + override fun anyNumber(): ClientDslProperty = Request().anyNumber() - override fun anyInteger(): ClientDslProperty = request.anyInteger() + override fun anyInteger(): ClientDslProperty = Request().anyInteger() - override fun anyPositiveInt(): ClientDslProperty = request.anyPositiveInt() + override fun anyPositiveInt(): ClientDslProperty = Request().anyPositiveInt() - override fun anyDouble(): ClientDslProperty = request.anyDouble() + override fun anyDouble(): ClientDslProperty = Request().anyDouble() - override fun anyHex(): ClientDslProperty = request.anyHex() + override fun anyHex(): ClientDslProperty = Request().anyHex() - override fun aBoolean(): ClientDslProperty = request.aBoolean() + override fun aBoolean(): ClientDslProperty = Request().aBoolean() - override fun anyIpAddress(): ClientDslProperty = request.anyIpAddress() + override fun anyIpAddress(): ClientDslProperty = Request().anyIpAddress() - override fun anyHostname(): ClientDslProperty = request.anyHostname() + override fun anyHostname(): ClientDslProperty = Request().anyHostname() - override fun anyEmail(): ClientDslProperty = request.anyEmail() + override fun anyEmail(): ClientDslProperty = Request().anyEmail() - override fun anyUrl(): ClientDslProperty = request.anyUrl() + override fun anyUrl(): ClientDslProperty = Request().anyUrl() - override fun anyHttpsUrl(): ClientDslProperty = request.anyHttpsUrl() + override fun anyHttpsUrl(): ClientDslProperty = Request().anyHttpsUrl() - override fun anyUuid(): ClientDslProperty = request.anyUuid() + override fun anyUuid(): ClientDslProperty = Request().anyUuid() - override fun anyDate(): ClientDslProperty = request.anyDate() + override fun anyDate(): ClientDslProperty = Request().anyDate() - override fun anyDateTime(): ClientDslProperty = request.anyDateTime() + override fun anyDateTime(): ClientDslProperty = Request().anyDateTime() - override fun anyTime(): ClientDslProperty = request.anyTime() + override fun anyTime(): ClientDslProperty = Request().anyTime() - override fun anyIso8601WithOffset(): ClientDslProperty = request.anyIso8601WithOffset() + override fun anyIso8601WithOffset(): ClientDslProperty = Request().anyIso8601WithOffset() - override fun anyNonBlankString(): ClientDslProperty = request.anyNonBlankString() + override fun anyNonBlankString(): ClientDslProperty = Request().anyNonBlankString() - override fun anyNonEmptyString(): ClientDslProperty = request.anyNonEmptyString() + override fun anyNonEmptyString(): ClientDslProperty = Request().anyNonEmptyString() - override fun anyOf(vararg values: String?): ClientDslProperty = request.anyOf(*values) + override fun anyOf(vararg values: String?): ClientDslProperty = Request().anyOf(*values) + + internal fun get(): Request { + val request = Request() + method?.also { request.method = method!! } + url?.also { request.url = url!! } + urlPath?.also { request.urlPath = urlPath!! } + headers?.also { request.headers = headers!! } + cookies?.also { request.cookies = cookies!! } + body?.also { request.body = body!! } + multipart?.also { request.multipart = multipart!! } + bodyMatchers?.also { request.bodyMatchers = bodyMatchers!! } + return request + } } \ No newline at end of file diff --git a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/ResponseDsl.kt b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/ResponseDsl.kt index 7eea142115..1dd08eede9 100644 --- a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/ResponseDsl.kt +++ b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/ResponseDsl.kt @@ -16,73 +16,118 @@ package org.springframework.cloud.contract.spec.internal +import org.springframework.cloud.contract.spec.toDslProperties +import org.springframework.cloud.contract.spec.toDslProperty + /** * @author Tim Ysewyn */ @ContractDslMarker class ResponseDsl : CommonDsl(), RegexCreatingProperty { - private val response = Response() + var status: DslProperty? = null + var delay: DslProperty? = null + var headers: Headers? = null + var cookies: Cookies? = null + var body: Body? = null + var async: Boolean = false + var bodyMatchers: ResponseBodyMatchers? = null - companion object { - fun make(block: ResponseDsl.() -> Unit): Response = ResponseDsl().apply(block).get() + fun status(code: Int) { + this.status = DslProperty(code) } - private fun get(): Response = response - - fun status(code: Int) = response.status(code) - - fun body(pair: Pair) = response.body(mapOf(pair)) - - fun body(vararg pairs: Pair) = response.body(pairs.toMap()) - - fun headers(block: Headers.() -> Unit) { - response.headers = Headers().apply(block) + fun fixedDelayMilliseconds(delay: Long) { + this.delay = delay.toDslProperty() } - fun bodyMatchers(block: ResponseBodyMatchers.() -> Unit) { - response.bodyMatchers = ResponseBodyMatchers().apply(block) + fun headers(headers: Headers.() -> Unit) { + this.headers = Headers().apply(headers) } - override fun anyAlphaUnicode(): ServerDslProperty = response.anyAlphaUnicode() + fun cookies(cookies: Cookies.() -> Unit) { + this.cookies = Cookies().apply(cookies) + } - override fun anyAlphaNumeric(): ServerDslProperty = response.anyAlphaNumeric() + fun body(body: Map) { + this.body = Body(body.toDslProperties()) + } - override fun anyNumber(): ServerDslProperty = response.anyNumber() + fun body(vararg body: Pair) { + this.body = Body(body.toMap().toDslProperties()) + } - override fun anyInteger(): ServerDslProperty = response.anyInteger() + fun body(body: Pair) { + this.body = Body(mapOf(body).toDslProperties()) + } - override fun anyPositiveInt(): ServerDslProperty = response.anyPositiveInt() + fun body(body: List) { + this.body = Body(body.toDslProperties()) + } - override fun anyDouble(): ServerDslProperty = response.anyDouble() + fun body(body: DslProperty) { + this.body = Body(body.toDslProperty()) + } - override fun anyHex(): ServerDslProperty = response.anyHex() + fun body(body: Any) { + this.body = Body(body) + } - override fun aBoolean(): ServerDslProperty = response.aBoolean() + fun bodyMatchers(bodyMatchers: ResponseBodyMatchers.() -> Unit) { + this.bodyMatchers = ResponseBodyMatchers().apply(bodyMatchers) + } - override fun anyIpAddress(): ServerDslProperty = response.anyIpAddress() + override fun anyAlphaUnicode(): ServerDslProperty = Response().anyAlphaUnicode() - override fun anyHostname(): ServerDslProperty = response.anyHostname() + override fun anyAlphaNumeric(): ServerDslProperty = Response().anyAlphaNumeric() - override fun anyEmail(): ServerDslProperty = response.anyEmail() + override fun anyNumber(): ServerDslProperty = Response().anyNumber() - override fun anyUrl(): ServerDslProperty = response.anyUrl() + override fun anyInteger(): ServerDslProperty = Response().anyInteger() - override fun anyHttpsUrl(): ServerDslProperty = response.anyHttpsUrl() + override fun anyPositiveInt(): ServerDslProperty = Response().anyPositiveInt() - override fun anyUuid(): ServerDslProperty = response.anyUuid() + override fun anyDouble(): ServerDslProperty = Response().anyDouble() - override fun anyDate(): ServerDslProperty = response.anyDate() + override fun anyHex(): ServerDslProperty = Response().anyHex() - override fun anyDateTime(): ServerDslProperty = response.anyDateTime() + override fun aBoolean(): ServerDslProperty = Response().aBoolean() - override fun anyTime(): ServerDslProperty = response.anyTime() + override fun anyIpAddress(): ServerDslProperty = Response().anyIpAddress() - override fun anyIso8601WithOffset(): ServerDslProperty = response.anyIso8601WithOffset() + override fun anyHostname(): ServerDslProperty = Response().anyHostname() - override fun anyNonBlankString(): ServerDslProperty = response.anyNonBlankString() + override fun anyEmail(): ServerDslProperty = Response().anyEmail() - override fun anyNonEmptyString(): ServerDslProperty = response.anyNonEmptyString() + override fun anyUrl(): ServerDslProperty = Response().anyUrl() - override fun anyOf(vararg values: String?): ServerDslProperty = response.anyOf(*values) + override fun anyHttpsUrl(): ServerDslProperty = Response().anyHttpsUrl() + + override fun anyUuid(): ServerDslProperty = Response().anyUuid() + + override fun anyDate(): ServerDslProperty = Response().anyDate() + + override fun anyDateTime(): ServerDslProperty = Response().anyDateTime() + + override fun anyTime(): ServerDslProperty = Response().anyTime() + + override fun anyIso8601WithOffset(): ServerDslProperty = Response().anyIso8601WithOffset() + + override fun anyNonBlankString(): ServerDslProperty = Response().anyNonBlankString() + + override fun anyNonEmptyString(): ServerDslProperty = Response().anyNonEmptyString() + + override fun anyOf(vararg values: String?): ServerDslProperty = Response().anyOf(*values) + + internal fun get(): Response { + val response = Response() + status?.also { response.status = status} + delay?.also { response.delay = delay} + headers?.also { response.headers = headers } + cookies?.also { response.cookies = cookies } + body?.also { response.body = body } + response.async = async + bodyMatchers?.also { response.bodyMatchers = bodyMatchers } + return response + } } diff --git a/specs/spring-cloud-contract-spec-kotlin/src/test/kotlin/org/springframework/cloud/contract/spec/ContractTests.kt b/specs/spring-cloud-contract-spec-kotlin/src/test/kotlin/org/springframework/cloud/contract/spec/ContractTests.kt index 9205a574b3..37f195eccf 100644 --- a/specs/spring-cloud-contract-spec-kotlin/src/test/kotlin/org/springframework/cloud/contract/spec/ContractTests.kt +++ b/specs/spring-cloud-contract-spec-kotlin/src/test/kotlin/org/springframework/cloud/contract/spec/ContractTests.kt @@ -20,8 +20,12 @@ import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertDoesNotThrow import org.junit.jupiter.api.assertThrows -import org.springframework.cloud.contract.spec.Contract.make -import org.springframework.cloud.contract.spec.internal.DslProperty +import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract +import org.springframework.cloud.contract.spec.internal.HttpMethods +import org.springframework.cloud.contract.spec.internal.HttpStatus +import org.springframework.cloud.contract.spec.internal.RegexProperty +import org.springframework.cloud.contract.spec.internal.Url +import org.springframework.cloud.contract.spec.internal.UrlPath /** * Tests written based on the Java contract tests written in Groovy @@ -32,10 +36,10 @@ class ContractTests { @Test fun `should work for http`() { - val contract = ContractDsl.make { + val contract = contract { request { - url("/foo") - method("PUT") + url = Url("/foo") + method(HttpMethods.HttpMethod.PUT) headers { header("foo", "bar") } @@ -52,14 +56,38 @@ class ContractTests { assertDoesNotThrow { Contract.assertContract(contract) + }.also { + val request = contract.request + assertThat(request.url.clientValue).isEqualTo("/foo") + assertThat(request.url.serverValue).isEqualTo("/foo") + assertThat(request.method.clientValue).isEqualTo("PUT") + assertThat(request.method.serverValue).isEqualTo("PUT") + val headers = request.headers.entries + assertThat(headers).hasSize(1) + assertThat(headers.elementAt(0).name).isEqualTo("foo") + assertThat(headers.elementAt(0).clientValue).isEqualTo("bar") + assertThat(headers.elementAt(0).serverValue).isEqualTo("bar") + assertThat(request.body.clientValue).isEqualTo(mapOf("foo" to "bar")) + assertThat(request.body.serverValue).isEqualTo(mapOf("foo" to "bar")) + }.also { + val response = contract.response + assertThat(response.status.clientValue).isEqualTo(200) + assertThat(response.status.serverValue).isEqualTo(200) + val headers = response.headers.entries + assertThat(headers).hasSize(1) + assertThat(headers.elementAt(0).name).isEqualTo("foo2") + assertThat(headers.elementAt(0).clientValue).isEqualTo("bar") + assertThat(headers.elementAt(0).serverValue).isEqualTo("bar") + assertThat(response.body.clientValue).isEqualTo(mapOf("foo2" to "bar")) + assertThat(response.body.serverValue).isEqualTo(mapOf("foo2" to "bar")) } } @Test fun `should fail when no method is present`() { - val contract = ContractDsl.make { + val contract = contract { request { - url("/foo") + url = Url("/foo") } response { status(200) @@ -75,7 +103,7 @@ class ContractTests { @Test fun `should fail when no url is present`() { - val contract = ContractDsl.make { + val contract = contract { request { method("GET") } @@ -93,9 +121,9 @@ class ContractTests { @Test fun `should fail when no status is present`() { - val contract = ContractDsl.make { + val contract = contract { request { - url("/foo") + url = Url("/foo") method("GET") } response { @@ -111,7 +139,7 @@ class ContractTests { @Test fun `should work for messaging`() { - val contract = ContractDsl.make { + val contract = contract { input { messageFrom("input") messageBody("foo" to "bar") @@ -130,12 +158,34 @@ class ContractTests { assertDoesNotThrow { Contract.assertContract(contract) + }.also { + val input = contract.input + assertThat(input.messageFrom.clientValue).isEqualTo("input") + assertThat(input.messageFrom.serverValue).isEqualTo("input") + assertThat(input.messageBody.clientValue).isEqualTo(mapOf("foo" to "bar")) + assertThat(input.messageBody.serverValue).isEqualTo(mapOf("foo" to "bar")) + val headers = input.messageHeaders.entries + assertThat(headers).hasSize(1) + assertThat(headers.elementAt(0).name).isEqualTo("foo") + assertThat(headers.elementAt(0).clientValue).isEqualTo("bar") + assertThat(headers.elementAt(0).serverValue).isEqualTo("bar") + }.also { + val output = contract.outputMessage + assertThat(output.sentTo.clientValue).isEqualTo("output") + assertThat(output.sentTo.serverValue).isEqualTo("output") + assertThat(output.body.clientValue).isEqualTo("foo2" to "bar") + assertThat(output.body.serverValue).isEqualTo("foo2" to "bar") + val headers = output.headers.entries + assertThat(headers).hasSize(1) + assertThat(headers.elementAt(0).name).isEqualTo("foo2") + assertThat(headers.elementAt(0).clientValue).isEqualTo("bar") + assertThat(headers.elementAt(0).serverValue).isEqualTo("bar") } } @Test fun `should work for messaging with pattern properties`() { - val contract = ContractDsl.make { + val contract = contract { input { messageFrom("input") messageBody("foo" to anyNonBlankString()) @@ -159,15 +209,15 @@ class ContractTests { @Test fun `should set a description`() { - val contract = ContractDsl.make { - description(""" + val contract = contract { + description = """ given: An input when: Sth happens then: Output -""") +""" } assertDoesNotThrow { @@ -186,8 +236,8 @@ then: @Test fun `should set a name`() { - val contract = ContractDsl.make { - name("some_special_name") + val contract = contract { + name = "some_special_name" } assertDoesNotThrow { @@ -199,8 +249,8 @@ then: @Test fun `should mark a contract ignored`() { - val contract = ContractDsl.make { - ignored() + val contract = contract { + ignored = true } assertDoesNotThrow { @@ -212,46 +262,46 @@ then: @Test fun `should make equals and hashcode work properly for URL`() { - val a: Contract = ContractDsl.make { + val a: Contract = contract { request { method("GET") - url("/1") + url = Url("/1") } } - val b: Contract = ContractDsl.make { + val b: Contract = contract { request { method("GET") - url("/1") + url = Url("/1") } } assertDoesNotThrow { Contract.assertContract(a) Contract.assertContract(b) - }. also { + }.also { assertThat(a).isEqualTo(b) } } @Test fun `should make equals and hashcode work properly for URL with consumer producer`() { - val a: Contract = ContractDsl.make { + val a: Contract = contract { request { method("GET") - url(value(c("/1"), p("/1"))) + url = Url(value(c("/1"), p("/1"))) } } - val b: Contract = ContractDsl.make { + val b: Contract = contract { request { method("GET") - url(value(c("/1"), p("/1"))) + url = Url(value(c("/1"), p("/1"))) } } assertDoesNotThrow { Contract.assertContract(a) Contract.assertContract(b) - }. also { + }.also { assertThat(a).isEqualTo(b) } } @@ -259,35 +309,35 @@ then: @Test fun `should return true when comparing two equal contracts with interpolated string`() { val index = 1 - val a: Contract = ContractDsl.make { + val a: Contract = contract { request { - method(PUT()) + method(HttpMethods.HttpMethod.PUT) headers { contentType(applicationJson()) } - url( "/$index") + url = Url("/$index") } response { - status(OK()) + status(HttpStatus.OK()) } } - val b: Contract = ContractDsl.make { + val b: Contract = contract { request { - method(PUT()) + method(HttpMethods.HttpMethod.PUT) headers { contentType(applicationJson()) } - url("/$index") + url = Url("/$index") } response { - status(OK()) + status(HttpStatus.OK()) } } assertDoesNotThrow { Contract.assertContract(a) Contract.assertContract(b) - }. also { + }.also { assertThat(a).isEqualTo(b) } } @@ -295,46 +345,46 @@ then: @Test fun `should return false when comparing two unequal contracts with interpolated string`() { var index = 1 - val a: Contract = ContractDsl.make { + val a: Contract = contract { request { - method(PUT()) + method(HttpMethods.HttpMethod.PUT) headers { contentType(applicationJson()) } - url( "/$index") + url = Url("/$index") } response { - status(OK()) + status(HttpStatus.OK()) } } index = 2 - val b: Contract = ContractDsl.make { + val b: Contract = contract { request { - method(PUT()) + method(HttpMethods.HttpMethod.PUT) headers { contentType(applicationJson()) } - url("/$index") + url = Url("/$index") } response { - status(OK()) + status(HttpStatus.OK()) } } assertDoesNotThrow { Contract.assertContract(a) Contract.assertContract(b) - }. also { + }.also { assertThat(a).isNotEqualTo(b) } } @Test fun `should return true when comparing two equal complex contracts`() { - val a: Contract = ContractDsl.make { + val a: Contract = contract { request { - method(GET()) - url("/path") + method(HttpMethods.HttpMethod.GET) + url = Url("/path") headers { header("Accept", value( consumer(regex("text/.*")), @@ -347,8 +397,8 @@ then: } } response { - status(OK()) - body("id" to ("value" to "132"), + status(HttpStatus.OK()) + body("id" to mapOf("value" to "132"), "surname" to "Kowalsky", "name" to "Jan", "created" to "2014-02-02 12:23:43" @@ -358,10 +408,10 @@ then: } } } - val b: Contract = ContractDsl.make { + val b: Contract = contract { request { - method(GET()) - url("/path") + method(HttpMethods.HttpMethod.GET) + url = Url("/path") headers { header("Accept", value( consumer(regex("text/.*")), @@ -374,8 +424,8 @@ then: } } response { - status(OK()) - body("id" to ("value" to "132"), + status(HttpStatus.OK()) + body("id" to mapOf("value" to "132"), "surname" to "Kowalsky", "name" to "Jan", "created" to "2014-02-02 12:23:43" @@ -388,25 +438,60 @@ then: assertDoesNotThrow { Contract.assertContract(a) Contract.assertContract(b) - }. also { + }.also { assertThat(a).isEqualTo(b) + }. also { + val request = a.request + assertThat(request.url.clientValue).isEqualTo("/path") + assertThat(request.url.serverValue).isEqualTo("/path") + assertThat(request.method.clientValue).isEqualTo("GET") + assertThat(request.method.serverValue).isEqualTo("GET") + val headers = request.headers.entries + assertThat(headers).hasSize(2) + assertThat(headers.elementAt(0).name).isEqualTo("Accept") + assertThat(headers.elementAt(0).clientValue).isInstanceOf(RegexProperty::class.java) + assertThat((headers.elementAt(0).clientValue as RegexProperty).pattern()).isEqualTo("text/.*") + assertThat(headers.elementAt(0).serverValue).isEqualTo("text/plain") + assertThat(headers.elementAt(1).name).isEqualTo("X-Custom-Header") + assertThat(headers.elementAt(1).clientValue).isInstanceOf(RegexProperty::class.java) + assertThat((headers.elementAt(1).clientValue as RegexProperty).pattern()).isEqualTo("^.*2134.*\$") + assertThat(headers.elementAt(1).serverValue).isEqualTo("121345") + }.also { + val response = a.response + assertThat(response.status.clientValue).isEqualTo(200) + assertThat(response.status.serverValue).isEqualTo(200) + val headers = response.headers.entries + assertThat(headers).hasSize(1) + assertThat(headers.elementAt(0).name).isEqualTo("Content-Type") + assertThat(headers.elementAt(0).clientValue).isEqualTo("text/plain") + assertThat(headers.elementAt(0).serverValue).isEqualTo("text/plain") + assertThat(response.body.clientValue).isEqualTo(mapOf("id" to mapOf("value" to "132"), + "surname" to "Kowalsky", + "name" to "Jan", + "created" to "2014-02-02 12:23:43" + )) + assertThat(response.body.serverValue).isEqualTo(mapOf("id" to mapOf("value" to "132"), + "surname" to "Kowalsky", + "name" to "Jan", + "created" to "2014-02-02 12:23:43" + )) } } @Test fun `should support bodyMatchers`() { - val contract = ContractDsl.make { + val contract = contract { request { - method(GET()) - url("/path") - body("id" to ("value" to "132")) + method(HttpMethods.HttpMethod.GET) + url = Url("/path") + body("id" to mapOf("value" to "132")) bodyMatchers { jsonPath("$.id.value", byRegex(anInteger())) } } response { - status(OK()) - body("id" to ("value" to "132"), + status(HttpStatus.OK()) + body("id" to mapOf("value" to "132"), "surname" to "Kowalsky", "name" to "Jan", "created" to "2014-02-02 12:23:43" @@ -422,9 +507,111 @@ then: assertDoesNotThrow { Contract.assertContract(contract) - }. also { - assertThat(contract.request.bodyMatchers.hasMatchers()).isTrue() - assertThat(contract.response.bodyMatchers.hasMatchers()).isTrue() + }.also { + val request = contract.request + assertThat(request.url.clientValue).isEqualTo("/path") + assertThat(request.url.serverValue).isEqualTo("/path") + assertThat(request.method.clientValue).isEqualTo("GET") + assertThat(request.method.serverValue).isEqualTo("GET") + assertThat(request.bodyMatchers.hasMatchers()).isTrue() + }.also { + val response = contract.response + assertThat(response.status.clientValue).isEqualTo(200) + assertThat(response.status.serverValue).isEqualTo(200) + assertThat(response.bodyMatchers.hasMatchers()).isTrue() + } + } + + @Test + fun `should support query parameters for url`() { + val contract = contract { + request { + method(HttpMethods.HttpMethod.GET) + url = Url("/path") withQueryParameters { + parameter("foo", "bar") + } + } + response { + status(HttpStatus.OK()) + } + } + + assertDoesNotThrow { + Contract.assertContract(contract) + }.also { + val request = contract.request + assertThat(request.url.clientValue).isEqualTo("/path") + val queryParameters = request.url.queryParameters.parameters + assertThat(queryParameters.elementAt(0).name).isEqualTo("foo") + assertThat(queryParameters.elementAt(0).clientValue).isEqualTo("bar") + assertThat(queryParameters.elementAt(0).serverValue).isEqualTo("bar") + assertThat(request.url.serverValue).isEqualTo("/path") + assertThat(request.method.clientValue).isEqualTo("GET") + assertThat(request.method.serverValue).isEqualTo("GET") + }.also { + val response = contract.response + assertThat(response.status.clientValue).isEqualTo(200) + assertThat(response.status.serverValue).isEqualTo(200) + } + } + + @Test + fun `should support query parameters for url path`() { + val contract = contract { + request { + method(HttpMethods.HttpMethod.GET) + urlPath = UrlPath("/path") withQueryParameters { + parameter("foo", "bar") + } + } + response { + status(HttpStatus.OK()) + } + } + + assertDoesNotThrow { + Contract.assertContract(contract) + }.also { + val request = contract.request + assertThat(request.urlPath.clientValue).isEqualTo("/path") + assertThat(request.urlPath.serverValue).isEqualTo("/path") + val queryParameters = request.urlPath.queryParameters.parameters + assertThat(queryParameters.elementAt(0).name).isEqualTo("foo") + assertThat(queryParameters.elementAt(0).clientValue).isEqualTo("bar") + assertThat(queryParameters.elementAt(0).serverValue).isEqualTo("bar") + assertThat(request.method.clientValue).isEqualTo("GET") + assertThat(request.method.serverValue).isEqualTo("GET") + }.also { + val response = contract.response + assertThat(response.status.clientValue).isEqualTo(200) + assertThat(response.status.serverValue).isEqualTo(200) + } + } + + @Test + fun `should work with list as body`() { + val contract = contract { + request { + method(HttpMethods.HttpMethod.PUT) + url = Url("/path") + body(listOf("foo", "bar")) + } + response { + status(HttpStatus.OK()) + body(listOf("foo2", "bar2")) + } + } + + assertDoesNotThrow { + Contract.assertContract(contract) + }.also { + val request = contract.request + assertThat(request.body.clientValue).isEqualTo(listOf("foo", "bar")) + assertThat(request.body.serverValue).isEqualTo(listOf("foo", "bar")) + }.also { + val response = contract.response + assertThat(response.body.clientValue).isEqualTo(listOf("foo2", "bar2")) + assertThat(response.body.serverValue).isEqualTo(listOf("foo2", "bar2")) } } } \ No newline at end of file