Hello all, we have been trying to build provider t...
# pact-js
e
Hello all, we have been trying to build provider tests with the pact-js library but have a problem so thought to reach out. It appears the
Verifier
is unable to verify both synchronous and asynchronous contracts for a singular Provider. We can build a test solely for synchronous contracts using
Verifier
and solely for asynchronous contract using MessageProviderPact but using
Verifier.messageProviders
opt breaks those same verifications. We have created a example project to demonstrate. Does anyone have any experience of running asynchronous and synchronous side by side for one Provider? Any guidance would be appreciated In other languages it appears that people get around this by using filters such as Java however pact-js doesn't have this. Filtering upon interaction type would solve our problem and allow us to verify both asynchronous and synchronous contracts for one Provider under two test files. To explore a possible solution, I made changes to the pact-js library to introduce comparable filter functionality in this draft fork. This was supported by AI and I have not contributed to pact-js before so I would be open to discussion if this is the correct approach Thanks, Eoin : )
👋 1
m
So it definitely can verify both async and HTTP interactions in a single test. Is the problem that you want to run it across two? Thanks for creating the demo, that’s helpful. In case you are wanting to just verify in a single test, this example actually shows how to verify HTTP, messages and plugin based interactions in a single test: https://github.com/pact-foundation/pact-js/blob/master/examples/v4/plugins/test/matt.provider.spec.ts#L29.
RE: https://github.com/eoinkane/pact-js/pull/1 Unfortunately, whilst it looks convincing the change can’t really happen here (at least not without a lot more code/logic/etc.). For example, it just loads pacts that are explicitly given to it - not through ones using selectors (which is one of the primary use cases). All of that logic and parsing happens in the core engine (exposed via FFI functions here). And even if it did that, we’d need a solution to combine the verification results that go back to the broker, is that API only atomically accepts a result per pact. There’s more, but anyway you get the gist.
RE: example above. Line 30: points to the locally running HTTP provider 31-37: TCP transport setup for plugin (not required for you) 41-93: message interactions
e
We would be happy to run them all in one test, the problem is that we are struggling to get them running in a single test. Our demo file verifier-only-with-message-providers.pact.test.ts results in the failure shown for the async contract despite working fine in isolation
I will look at that example and try retrofit it as well. That is a useful example, I can see it doing both sync and async. I think I avoided previously just due to the plugin stuff
👍 1
m
OK so I think there may be a bug somewhere - the test ^^ should be allowed to happen. I suspect it may be an issue in the proxy/middleware. What should happen in Pact JS is that it should appropriately route incoming verifications to the correct place. It seems it’s not doing that. Background: there is a proxy that accepts inbound connections from the core engine. Because the core is not in JS, we need a way to communicate to the JS boundary for message calling - we use HTTP to do this. Messages come in to a specific HTTP route and are bound to a message handler specified in
messageProviders
. This looks to not be working as expected. Regular HTTP verifications are coming in through the proxy and into the HTTP provider (system under test). So I suspect it’s some switching/matching logic in there that’s failing. Why it works for the V4 example I provided I don’t know yet, but might provide a clue Messages are sent on a specific HTTP path and are then routed
Found it facepalm https://github.com/pact-foundation/pact-js/blob/67082eac362570da14f56c34479c641b07683fbd/src/dsl/verifier/verifier.ts#L128-L135
Copy code
transports: this.config.transports?.concat([
          {
            port,
            path: this.messageTransportPath,
            protocol: 'message',
          },
        ]),
Means if there are no user-defined transports, the message transport is not configured. should be (something like)
Copy code
transports: (this.config.transports || []).concat([
          {
            port,
            path: this.messageTransportPath,
            protocol: 'message',
          },
        ]),
I’ll put out another release today - I’m pretty sure this fixes it (tested locally with your example)
I’ll have to tidy up the examples after the xmas break some time