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

Feature Request - Automatically replace path with provider state when using pathFromProviderState #441

Open
johnwilliams-12 opened this issue Jun 13, 2024 · 6 comments
Labels
enhancement Indicates new feature requests help wanted Indicates that a maintainer wants help on an issue or pull request

Comments

@johnwilliams-12
Copy link

Expectation: When using pathFromProviderState in a consumer pact test, I expect that the path param in the created pact is replaced by the supplied provider state. That is, when verifying a consumer pact using the standalone pact-verifier (version 1.1.1), I would expect the request that is sent to contain the supplied provider state, but instead the request path of the “example” parameter in the pathFromProviderState property is used.

Consider the following example:

@Pact(provider = "SomeProvider", consumer = "SomeConsumer")
public RequestResponsePact samplePact(PactDslWithProvider builder) {
    var responseHeaders = new HashMap<String, String>();
    responseHeaders.put("Content-Type", "application/json");

    PactDslJsonBody responseBody = new PactDslJsonBody()
            .stringValue("name", "John");

    return builder
            .given("User exists", "name", "John")
            .uponReceiving("Hello John")
            .pathFromProviderState("/api/hello/{name}", "/api/hello/James")
            .method("GET")
            .willRespondWith()
            .status(200)
            .headers(responseHeaders)
            .body(responseBody)
            .toPact();
}

@Test
@PactTestFor(providerName = "SomeProvider", pactMethod = "samplePact")
public void testForSamplePact(MockServer mockServer) throws ExecutionException, InterruptedException {
    HelloApi.HelloName request = HelloApi.HelloName
            .builder()
            .name("James")
            .build();

    testClient.apply(request).get().getResponse();
}

Executing this test creates below pact.

{
  "consumer": {
    "name": "SomeConsumer"
  },
  "interactions": [
    {
      "description": "Hello John",
      "providerStates": [
        {
          "name": "User exists",
          "params": {
            "name": "John"
          }
        }
      ],
      "request": {
        "generators": {
          "path": {
            "dataType": "STRING",
            "expression": "/api/hello/{name}",
            "type": "ProviderState"
          }
        },
        "method": "GET",
        "path": "/api/hello/James"
      },
      "response": {
        "body": {
          "name": "John"
        },
        "headers": {
          "Content-Type": "application/json"
        },
        "status": 200
      }
    }
  ],
  "metadata": {
    "pact-jvm": {
      "version": "4.6.7"
    },
    "pactSpecification": {
      "version": "3.0.0"
    }
  },
  "provider": {
    "name": "SomeProvider"
  }
}

When using the pact-verifier the request that is sent is always equal to the path in the pact file (i.e. /api/hello/James) . I would expect/hope that the supplied provider state would actually be applied to the request when the pact-verifier sends the request. In this case the request would then be /api/hello/John. In theory, I could obtain the provider state from the request made to the —state-change-url. This way I could replace the path of the request with the provider state, but I would expect that that would happen out of the box. Is it a deliberate choice that this doesn’t happen? If not, could this be added to the pact-verifier in a future version?

@YOU54F
Copy link
Member

YOU54F commented Jun 14, 2024

pact-jvm does not use the pact-reference repo, which is used to build the rust core

pact-jvm has its own implementation

https://docs.pact.io/diagrams/ecosystem#java-goldberg-machine

does this work correctly with a pact-jvm provider?

@johnwilliams-12
Copy link
Author

I'm not exactly sure what you mean here. Are you referring to something like this: https://stackoverflow.com/a/63956890, where we use a provider test to overwrite the provided state? We are building a general/agnostic implementation in which we don't write any provider specific tests. So the only time we could make some replacements is when we retrieve the provider state from the state change url (right before verifying the pact using the pact-verifier).

Or are you saying that the functionality I'm expecting is available in the rust core but not in the pact-jvm since it has a different implementation? But this I don't fully get either as we only use pact-jvm to create the pact files and the verifier for verification. Would that mean that the verifier can't handle pacts created by pact-jvm?

@johnwilliams-12
Copy link
Author

To clarify the situation, the feature request is twofold:

  1. As described above, we would like to see that the pact-verifier uses the provider state parameters as provided in a consumer pact. Right now, this is not the case as the example path specified in the pathFromProviderState property is always used.
  2. Secondly, we would like to add the option that the provider could overwrite the given provider state parameters. This is of course possible when writing a provider test, but as specified above, we are creating a generic/agnostic implementation in which no provider specific tests are written as this mechanism should work for any provider. Still, it could be the case that the given provider state doesn't exist on the provider side, hence we need a mechanism to overwrite the given state. We could achieve this ourselves by overwriting the state retrieved from the --state-change-url, but, I think this should be a feature part of the pact-verifier to reach feature parity with a standard consumer/provider pact test.

@mefellows
Copy link
Member

If I understand the ask, I support both the idea of dynamic replacement of items that use provider state generators (item [1] in your summary) and dynamic provider state values supplied by the provider.

We would need to work out implementation details, presumably this would be an HTTP contract between the verifier and the API (and documented here: https://github.com/pact-foundation/pact-reference/tree/master/rust/pact_verifier_cli#state-change-requests)

@mefellows
Copy link
Member

@YOU54F @uglyog would also appreciate your thoughts.

@mefellows mefellows added help wanted Indicates that a maintainer wants help on an issue or pull request enhancement Indicates new feature requests labels Jul 4, 2024
@rholshausen rholshausen added bug Indicates an unexpected problem or unintended behavior enhancement Indicates new feature requests and removed enhancement Indicates new feature requests bug Indicates an unexpected problem or unintended behavior labels Jul 9, 2024
@rholshausen
Copy link
Contributor

Just a note, this expression "expression": "/api/hello/{name}", is not valid, it should have a $ (i.e. "expression": "/api/hello/${name}",)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Indicates new feature requests help wanted Indicates that a maintainer wants help on an issue or pull request
Projects
None yet
Development

No branches or pull requests

4 participants