<#1107 Specifying Content-Type serializes Matcher ...
# pact-js-development
g
#1107 Specifying Content-Type serializes Matcher object Issue created by andreas-sundstrom Software versions Please provide at least OS and version of pact-js • OS: e.g. Windows 10 Enterprise 22H2 19045.3208 • Consumer Pact library: @pact-foundation/pact 12.1.0 • Node Version:
18.16.1
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 and have read the section on intermittent test failures ☑︎ 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 (see below) to illustrate the problem Expected behaviour Testing an api-client for an endpoint that returns a string I create a pact provider that responds with a body and an exact content-type. The matching should only ensure it's a string body, but the content-type header must be exact match:
Copy code
.willRespondWith({
              status: 200,
              headers: {
                'Content-Type': 'text/plain',
              },
              body: MatchersV3.string('07/14/2023 23:47:00'),
            })
I expect something like:
Copy code
"response": {
        "body": "07/14/2023 23:47:00",
        "headers": {
          "Content-Type": "text/plain"
        },
        "matchingRules": {
          "body": {
            "$": {
              "combine": "AND",
              "matchers": [
                {
                  "match": "type"
                }
              ]
            }
          }
        },
        "status": 200
Actual behaviour When providing a content-type header, the actual matcher is serialized to a json-string:
Copy code
"response": {
        "body": "{\"pact:matcher:type\":\"type\",\"value\":\"07/14/2023 23:47:00\"}",
        "headers": {
          "Content-Type": "text/plain"
        },
        "status": 200
      }
When not providing a content-type header the body is correct but the header is incorrect:
Copy code
"response": {
        "body": "07/14/2023 23:47:00",
        "headers": {
          "Content-Type": "application/json"
        },
        "matchingRules": {
          "body": {
            "$": {
              "combine": "AND",
              "matchers": [
                {
                  "match": "type"
                }
              ]
            }
          }
        },
        "status": 200
Steps to reproduce
Copy code
// Set up
const pactFileDir = './pacts/';
const consumerName = 'patientoversikt-client';
const providerName = 'patientoversikt-api';
const pactFilePath = `${pactFileDir}${consumerName}-${providerName}.json`;

const mockProvider = new PactV3({
  consumer: consumerName,
  logLevel: 'error',
  dir: pactFileDir,
  provider: providerName,
});

test('latest timestamp', async () => {
          // Arrange
          mockProvider
            .given('latest timestamp')
            .uponReceiving(
              'a request to get data with the most recent time stamp',
            )
            .withRequest({
              method: 'GET',
              path: `/api/v1/vhs/unapproved-care-events/get-latest-time-stamp-from-takecare`,
            })
            .willRespondWith({
              status: 200,
              headers: {
                'Content-Type': 'text/plain',
              },
              body: MatchersV3.string('07/14/2023 23:47:00'),
            });

          return mockProvider.executeTest(async mockService => {
            // Act
            const mockedApi = api(mockService.url);
            const timestamp =
              await mockedApi.fetchLatestTimestampFromTakeCare();

            // Assert - did we get the expected response
            if (timestamp !== undefined) {
              expect(timestamp.data).toEqual('07/14/2023 23:47:00');
            }
          });
        });
Generated pact-file (stub):
Copy code
{
  "description": "a request to get data with the most recent time stamp",
  "providerStates": [
    {
      "name": "latest timestamp"
    }
  ],
  "request": {
    "method": "GET",
    "path": "/api/v1/vhs/unapproved-care-events/get-latest-time-stamp-from-takecare"
  },
  "response": {
    "body": "{\"pact:matcher:type\":\"type\",\"value\":\"07/14/2023 23:47:00\"}",
    "headers": {
      "Content-Type": "text/plain"
    },
    "status": 200
  }
}
If removing the header in the response the body matching rule is correct but content-type is wrong:
Copy code
.willRespondWith({
              status: 200,
              body: MatchersV3.string('07/14/2023 23:47:00'),
            });
Copy code
"response": {
        "body": "07/14/2023 23:47:00",
        "headers": {
          "Content-Type": "application/json"
        },
        "matchingRules": {
          "body": {
            "$": {
              "combine": "AND",
              "matchers": [
                {
                  "match": "type"
                }
              ]
            }
          }
        },
        "status": 200
      }
Relevant log files Please ensure you set logging to
DEBUG
and attach any relevant log files here (or link to a gist).
``` [102442.638] INFO (12244): 0.4.6: pact native library successfully found, and the correct version 2023-07-28T082442.645840Z DEBUG ThreadId(01) pact_ffi:mock serverhandles parsed header value: Left("text/plain") 2023-07-28T082442.646751Z DEBUG ThreadId(01) pact_plugin_driver:catalogue manager Updated catalogue entries: core/transport/http core/transport/https 2023-07-28T082442.647031Z 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-07-28T082442.647208Z 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 src/api.test.ts 2023-07-28T082442.667398Z DEBUG tokio-runtime-worker hyper:protoh1io parsed 4 headers 2023-07-28T082442.667906Z DEBUG tokio-runtime-worker hyper:protoh1conn incoming body is empty 2023-07-28T082442.668277Z DEBUG tokio-runtime-worker pact_mock_server:hyper server Creating pact request from hyper request 2023-07-28T082442.668585Z DEBUG tokio-runtime-worker pact_mock_server:hyper server Extracting query from uri /api/v1/vhs/unapproved-care-events/get-latest-time-stamp-from-takecare 2023-07-28T082442.668987Z INFO tokio-runtime-worker pact_mock_server:hyper server Received request GET /api/v1/vhs/unapproved-care-events/get-latest-time-stamp-from-takecare 2023-07-28T082442.669319Z DEBUG tokio-runtime-worker pact_mock_server:hyper server ---------------------------------------------------------------------------------------- method: GET path: /api/v1/vhs/unapproved-care-events/get-latest-time-stamp-from-takecare query: None headers: Some({"user-agent": ["axios/0.26.1"], "accept": ["application/json", "text/plain", "*/*"], "connection": ["close"], "host": ["127.0.0.1:59990"]}) body: Empty -------------… pact-foundation/pact-js