Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request validation fails after upgrade to v12 #1106

Open
4 of 5 tasks
pieter-stek opened this issue Jul 27, 2023 · 6 comments
Open
4 of 5 tasks

Request validation fails after upgrade to v12 #1106

pieter-stek opened this issue Jul 27, 2023 · 6 comments
Labels
bug Indicates an unexpected problem or unintended behavior smartbear-supported SmartBear engineering team will support this issue. See https://docs.pact.io/help/smartbear triage This issue is yet to be triaged by a maintainer upstream Indicates that an issue relates to an upstream problem (such as in pact-reference)

Comments

@pieter-stek
Copy link

pieter-stek commented Jul 27, 2023

Software versions

  • OS: Windows 11
  • Consumer Pact library: PactJS 12.1.0
  • Provider Pact library: au.com.dius.pact.provider:junit5:4.6.1
  • Node Version: 16.18.0

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

I updated PactJS from 11.0.2 to 12.1.0 and without any other changes the contract test started failing.

Actual behaviour

Mock server failed with the following mismatches:

        0) The following request was incorrect:

                PUT /picking-capacity/capacities/1

                      'Content-Type': Expected value 'application/json' at index 1 but was missing

Steps to reproduce

import { PactV3 } from "@pact-foundation/pact";
import axios from "axios";
import path from "path";

const provider = new PactV3({
    port: 8082,
    dir: path.resolve(process.cwd(), "pacts"),
    cors: true,
    pactfileWriteMode: "update",
    consumer: "application",
    provider: "applicationApi",
    logLevel: "debug",
  });
  
  describe("serviceUnderTest", () => {
  
    it("should validate PUT request", async () => {
      await provider.addInteraction({
        states: [{ description: "resource exists" }],
        uponReceiving: "update",
        withRequest: {
          method: "PUT",
          path: "/resource/1",
          headers: {
            "Content-Type": "application/json",
          },
          body: {},
        },
        willRespondWith: {
          status: 200,
          headers: {
            "Content-Type": "application/json",
          },
          body: {},
        },
      });
  
      await provider.executeTest(async () => {
        await axios.put("http://localhost:8082/resource/1", {});
      });
    });
  })

Relevant log files

pact-debug.log

@pieter-stek pieter-stek added bug Indicates an unexpected problem or unintended behavior triage This issue is yet to be triaged by a maintainer labels Jul 27, 2023
@mefellows
Copy link
Member

It looks like the core is expecting two headers, as can be seen by it expecting it at index 1 (not index 0, for 1 value for content-type header)

It received the right request:

2023-07-27T12:05:59.358269Z DEBUG tokio-runtime-worker pact_mock_server::hyper_server: Creating pact request from hyper request
2023-07-27T12:05:59.358285Z DEBUG tokio-runtime-worker pact_mock_server::hyper_server: Extracting query from uri /resource/1
2023-07-27T12:05:59.358364Z  INFO tokio-runtime-worker pact_mock_server::hyper_server: Received request PUT /resource/1
2023-07-27T12:05:59.358373Z DEBUG tokio-runtime-worker pact_mock_server::hyper_server:
      ----------------------------------------------------------------------------------------
       method: PUT
       path: /resource/1
       query: None
       headers: Some({"host": ["localhost:8082"], "user-agent": ["axios/1.4.0"], "connection": ["keep-alive"], "accept": ["application/json", "text/plain", "*/*"], "content-length": ["8"], "content-type": ["application/json"], "accept-encoding": ["gzip", "compress", "deflate", "br"]})
       body: Present(8 bytes, application/json) '{"id":1}'
      ----------------------------------------------------------------------------------------

But you can see it's expecting two:

2023-07-27T12:04:10.904720Z  INFO tokio-runtime-worker pact_matching: comparing to expected HTTP Request ( method: PUT, path: /resource/1, query: None, headers: Some({"Content-Type": ["application/json", "application/json"]}), body: Present(8 bytes, application/json) )

It works in v0.4.5 of libpact_ffi so something between that and v0.4.6 is causing it. I'll continue to investigate.

@mefellows mefellows added smartbear-supported SmartBear engineering team will support this issue. See https://docs.pact.io/help/smartbear upstream Indicates that an issue relates to an upstream problem (such as in pact-reference) labels Jul 27, 2023
@mefellows
Copy link
Member

I've traced it to this commit. I'll raise this issue upstream to track it, thanks for reporting.

@github-actions
Copy link

👋 Hi! The 'smartbear-supported' label has just been added to this issue, which will create an internal tracking ticket in PactFlow's Jira (PACT-1219). We will use this to prioritise and assign a team member to this task. All activity will be public on this ticket. For now, sit tight and we'll update this ticket once we have more information on the next steps.

See our documentation for more information.

@mefellows
Copy link
Member

I should say, in this case, I think because the Content-Type is a special header and it's defaulting to application/json (possibly why it's expecting two header values) you can simply omit that header from your expectations and things will work. It doesn't seem to affect other headers, which strengthens that theory. This test for example should work:

import { PactV3 } from '@pact-foundation/pact';
import axios from 'axios';
import path from 'path';

const provider = new PactV3({
  port: 8082,
  dir: path.resolve(process.cwd(), 'pacts'),
  cors: true,
  consumer: 'application',
  provider: 'applicationApi',
  logLevel: 'debug',
});

describe('serviceUnderTest', () => {
  it('should validate PUT request', async () => {
    await provider.addInteraction({
      states: [{ description: 'resource exists' }],
      uponReceiving: 'update',
      withRequest: {
        method: 'PUT',
        path: '/resource/1',
        headers: {
          Foo: 'bar',
        },
        body: {
          id: 1,
        },
      },
      willRespondWith: {
        status: 200,
        headers: {
          'Content-Type': 'application/json',
        },
        body: {
          id: 1,
        },
      },
    });

    await provider.executeTest(async () => {
      await axios.put(
        'http://localhost:8082/resource/1',
        {
          id: 1,
        },
        {
          headers: {
            Foo: 'bar',
          },
        }
      );
    });
  });
});

@pieter-stek
Copy link
Author

I can confirm that if I omit the Content-Type header from the request expectation, the test succeeds. The corresponding provider tests also still succeed if I do that.

@mefellows
Copy link
Member

Thanks for confirming.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Indicates an unexpected problem or unintended behavior smartbear-supported SmartBear engineering team will support this issue. See https://docs.pact.io/help/smartbear triage This issue is yet to be triaged by a maintainer upstream Indicates that an issue relates to an upstream problem (such as in pact-reference)
Projects
None yet
Development

No branches or pull requests

2 participants