Hello! I’m trying to write a Pact test and I get t...
# pact-js
d
Hello! I’m trying to write a Pact test and I get the following error:
Mismatch with header 'Accept': Expected 'application/problem+json' to match '^(.*application\/problem\+json.*application\/json.*)|(.*application\/json.*application\/problem\+json.*)$'
. When I log the request who was sent, I see the following:
"accept": ["application/problem+json", "application/json", "text/plain", "*/*"]
. So it looks like Pact interprets the Accept header as an array of string and then only compares the first one with the regex instead of comparing them all together. This was working on previous versions of Pact. Any idea?
m
one is a bug in Pact JS (I think) and the other is a bug in the rust core (I also think)
@uglyog will probably be able to advise more. I think for multi-valued headers, Pact JS could use the FFI function that enumerates the header values (see https://github.com/pact-foundation/pact-js/issues/964#issuecomment-1288295557). Thoughts Ron?
d
Alright. I have no clue on how could I help you on this 😞
m
I think https://github.com/pact-foundation/pact-js/blob/c6c3fae3d59a9f72e10906b3b14563247c8200cb/src/v3/types.ts#L81 needs to be updated to support an array value OR we detect the presence of
;
and split it directly here: https://github.com/pact-foundation/pact-js/blob/c6c3fae3d59a9f72e10906b3b14563247c8200cb/src/v3/ffi.ts#L15 Then we would simply call
interaction.withRequestHeader
multiple times for a given header value, enumerating the second argument (which specifies the header value index) that is currently hard coded to
0
Basically, we treat the header as a single value, but the core (properly, I guess) treats it as a multi valued object. The confusion arises because the core automatically splits it apart, when it checks, but uses the non split expectation from the test - so the comparison fails
d
I tried to implement a solution but I don’t reach a good solution. What I don’t get is the following: If we split the string by
,
, during the first iteration, in my example, I’ll have
application/problem+json
and this has to match the Regex
(.*application\/problem\+json.*application\/json.*)|(.*application\/json.*application\/problem\+json.*)
and it will not.
Any idea @Matt (pactflow.io / pact-js / pact-go)?
m
Hi Dany, sorry I missed this yesterday. It’s a bug in Pact JS so I don’t think it can be worked around. That being said, do you actually need the regex? This is on the request side, so I’m wondering if you really need to do that
d
But I tried to contribute to Pact JS to fix the bug, I didn’t tried a workaround on my side 🙂
And yes I need the Regex 😞
I tried to implement your proposition on Pact JS but as said before, if we call
interaction.withRequestHeader
multiple times it’ll not work as in the regex we expect all the values on which we iterate and not only one.
Or maybe I misunderstood / misimplemented your proposition
@Matt (pactflow.io / pact-js / pact-go)
m
Sorry Dany, I haven’t had a chance to look into it for you. As noted, there is a bug that needs to be addressed. I’ll see if I can prioritise it next week
d
Hi Matt, Please let me know if I can contribute to this 🙂
🙏 1
m
I tried to implement your proposition on Pact JS but as said before, if we call
interaction.withRequestHeader
multiple times it’ll not work as in the regex we expect all the values on which we iterate and not only one.
why do you need to regex the header at all though? What are you trying to achieve exactly? By specifying you’ll send through those headers, the mock service should check for you anyway.
d
In my case I want to verify that the value of the
Accept
header in the request matches the following Regex:
(.*application\/problem\+json.*application\/json.*)|(.*application\/json.*application\/problem\+json.*)
. It just means I want contains
application/problem+json
and
application/json
.
m
But that’s what the mock server will do - it checks what you told it. A regex is only needed there if you’re not confident you’re going to send the exact value.
i.e. it’s a matcher for the consumer test, which weakens the test (matchers on the request I would generally consider to be a code smell)
d
I see your point. In my case I’m not sure that the value will be
application/problem+json, application/json
. It could also be
application/json, application/problem+json
. Both are correct for my use case.
👍 1
m
perfect!
Try setting the header without the regex then
let’s see if that passes
d
But how can I do that? I want both to be correct. I can only set one value right not two ?
m
I think you can just set it as
application/problem+json, application/json
and the core will split it into two, and then check against the headers you sent
mmm maybe that won’t work
Let me have a play after I put the kids down.
This should help. I think there might still be an issue in the rust core, but let’s work one issue at a time
If it passes, i’ll merge it in. It should allow you to write this in hte mock setup:
Copy code
accept: ['application/matt', 'text/matt']
And then in your HTTP client:
Copy code
return axios
            .request({
              baseURL: mockserver.url,
              headers: {
                Accept: 'application/matt, text/matt',
              },
              data: 'hello',
              method: 'POST',
              url: '/matt',
            })
type thing. I think order will matter though
You can also still add matchers to each of those values I believe
d
It’s exactly what I have implemented but it was not solving my issue with the Regex. I’ll test it as soon as I’ve some free time!
👍 1
m
I'll chat with Ron tomorrow to see if I can get some more insight into how to implement it effectively
It’s exactly what I have implemented but it was not solving my issue with the Regex. I’ll test it as soon as I’ve some free time!
I think you can drop the regex now though, because you’re able to specify that your client is going to send multiple accept headers
I ran through a quick test again with fresh eyes, and I think this should work the way you need it
d
I just had time to test it and it still doesn’t work 😞 But I tried on a version that uses the old Matchers, not the V3. I got the following error:
Mismatch with header 'Accept': Expected header 'Accept' to have value 'application/problem+jsonapplication/jsontext/plain*/*' but was 'application/problem+json'.
Something happens with my Accept header as all the commas between the values disappear. Any idea @Matt (pactflow.io / pact-js / pact-go)?
I also get a second error which is related with the body and not the headers:
Type mismatch: Expected Map {"pact:matcher:type":"type","value":false} but received Boolean false
.
m
Can you please share the test? I might need to backport the change to the non v3 interface