pact-foundation / pact-js

JS version of Pact. Pact is a contract testing framework for HTTP APIs and non-HTTP asynchronous messaging systems.
https://pact.io
Other
1.63k stars 348 forks source link

Question: Having Pact-JS fill the matchingRules object in Pact json files #615

Closed Kampfmoehre closed 3 years ago

Kampfmoehre commented 3 years ago

Is there a way to have Pact JS fill in the matchingRules object in Pact json files and have the content object be the example body of the message?

I am trying to set up Pact between a NodeJS AMQP consumer and a .NET provider. Since the official Pact.net implementation does not support Message Pacts I use ComPact. I have successfully make them work together with plain objects however I can not get it to work with matchers. It is expecting the rules in the matchingRules object and that each contents object in messages has the plain example object.

Is there a way to make Pact JS write the matching rules into the matchingRules object instead of the contents object? Here is an example from the official Pact Specification on how the matchingRules object should look like.

I have tried the latest 9x version as well as the 10.0.0-beta.31 version.

TimothyJones commented 3 years ago

It’s hard to answer this without seeing your code, but you shouldn’t need to depend on a specific output format in the pact file. You can generally consider the pact file opaque.

You can match on the types of each element in a body by using something like this:

content: Matchers.like({ /* your example body here */ }) 

Note that this just matches on the raw types, so it is usually better practice to be more explicit.

TimothyJones commented 3 years ago

If this doesn’t answer your question, please post your code and we’ll take a look.

Kampfmoehre commented 3 years ago

To clarify, I do not mean any code but the resulting pact json file that gets uploaded to a Pact Broker or can be used to verify the provider later. The code I use is just like the example code from the Readme, a message consumer pact that results in a JSON string that I can pass to my AMQP consumer function in JS. The problem is to use the resulting Pact JSON file on the provider side (using the .NET implementation ComPact). But since I can see JSON like the following in the official Pact specification repo I don't think it is a problem with the .NET library.

In the end I just want to have something like this in the generated Pact file and ask if it is possible to achieve this with PactJS:

{
  "messages": [
    {
      "description": "Published credit data",
      "providerState": "or maybe 'scenario'? not sure about this",
      "contents": {
        "foo": "bar"
      },
      "metaData": {
        "contentType": "application/json"
      }
    }
  ],
  "matchingRules": {
    "body": {
      "$.animals": { "matchers": [{"min": 1, "match": "type"}] },
      "$.animals[*].*": { "matchers": [{"match": "type"}] },
      "$.animals[*].children": { "matchers": [{"min": 1}] },
      "$.animals[*].children[*].*": { "matchers": [{"match": "type"}] },
      "$.animals[*].children[*].*.name": { "matchers": [{"match": "equality"}] }
    }
  }
}

Note: I just copied examples from the official spec that do not match. They are just for visualizing what I am trying to achieve.

TimothyJones commented 3 years ago

The part of the spec you linked above is about changing the default behaviour of cascading matches. It doesn’t say (and the format doesn’t require) that all fields be explicitly named to match on type.

Either way, it is still the case that you shouldn’t need to look inside the pact file or specify a specific serialisation.

If the pact file generated by pact-js isn’t understood correctly by ComPact, then I suspect ComPact is not compliant.

Kampfmoehre commented 3 years ago

Okay thank you for clarification, I will then see if ComPact can work with what I have.