pact-foundation / docs.pact.io

Pact documentation website
17 stars 97 forks source link

Update matchers page to have examples from every language #88

Open bethesque opened 3 years ago

bethesque commented 3 years ago

https://docs.pact.io/getting_started/matching

bethesque commented 2 years ago

Good for anyone doing hacktober! Doesn't have to be all the examples, just happy to take them one at a time.

YOU54F commented 2 years ago

This looks promising as a starter for 10

https://docusaurus.io/docs/markdown-features/code-blocks#multi-language-support-code-blocks

Really digging what these guys are doing at the moment, came onto my radar the other day https://pusher.com/

Screenshot 2022-03-17 at 19 37 37

mefellows commented 2 years ago

Yeah those code gates look handy. From memory, they also have the ability to store a language preference, which stays with you throughout the docs. This could mean we could provide a general guide that's applicable to all languages, but have language specific code blocks to accompany them.

YOU54F commented 2 years ago

Pact matching features

Matcher types

method description
boolean Match a boolean value (using equality)
string Match a string value
integer Will match all numbers that are integers (both ints and longs)
decimal Will match all real numbers (floating point and decimal)
hexadecimal Will match all hexadecimal encoded strings
iso8601Date Will match string containing basic ISO8601 dates (e.g. 2016-01-01)
iso8601DateTime Will match string containing ISO 8601 formatted dates (e.g. 2015-08-06T16:53:10+01:00)
iso8601DateTimeWithMillis Will match string containing ISO 8601 formatted dates, enforcing millisecond precision (e.g. 2015-08-06T16:53:10.123+01:00)
rfc3339Timestamp Will match a string containing an RFC3339 formatted timestapm (e.g. Mon, 31 Oct 2016 15:21:41 -0400)
iso8601Time Will match string containing times (e.g. T22:44:30.652Z)
ipv4Address Will match string containing IP4 formatted address
ipv6Address Will match string containing IP6 formatted address
uuid Will match strings containing UUIDs
email Will match strings containing Email address

Matcher Links

Regular Expressions

Ruby

animal_service.given("an alligator named Mary exists").
  upon_receiving("a request for an alligator").
  with(
    method: "get",
    path: "/alligators/Mary",
    headers: {"Accept" => "application/json"}).
  will_respond_with(
    status: 200,
    headers: {"Content-Type" => "application/json"},
    body: {
      name: "Mary",
      dateOfBirth: Pact.term(
        generate: "02/11/2013",
        matcher: /\d{2}\/\d{2}\/\d{4}/)
    })

Java

service {
    uponReceiving('a request')
    withAttributes(method: 'get', path: '/')
    withBody {
      name(~/\w+/, 'harry')
      surname regexp(~/\w+/, 'larry')
      position regexp(~/staff|contractor/, 'staff')
      happy(true)
    }
}

Go

pact.
    AddInteraction().
    Given("User sally exists").
    UponReceiving("A request to login with user 'sally'").
    WithRequest(request{
      Method: "GET",
      Path:   term("/users/10", "/users/[0-9]+"),
    }).
    WillRespondWith(dsl.Response{
      Status:  200,
      Body:    dsl.Match(model.User{}),
      Headers: commonHeaders,
    })

JS

const { term } = pact
provider.addInteraction({
  state: "Has some animals",
  uponReceiving: "a request for an animal",
  withRequest: {
    method: "GET",
    path: "/animals/1",
  },
  willRespondWith: {
    status: 200,
    headers: {
      "Content-Type": "application/json; charset=utf-8",
    },
    body: {
      id: 100,
      name: "billy",
      gender: term({
        matcher: "F|M",
        generate: "F",
      }),
    },
  },
})

C++

this.pact
    .UponReceiving("a request to retrieve all events")
        .WithRequest(HttpMethod.Get, "/events")
        .WithHeader("Accept", "application/json")
    .WillRespond()
        .WithStatus(HttpStatusCode.OK)
        .WithHeader("Content-Type", "application/json; charset=utf-8")
        .WithJsonBody(Match.MinType(new
        {
            eventId = Match.Type("3E83A96B-2A0C-49B1-9959-26DF23F83AEB"),
            timestamp = Match.Type("2014-06-30T01:38:00.8518952"),
            eventType = Match.Regex("SearchView", "SearchView|DetailsView")
        }, 1));

python

from pact import Term
...
body = {
    'username': 'UserA',
    'last_modified': Term('\d+-\d+-\d+T\d+:\d+:\d+', '2016-12-15T20:16:01')
}

(pact
 .given('UserA exists and is not an administrator')
 .upon_receiving('a request for UserA')
 .with_request('get', '/users/UserA/info')
 .will_respond_with(200, body=body))
YOU54F commented 2 years ago

Ruby regex backslash escaping causing js pain again

https://pact-foundation.slack.com/archives/C9VBGLUM9/p1651866363050989

Lewiscowles1986 commented 9 months ago

Has this changed, because it does not reflect https://github.com/pact-foundation/pact-specification/tree/version-4#supported-generators and I can already see that causing confusion.

For example the date-time here has timezone information. While I can see that could be optional, it's not explicit which of the two sources should be canonical; which makes reviewing or understanding difficult. IMO both should be valid date-time signatures.