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

Generating path with fromProviderState and matching path using Regex #1089

Open
3 of 5 tasks
agross opened this issue May 9, 2023 · 5 comments
Open
3 of 5 tasks

Generating path with fromProviderState and matching path using Regex #1089

agross opened this issue May 9, 2023 · 5 comments
Labels
triage This issue is yet to be triaged by a maintainer

Comments

@agross
Copy link

agross commented May 9, 2023

Software versions

  • OS: macOS 13.1
  • Consumer Pact library: 11.0.2
  • Provider Pact library: unrelated for this issue
  • Node Version: v18.16.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

In my project we have a situation where a URL path contains a provider state-generated string (buildingId):

/plans/buildings/${buildingId}/floors

We also use the Pact stub server for client-side development and need to match paths received by the stub server against this URL pattern.

A teammate defined the interaction like this (excerpt):

.withRequest({
          method: "GET",
          path: fromProviderState(
            '/plans/buildings/${buildingId}/floors',
            Matchers.regex(
              /^\/plans\/buildings\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/floors$/,
              '/plans/buildings/8e824a37-408c-4341-9c98-38ec9a3953f3/floors'
            )
          ) as Matchers.Path)

This left us with this Pact JSON file (excerpt):

{
      "providerStates": [
        {
          "name": "building with floors",
          "params": {
            "buildingId": "b0be1c67-51e7-4657-8a63-196f2da18e73"
          }
        }
      ],
      "request": {
        "generators": {
          "path": {
            "expression": "/plans/buildings/${buildingId}/floors",
            "type": "ProviderState"
          }
        },
        "matchingRules": {
          "path": {
            "combine": "AND",
            "matchers": [
              {
                "match": "type"
              }
            ]
          }
        },
        "method": "GET",
        "path": "{\"pact:matcher:type\":\"regex\",\"regex\":\"^\\\\/plans\\\\/buildings\\\\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\\\/floors$\",\"value\":\"/plans/buildings/8e824a37-408c-4341-9c98-38ec9a3953f3/floors\"}"
      },

...which contains the string representation of the Regex matcher above as the example path. The generator element looks fine and the provider can be verified with a dynamic provider-generated buildingId.

What we rather want is a matchingRules entry that adheres to the URL pattern for the /plans/buildings/${buildingId}/floors path. The JSON above would match any string, essentially capturing all requests.

The following JSON contains the path matcher we wish for was generated from this piece:

        .withRequest({
          method: "GET",
          path: Matchers.regex(
            /^\/plans\/buildings\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/floors$/,
            "/plans/buildings/8e824a37-408c-4341-9c98-38ec9a3953f3/floors"
          ),
{
  "description": "A request for loading available floors",
  "providerStates": [
    {
      "name": "building with floors",
      "params": {
        "buildingId": "b0be1c67-51e7-4657-8a63-196f2da18e73",
        "stub": true
      }
    }
  ],
  "request": {
    "matchingRules": {
      "path": {
        "combine": "AND",
        "matchers": [
          {
            "match": "regex",
            "regex": "^\\/plans\\/buildings\\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\/floors$"
          }
        ]
      }
    },
    "method": "GET",
    "path": "/plans/buildings/8e824a37-408c-4341-9c98-38ec9a3953f3/floors"
  }

Is this possible? If yes, how?

I imagine this URL pattern is not uncommon, but I could not find any examples. The only Stack Overflow question I could find has been kind of inactive with no solution provided.

@agross agross added the bug Indicates an unexpected problem or unintended behavior label May 9, 2023
@mefellows mefellows added enhancement and removed bug Indicates an unexpected problem or unintended behavior labels May 10, 2023
@mefellows
Copy link
Member

This is a @uglyog question I think. I don't think we currently support this do we?

@rholshausen
Copy link

You can't use a regex matcher with the fromProviderState function, it expects two parameters, an expression to replace and an example value.

From the Pact file, you can see it is just taking the second parameter and calling toString() on it

"path": "{"pact:matcher:type":"regex","regex":"^\\/plans\\/buildings\\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\/floors$","value":"/plans/buildings/8e824a37-408c-4341-9c98-38ec9a3953f3/floors"}"

@agross
Copy link
Author

agross commented Jun 26, 2023

You can't use a regex matcher with the fromProviderState function

Yes, this is what we found and the reason this issue exists.

Are such URL patterns uncommon with Pact users?

@rholshausen
Copy link

This is the first time I've seen anyone needing to do this.

To support this, the regex matcher will need to be defined after the fromProviderState function is done, but I don't think the current JS DSL has a way of doing this.

@mefellows
Copy link
Member

It's not that the URL pattern is uncommon, it's the specific set of features needed. I'll have to think about how we can support it, perhaps in a V4 interface.

@mefellows mefellows added triage This issue is yet to be triaged by a maintainer and removed Triage labels Jul 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
triage This issue is yet to be triaged by a maintainer
Projects
None yet
Development

No branches or pull requests

3 participants