How do I view the actual full response headers and...
# pact-js
j
How do I view the actual full response headers and body when doing a pact verification? The console logs in the
Verifier
callback don't actually print when there's a failure, so how do I inspect the results?
Copy code
import { Verifier } from '@pact-foundation/pact'

const { API_URL, PACTFLOW_TOKEN } = process.env

const opts = {
  providerBaseUrl: API_URL,
  pactBrokerUrl: '<https://my-pactflow.pactflow.io/>',
  pactBrokerToken: PACTFLOW_TOKEN,
  provider: 'normalizer',
  consumerVersionTags: ['v2'],
  providerVersionTags: ['v1'],
  providerVersionBranch: 'my-branch',
  providerVersion: 'v1'
}
console.log(opts)
new Verifier(opts).verifyProvider().then(output => {
  console.log('Verify provider function')
  console.log(output)
})
ah I figured this out by using the
requestFilter
middleware to access the response
Copy code
requestFilter: (req, res) => {
    console.log(res)
  }
ok so two things: 1. the response body is a huge object that I don't know what to make sense of; looks nothing like what my provider actually sends 2. by simply adding this
requestFilter
function, my verification test breaks in a different way with the error
Request Failed - One or more of the setup state change handlers has failed
How do you all deal with this?
m
Hey Joel! ok, a few things. 1. the request filter is not really meant for logging. If you do use it, there is a third argument to the fn called
next
which needs to be called as the last thing i.e.
next()
(it’s actually just a standard Express middleware, so it needs to return. This is why your state change handlers are failing. See https://github.com/pact-foundation/pact-js/blob/master/docs/provider.md#modify-requests-prior-to-verification-request-filters 2. the
new Verifier(opts).verifyProvider().then(…
is a promise - this looks to be dangling (i.e. unhandled), and so it seems possible the test is finishing before the verification can report problems back
💯 1
Problems should be properly reported and printed to console otherwise
Lastly, you could set the
logLevel
property to
DEBUG
(or perhaps
TRACE
) and see all of the gory detail
j
Thank you, I'll try this when I get home later tonight
👍 1
Ah that's the string that logLevel field needed. Ok cool
m
Are you using JS or typescript? Even if using JS, most editors will show you the types available to the verifier
j
Typescript. For some reason my vscode IDE just says it's string type
alright that worked! Thank you. I'm still trying to understand the the actual sent request/response pairs, and printing doesn't seem to be helping. The entire
res
or
req
objects are huge and don't seem to contain the headers or body detailed in the pact. For example, these are my print statements
Copy code
requestFilter: (req, res, next) => {
    req.headers['Authorization'] = `Bearer ${jwtGenerator()}`
    console.log(req.headers)
    console.log(req.body)
    next()
  },
but the
req.body
isn't what I'm expecting at all (it should be an address object)
Copy code
{
  'content-type': 'application/json',
  accept: '*/*',
  'accept-encoding': 'gzip, deflate',
  host: '127.0.0.1:34111',
  'content-length': '76',
  Authorization: 'Bearer my-correct-token-here'
}
{
  action: 'teardown',
  params: {},
  state: 'I am able to normalize addresses'
}
👍 1
I guess what I'm looking for is a better log than the test output
Copy code
1) Verifying a pact between flow-controller and normalizer Given I am able to normalize addresses - a request to normalize an address
    1.1) has a matching body
           / -> Expected body Present(1698 bytes) but was empty
    1.2) has status code 200
           expected 200 but was 204
    1.3) includes header 'Accept' with value '"application/json"'
           Expected header 'Accept' to have value '"application/json"' but was ''
           Expected header 'Content-Type' to have value '"application/json"' but was ''
I'd like to see the full response to figure out why it returned 204, especially since when I open up my running server logs I don't see a 204 status code anywhere, just 401 unauthorized
OHHH there are multiple
req
and
res
objects... I was looking at the wrong one. Ok slowly starting to wrap my head around this....
1
m
Yes, it’s middleware. There is actually a separate set of calls (provider states) that you might be first seeing, followed by the actual calls to your API. It’s a really advanced feature that is for edge cases.
I’d like to see the full response to figure out why it returned 204, especially since when I open up my running server logs I don’t see a 204 status code anywhere, just 401 unauthorized
hmm perhaps it’s
TRACE
logs that log the full request/response.
Jus checked, you should be seeing something like this when set to `debug`:
Copy code
[12:26:29.534] DEBUG (99705): pact@11.0.2: incoming request: {"body":{},"headers":{"accept":"text/plain","authorization":"Bearer token","accept-encoding":"gzip, deflate","host":"127.0.0.1:50430"},"method":"GET","path":"/animals/100"}
Middleware invoked before provider API - injecting Authorization token
[12:26:29.536] DEBUG (99705): pact@11.0.2: Proxying GET: /animals/100
[12:26:29.544] DEBUG (99705): pact@11.0.2: outgoing response: {"body":"id=100;first_name=Nanny;last_name=Doe;animal=goat","headers":{"x-powered-by":"Express","access-control-allow-origin":"*","content-type":"text/plain; charset=utf-8","date":"Mon, 13 Nov 2023 01:26:29 GMT","connection":"close","content-length":"49"},"status":200}
j
yes, the trace log helped a ton! Thanks, I figured out the issue with the 204 error, my request was just incorrect for our use case. Fixed it.
👍 1
Of course I'm having another issue though - I've changed the pact version tags and am getting
Copy code
2023-11-13T20:12:39.610158Z  INFO ThreadId(11) pact_verifier::pact_broker: Fetching path '/pacts/provider/normalizer/for-verification' from pact broker
2023-11-13T20:12:40.250435Z ERROR ThreadId(11) pact_verifier: No pacts found matching the given consumer version selectors in pact broker '<https://my-broker.pactflow.io/>': Link/Resource was not found - No pacts were found for this provider
In the broker, the consumer version has been published as
1.0.0
, and my verification looks like this
Copy code
new Verifier({
  providerBaseUrl: API_URL,
  pactBrokerUrl: '<https://my-broker.pactflow.io/>',
  pactBrokerToken: PACTFLOW_TOKEN,
  provider: 'normalizer',
  consumerVersionTags: ['1.0.0'],
  providerVersionTags: ['v1'],
  providerVersionBranch: 'my-branch',
  providerVersion: 'v1',
  // logLevel: 'trace',
  //@ts-ignore
  requestFilter: (req, res, next) => {
    req.headers['Authorization'] = `Bearer ${jwtGenerator()}`
    console.log(res.statusCode)
    console.log(req.headers)
    next()
  }
})
  .verifyProvider()
  .then(output => {
    console.log('Verify provider function')
    console.log(output)
  })
Did I specify the
consumerVersionTags
list incorrectly?
m
This should be one ore more tags associated with a consumer, not the version of the consumer (hence why it’s not finding it, because there are no tags for that consumer)
Copy code
consumerVersionTags: ['1.0.0'],
Similarly, this should be one ore more tags to apply to the provider _version (_which is
v1
)
upon verification. It would then tag it as
v1
as well, which is probably not what you want
Copy code
providerVersionTags: ['v1'],
You should be avoiding tags though and using branches/environments/releases instead: • https://docs.pact.io/pact_broker/brancheshttps://docs.pact.io/pact_broker/recording_deployments_and_releases
j
Ahh ok so it needs the tag not the version, I see. I was following the docs for publishing to the broker and it had omitted the tag argument. I'll re add it
m
yep, I’d avoid tags altogether though if you’re starting fresh. They are the “old” way of doing this.
j
Oh then how do I get verification to work without a consumer tag?
Is there a branch option for verification?
1
m
(I’ll update this. I can see this is out of date, or at least implies that tags is the way to go: https://github.com/pact-foundation/pact-js/blob/master/docs/provider.md#verification-options)
j
Awesome this looks much nicer
💯 1
I must be missing something. I published the consumer with the
--branch=main
property, but still getting this failure on verification
Copy code
2023-11-14T15:05:11.303680Z  INFO ThreadId(11) pact_verifier::pact_broker: Fetching path '/' from pact broker
2023-11-14T15:05:12.241720Z  INFO ThreadId(11) pact_verifier::pact_broker: Fetching path '/pacts/provider/normalizer/for-verification' from pact broker
2023-11-14T15:05:13.544083Z  INFO ThreadId(11) pact_verifier::pact_broker: error response for pacts for verification: failed validation - ["consumerVersionSelectors: must specify a value for environment or tag or branch, or specify mainBranch=true, matchingBranch=true, latest=true, deployed=true, released=true or deployedOrReleased=true (at index 2)"] 
2023-11-14T15:05:13.544474Z ERROR ThreadId(11) pact_verifier: No pacts found matching the given consumer version selectors in pact broker '<https://updaterinc.pactflow.io/>': failed validation - ["consumerVersionSelectors: must specify a value for environment or tag or branch, or specify mainBranch=true, matchingBranch=true, latest=true, deployed=true, released=true or deployedOrReleased=true (at index 2)"]
2023-11-14T15:05:13.544587Z ERROR ThreadId(11) pact_verifier: Failed to load pact - No pacts found matching the given consumer version selectors in pact broker '<https://updaterinc.pactflow.io/>'
The error message is saying to setup my consumerVersionSelectors, but I have, and they look like this
Copy code
consumerVersionSelectors: [
    { mainBranch: true },
    { matchingBranch: true },
    { consumer: 'flow-controller' },
    { branch: 'main' }
  ]
m
is
providerBranch
set (on the
VerifierOptions
type)? I think possibly,
matchingBranch
validation is failing because it doesn’t know the provider’s branch. We could possibly improve the client side validation in this case (and also the error message coming from the broker, which isn’t helpful in this case)
j
Oh I had
providerVersionBranch
set. Ok so I set
providerBranch
but still getting the same error
good news I was able to get verification to work just by hard copying over the pactfile, so that's a good step. Just want to make this work with the pact broker so I can start setting up CI
finally got the broker to work; I had to delete mainBranch, matchingBranch, and consumer options from the
consumerVersionSelectors
object
Copy code
{
  providerBaseUrl: API_URL,
  pactBrokerUrl: '<https://updaterinc.pactflow.io/>',
  pactBrokerToken: PACTFLOW_TOKEN,
  // pactUrls: ['./src/flow-controller-normalizer.json'],
  provider: 'normalizer',
  providerVersionBranch: 'UCS-779-verify-normalizer',
  providerVersion: '8edfcd4984a01a823b0b56e5ee8c306d847751e0',
  consumerVersionSelectors: [
    // { mainBranch: true },
    // { matchingBranch: true },
    // { consumer: 'flow-controller' },
    { branch: 'main' }
  ],
  //@ts-ignore
  requestFilter: (req, res, next) => {
    req.headers['Authorization'] = `Bearer ${jwtGenerator()}`
    next()
  }
}
🤔 1
m
hmm strange that
mainBranch
doesn’t work 🤔
Sorry about the confusion, you’re right with
providerVersionBranch
. Either should work though
j
What file are those comments located in? I followed the type defs but there were no comments like that
m
j
how do you guys handle
consumer-app-version
in ci? I thought if I had the
--branch
flag I wouldn't need to use this?
Copy code
No value provided for required options '--consumer-app-version'
we don't do semantic versioning so could I just make up a hardcoded string here?
ohhh this should be git sha, nevermind that will work
👉 1
m
branch
is more to indicate the feature/line of work happening. The version is extremely important, because that uniquely identifies the piece of software that is being changed/deployed/verified etc.