pact-foundation / pact-net

.NET version of Pact. Enables consumer driven contract testing, providing a mock service and DSL for the consumer project, and interaction playback and verification for the service provider project.
https://pact.io
MIT License
842 stars 231 forks source link

Please support eachItem Matcher #463

Closed jvmlet closed 11 months ago

jvmlet commented 1 year ago

Please support eachItem matcher for collection attributes

mefellows commented 1 year ago

Can you please confirm exactly what you need? The matchers in V3 can be found here: https://github.com/pact-foundation/pact-specification/tree/version-3

jvmlet commented 1 year ago

What would be the c# api call to say that each item in response.attr1 should be string that matches some regex, assuming that response.attr1 is arrray of strings.

mefellows commented 1 year ago

I think this one: https://github.com/pact-foundation/pact-net/blob/master/src/PactNet.Abstractions/Matchers/MinMaxTypeMatcher.cs#L9

adamrodger commented 11 months ago

A test like this:

[Fact]
public async Task EachLikeRegexTest()
{
    this.pact
        .UponReceiving("an each like regex request")
            .WithRequest(HttpMethod.Post, "/api/orders/search")
            .WithJsonBody(new
             {
                 OrderIds = Match.MinType(Match.Regex("abc123", @"^[a-z0-9]+$"), 1)
             })
        .WillRespond()
            .WithStatus(HttpStatusCode.OK);
    // TODO: actually verify the response body

    await this.pact.VerifyAsync(async ctx =>
    {
        var client = new HttpClient { BaseAddress = ctx.MockServerUri };

        const string content = """
                               {
                                   "orderIds": ["abc123", "def456"]
                               }
                               """;

        var response = await client.PostAsync("/api/orders/search", new StringContent(content, Encoding.UTF8, "application/json"));

        response.EnsureSuccessStatusCode();
    });
}

would produce a response where each item in the string collection is checked against a regex:

"interactions": [
  {
    "description": "an each like regex request",
    "request": {
      "body": {
        "content": {
          "orderIds": [
            "abc123"
          ]
        },
        "contentType": "application/json",
      },
      "headers": {
        "Content-Type": [
          "application/json"
        ]
      },
      "matchingRules": {
        "body": {
          "$.orderIds": {
            "combine": "AND",
            "matchers": [
              {
                "match": "type",
                "min": 1
              }
            ]
          },
          "$.orderIds[*]": {
            "combine": "AND",
            "matchers": [
              {
                "match": "regex",
                "regex": "^[a-z0-9]+$"
              }
            ]
          }
        }
      },
      "method": "POST",
      "path": "/api/orders/search"
    },
    "response": {
      "status": 200
    },
    "type": "Synchronous/HTTP"
  }
]