<#470 Pact consumer core crash prevents interactio...
# pact-js-development
g
#470 Pact consumer core crash prevents interactions being completed when using V4 spec Issue created by lhokktyn Software versions Please provide at least OS and version of pact-js • OS: Mac OSX 13.6 • Pact Node version:
@pact-foundation/pact@12.1.0
• Node Version:
18.13.0
• Other Versions: Any other versions you think might be relevant (optional) Issue Checklist Please confirm the following: ☑︎ I have upgraded to the latest ☑︎ I have the read the FAQs in the Readme ☑︎ I have triple checked, that there are no unhandled promises in my code ☑︎ I have set my log level to debug and attached a log file showing the complete request/response cycle ☑︎ For bonus points and virtual high fives, I have created a reproduceable git repository code snippet (see below) to illustrate the problem Expected behaviour When more than one interaction is tested with
pact.addInteraction()...executeTest()
, both tests pass without error. Actual behaviour The first test passes, but the next one fails with the error:
Copy code
Test failed for the following reasons:

  Mock server failed with the following mismatches:

        0) The following request was expected but not received: 
            Method: GET
            Path: /pet/one
            Headers:
              Accept: application/json
Pact appears to be re-driving the first interaction, so in subsequent
executeTest()
calls the mock server is receiving the wrong request. This feels like user error, but for the life of me I'm not seeing where I've gone wrong! The docs all appear to be geared around V3 at the moment whilst V4 support is in beta, so I've been using examples such as this one to pull things together. Steps to reproduce Minimal-ish script to replicate (
replicate.js
):
Copy code
import { PactV4, SpecificationVersion, MatchersV3 } from "@pact-foundation/pact";

const { string, number, regex } = MatchersV3;

const provider = new PactV4({
  consumer: "consumer",
  provider: "provider",
  spec: SpecificationVersion.SPECIFICATION_VERSION_V4,
  logLevel: "fatal",
});

const test1 = async () => {
  const petId = "one";
  await provider
    .addInteraction()
    .uponReceiving("a request for a pet with an invalid ID")
    .withRequest('get', regex("/pet/[a-z]+", `/pet/${petId}`), (builder) => builder
      .headers({ Accept: "application/json" })
    )
    .willRespondWith(400, (builder) => builder
      .headers({ "content-type": "application/json" })
      .jsonBody({
        code: number(1),
        type: string("error"),
        message: string("Invalid ID supplied"),
      })
    )
    .executeTest(async (mockserver) => {
      await fetch(`${mockserver.url}/pet/${petId}`, {
        headers: {
          Accept: "application/json",
        },
      });
    });
};

const test2 = async () => {
  const petId = 100;
  await provider
    .addInteraction()
    .given("no pets exist")
    .uponReceiving("a request for a pet with an ID")
    .withRequest('get', regex("/pet/[0-9]+", `/pet/${petId}`), (builder) => builder
      .headers({ Accept: "application/json" })
    )
    .willRespondWith(404, (builder) => builder
      .headers({ "content-type": "text/plain" })
    )
    .executeTest(async (mockserver) => {
      await fetch(`${mockserver.url}/pet/${petId}`, {
        headers: {
          Accept: "application/json",
        },
      });
    });
  };

const delay = (t) => new Promise((r) => setTimeout(r, t));

try {
  await test1();
  await delay(1000); // not needed
  await test2();
} catch(e) {
  console.log(e.message);
}
Run with:
Copy code
ENABLE_FEATURE_V4=1 PACT_DO_NOT_TRACK=1 node replicate.js
To confirm behaviour with a single test running, comment out
await test1()
and re-run - it should pass with no error. Relevant log files Minimal logs:
Copy code
2023-10-26T11:43:45.687066Z  INFO tokio-runtime-worker pact_mock_server::hyper_server: Received request GET /pet/one
2023-10-26T11:43:45.688576Z  INFO tokio-runtime-worker pact_matching: comparing to expected HTTP Request ( method: get, path: /pet/one, query: None, headers: Some({"Accept": ["application/json"]}), body: Missing )
2023-10-26T11:43:45.694120Z  INFO tokio-runtime-worker pact_mock_server::hyper_server: Request matched, sending response
2023-10-26T11:43:46.710220Z  INFO tokio-runtime-worker pact_mock_server::hyper_server: Received request GET /pet/100
2023-10-26T11:43:46.710271Z  INFO tokio-runtime-worker pact_matching: comparing to expected HTTP Request ( method: get, path: /pet/one, query: None, headers: Some({"Accept": ["application/json"]}), body: Missing )
2023-10-26T11:43:46.710371Z  INFO tokio-runtime-worker pact_matching: comparing to expected HTTP Request ( method: get, path: /pet/100, query: None, headers: Some({"Accept": ["application/json"]}), body: Missing )
2023-10-26T11:43:46.710428Z  INFO tokio-runtime-worker pact_mock_server::hyper_server: Request matched, sending response
Full debug logs: ``` [124518.045] INFO (73031): 0.4.6: pact native library successfully found, and the correct version 2023-10-26T114518.052784Z DEBUG ThreadId(01) pact_ffi:mock serverhandles detected pactmatchertype, will configure a matcher 2023-10-26T114518.053474Z DEBUG ThreadId(01) pact_ffi:mock serverhandles parsed header value: Left("application/json") 2023-10-26T114518.053881Z DEBUG ThreadId(01) pact_ffi:mock serverhandles parsed header value: Left("application/json") 2023-10-26T114518.055043Z DEBUG ThreadId(01) pact_plugin_driver:catalogue manager Updated catalogue entries: core/transport/http core/transport/https 2023-10-26T114518.055137Z DEBUG ThreadId(01) pact_plugin_driver:catalogue manager Updated catalogue entries: core/content-generator/binary core/content-generator/json core/content-matcher/json core/content-matcher/multipart-form-data core/content-matcher/text core/content-matcher/xml 2023-10-26T114518.055191Z DEBUG ThreadId(01) pact_plugin_driver:catalogue manager Updated catalogue entries: core/matcher/v1-equality core/matcher/v2-max-type core/matcher/v2-min-type core/matcher/v2-minmax-type core/matcher/v2-regex core/matcher/v2-type core/matcher/v3-content-type core/matcher/v3-date core/matcher/v3-datetime core/matcher/v3-decimal-type core/matcher/v3-includes core/matcher/v3-integer-type core/matcher/v3-null core/matcher/v3-number-type core/matcher/v3-time core/matcher/v4-array-contains core/matcher/v4-equals-ignore-order core/matcher/v4-max-equals-ignore-order core/matcher/v4-min-equals-ignore-order core/matcher/v4-minmax-equals-ignore-order core/matcher/v4-not-empty core/matcher/v4-semver 2023-10-26T114518.055681Z DEBUG ThreadId(01) pact_mock_server:mock server Started mock server on 127.0.0.1:52832 2023-10-26T114518.082974Z DEBUG tokio-runtime-worker hyper:protoh1io parsed 7 headers 2023-10-26T114518.083030Z DEBUG tokio-runtime-worker hyper:protoh1conn incoming body is empty 2023-10-26T114518.083086Z DEBUG tokio-runtime-worker pact_mock_server:hyper server Creating pact request from hyper request 2023-10-26T114518.083118Z DEBUG tokio-runtime-worker pact_mock_server:hyper server Extracting query from uri /pet/one 2023-10-26T114518.083188Z INFO tokio-runtime-worker pact_mock_server:hyper server Received request GET /pet/one 2023-10-26T114518.083204Z DEBUG tokio-runtime-worker pact_mock_server:hyper server ---------------------------------------------------------------------------------------- method: GET path: /pet/one query: None headers: Some({"sec-fetch-mode": ["cors"], "accept-encoding": ["gzip", "deflate"], "accept": ["application/json"], "host": ["127.0.0.1:52832"], "accept-language": ["*"], "user-agent": ["undici"], "connection": ["keep-alive"]}) body: Empty ---------------------------------------------------------------------------------------- 2023-10-26T114518.083301Z INFO tokio-runtime-worker pact_matching: comparing to expected HTTP Request ( met… pact-foundation/pact-js-core