"@pact-foundation/karma-pact": "2.1.5",
"@pact-foundation/pact-node": "6.18.3",
"@pact-foundation/pact-web": "5.9.1",
I need to provide a pact for request like /request?param=1¶m=2
withRequest: {
method: 'GET',
path: '/request',
query: {
param: Matchers.eachLike('1', {min:1})
}
},
This doesn't help, only one param is accepted
## Relevant log files
I, [2018-06-20T14:31:18.932060 #72648] INFO -- : Registered expected interaction GET request?param=%5B%221%22%5D
You should be able to do {param: Matchers.eachLike('1', {min: 1}) }, as the underlying params map is modelled as String => String[]. If that doesn't work, we'll need to correct the JS code so that it understands this format.
Incorrect requests:
GET request?param=1¶m=2 (request query did not match)
I guess it needs t be fixed in pact)
Can you paste in the full logs please?
I, [2018-06-20T14:31:18.881790 #72648] INFO -- : Received OPTIONS request for mock service administration endpoint DELETE /interactions. Returning CORS headers: {"Access-Control-Allow-Origin":"http://localhost:9876","Access-Control-Allow-Headers":"content-type,x-pact-mock-service","Access-Control-Allow-Methods":"DELETE, POST, GET, HEAD, PUT, TRACE, CONNECT, PATCH"}.
I, [2018-06-20T14:31:18.889502 #72648] INFO -- : Cleared interactions
I, [2018-06-20T14:31:18.932060 #72648] INFO -- : Registered expected interaction GET request?param=%5B%221%22%5D
D, [2018-06-20T14:31:18.933876 #72648] DEBUG -- : {
"description": "list of managers with specific chiefs ans status",
"providerState": "there are managers",
"request": {
"method": "GET",
"path": "request",
"query": {
"param": [
{
"json_class": "Pact::ArrayLike",
"contents": "param",
"min": 1
}
]
},
"headers": {
"Accept": "application/json, text/plain, */*"
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": {
"success": "true",
}
}
}
I, [2018-06-20T14:31:18.950371 #72648] INFO -- : Received request GET request?param=1¶m=2
D, [2018-06-20T14:31:18.950608 #72648] DEBUG -- : {
"path": "request",
"query": "param=1¶m=2",
"method": "get",
"headers": {
"X-Forwarded-Host": "localhost:9876",
"X-Forwarded-Proto": "http",
"X-Forwarded-Port": "9876",
"X-Forwarded-For": "127.0.0.1",
"Cookie": "io=dSD6fXEvBqVabjlaAAAA",
"Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8",
"Accept-Encoding": "gzip, deflate, br",
"Referer": "http://localhost:9876/context.html",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36",
"Accept": "application/json, text/plain, */*",
"Connection": "close",
"Host": "localhost:9876",
"Version": "HTTP/1.1"
}
}
E, [2018-06-20T14:31:18.951925 #72648] ERROR -- : No matching interaction found for GET request?param=1¶m=2
E, [2018-06-20T14:31:18.951963 #72648] ERROR -- : Interaction diffs for that route:
E, [2018-06-20T14:31:18.954152 #72648] ERROR -- : Diff with interaction: "list of managers with specific chiefs ans status" given "there are managers"
Diff
--------------------------------------
Key: - is expected
+ is actual
Matching keys and values are not shown
{
"query": {
"param": [
- [
- "param",
- ],
+ "1",
+ "2"
]
}
}
Description of differences
--------------------------------------
* Expected an Array but got a String ("1") at $.query.param[0]
* Actual array is too long and should not contain "2" at $.query.param[1]
I, [2018-06-20T14:31:23.931280 #72648] INFO -- : Received OPTIONS request for mock service administration endpoint GET /interactions/verification. Returning CORS headers: {"Access-Control-Allow-Origin":"http://localhost:9876","Access-Control-Allow-Headers":"content-type,x-pact-mock-service","Access-Control-Allow-Methods":"DELETE, POST, GET, HEAD, PUT, TRACE, CONNECT, PATCH"}.
W, [2018-06-20T14:31:23.936253 #72648] WARN -- : Verifying - actual interactions do not match expected interactions.
Incorrect requests:
GET request?param=1¶m=2 (request query did not match)
W, [2018-06-20T14:31:23.936294 #72648] WARN -- : Incorrect requests:
GET request?param=1¶m=2 (request query did not match)
I, [2018-06-20T14:31:23.947509 #72648] INFO -- : Received OPTIONS request for mock service administration endpoint POST /pact. Returning CORS headers: {"Access-Control-Allow-Origin":"http://localhost:9876","Access-Control-Allow-Headers":"content-type,x-pact-mock-service","Access-Control-Allow-Methods":"DELETE, POST, GET, HEAD, PUT, TRACE, CONNECT, PATCH"}.
I, [2018-06-20T14:31:23.971299 #72648] INFO -- : Received OPTIONS request for mock service administration endpoint DELETE /interactions. Returning CORS headers: {"Access-Control-Allow-Origin":"http://localhost:9876","Access-Control-Allow-Headers":"content-type,x-pact-mock-service","Access-Control-Allow-Methods":"DELETE, POST, GET, HEAD, PUT, TRACE, CONNECT, PATCH"}.
I, [2018-06-20T14:31:23.975378 #72648] INFO -- : Cleared interactions
Yes, this is possible, however eachLike is for arrays, which is why it's saying it's expecting Expected an Array but got a String ("1") at ... - I think you just want like.
Can you please try and see how that goes?
Sorry, I realise you wanted to match on multiple params with the same name (aka an array in the qs). This is the object we serialise before sending to the mock service in the latest version of pact (v5.9.1 and the 6.x.x branch)
"request": {
"method": "GET",
"path": "/animals/available",
"query": {
"page": {
"contents": {
"generate": "1",
"matcher": ".*"
},
"json_class": "Pact::ArrayLike",
"min": 1
}
}
},
@cakeinpanic can you please properly complete the issue template? This will help us track down the cause of the issue.
@bethesque it seems the mock service is expecting page to be the shape of an array containing array items:
{
"query": {
"param": [
- [
- "param",
- ],
+ "1",
+ "2"
]
}
}
@mefellows is there code in the JS that turns the string => string map of params into string => string[]? There is in the ruby code. I was able to recreate the issue in the Ruby code, then fix it by adding logic into the "convert to string => string[]" code to not wrap an array around an ArrayLike, and this fixed the issue. Here's my commit.
https://github.com/pact-foundation/pact-support/commit/b4a9ec7b378c64a63e96bfa236198b99bf2716df
This is what my logs look like now:
I, [2018-06-28T08:54:23.457031 #68510] INFO -- : Cleared interactions for example "BarClient can retrieve a thing"
I, [2018-06-28T08:54:23.460084 #68510] INFO -- : Registered expected interaction GET /thing?param=%5B%221%22%5D
D, [2018-06-28T08:54:23.460247 #68510] DEBUG -- : {
"description": "a retrieve thing request",
"request": {
"method": "get",
"path": "/thing",
"query": {
"param": {
"json_class": "Pact::ArrayLike",
"contents": "1",
"min": 1
}
},
"headers": {
"Accept": "application/json"
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": {
"company": {
"json_class": "Pact::SomethingLike",
"contents": "My big company"
},
"factories": {
"json_class": "Pact::ArrayLike",
"contents": {
"location": "Sydney",
"capacity": 5
},
"min": 1
}
}
}
}
I, [2018-06-28T08:54:23.487164 #68510] INFO -- : Received request GET /thing?param=2
D, [2018-06-28T08:54:23.487317 #68510] DEBUG -- : {
"path": "/thing",
"query": "param=2",
"method": "get",
"headers": {
"User-Agent": "Faraday v0.15.2",
"Accept": "application/json",
"Accept-Encoding": "gzip;q=1.0,deflate;q=0.6,identity;q=0.3",
"Connection": "close",
"Host": "localhost:4638",
"Version": "HTTP/1.1"
}
}
I, [2018-06-28T08:54:23.487634 #68510] INFO -- : Found matching response for GET /thing?param=%5B%221%22%5D
D, [2018-06-28T08:54:23.487737 #68510] DEBUG -- : {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": {
"company": {
"json_class": "Pact::SomethingLike",
"contents": "My big company"
},
"factories": {
"json_class": "Pact::ArrayLike",
"contents": {
"location": "Sydney",
"capacity": 5
},
"min": 1
}
}
}
I, [2018-06-28T08:54:23.491053 #68510] INFO -- : Verifying - interactions matched for example "BarClient can retrieve a thing"
I, [2018-06-28T08:54:23.493780 #68510] INFO -- : Writing pact for Bar to /Users/bethanyskurrie/workspace/pact-foundation/pact-ruby-e2e-example/consumer/spec/pacts/foo-bar.json
Note that this...
"param": [
{
"json_class": "Pact::ArrayLike",
"contents": "param",
"min": 1
}
]
now looks like this:
"param": {
"json_class": "Pact::ArrayLike",
"contents": "param",
"min": 1
}
You'll need to do the same to pact-js.
Sorry Beth I thought I responded to this, I'll investigate again tomorrow.
I'm relatively confident we _don't_ do that. As per above the query we send through looks like this:
"query": {
"page": {
"contents": {
"generate": "1",
"matcher": ".*"
},
"json_class": "Pact::ArrayLike",
"min": 1
}
}
Hey Matt, your example doesn't match the problem code. An arraylike doesn't have a generate and matcher, it just has content.
The log shows there is an array being introduced somewhere!
query": {
"param": [
{
"json_class": "Pact::ArrayLike",
"contents": "param",
"min": 1
}
]
},
@cakeinpanic could you recreate the issue in a git repository, and post it here so we have an executable example to run?
I'll check now Beth
You're quite right about that example, I did it a while ago so can't recall how that came about. In any case, I've just created an example now:
This is the test setup:
describe.only("get /dogs using builder pattern", () => {
before(() => {
const interaction = new Interaction()
.given("I have a list of dogs")
.uponReceiving("a request for all dogs")
.withRequest({
method: "GET",
path: "/dogs",
headers: {
Accept: "application/json",
},
query: {
param: eachLike("1"),
},
})
.willRespondWith({
status: 200,
headers: {
"Content-Type": "application/json",
},
body: EXPECTED_BODY,
});
return provider.addInteraction(interaction);
});
...
This is what the actual JSON document looks like that is sent to the mock server:
{
"providerState": "I have a list of dogs",
"description": "a request for all dogs",
"request": {
"method": "GET",
"path": "/dogs",
"headers": {
"Accept": "application/json"
},
"query": {
"param": {
"contents": "1",
"json_class": "Pact: :ArrayLike",
"min": 1
}
}
},
"response": {
"body": [
{
"dog": 1
},
{
"dog": 2
}
],
"headers": {
"Content-Type": "application/json"
},
"status": 200
}
}
This is the relevant snippet of the mockservice logs:
I, [2018-07-13T08:47:40.660478 #93921] INFO -- : Registered expected interaction GET /dogs?param=%5B%221%22%5D
D, [2018-07-13T08:47:40.660700 #93921] DEBUG -- : {
"description": "a request for all dogs",
"providerState": "I have a list of dogs",
"request": {
"method": "GET",
"path": "/dogs",
"query": {
"param": [
{
"json_class": "Pact::ArrayLike",
"contents": "1",
"min": 1
}
]
},
"headers": {
"Accept": "application/json"
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": [
{
"dog": 1
},
{
"dog": 2
}
]
}
}
This script reproduces the issue:
#!/bin/bash
pact-mock-service -p 1234 &
sleep 5
pid=$!
echo "--> Creating expectation"
curl -v -X POST -H "content-type: application/json" -H "X-Pact-Mock-Service: true" localhost:1234/interactions -d '{
"providerState": "I have a list of dogs",
"description": "a request for all dogs",
"request": {
"method": "GET",
"path": "/dogs",
"headers": {
"Accept": "application/json"
},
"query": {
"param": {
"contents": "1",
"json_class": "Pact::ArrayLike",
"min": 1
}
}
},
"response": {
"body": [
{
"dog": 1
},
{
"dog": 2
}
],
"headers": {
"Content-Type": "application/json"
},
"status": 200
}
}'
echo "--> Running test"
curl -v "localhost:1234/dogs?param=1¶m=2" | jq .
echo "--> Shutting down"
kill -s TERM $pid
I think it's fixed in the latest version of the standalone. Here is my test:
https://travis-ci.org/pact-foundation/pact-ruby-standalone-e2e-example/builds/403509056
The previous build on that branch failed with the old version of the standalone.
What is wrong is the serialization of the query params back to the string in the pact. I'll have a look at that.
I believe this is fixed now, including the query param serialization. Closing. Please reopen if your retesting fails.
For posterity, if you need the _array_ style parameter names (e.g. ?param[]=1¶m[]=2) then you need to include the brackets in the query parameter key.
e.g.
query: {
'param[]': eachLike("1"),
},
Will match the above example.