Giter Site home page Giter Site logo

pact-foundation / pact-ruby Goto Github PK

View Code? Open in Web Editor NEW
2.2K 71.0 215.0 2.99 MB

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.

Home Page: https://pact.io

License: MIT License

Ruby 99.25% HTML 0.39% Shell 0.36%
hacktoberfest contract-testing smartbear-supported

pact-ruby's Issues

Change the request and response validation to use paths mapped to matchers

The current validation of the requests and response bodies is by comparison of the whole expected body. It does allow more to be in the actual body, but it is awkward when the bodies get large.

One idea id to allow paths to be mapped to a matcher. This would work in a XPath or JSON Path style. That way you can have a number of paths to execute the matcher against.

Pact::Term displays incorrectly in pact:verify output in 1.1.0.rc1

It should show the regular expression, not the json.

     Failure/Error: expect(response_body).to match_term expected_response_body
       {
         "_links": {
           "expected": {
             "self": {
               "href": {
                 "json_class": "Pact::Term",
                 "data": {
                   "generate": "http://localhost:1234/pacticipants/Condor/versions/1.3.0/tags/prod",
                   "matcher": {
                     "json_class": "Regexp",
                     "o": 0,
                     "s": "http://.*/pacticipants/Condor/versions/1.3.0/tags/prod"
                   }
                 }
               }
             }
           },
           "actual": "<key not found>"
         }
       }

Allow rspec methods to be used within provider state blocks

I'd like to be able to use the new RSpec syntax while setting up provider states.

For example:

provider_state "some state exists" do
  set_up do
    allow(Foo).to receive(:bar).and_return('baz')
  end
end

The current workaround for this is simply to use the older deprecated RSpec syntax.

provider_state "some state exists" do
  set_up do
    Foo.stub(:bar).and_return('baz')
  end
end

Support hashes for query param matching

I currently have a requirement to match a request with three query string parameters and at the moment the only way I can do this is to match the whole query string with the parameters in the "correct order" as per what is actually sent:

  describe "fetching updated agencies" do
    before do
      cp_services
        .given("an updated agency")
        .upon_receiving("a request for updated agencies")
        .with( method: :get, path: '/services/agencies', query: "updated_from=#{updated_from}&per_page=#{per_page}&api_key=#{api_key}" )

What I'd like to do is something like this:

  describe "fetching updated agencies" do
    before do
      cp_services
        .given("an updated agency")
        .upon_receiving("a request for updated agencies")
        .with( method: :get, path: '/services/agencies', query: { updated_from: updated_from, per_page: per_page, api_key: api_key } )

We can already do this sort of thing with HTTP headers so it would only make sense to make them work the same way

Message for duplicate interaction should specify that the headers/body/path are differerent

RuntimeError:
       Interaction with same description (a request retrieve a committed revenue sync) and provider state (a committed-revenue-sync exists with ID 123) already exists

Duplicate description/provider state is allowed so long as the entire interaction itself is identical.

Suggested new message:

An interaction with same description (a request retrieve a committed revenue sync) and provider state (a committed-revenue-sync exists with ID 123) has already been used, however, its has different request and/or response details. Please use a new description or provider state.

Duplicate detection failing with SomethingLike

I mentioned on the mailing list that setting up an identical second interaction was being rejected when it contained a Pact::SomethingLike, but not when it contained a Pact::Term.

This is the track the issue.

I have not yet reproduced it on a small example, however, I have just noticed that in the json pact file, the Pact::SomethingLike is serialised to "amount": "#Pact::SomethingLike:0x00000002b10d58"
whereas the Pact::Term is correctly serialised to
"myobject": {
"json_class": "Pact::Term",
"data": {
"generate": "123",
"matcher": {
"json_class": "Regexp",
"o": 0,
"s": "\d+"
}
}
},

In my existing case, this is in the response body, a few level down in a hash, along the lines of:
body: {
data: {
embeded_data: {
name: Pact::Term(...)
}
}
info: {
amount: Pact::SomethingLike("20.00")
}
}

Maybe something is going wrong with a serialisation of Pact::SomethingLike when it's embedded a few level down in a hash.

Create pact init

Submit PRs to: https://github.com/bethesque/pact-init-consumer

pact-init-consumer --consumer "My Consumer" --provider "My Provider" should create
spec/service_providers/pact_helper.rb

require 'pact/consumer/rspec'

Pact.service_consumer 'My Consumer' do
  has_pact_with 'My Provider' do
    mock_service :my_provider do
      port 1234
    end
  end
end

--consumer and --provider should be optional, and if no values are given use "My Consumer" and "My Provider".

Submit PRs to: https://github.com/bethesque/pact-init-provider
pact-init-provider --provider "My Provider" --consumer "My Consumer" should create
spec/service_consumers/pact_helper.rb

require 'pact/provider/rspec'
require "service_consumers/provider_states_for_my_consumer"

Pact.service_provider 'My Provider' do
  honours_pact_with 'My Consumer' do
    pact_uri ''
  end
end

spec/service_consumers/provider_states_for_my_consumer.rb

Pact.provider_states_for 'My Consumer' do
  provider_state 'there is a thing' do
    set_up do
      # Set up the provider state here (eg. insert record into a database)
    end
  end
end

Absolute URLs in responses

Hey folks,

We've got a server here which is generating a HAL response with absolute URLs. We're hitting a bit of a chicken and the egg problem, and I'm wondering if anyone has any suggestions (or if we're just doing something stupid).

  • When running the specs with the mock server, the server is running on localhost:1234. The server uses req.host to generate absolute urls, which results in a HAL response containing http://localhost:1234/v1/blah. These urls are recorded in the pact.
  • When verifying the pact, the requests are made with a Host header of example.org which obviously causes the server to respond with http://example.org/v1/blah, violating the pact.

I've tried not using req.host to generate the URL and instead making it a config setting for the app; however, the problem still exists that the mock server needs to listen on localhost:1234.

Ultimately, there always seems to be a mismatch between the hostname of the mock server, and the server the verification is being run against.

Any suggestions? Am I missing something obvious here?

Separate pact-server & pact

This would reduce the code size, making it much easier to identify e.g. concurrency bugs in the pact server implementation.

CSV differ

Hi Beth,

I've created a CSV differ for pact.
It doesn't have tests yet and uses cucumber tables for diffing (which seems a little awkward), but it works in manual tests on an adapted example.
Maybe you can have a look if this goes in the right direction.
I don't know how much time I can spend on this, but hopefully get to write some basic tests at least.

Best
Martin

Set order of interactions in pact file

When rspec runs with random order, the interactions are added to the pact file in the random order, and hence, the pact file changes significantly each time, and it is hard to see what the actual genuine changes are. Allow the order of the interactions to be written consistently.

Support other body types than JSON

Currently Pact assumes everything is JSON.

We need to add a may to transform different mime types into something that can be compared. Initially only JSON and XML need be supported until someone finds a need for another format

Display request diffs in after hook for consumer

Current message

An error occurred in an after hook
  RuntimeError: Actual interactions do not match expected interactions for mock XXX.

Incorrect requests:
    POST /xxx (request body did not match)

See log/xxx_mock_service.log for details.

Showing diffs here would be easier than traipsing through logs.

Require a way to validate a pact against a running server

Not all apps are Rack apps. Sometimes we have integration points with servers outside our control.

We should allow the Pact verification to hit a running server instead of starting up a Rack app.

Two ideas:
Maybe the Pact.service_provider configuration could have a URL configuration instead of an app?

Pact.service_provider "Horrific Monolith" do
    base_url "http://blah"

   honours_pact_with ...
end

Or maybe just a rake task, seeing as you probably won't have an actual ruby project to run it in.

Pact::RunningAppVerificationTask.new do | task |
  task.pact_uri = "./spec/pacts/my-consumer_horrific_monolith.json"
  task.app_base_url = "http://blah"
end

Running pact with existing contact

Ok following my twitter conversation that is probably better place to have proper discussion.
The scenario I have is the following

  1. I generate contracts based on my consumer/service_providers/service_spec.rb
  2. I would like to be able to use generated contracts to run set of tests(JS) using pact as replacement for real service. I figured out how to make pact run but it does not load any interactions.
    I have already generated the contract why can't we just add an option --contract so that server loads interactions from contract. They are generated from expected interactions so there should be a way to get expected interaction back from them.

Example of how TW does something similar -> https://github.com/thoughtworks/pacto#pacto-server-non-ruby-usage
As extra benefit that way pact can be used with any language at least to perform stubbing

Authentication tokens/step in pact.

So at the moment we are having to modify the pact.json files before running pact. This is for inserting authentication tokens with expiry in about 2 hours into the pacts.

pacts = File.join(File.dirname(File.expand_path(__FILE__)), '../src/test/resources/pacts/*.json')
Dir.glob(pacts).each do |f|
  text = File.read(f)
  output_of_gsub = text.gsub(/\"Authorization\"\s*:\s*\".+\"/) { "\"Authorization\": \"ioof-token #{token}\"" }
  File.open(f, "w") { |file| file.puts output_of_gsub }
end

It would be good to be able to nicely insert/modify headers of the request before they are sent without modifying the pact files.

Cheers,

For HAL responses, should pact mock service url "localhost:1234" be displayed in generated documentation?

When using a Pact::Term.new(generate: "http://localhost:1234/some-path", matcher: %r{http://.*/some-path})
Or should it be replaced with example.org? Or the regexp?

{
  "status": 200,
  "headers": {
    "Content-Type": "application/hal+json"
  },
  "body": {
    "_links": {
      "some-resource": {
        "href": "http://localhost:1234/some-resource"
      }
    }
  }
}

or

{
  "status": 200,
  "headers": {
    "Content-Type": "application/hal+json"
  },
  "body": {
    "_links": {
      "some-resource": {
        "href": "http://example.org/some-resource"
      }
    }
  }
}

or

{
  "status": 200,
  "headers": {
    "Content-Type": "application/hal+json"
  },
  "body": {
    "_links": {
      "some-resource": {
        "href": "http:\/\/.*/some-resource"
      }
    }
  }
}

Thoughts:
Regular expressions can be hard to read, example data is more meaningful, especially for something like a timestamp.

Pact::Terms are visible in the generated docs

"startDate": {
        "json_class": "Pact::Term",
        "data": {
          "generate": "2013-10-01T10:00:00.000Z",
          "matcher": {"json_class":"Regexp","o":0,"s":"\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z"}
        }
      }

It should show the example value.

Headers are modified when they shouldn't be

When using custom headers (Blah-Blah-Blah) all dashes are re-written as underscores (Blah_Blah_Blah).

Consumer tests correctly validate against dashes in the request, but when they're replayed back against the provider the headers get changed. Either the consumer tests should rewrite the headers to use underscores or the provider side shouldn't change the request. As it stands currently tests on one side will pass and the other will fail even though the specification is correct.

Add warning when no expectations are made of the response body for a post/put/patch

Each interaction is tested in isolation, meaning you can't do a PUT/POST/PATCH, and then follow it with a GET to ensure that the values you sent were actually read successfully by the provider. If you send a lastname instead of a surname field, a provider will most likely ignore the misnamed field, and return a 200, failing to alert you to the fact that your lastname has gone to the big /dev/null in the sky.

The code should warn you when a POST/PUT/PATCH request is defined, with a non-empty body, that does not make any expectations about the response.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.