Skip to content

Commit

Permalink
fix: write empty bodies to the Pact file #1611
Browse files Browse the repository at this point in the history
  • Loading branch information
rholshausen committed Oct 25, 2022
1 parent 870a999 commit fc7e13e
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package au.com.dius.pact.consumer.dsl

import au.com.dius.pact.consumer.ConsumerPactBuilder
import au.com.dius.pact.core.model.OptionalBody
import au.com.dius.pact.core.model.PactSpecVersion
import au.com.dius.pact.core.model.V4Pact
import au.com.dius.pact.core.model.generators.Generators
import au.com.dius.pact.core.model.matchingrules.MatchingRuleGroup
import au.com.dius.pact.core.model.matchingrules.MatchingRulesImpl
Expand Down Expand Up @@ -162,4 +164,27 @@ class PactDslResponseSpec extends Specification {
!['pactSpecification', 'pact-jvm', 'plugins'].contains(it.key)
} == [test: new JsonValue.StringValue('value')]
}

@Issue('#1611')
def 'supports empty bodies'() {
given:
def builder = ConsumerPactBuilder.consumer('empty-body-consumer')
.hasPactWith('empty-body-service')
.uponReceiving('a request for an empty body')
.path('/path')
.willRespondWith()
.body("")

when:
def pact = builder.toPact()
def interaction = pact.interactions.first()
def pactV4 = builder.toPact(V4Pact)
def v4Interaction = pactV4.interactions.first()

then:
interaction.response.body.state == OptionalBody.State.EMPTY
interaction.toMap(PactSpecVersion.V3).response == [status: 200, body: '']
v4Interaction.response.body.state == OptionalBody.State.EMPTY
v4Interaction.toMap(PactSpecVersion.V4).response == [status: 200, body: [content: '']]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -179,31 +179,34 @@ data class OptionalBody @JvmOverloads constructor(

fun toV4Format(): Map<String, Any?> {
return when (state) {
State.PRESENT -> if (value!!.isNotEmpty()) {
if (contentTypeHint == ContentTypeHint.BINARY || contentType.isBinaryType()) {
mapOf(
"content" to valueAsBase64(),
"contentType" to contentType.toString(),
"encoded" to "base64",
"contentTypeHint" to contentTypeHint.name
)
} else if (contentType.isJson()) {
mapOf(
"content" to JsonParser.parseString(valueAsString()),
"contentType" to contentType.toString(),
"encoded" to false
)
State.PRESENT -> {
if (value!!.isNotEmpty()) {
if (contentTypeHint == ContentTypeHint.BINARY || contentType.isBinaryType()) {
mapOf(
"content" to valueAsBase64(),
"contentType" to contentType.toString(),
"encoded" to "base64",
"contentTypeHint" to contentTypeHint.name
)
} else if (contentType.isJson()) {
mapOf(
"content" to JsonParser.parseString(valueAsString()),
"contentType" to contentType.toString(),
"encoded" to false
)
} else {
mapOf(
"content" to valueAsString(),
"contentType" to contentType.toString(),
"encoded" to false,
"contentTypeHint" to contentTypeHint.name
)
}
} else {
mapOf(
"content" to valueAsString(),
"contentType" to contentType.toString(),
"encoded" to false,
"contentTypeHint" to contentTypeHint.name
)
mapOf("content" to "")
}
} else {
mapOf("content" to "")
}
State.EMPTY -> mapOf("content" to "")
else -> mapOf()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ open class RequestResponseInteraction @JvmOverloads constructor(
companion object : KLogging() {
const val COMMA = ", "

@JvmStatic
fun requestToMap(request: Request, pactSpecVersion: PactSpecVersion): Map<String, Any?> {
val map = mutableMapOf<String, Any?>(
"method" to request.method.toUpperCase(),
Expand All @@ -89,9 +90,13 @@ open class RequestResponseInteraction @JvmOverloads constructor(
if (request.query.isNotEmpty()) {
map["query"] = if (pactSpecVersion >= PactSpecVersion.V3) request.query else mapToQueryStr(request.query)
}

if (request.body.isPresent()) {
map["body"] = setupBodyForJson(request)
} else if (request.body.isEmpty()) {
map["body"] = ""
}

if (request.matchingRules.isNotEmpty()) {
map["matchingRules"] = request.matchingRules.toMap(pactSpecVersion)
}
Expand All @@ -102,14 +107,19 @@ open class RequestResponseInteraction @JvmOverloads constructor(
return map
}

@JvmStatic
fun responseToMap(response: Response, pactSpecVersion: PactSpecVersion): Map<String, Any?> {
val map = mutableMapOf<String, Any?>("status" to response.status)
if (response.headers.isNotEmpty()) {
map["headers"] = response.headers.entries.associate { (key, value) -> key to value.joinToString(COMMA) }
}

if (response.body.isPresent()) {
map["body"] = setupBodyForJson(response)
} else if (response.body.isEmpty()) {
map["body"] = ""
}

if (response.matchingRules.isNotEmpty()) {
map["matchingRules"] = response.matchingRules.toMap(pactSpecVersion)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ data class HttpRequest @JvmOverloads constructor(
if (query.isNotEmpty()) {
map["query"] = query
}
if (body.isPresent()) {
if (body.isPresent() || body.isEmpty()) {
map["body"] = body.toV4Format()
}
if (matchingRules.isNotEmpty()) {
Expand Down Expand Up @@ -152,7 +152,7 @@ data class HttpResponse @JvmOverloads constructor(
if (headers.isNotEmpty()) {
map["headers"] = headers
}
if (body.isPresent()) {
if (body.isPresent() || body.isEmpty()) {
map["body"] = body.toV4Format()
}
if (matchingRules.isNotEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package au.com.dius.pact.core.model

import spock.lang.Issue
import spock.lang.Specification

class HttpRequestSpec extends Specification {
@Issue('#1611')
def 'supports empty bodies'() {
expect:
new HttpRequest('GET', '/', [:], [:], OptionalBody.empty()).toMap() ==
[method: 'GET', path: '/', body: [content: '']]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package au.com.dius.pact.core.model

import spock.lang.Issue
import spock.lang.Specification

class HttpResponseSpec extends Specification {
@Issue('#1611')
def 'supports empty bodies'() {
expect:
new HttpResponse(200, [:], OptionalBody.empty()).toMap() == [status: 200, body: [content: '']]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ class OptionalBodySpec extends Specification {
where:
body | v4Format
OptionalBody.missing() | [:]
OptionalBody.body(''.bytes, ContentType.UNKNOWN) | [:]
OptionalBody.body(''.bytes, ContentType.UNKNOWN) | [content: '']
OptionalBody.body('{}'.bytes, ContentType.UNKNOWN) | [content: new JsonValue.Object(), contentType: 'application/json', encoded: false]
OptionalBody.body('{}'.bytes, ContentType.JSON) | [content: new JsonValue.Object(), contentType: 'application/json', encoded: false]
OptionalBody.body([0xff, 0xd8, 0xff, 0xe0] as byte[], new ContentType('image/jpeg')) | [content: '/9j/4A==', contentType: 'image/jpeg', encoded: 'base64', contentTypeHint: 'DEFAULT']
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,13 @@ class RequestResponseInteractionSpec extends Specification {
'include[]=needs_grading_count&include[]=permissions&include[]=current_grading_period_scores&' +
'include[]=course_image&include[]=favorites'
}

@Issue('#1611')
def 'supports empty bodies'() {
expect:
RequestResponseInteraction.requestToMap(new Request(body: OptionalBody.empty()), PactSpecVersion.V3) ==
[method: 'GET', path: '/', body: '']
RequestResponseInteraction.responseToMap(new Response(body: OptionalBody.empty()), PactSpecVersion.V3) ==
[status: 200, body: '']
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package au.com.dius.pact.core.model

import au.com.dius.pact.core.support.json.JsonValue
import spock.lang.Specification

import static au.com.dius.pact.core.model.V4PactKt.bodyFromJson

class V4PactKtSpec extends Specification {
def 'bodyFromJson - when body is empty in the Pact file'() {
expect:
bodyFromJson('body', new JsonValue.Object(json), [:]) == body

where:

json | body
[:] | OptionalBody.missing()
[body: JsonValue.Null.INSTANCE] | OptionalBody.nullBody()
[body: new JsonValue.StringValue('')] | OptionalBody.empty()
[body: new JsonValue.Object([content: new JsonValue.StringValue('')])] | OptionalBody.empty()
}
}

0 comments on commit fc7e13e

Please sign in to comment.