Hi all. This is my first time using pact and I've ...
# pact-js
s
Hi all. This is my first time using pact and I've hit a bit of a wall. I've written this consumer test, and it passes. But the pact file is not generated. Am I missing something?
Copy code
import path from "path";
import {
  MatchersV3,
  PactV4,
  SpecificationVersion,
} from "@pact-foundation/pact";
import axios from "axios";

const pact = new PactV4({
  dir: path.resolve(process.cwd(), "pact/pacts"),
  consumer: "Consumer",
  provider: "Provider",
  spec: SpecificationVersion.SPECIFICATION_VERSION_V4,
  logLevel: "info",
});

const { uuid, string, timestamp } = MatchersV3;

describe("Creating new feedback", () => {
  it("should create feedback", async () => {
    const dialogueId = "123e4567-e89b-12d3-a456-426614174000";
    const dateTimeWithMicrosecondsRegex =
      "^\\d{4}-[01]\\d-[0-3]\\d[T][0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d{6}Z$";
    const uuidRegex =
      "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$";

    const expectedBody = {
      ext_feedback_id: uuid(),
      status_id: string("pending"),
      created_at: timestamp(
        "yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'",
        "2024-04-12T09:36:00.047710Z",
      ),
      updated_at: timestamp(
        "yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'",
        "2024-04-12T09:36:00.047710Z",
      ),
    };

    pact
      .addInteraction()
      .uponReceiving("a request to create feedback")
      .withRequest("POST", `/${dialogueId}/feedback/`, (request) => {
        request.headers({
          "Content-Type": "application/json",
        });
      })
      .willRespondWith(202, (response) => {
        response
          .headers({ "Content-Type": "application/json" })
          .jsonBody(expectedBody);
      })

      .executeTest((mockserver) => {
        return axios
          .request({
            baseURL: mockserver.url,
            method: "POST",
            url: `/${dialogueId}/feedback/`,
          })
          .then((response) => {
            expect(response.status).toBe(202);
            expect(response.data).toMatchObject({
              ext_feedback_id: expect.any(String),
              status_id: "pending",
              created_at: expect.any(String),
              updated_at: expect.any(String),
            });
            expect(response.data.ext_feedback_id).toMatch(
              new RegExp(uuidRegex),
            );
            expect(response.data.created_at).toMatch(
              new RegExp(dateTimeWithMicrosecondsRegex),
            );
            expect(response.data.updated_at).toMatch(
              new RegExp(dateTimeWithMicrosecondsRegex),
            );
          });
      });
  });
});
👋 1
m
Mind sharing the log output from the run? Idy set the log level to DEBUG
s
Copy code
RUNS  pact/feedback/create-feedback.test.ts
[12:33:59.889] INFO (66375): 0.4.16: pact native library successfully found, and the correct version
2024-04-12T11:33:59.899588Z ERROR ThreadId(01) pact_ffi::mock_server::handles: Failed to parse the value: expected value at line 1 column 1
2024-04-12T11:33:59.902387Z ERROR ThreadId(01) pact_ffi::mock_server::handles: Failed to parse the value: expected value at line 1 column 1
2024-04-12T11:33:59.902401Z DEBUG ThreadId(01) pact_ffi::mock_server::handles: parsed header value: Left("application/json")
2024-04-12T11:33:59.902952Z ERROR ThreadId(01) pact_ffi::mock_server::handles: Failed to parse the value: expected value at line 1 column 1
2024-04-12T11:33:59.902957Z DEBUG ThreadId(01) pact_ffi::mock_server::handles: parsed header value: Left("application/json")
2024-04-12T11:33:59.903541Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: Path = $
2024-04-12T11:33:59.903544Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: Configuring a normal object
2024-04-12T11:33:59.903907Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: Path = $.created_at
2024-04-12T11:33:59.903913Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: detected pact:matcher:type, will configure a matcher
2024-04-12T11:33:59.903976Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: Path = $.ext_feedback_id
2024-04-12T11:33:59.903978Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: detected pact:matcher:type, will configure a matcher
2024-04-12T11:33:59.903982Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: detected pact:generator:type, will configure a generators
2024-04-12T11:33:59.904217Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: Path = $.status_id
2024-04-12T11:33:59.904229Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: detected pact:matcher:type, will configure a matcher
2024-04-12T11:33:59.904436Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: Path = $.updated_at
2024-04-12T11:33:59.904444Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: detected pact:matcher:type, will configure a matcher
2024-04-12T11:33:59.906949Z DEBUG ThreadId(01) pact_plugin_driver::catalogue_manager: Updated catalogue entries:
core/transport/http
core/transport/https
2024-04-12T11:33:59.907634Z 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
2024-04-12T11:33:59.907663Z 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
 PASS  pact/feedback/create-feedback.test.ts
  Creating new feedback
    ✓ should create feedback (20 ms)


Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.177 s
If I return the
pact
object in the test, ie:
Copy code
return pact
      .addInteraction()
      .uponReceiving("a request to create feedback")
// etc
The test fails as follows:
Copy code
npm run test:pact

> geep-experience@0.1.0 test:pact
> jest pact

info  - Loaded env from /Users/sam/projects/geep/.env

 RUNS  pact/feedback/create-feedback.test.ts
[12:35:41.343] INFO (67840): 0.4.16: pact native library successfully found, and the correct version
2024-04-12T11:35:41.349665Z ERROR ThreadId(01) pact_ffi::mock_server::handles: Failed to parse the value: expected value at line 1 column 1
2024-04-12T11:35:41.350214Z ERROR ThreadId(01) pact_ffi::mock_server::handles: Failed to parse the value: expected value at line 1 column 1
2024-04-12T11:35:41.350221Z DEBUG ThreadId(01) pact_ffi::mock_server::handles: parsed header value: Left("application/json")
2024-04-12T11:35:41.350349Z ERROR ThreadId(01) pact_ffi::mock_server::handles: Failed to parse the value: expected value at line 1 column 1
2024-04-12T11:35:41.350362Z DEBUG ThreadId(01) pact_ffi::mock_server::handles: parsed header value: Left("application/json")
2024-04-12T11:35:41.350410Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: Path = $
2024-04-12T11:35:41.350414Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: Configuring a normal object
2024-04-12T11:35:41.350423Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: Path = $.created_at
2024-04-12T11:35:41.350425Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: detected pact:matcher:type, will configure a matcher
2024-04-12T11:35:41.350436Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: Path = $.ext_feedback_id
2024-04-12T11:35:41.350439Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: detected pact:matcher:type, will configure a matcher
2024-04-12T11:35:41.350442Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: detected pact:generator:type, will configure a generators
2024-04-12T11:35:41.350452Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: Path = $.status_id
2024-04-12T11:35:41.350453Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: detected pact:matcher:type, will configure a matcher
2024-04-12T11:35:41.350458Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: Path = $.updated_at
2024-04-12T11:35:41.350460Z DEBUG ThreadId(01) pact_ffi::mock_server::bodies: detected pact:matcher:type, will configure a matcher
2024-04-12T11:35:41.350927Z DEBUG ThreadId(01) pact_plugin_driver::catalogue_manager: Updated catalogue entries:
core/transport/http
core/transport/https
2024-04-12T11:35:41.350950Z 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
2024-04-12T11:35:41.350973Z 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
 RUNS  pact/feedback/create-feedback.test.ts
2024-04-12T11:35:41.365374Z DEBUG tokio-runtime-worker hyper::proto::h1::io: parsed 9 headers
2024-04-12T11:35:41.365397Z DEBUG tokio-runtime-worker hyper::proto::h1::conn: incoming body is empty
2024-04-12T11:35:41.366161Z DEBUG tokio-runtime-worker pact_mock_server::hyper_server: Creating pact request from hyper request
2024-04-12T11:35:41.366479Z DEBUG tokio-runtime-worker pact_mock_server::hyper_server: Extracting query from uri /123e4567-e89b-12d3-a456-426614174000/feedback/
2024-04-12T11:35:41.367326Z  INFO tokio-runtime-worker pact_mock_server::hyper_server: Received request POST /123e4567-e89b-12d3-a456-426614174000/feedback/
2024-04-12T11:35:41.367334Z DEBUG tokio-runtime-worker pact_mock_server::hyper_server: 
      ----------------------------------------------------------------------------------------
       method: POST
       path: /123e4567-e89b-12d3-a456-426614174000/feedback/
       query: None
       headers: Some({"referer": ["<http://localhost/>"], "user-agent": ["Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML", "like Gecko) jsdom/20.0.3"], "content-length": ["0"], "connection": ["keep-alive"], "accept-encoding": ["gzip", "deflate"], "accept": ["application/json", "text/plain", "*/*"], "accept-language": ["en"], "origin": ["<http://localhost>"], "host": ["127.0.0.1:8080"]})
       body: Empty
      ----------------------------------------------------------------------------------------
      
2024-04-12T11:35:41.367537Z  INFO tokio-runtime-worker pact_matching: comparing to expected HTTP Request ( method: POST, path: /123e4567-e89b-12d3-a456-426614174000/feedback/, query: None, headers: Some({"Content-Type": ["application/json"]}), body: Missing )
2024-04-12T11:35:41.367689Z DEBUG tokio-runtime-worker pact_matching:      body: ''
2024-04-12T11:35:41.367691Z DEBUG tokio-runtime-worker pact_matching:      matching_rules: MatchingRules { rules: {HEADER: MatchingRuleCategory { name: HEADER, rules: {} }, PATH: MatchingRuleCategory { name: PATH, rules: {} }} }
2024-04-12T11:35:41.367694Z DEBUG tokio-runtime-worker pact_matching:      generators: Generators { categories: {} }
2024-04-12T11:35:41.369183Z DEBUG tokio-runtime-worker pact_matching::matchers: String -> String: comparing '/123e4567-e89b-12d3-a456-426614174000/feedback/' to '/123e4567-e89b-12d3-a456-426614174000/feedback/' ==> true cascaded=false matcher=Equality
2024-04-12T11:35:41.369684Z DEBUG tokio-runtime-worker pact_matching: expected content type = 'application/json', actual content type = '*/*'
2024-04-12T11:35:41.369872Z DEBUG tokio-runtime-worker pact_matching: content type header matcher = 'RuleList { rules: [], rule_logic: And, cascaded: false }'
2024-04-12T11:35:41.370505Z DEBUG tokio-runtime-worker pact_matching: --> Mismatches: [HeaderMismatch { key: "Content-Type", expected: "\"application/json\"", actual: "", mismatch: "Expected a header 'Content-Type' but was missing" }]
2024-04-12T11:35:41.370679Z DEBUG tokio-runtime-worker pact_mock_server::hyper_server: Request did not match: Request did not match - HTTP Request ( method: POST, path: /123e4567-e89b-12d3-a456-426614174000/feedback/, query: None, headers: Some({"Content-Type": ["application/json"]}), body: Missing )    0) Expected a header 'Content-Type' but was missing
2024-04-12T11:35:41.370914Z DEBUG tokio-runtime-worker hyper::proto::h1::io: flushed 861 bytes
2024-04-12T11:35:41.381329Z DEBUG ThreadId(01) pact_matching::metrics: Could not get the tokio runtime, will not send metrics - there is no reactor running, must be called from the context of a Tokio 1.x runtime
2024-04-12T11:35:41.381350Z DEBUG ThreadId(01) pact_mock_server::server_manager: Shutting down mock server with ID 40bd34e6-8e00-4713-bec7-f03f9694aed9 - MockServerMetrics { requests: 1, requests_by_path: {"/123e4567-e89b-12d3-a456-426614174000/feedback/": 1} }
2024-04-12T11:35:41.381360Z DEBUG ThreadId(01) pact_mock_server::mock_server: Mock server 40bd34e6-8e00-4713-bec7-f03f9694aed9 shutdown - MockServerMetrics { requests: 1, requests_by_path: {"/123e4567-e89b-12d3-a456-426614174000/feedback/": 1} }
2024-04-12T11:35:41.381426Z DEBUG tokio-runtime-worker hyper::server::shutdown: signal received, starting graceful shutdown
2024-04-12T11:35:41.382144Z DEBUG ThreadId(01) pact_ffi::plugins: pact_ffi::plugins::pactffi_cleanup_plugins FFI function invoked
[12:35:41.383] ERROR (67840): pact@12.4.0: Test failed for the following reasons:

  Mock server failed with the following mismatches:

        0) The following request was incorrect: 

                POST /123e4567-e89b-12d3-a456-426614174000/feedback/
 FAIL  pact/feedback/create-feedback.test.ts
  Creating new feedback
    ✕ should create feedback (36 ms)

  ● Creating new feedback › should create feedback

    AxiosError: Request failed with status code 500

      at settle (node_modules/axios/lib/core/settle.js:19:12)
      at XMLHttpRequest.onloadend (node_modules/axios/lib/adapters/xhr.js:111:7)
      at XMLHttpRequest.invokeTheCallbackFunction (node_modules/jsdom/lib/jsdom/living/generated/EventHandlerNonNull.js:14:28)
      at XMLHttpRequest.<anonymous> (node_modules/jsdom/lib/jsdom/living/helpers/create-event-accessor.js:35:32)
      at innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:350:25)
      at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:286:3)
      at XMLHttpRequestImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:233:9)
      at fireAnEvent (node_modules/jsdom/lib/jsdom/living/helpers/events.js:18:36)
      at Request.<anonymous> (node_modules/jsdom/lib/jsdom/living/xhr/XMLHttpRequest-impl.js:891:5)
      at IncomingMessage.<anonymous> (node_modules/jsdom/lib/jsdom/living/helpers/http-request.js:230:42)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        1.222 s
m
I'm confused. Obviously you need to return or await the promise, which is why the pact isn't written in the first output. If the test fails, it won't write the pact either. You need to fix the test
The content type header is missing it seems from your client code
s
Thanks and sorry for that misunderstanding. All working now since the content type headers now match (should have been
"Content-Length": 0
anyway) 🙏
👍 1