Skip to content

Commit

Permalink
fix: correctly decode Pact files with JSON string contents #1658
Browse files Browse the repository at this point in the history
  • Loading branch information
rholshausen committed Jan 30, 2023
1 parent b3b159d commit 4c74ef9
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ class PactConsumerTestExt : Extension, BeforeTestExecutionCallback, BeforeAllCal

pactsToWrite.merge(
Pair(pact.consumer, pact.provider),
Pair(pact as BasePact, version)
Pair(pact, version)
) { (currentPact, currentVersion), _ ->
val mergedPact = currentPact.mergeInteractions(pact.interactions) as BasePact
Pair(mergedPact, maxOf(version, currentVersion))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package au.com.dius.pact.consumer.junit5

import au.com.dius.pact.consumer.MockServer
import au.com.dius.pact.consumer.dsl.PactDslJsonRootValue
import au.com.dius.pact.consumer.dsl.PactDslWithProvider
import au.com.dius.pact.core.model.PactSpecVersion
import au.com.dius.pact.core.model.V4Pact
import au.com.dius.pact.core.model.annotations.Pact
import org.apache.hc.client5.http.fluent.Request
import org.apache.hc.core5.http.ClassicHttpResponse
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith

@ExtendWith(PactConsumerTestExt)
@PactTestFor(providerName = 'JsonStringAtRootTest', pactVersion = PactSpecVersion.V4)
class JsonStringAtRootTest {
final static String JOB_ID = '08f7a210-95db-4827-bcc8-d2025ba506cf'

@Pact(consumer = 'Consumer')
V4Pact pact(PactDslWithProvider builder) {
builder
.uponReceiving('a request for some JSON')
.path('/endpoint')
.willRespondWith()
.status(201)
.body(PactDslJsonRootValue.uuid(JOB_ID))
.toPact(V4Pact)
}

@Test
void test(MockServer mockServer) {
ClassicHttpResponse httpResponse = Request.get("${mockServer.url}/endpoint")
.execute().returnResponse() as ClassicHttpResponse
assert httpResponse.code == 201
assert httpResponse.getHeader('content-type').value == 'application/json; charset=UTF-8'
assert httpResponse.entity.content.text == '"' + JOB_ID + '"'
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ data class OptionalBody @JvmOverloads constructor(
mapOf(
"content" to JsonParser.parseString(valueAsString()),
"contentType" to contentType.toString(),
"encoded" to false
"encoded" to "json"
)
} else {
mapOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ object DefaultPactWriter : PactWriter, KLogging() {
* @param pactSpecVersion Pact version to use to control writing
*/
override fun writePact(pact: Pact, writer: PrintWriter, pactSpecVersion: PactSpecVersion) : Result<Int, Throwable> {
val json = if (pactSpecVersion == PactSpecVersion.V4) {
val json = if (pactSpecVersion >= PactSpecVersion.V4) {
Json.prettyPrint(pact.sortInteractions().asV4Pact()
.expect { "Failed to upcast to a V4 pact" }.toMap(pactSpecVersion))
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,14 @@ fun bodyFromJson(field: String, json: JsonValue, headers: Map<String, Any>): Opt
val bodyBytes = if (encoded) {
when (encoding) {
"base64" -> Base64.getDecoder().decode(Json.toString(jsonBody["content"]))
"json" -> Json.toString(jsonBody["content"]).toByteArray(contentType.asCharset())
"json" -> jsonBody["content"].serialise().toByteArray(contentType.asCharset())
else -> {
logger.warn { "Unrecognised body encoding scheme '$encoding', will use the raw body" }
Json.toString(jsonBody["content"]).toByteArray(contentType.asCharset())
}
}
} else if (contentType.isJson()) {
jsonBody["content"].serialise().toByteArray(contentType.asCharset())
} else {
Json.toString(jsonBody["content"]).toByteArray(contentType.asCharset())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ class OptionalBodySpec extends Specification {
body | v4Format
OptionalBody.missing() | [:]
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('{}'.bytes, ContentType.UNKNOWN) | [content: new JsonValue.Object(), contentType: 'application/json', encoded: 'json']
OptionalBody.body('{}'.bytes, ContentType.JSON) | [content: new JsonValue.Object(), contentType: 'application/json', encoded: 'json']
OptionalBody.body([0xff, 0xd8, 0xff, 0xe0] as byte[], new ContentType('image/jpeg')) | [content: '/9j/4A==', contentType: 'image/jpeg', encoded: 'base64', contentTypeHint: 'DEFAULT']
OptionalBody.body('kjlkjlkjkl'.bytes, new ContentType('application/other'), ContentTypeHint.BINARY) | [content: 'a2psa2psa2prbA==', contentType: 'application/other', encoded: 'base64', contentTypeHint: 'BINARY']
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,15 +345,15 @@ class PactWriterSpec extends Specification {
| "contents": {
| "content": "this is a message",
| "contentType": "application/json",
| "encoded": false
| "encoded": "json"
| }
| },
| "response": [
| {
| "contents": {
| "content": "this is a response",
| "contentType": "application/json",
| "encoded": false
| "encoded": "json"
| }
| }
| ],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,26 @@ class V4PactKtSpec extends Specification {
[body: new JsonValue.StringValue('')] | OptionalBody.empty()
[body: new JsonValue.Object([content: new JsonValue.StringValue('')])] | OptionalBody.empty()
}

@SuppressWarnings('LineLength')
def 'bodyFromJson - handling different types of encoding'() {
expect:
bodyFromJson('body', new JsonValue.Object([
body: new JsonValue.Object([
content: content,
encoded: encoding,
contentType: new JsonValue.StringValue(contentType)
])
]), [:]) == body

where:

content | encoding | contentType | body
new JsonValue.Object([:]) | JsonValue.False.INSTANCE | 'application/json' | OptionalBody.body('{}'.bytes, ContentType.JSON)
new JsonValue.Object([:]) | JsonValue.False.INSTANCE | '' | OptionalBody.body('{}'.bytes, ContentType.JSON)
new JsonValue.StringValue('ABC') | JsonValue.False.INSTANCE | 'application/json' | OptionalBody.body('"ABC"'.bytes, ContentType.JSON)
new JsonValue.StringValue('ABC') | new JsonValue.StringValue('json') | 'application/json' | OptionalBody.body('"ABC"'.bytes, ContentType.JSON)
new JsonValue.StringValue('IkFCQyI=') | JsonValue.True.INSTANCE | 'application/json' | OptionalBody.body('"ABC"'.bytes, ContentType.JSON)
new JsonValue.StringValue('IkFCQyI=') | new JsonValue.StringValue('base64') | 'application/json' | OptionalBody.body('"ABC"'.bytes, ContentType.JSON)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,22 @@ class JsonSpec extends Specification {
'{"a": "A", "b": 1, "c": [100], "d": {"href": "blah"}}' | '{\n "a": "A",\n "b": 1,\n "c": [\n 100\n ],\n "d": {\n "href": "blah"\n }\n}'
}

@Unroll
def 'toString - #desc'() {
expect:
Json.INSTANCE.toString(json == null ? json : JsonParser.parseString(json)) == value

where:

desc | json | value
'Null' | null | 'null'
'Json Null' | 'null' | 'null'
'Boolean True' | 'true' | 'true'
'Boolean False' | 'false' | 'false'
'integer' | '112' | '112'
'float' | '112.66' | '112.66'
'string' | '"hello"' | 'hello'
'list' | '["hello", 1, true, {"a": "A"}]' | '["hello",1,true,{"a":"A"}]'
'object' | '{"hello": "world", "list": [1, 2, 3]}' | '{"hello":"world","list":[1,2,3]}'
}
}

0 comments on commit 4c74ef9

Please sign in to comment.