Martin Mineo
03/07/2025, 1:16 PMBertrand Ernst
03/13/2025, 1:25 PMpact-js?
To be more precise, I would like to manage the mock server myself using the pact-cli Docker image instead of having pact-js launch a mock-server for me.
I looked at the options to setup the provider with the host and port of a running mock-server but couldn't find anything.
Is this at all possible?
Thanks in advance !Gabriel Vasconcelos
03/17/2025, 2:04 PMLachlan Newman
03/18/2025, 5:05 AMBertrand Ernst
03/28/2025, 11:05 AMpact-js along with jest .
Above every test suite that is executed, I have the following error message:
Failed to initialise global tracing subscriber - a global default trace dispatcher has already been set
As I understand, this comes from the reference implementation where there are several instance of such error message being sent:
https://github.com/search?q=repo%3Apact-foundation%2Fpact-reference%20set_global_default&type=code
I initialize my provider using new PactV3(...) in a beforeEach block within a setupFilesAfterEnv file (is this best practice?).
https://jestjs.io/docs/configuration#setupfilesafterenv-array
What is the best way to get rid of this error?
Note that it's not blocking, my tests run just as well but it's annoying. 🙂Abubakar Mehmood
03/31/2025, 10:24 AM/_pactSetup endpoint but I haven't set it up (neither does the above-mentioned example). Logs:
2025-03-31T07:33:34.581653Z DEBUG ThreadId(02) verify_interaction{interaction="a request to create a quote"}: hyper_util::client::legacy::connect::http: connecting to 127.0.0.1:51891
2025-03-31T07:33:34.581929Z DEBUG ThreadId(02) verify_interaction{interaction="a request to create a quote"}: hyper_util::client::legacy::connect::http: connected to 127.0.0.1:51891
[08:33:34.604] DEBUG (38248): pact@15.0.1: hooks state counter is 1 after receiving "setup" action
[08:33:34.605] DEBUG (38248): pact@15.0.1: incoming request: {"body":{"action":"setup","params":{},"state":"quote can be created"},"headers":{"content-type":"application/json","accept":"*/*","accept-encoding":"gzip, deflate","host":"127.0.0.1:51891","content-length":"61"},"method":"POST","path":"/_pactSetup"}
(followed by timeout)
2025-03-31T07:34:04.691883Z DEBUG ThreadId(02) verify_interaction{interaction="a request to create a quote"}: pact_verifier::provider_client: State change request failed with error error sending request for url (<http://127.0.0.1:51891/_pactSetup>)
While the docs here seem to mention that we need to set up an (or two, according to this old answer) HTTP endpoints for the states, I couldn't find any details of what the endpoints should look like, and how are the e2e tests working without setting up those endpoints.
2. pactjs seems to start its own mock server and call the endpoint to verify on that base URL instead of using the providerBaseUrl I've specified. Excerpt of code:
const server = express();
server.use(cors());
const app = server.listen(53404, () => {
console.log(`Server listening on <http://localhost:53404>`);
});
server.post('/v3/forex/quote', (req, res) => {
res.append('Content-Type', 'application/json').status(200).send({
dummy: 123456789, // This is supposed to be replaced in the request filters
});
});
const opts = {
provider: 'MyProvider',
logLevel: "debug",
providerBaseUrl: `<http://localhost:53404>`,
stateHandlers: {
'quote can be created': async () => {
await redisClient.set("some data");
//console.log('handler finished');
return Promise.resolve();
},
},
// Override request handling to call the Lambda function directly
requestFilter: async (req, res, next) => {
// omitted for brevity
}
};
const verifier = new Verifier(opts);
Logs show a different port (53741), instead of 53404. It changes every time, though:
2025-03-31T08:39:11.753646Z INFO ThreadId(02) verify_interaction{interaction="a request to create a quote"}: pact_verifier::provider_client: Sending request to provider at <http://127.0.0.1:53741/>
2025-03-31T08:39:11.753655Z DEBUG ThreadId(02) verify_interaction{interaction="a request to create a quote"}: pact_verifier::provider_client: Provider details = ProviderInfo { name: "ForexV3-Funding", protocol: "http", host: "127.0.0.1", port: Some(53741), path: "/", transports: [ProviderTransport { transport: "http", port: Some(53741), path: Some("/"), scheme: Some("http") }] }
2025-03-31T08:39:11.753676Z INFO ThreadId(02) verify_interaction{interaction="a request to create a quote"}: pact_verifier::provider_client: Sending request HTTP Request ( method: POST, path: /v3/forex/quote, query: None, headers: Some({"Content-Type": ["application/json"]}), body: Present(115 bytes, application/json) )
2025-03-31T08:39:11.753689Z DEBUG ThreadId(02) verify_interaction{interaction="a request to create a quote"}: pact_verifier::provider_client: body:
{"buy_amount":"18.358","buy_currency":"GBP","customer":{"id":"C-98YE32ZY"},"sell_currency":"USD","type":"customer"}
2025-03-31T08:39:11.753743Z DEBUG ThreadId(02) verify_interaction{interaction="a request to create a quote"}: hyper_util::client::legacy::pool: reuse idle connection for ("http", 127.0.0.1:53741)
[09:39:11.756] DEBUG (40620): pact@15.0.1: incoming request: {"body":{"buy_amount":"18.358","buy_currency":"GBP","customer":{"id":"C-98YE32ZY"},"sell_currency":"USD","type":"customer"},"headers":{"content-type":"application/json","accept":"*/*","accept-encoding":"gzip, deflate","host":"127.0.0.1:53741","content-length":"115"},"method":"POST","path":"/v3/forex/quote"}Ayoub BOULAHTAR
04/04/2025, 11:05 AMprovider
.addInteraction()
.given('one or more requested row exist')
.withRequest('GET', '/base/url', (builder) => {
builder.query({
ids: MatchersV3.eachLike(1),
});
builder.headers({
'Content-Type': 'application/json',
});
})Ruud Welling
04/25/2025, 3:05 PMNeil McLaughlin
05/02/2025, 9:03 AMfromProviderState using the V3Interaction, but I can’t seem to
get it working with the V4Interaction model.
The fromProviderState call initially seems like its working in that the test passes, but the mock server
seems to match any path, not just the specified path.
Also, I’ve noticed that this method seems to have been dropped from the documentation in both the Java and JS versions
of the pact documentation.
The initial version (static path) is working, but it bakes a specific id into the contract.
v4InteractionWithResponse = mockServer
.addInteraction()
.uponReceiving("a request for an advert")
.given("basic car advert")
.withRequest(
"GET",
"/product-page/v1/advert/201602281465747",
(builder) => {
builder.query({ channel: "cars" });
},
)
So the next step was to parameterize the path using fromProviderState.
v4InteractionWithResponse = mockServer
.addInteraction()
.uponReceiving("a request for an advert")
.given("basic car advert")
.withRequest(
"GET",
fromProviderState(
"/product-page/v1/advert/${advertId}",
"/product-page/v1/advert/201602281465747",
),
(builder) => {
builder.query({ channel: "cars" });
},
)Yassen Damyanov
05/10/2025, 4:50 PMAccept header values as an array as opposed to a comma delimited string? Details in 💬 ➡️Jesse Vander Does
05/19/2025, 2:35 PMprovider
.addInteraction()
.given('a valid record can be saved')
.uponReceiving('a request to save a record')
.withRequest('POST', `/api/resource/${id}`, (builder) => {
builder.headers(
'multipart/form-data; boundary=.*',
);
})Victor COATALEM
06/19/2025, 10:31 AMsource, reason, ...). Basically I don't care about the file in itself, but I want to write matchers on the metadata fields. However I can't seem to make that work. Matching the reason field against anything yields the error: Failed to parse the expected body as a MIME multipart body: 'incomplete multipart stream' .
I posted my example on this issue . Any input would be greatly appreciated 🙏Teresa Marcelino
06/23/2025, 3:32 PMDELETE request. The mock expects a JSON request body like this:
{
"objectsIds": [
1,
2,
3
]
}
But the test fails sayingfail:
Expected body Present(45 bytes, application/json) but was emptyMy request call looks like this:
makeRequestAcceptingJsonResponse("DELETE", mockServer.url, path, {
objectsIds: [1, 2, 3],
} /*payload*/);
And my request function:
return axios.request({
baseURL,
data: payload,
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
method,
url: path,
validateStatus: () => true,
});
I suspect Axios might be dropping the body on DELETE requests. If I change to a POST, request body is being sent correctly.
Has anyone seen this or knows how to fix it?
Thanks! 🙏Zachary Lysobey
06/24/2025, 9:40 PMpact-js docs on Provider verification:
> https://github.com/pact-foundation/pact-js/blob/master/docs/provider.md?plain=1#L122-L125
const opts = {
...
stateHandlers: {
[null]: () => {
// This is the "default" state handler, when no state is given
}
"Has no animals": () => {
// ...
There are a couple issues with this.
1) just above, it says "Here is an example from our e2e suite:". But the [null] case is not part of that example
2) its missing a comma after the [null] case, so the syntax is broken.
3) This works in JavaScript, but does not in TypeScript. TS is stricter with computed properties: > A computed property name must be of type 'string', 'number', 'symbol', or 'any'
I think [null] would be coerced into "null" at runtime with JS, so maybe that works?
I'm happy to make a PR fixing this. I'd of course add the missing ,, and I guess update [null] to be just "null" (?). But I'm not sure what to do about 1) with the inaccurate note about the example code.
Any advice?Cody Jenkins
07/14/2025, 7:55 AMZachary Lysobey
07/14/2025, 5:15 PMZachary Lysobey
07/14/2025, 7:59 PMZachary Lysobey
07/14/2025, 8:01 PMjest-pact library?
At first glance, it looks like its getting frequent updates, but as far as I can tell it doesn't work with PactV4. I'm assuming then that I should be avoiding it?
> https://github.com/pact-foundation/jest-pactEmil
07/22/2025, 6:20 AMvalueFromProviderState() works perfectly for this, but pact-js only has fromProviderState() which appears to be converting everything to strings, making the provider test fail.
Is there a way to access provider state values in pact-js without string coercion, or is this feature planned?
Thank you in advance!Slackbot
08/22/2025, 10:49 AMboden winkel
08/28/2025, 3:15 PMboden winkel
09/03/2025, 12:33 PMKieran McCarthy
10/11/2025, 10:48 AMSSh
10/16/2025, 3:35 PMlike matcher in case when it faced array inside object?
Ex,:
like({
field1: "one",
field2: 2,
field3: [1, 2, 3],
})
or
like({
field1: "one",
field2: 2,
field3: [{f1: "ff", f2: 2}, {f1: "aa", f2: 5},{ f1: "dd", f2: 1},],
})
In https://docs.pact.io/implementation_guides/javascript/docs/matching
I see next for like matcher
Note that you can wrap aand for V3 matcheraround a single value or an object. When wrapped around an object, all values and child object values will be matched according to types, unless overridden by something more specific like alike.term
Applies theOr I must explicitly declarematcher to value, which requires values to have the same type as the templatetype
eachLike for arrays in like section?Haiyang Huang
11/20/2025, 10:12 AM"@pact-foundation/pact-core": "^17.0.1",
"@pact-foundation/pact-core-linux-x64-glibc": "^17.0.1",Wojciech Wroblewski
11/26/2025, 1:59 PMdescribe('Pact Verification', () => {
it('validates the expectations of Consumer', async () => {
const opts = {
provider: '{my}-example-provider',
providerBaseUrl: '<http://localhost:3000>', // your service endpoint
pactBrokerUrl: 'https://{my-url}.<http://pactflow.io/|pactflow.io/>',
pactBrokerToken: '{my-token}',
consumerVersionTags: ['main'],
};
await new Verifier(opts).verifyProvider();
});
});
when running such a test I'm getting
2025-11-26T13:51:47.013550Z INFO ThreadId(11) pact_verifier::pact_broker: Fetching path '' from pact broker
2025-11-26T13:51:47.809031Z ERROR ThreadId(11) pact_verifier: No pacts found for provider '{my}-example-provider' matching the given consumer version selectors in pact broker 'https://{my-url}.<http://pactflow.io/|pactflow.io/>': Link/Resource was not found - No pacts for provider '{my}-example-provider' were found in the pact broker. URL: 'https://{my-url}.<http://pactflow.io/|pactflow.io/>'
2025-11-26T13:51:47.810401Z ERROR ThreadId(11) pact_verifier: Failed to load pact - No pacts found for provider '{my}-example-provider' matching the given consumer version selectors in pact broker 'https://{my-url}.<http://pactflow.io/|pactflow.io/>'
2025-11-26T13:51:47.811140Z WARN ThreadId(11) pact_matching::metrics:
There are pacts published by consumer for given provider in my instance and I also double checked that tag name is proper. I'm not sure about that 'Fetching path '' ...' which is empty, but I'm not sure what's the path and how to set it
What should I also check? Is there any option to improve verbosity or recommended debugging path?Alan Boshier
12/01/2025, 4:43 PMeachKeyMatches matcher properly; the documentation here is terse, and I haven't been able to find any working examples out there that really do a good job of explaining it. Any pointers much appreciated TIA.Cody Jenkins
12/09/2025, 12:35 AM{}. But if I remove the body or make it something else (e.g. {"foo":"bar"}) then it does not hang đź§µ
✍️ EDIT: Yep it's #1602 again. Fix for me was to add:
requestFilter: (req, _, next) => {
delete req.headers['content-length'];
next();
},Eoin K
12/18/2025, 9:22 AMVerifier 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 : )Vaibhav Suryawanshi
12/24/2025, 7:04 AM