pact 1.0.30 → 1.0.31
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.travis.yml +2 -2
- data/Gemfile.lock +0 -7
- data/README.md +50 -53
- data/Rakefile +1 -25
- data/documentation/Testing with pact.png +0 -0
- data/documentation/faq.md +45 -0
- data/documentation/raq.md +39 -0
- data/documentation/terminology.md +25 -0
- data/example/animal-service/Gemfile +4 -4
- data/example/animal-service/Gemfile.lock +20 -15
- data/example/animal-service/Rakefile +1 -1
- data/example/animal-service/config.ru +3 -0
- data/example/animal-service/db/animal_db.sqlite3 +0 -0
- data/example/animal-service/db/animals_db.sqlite3 +0 -0
- data/example/animal-service/lib/animal_service/animal_repository.rb +16 -0
- data/example/animal-service/lib/animal_service/api.rb +28 -0
- data/example/animal-service/lib/animal_service/db.rb +5 -0
- data/example/animal-service/spec/service_consumers/pact_helper.rb +10 -16
- data/example/animal-service/spec/service_consumers/provider_states_for_zoo_app.rb +13 -3
- data/example/zoo-app/Gemfile +0 -2
- data/example/zoo-app/Gemfile.lock +7 -8
- data/example/zoo-app/lib/zoo_app/animal_service_client.rb +8 -4
- data/example/zoo-app/spec/pacts/zoo_app-animal_service.json +18 -64
- data/example/zoo-app/spec/service_providers/animal_service_client_spec.rb +76 -0
- data/example/zoo-app/spec/service_providers/pact_helper.rb +1 -1
- data/example/zoo-app/spec/spec_helper.rb +0 -2
- data/lib/pact/app.rb +4 -2
- data/lib/pact/consumer/configuration.rb +2 -2
- data/lib/pact/consumer/consumer_contract_builder.rb +2 -1
- data/lib/pact/consumer/interactions_filter.rb +7 -0
- data/lib/pact/consumer/mock_service/app.rb +7 -2
- data/lib/pact/consumer/mock_service/interaction_mismatch.rb +6 -1
- data/lib/pact/consumer/mock_service/interaction_post.rb +1 -1
- data/lib/pact/consumer/mock_service/rack_request_helper.rb +1 -1
- data/lib/pact/consumer/rspec.rb +9 -15
- data/lib/pact/consumer/rspec/full_example_description.rb +28 -0
- data/lib/pact/consumer/spec_hooks.rb +31 -0
- data/lib/pact/consumer_contract/consumer_contract.rb +2 -31
- data/lib/pact/consumer_contract/file_name.rb +13 -0
- data/lib/pact/consumer_contract/pact_file.rb +24 -0
- data/lib/pact/provider/matchers.rb +3 -1
- data/lib/pact/provider/provider_state.rb +43 -20
- data/lib/pact/version.rb +1 -1
- data/pact.gemspec +0 -1
- data/spec/features/consumption_spec.rb +5 -0
- data/spec/lib/pact/consumer/consumer_contract_builder_spec.rb +162 -147
- data/spec/lib/pact/consumer/mock_service/app_spec.rb +52 -0
- data/spec/lib/pact/consumer/mock_service/interaction_mismatch_spec.rb +3 -3
- metadata +19 -25
- data/example/zoo-app/spec/service_providers/animal_service_spec.rb +0 -92
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -8,7 +8,6 @@ PATH
|
|
8
8
|
rack-test (~> 0.6.2)
|
9
9
|
randexp (~> 0.1.7)
|
10
10
|
rspec (~> 2.12)
|
11
|
-
thin
|
12
11
|
thor
|
13
12
|
webrick
|
14
13
|
|
@@ -27,9 +26,7 @@ GEM
|
|
27
26
|
coderay (1.0.9)
|
28
27
|
crack (0.4.1)
|
29
28
|
safe_yaml (~> 0.9.0)
|
30
|
-
daemons (1.1.9)
|
31
29
|
diff-lcs (1.2.4)
|
32
|
-
eventmachine (1.0.3)
|
33
30
|
fakefs (0.4.2)
|
34
31
|
find_a_port (1.0.1)
|
35
32
|
hashie (2.0.5)
|
@@ -59,10 +56,6 @@ GEM
|
|
59
56
|
rspec-mocks (2.14.3)
|
60
57
|
safe_yaml (0.9.5)
|
61
58
|
slop (3.4.6)
|
62
|
-
thin (1.6.1)
|
63
|
-
daemons (>= 1.0.9)
|
64
|
-
eventmachine (>= 1.0.0)
|
65
|
-
rack (>= 1.0.0)
|
66
59
|
thor (0.18.1)
|
67
60
|
thread_safe (0.1.3)
|
68
61
|
atomic
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Define a pact between service consumers and providers, enabling "consumer driven contract" testing.
|
4
4
|
|
5
|
-
Pact provides an RSpec DSL for service consumers to define the requests they will make to a service provider and the responses they expect back. These expectations are used in the consumers specs to provide a mock service provider. The interactions are recorded, and played back in the service provider specs to ensure the service provider actually does provide the response the consumer expects.
|
5
|
+
Pact provides an RSpec DSL for service consumers to define the HTTP requests they will make to a service provider and the HTTP responses they expect back. These expectations are used in the consumers specs to provide a mock service provider. The interactions are recorded, and played back in the service provider specs to ensure the service provider actually does provide the response the consumer expects.
|
6
6
|
|
7
7
|
This allows testing of both sides of an integration point using fast unit tests.
|
8
8
|
|
@@ -17,7 +17,25 @@ Travis CI Status: [![travis-ci.org Build Status](https://travis-ci.org/realestat
|
|
17
17
|
* Expected interactions are verified to have actually occurred in the consumer specs.
|
18
18
|
* The mocked responses are verified to be valid by replaying the interactions against the provider codebase.
|
19
19
|
* Rake verification tasks allow a pacts at one or more URIs to be checked against a given service provider codebase.
|
20
|
-
* Different versions of a consumer/provider
|
20
|
+
* Different versions of a consumer/provider pairs can be easily tested against each other, allowing confidence when deploying new versions of each (see the pact_broker and pact_broker-client gems).
|
21
|
+
|
22
|
+
## How does it work?
|
23
|
+
|
24
|
+
1. In the specs for the provider facing code in the consumer project, expectations are set up on a mock service provider.
|
25
|
+
1. When the specs are run, the requests, and their expected responses, are written to a "pact" file.
|
26
|
+
1. The requests in the pact file are later replayed against the provider, and the actual responses are checked to make sure they match the expected responses.
|
27
|
+
|
28
|
+
## Why is developing and testing with pacts better than using integration tests?
|
29
|
+
|
30
|
+
* Faster execution.
|
31
|
+
* No need to manage starting and stopping multiple processes.
|
32
|
+
* Reliable responses from mock service provider reduce likelihood of flakey tests.
|
33
|
+
* Only one component is being tested at a time, making the causes of test failures easier to identify.
|
34
|
+
* Design of service provider is improved by considering first how the data is actually going to be used, rather than how it is most easily retrieved and serialised.
|
35
|
+
|
36
|
+
## Google users group
|
37
|
+
|
38
|
+
https://groups.google.com/forum/#!forum/pact-support
|
21
39
|
|
22
40
|
## Installation
|
23
41
|
|
@@ -35,12 +53,12 @@ Imagine a model class that looks something like this. The attributes for a Somet
|
|
35
53
|
class SomethingModel
|
36
54
|
attr_reader :name
|
37
55
|
|
38
|
-
def
|
56
|
+
def initialize name
|
39
57
|
@name = name
|
40
58
|
end
|
41
59
|
|
42
60
|
def == other
|
43
|
-
other.is_a?(
|
61
|
+
other.is_a?(SomethingModel) && other.name == name
|
44
62
|
end
|
45
63
|
end
|
46
64
|
```
|
@@ -92,6 +110,8 @@ describe MyServiceProviderClient, :pact => true do
|
|
92
110
|
# Configure your client to point to the stub service on localhost using the port you have specified
|
93
111
|
MyServiceProviderClient.base_uri 'localhost:1234'
|
94
112
|
end
|
113
|
+
|
114
|
+
subject { MyServiceProviderClient.new }
|
95
115
|
|
96
116
|
describe "get_something" do
|
97
117
|
before do
|
@@ -107,7 +127,7 @@ describe MyServiceProviderClient, :pact => true do
|
|
107
127
|
end
|
108
128
|
|
109
129
|
it "returns a Something" do
|
110
|
-
expect(
|
130
|
+
expect(subject.get_something).to eq(SomethingModel.new('A small something'))
|
111
131
|
end
|
112
132
|
|
113
133
|
end
|
@@ -201,7 +221,7 @@ Yay! Your provider now honours the pact it has with your consumer. You can now h
|
|
201
221
|
|
202
222
|
### Using provider states
|
203
223
|
|
204
|
-
|
224
|
+
Provider states allow different fixtures to be loaded on the provider to allow you to test the same request with different expected responses.
|
205
225
|
|
206
226
|
For example, some code that creates the pact in a consumer project might look like this:
|
207
227
|
|
@@ -218,9 +238,19 @@ my_service.
|
|
218
238
|
given("a thing does not exist").
|
219
239
|
upon_receiving("a request for a thing").
|
220
240
|
with(method: 'get', path: '/thing').
|
221
|
-
will_respond_with(status: 404
|
241
|
+
will_respond_with(status: 404)
|
242
|
+
|
243
|
+
...
|
244
|
+
|
245
|
+
my_service.
|
246
|
+
given("an error occurs while retrieving a thing").
|
247
|
+
upon_receiving("a request for a thing").
|
248
|
+
with(method: 'get', path: '/thing').
|
249
|
+
will_respond_with(status: 500, :body => {message: "An error occurred"}, :headers => { 'Content-Type' => 'application/json'} )
|
222
250
|
```
|
223
251
|
|
252
|
+
|
253
|
+
|
224
254
|
To define service provider states that create the right data for "a thing exists" and "a thing does not exist", write the following in the service provider project. (The consumer name here must match the name of the consumer configured in your consumer project for it to correctly find these provider states.)
|
225
255
|
|
226
256
|
|
@@ -241,6 +271,12 @@ Pact.provider_states_for 'My Service Consumer' do
|
|
241
271
|
provider_state "a thing does not exist" do
|
242
272
|
no_op # If there's nothing to do because the state name is more for documentation purposes, you can use no_op to imply this.
|
243
273
|
end
|
274
|
+
|
275
|
+
provider_state "an error occurs while retrieving a thing" do
|
276
|
+
set_up do
|
277
|
+
ThingRepository.stub(:find).and_raise("An error occurred!")
|
278
|
+
end
|
279
|
+
end
|
244
280
|
end
|
245
281
|
|
246
282
|
```
|
@@ -329,63 +365,24 @@ To execute a subset of the specs when running any of the pact verification tasks
|
|
329
365
|
|
330
366
|
$ PACT_DESCRIPTION="a request for something" PACT_PROVIDER_STATE="something exists" rake pact:verify
|
331
367
|
|
332
|
-
|
333
|
-
|
334
|
-
A pact service can be run locally and is really useful for debugging purposes.
|
368
|
+
See [Frequently Asked Questions](https://github.com/realestate-com-au/pact/blob/master/documentation/faq.md) and [Rarely Asked Questions](https://github.com/realestate-com-au/pact/blob/master/documentation/raq.md) and [Terminology](https://github.com/realestate-com-au/pact/blob/master/documentation/terminology.md) for more information.
|
335
369
|
|
336
|
-
$ bundle exec pact service -p <port-num>
|
337
370
|
|
338
|
-
|
339
|
-
when diagnosing issues with pacts.
|
371
|
+
## Related Gems
|
340
372
|
|
341
|
-
|
373
|
+
[Pact Provider Proxy](https://github.com/bethesque/pact-provider-proxy) - Verify a pact against a running server, allowing you to use pacts with a provider of any language.
|
342
374
|
|
343
|
-
|
375
|
+
[Pact Broker](https://github.com/bethesque/pact_broker) - A pact repository. Provides endpoints to access published pacts, meaning you don't need to use messy CI URLs in your codebase. Enables cross testing of prod/head versions of your consumer and provider, allowing you to determine whether the head version of one is compatible with the production version of the other. Helps you to answer that ever so important question, "can I deploy without breaking all the things?"
|
344
376
|
|
345
|
-
|
346
|
-
Pact.service_consumer "My Consumer" do
|
347
|
-
app my_consumer_rack_app
|
348
|
-
port 4321
|
349
|
-
end
|
350
|
-
```
|
351
|
-
|
352
|
-
### Handling multiple headers with the same name
|
353
|
-
|
354
|
-
RFC 2616 states that two headers with the same name can interpreted as a single header with two comma-separated values. This is the safest way to specify multiple headers with the same name, as Rack will only pass the last value through when they are defined separately (see https://github.com/rack/rack/issues/436).
|
355
|
-
|
356
|
-
```ruby
|
357
|
-
my_service_provider.
|
358
|
-
.given("it is RFC 2616 compliant")
|
359
|
-
.upon_receiving("a request with a header with commas separated values")
|
360
|
-
.with( method: :get, path: '/', headers: {'X-Request-Multival' => "A, B"} )
|
361
|
-
.will_respond_with(
|
362
|
-
status: 200, headers: {'X-Response-Multival' => "C, D"}
|
363
|
-
)
|
364
|
-
|
365
|
-
```
|
366
|
-
|
367
|
-
### Pact file write mode
|
368
|
-
|
369
|
-
By default, the pact file will be overwritten (started from scratch) every time any rspec runs any spec using pacts. This means that if there are interactions that haven't been executed in the most recent rspec run, they are effectively removed from the pact file. If you have long running pact specs (e.g. they are generated using the browser with Capybara) and you are developing both consumer and provider in parallel, or trying to fix a broken interaction, it can be tedius to run all the specs at once. In this scenario, you can set the pactfile_write_mode to :update. This will keep all existing interactions, and update only the changed ones, identified by description and provider state. The down side of this is that if either of those fields change, the old interactions will not be removed from the pact file. As a middle path, you can set pactfile_write_mode to :smart. This will use :overwrite mode when running rake (as determined by a call to system using 'ps') and :update when running an individual spec.
|
370
|
-
|
371
|
-
### To use RSpec hooks for pact:verify
|
372
|
-
|
373
|
-
The pact:verify RSpec examples have the metadata `{:pact => :verify}` defined. You can add RSpec hooks using a filter as shown here:
|
374
|
-
|
375
|
-
```ruby
|
376
|
-
RSpec.configure do | config |
|
377
|
-
config.before :each, :pact => :verify do
|
378
|
-
# Your code here
|
379
|
-
end
|
380
|
-
end
|
381
|
-
```
|
377
|
+
[Pact Broker Client](https://github.com/bethesque/pact_broker-client) - Contains rake tasks for publishing pacts to the pact_broker.
|
382
378
|
|
383
|
-
|
379
|
+
[Shokkenki](https://github.com/brentsnook/shokkenki) - Another Consumer Driven Contract gem written by one of Pact's original authors, Brent Snook.
|
384
380
|
|
385
381
|
## TODO
|
386
382
|
|
387
383
|
Short term:
|
388
384
|
- FIX EXAMPLE!!!
|
385
|
+
- Support hash of query params
|
389
386
|
|
390
387
|
Long term:
|
391
388
|
- Provide more flexible matching (eg the keys should match, and the classes of the values should match, but the values of each key do not need to be equal). This is to make the pact verification less brittle.
|
data/Rakefile
CHANGED
@@ -1,22 +1,4 @@
|
|
1
|
-
require
|
2
|
-
module Bundler
|
3
|
-
class GemHelper
|
4
|
-
def install
|
5
|
-
desc "Build #{name}-#{version}.gem into the pkg directory"
|
6
|
-
task 'build' do
|
7
|
-
build_gem
|
8
|
-
end
|
9
|
-
|
10
|
-
desc "Build and install #{name}-#{version}.gem into system gems"
|
11
|
-
task 'install' do
|
12
|
-
install_gem
|
13
|
-
end
|
14
|
-
|
15
|
-
GemHelper.instance = self
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
Bundler::GemHelper.install_tasks
|
1
|
+
require "bundler/gem_tasks"
|
20
2
|
require 'rspec/core/rake_task'
|
21
3
|
|
22
4
|
Dir.glob('lib/tasks/**/*.rake').each { |task| load task }
|
@@ -25,9 +7,3 @@ RSpec::Core::RakeTask.new(:spec)
|
|
25
7
|
|
26
8
|
task :default => [:spec, :spec_with_active_support, 'pact:tests']
|
27
9
|
|
28
|
-
desc "Release to REA gems host"
|
29
|
-
task :publish => :build do
|
30
|
-
gem_file = "pkg/pact-#{Pact::VERSION}.gem"
|
31
|
-
require 'geminabox-client'
|
32
|
-
Geminabox::Client.new('http://rea-rubygems').upload(gem_file)
|
33
|
-
end
|
Binary file
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# Frequently asked questions
|
2
|
+
|
3
|
+
## How can I verify a pact against a non-ruby provider?
|
4
|
+
|
5
|
+
You can verify a pact against any running server, regardless of language, using [pact-provider-proxy](https://github.com/bethesque/pact-provider-proxy).
|
6
|
+
|
7
|
+
There is also a JVM version of pact under development. Have a look at [pact-jvm](https://github.com/DiUS/pact-jvm), the that contains the equivalent of pact/consumer and pact/provider.
|
8
|
+
|
9
|
+
### How can I create a pact for a consumer that is not ruby or on the JVM?
|
10
|
+
|
11
|
+
Become famous, and write a pact-consumer library yourself! Then let us know about it so we can put a link to it in the documentation.
|
12
|
+
|
13
|
+
### How can I specify hooks to be executed before/after all examples for pact:verify?
|
14
|
+
|
15
|
+
The pact:verify RSpec examples have the metadata `{:pact => :verify}` defined. You can add RSpec hooks using a filter as shown here:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
RSpec.configure do | config |
|
19
|
+
config.before :each, :pact => :verify do
|
20
|
+
# Your code here
|
21
|
+
end
|
22
|
+
end
|
23
|
+
```
|
24
|
+
|
25
|
+
See https://www.relishapp.com/rspec/rspec-core/docs/hooks/filters for more information.
|
26
|
+
|
27
|
+
### How can I run my consumer UI during my consumer specs so I can execute the tests using a browser?
|
28
|
+
|
29
|
+
Eg. for Capybara tests
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
Pact.service_consumer "My Consumer" do
|
33
|
+
app <your rack app here>
|
34
|
+
port 4321
|
35
|
+
end
|
36
|
+
```
|
37
|
+
|
38
|
+
### Should the database or any other part of the provider be stubbed?
|
39
|
+
|
40
|
+
This is a hotly debated issue.
|
41
|
+
|
42
|
+
The pact authors' experience with using pacts to test microservices has been that using the set_up hooks to populate the database, and running pact:verify with all the real provider code has worked very well, and gives us full confidence that the end to end scenario will work in the deployed code.
|
43
|
+
|
44
|
+
However, if you have a large and complex provider, you might decide to stub some of your application code. If you do, remember to add your own "verification" of your stubbed methods - write another test that will break if the behaviour of the stubbed methods changes.
|
45
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Rarely asked questions
|
2
|
+
|
3
|
+
### How can I run a standalone mock server?
|
4
|
+
|
5
|
+
By default, a mock service will be started automatically by the pact gem when running the consumer tests. A standalone mock service can be run locally and is useful for debugging purposes.
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
Pact.service_consumer "My Service Consumer" do
|
9
|
+
has_pact_with "My Service Provider" do
|
10
|
+
mock_service :my_service_provider do
|
11
|
+
port <port-num>
|
12
|
+
standalone true #Tell the pact gem not to automatically start the mock service
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
```
|
17
|
+
$ bundle exec pact service -p <port-num>
|
18
|
+
|
19
|
+
The service prints messages it recieves to stdout which can be really useful
|
20
|
+
when diagnosing issues with pacts.
|
21
|
+
|
22
|
+
### How can I specify multiple headers with the same name?
|
23
|
+
|
24
|
+
RFC 2616 states that two headers with the same name can interpreted as a single header with two comma-separated values. This is the safest way to specify multiple headers with the same name, as Rack will only pass the last value through when they are defined separately (see https://github.com/rack/rack/issues/436).
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
my_service_provider.
|
28
|
+
.given("it is RFC 2616 compliant")
|
29
|
+
.upon_receiving("a request with a header with commas separated values")
|
30
|
+
.with( method: :get, path: '/', headers: {'X-Request-Multival' => "A, B"} )
|
31
|
+
.will_respond_with(
|
32
|
+
status: 200, headers: {'X-Response-Multival' => "C, D"}
|
33
|
+
)
|
34
|
+
|
35
|
+
```
|
36
|
+
|
37
|
+
### What is this pact file write mode?
|
38
|
+
|
39
|
+
By default, the pact file will be overwritten (started from scratch) every time any rspec runs any spec using pacts. This means that if there are interactions that haven't been executed in the most recent rspec run, they are effectively removed from the pact file. If you have long running pact specs (e.g. they are generated using the browser with Capybara) and you are developing both consumer and provider in parallel, or trying to fix a broken interaction, it can be tedius to run all the specs at once. In this scenario, you can set the pactfile_write_mode to :update. This will keep all existing interactions, and update only the changed ones, identified by description and provider state. The down side of this is that if either of those fields change, the old interactions will not be removed from the pact file. As a middle path, you can set pactfile_write_mode to :smart. This will use :overwrite mode when running rake (as determined by a call to system using 'ps') and :update when running an individual spec.
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Terminology
|
2
|
+
|
3
|
+
### Service Consumer
|
4
|
+
|
5
|
+
A component that initiates a HTTP request to another component (the service provider). Note that this does not depend on the way the data flows - whether it is a GET or a PUT/POST/PATCH, the consumer is the initiator of the HTTP request.
|
6
|
+
|
7
|
+
### Service Provider
|
8
|
+
|
9
|
+
A server that responds to an HTTP request from another component (the service consumer).
|
10
|
+
|
11
|
+
### Mock Service Provider
|
12
|
+
|
13
|
+
Used by tests in the consumer project to mock out the actual service provider, meaning that integration-like tests can be run without requiring the actual service provider to be available.
|
14
|
+
|
15
|
+
### Pact file
|
16
|
+
|
17
|
+
A file containing the JSON serialised requests and responses that were defined in the consumer tests.
|
18
|
+
|
19
|
+
### Pact verification
|
20
|
+
|
21
|
+
To verify a pact, the requests contained in a pact file are replayed against the provider code, and the responses returned are checked to ensure they match those expected in the pact file.
|
22
|
+
|
23
|
+
## Provider state
|
24
|
+
|
25
|
+
A name describing a "state" (like a fixture) that the provider should be in when a given request is replayed against it. Eg. "there is an alligator called Mary" or "there are no alligators". A provider state name is specified when writing the consumer specs, then, when the pact verification is set up in the provider, the same name will be used to identify the set up code block that should be run before the request is executed.
|
@@ -1,7 +1,5 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
gem 'bundler', '~> 1.3.0'
|
4
|
-
|
5
3
|
group :development, :test do
|
6
4
|
gem 'rspec'
|
7
5
|
gem 'pact', path: '../../'
|
@@ -10,5 +8,7 @@ end
|
|
10
8
|
|
11
9
|
gem 'rake'
|
12
10
|
gem 'rack', '~>1.5.2'
|
13
|
-
gem 'json', '~>1.6
|
14
|
-
gem '
|
11
|
+
gem 'json', '~>1.6'
|
12
|
+
gem 'sqlite3'
|
13
|
+
gem 'sequel'
|
14
|
+
gem 'sinatra'
|
@@ -1,39 +1,35 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ../../
|
3
3
|
specs:
|
4
|
-
pact (1.0.
|
5
|
-
awesome_print (~> 1.1
|
4
|
+
pact (1.0.30)
|
5
|
+
awesome_print (~> 1.1)
|
6
6
|
find_a_port (~> 1.0.1)
|
7
|
-
hashie (~> 2.0)
|
8
7
|
json
|
9
8
|
rack-test (~> 0.6.2)
|
10
9
|
randexp (~> 0.1.7)
|
11
10
|
rspec (~> 2.12)
|
12
11
|
thin
|
13
12
|
thor
|
13
|
+
webrick
|
14
14
|
|
15
15
|
GEM
|
16
16
|
remote: https://rubygems.org/
|
17
17
|
specs:
|
18
|
-
awesome_print (1.
|
18
|
+
awesome_print (1.2.0)
|
19
19
|
coderay (1.0.9)
|
20
20
|
daemons (1.1.9)
|
21
21
|
diff-lcs (1.2.4)
|
22
22
|
eventmachine (1.0.3)
|
23
23
|
find_a_port (1.0.1)
|
24
|
-
hashie (2.0.5)
|
25
|
-
httparty (0.11.0)
|
26
|
-
multi_json (~> 1.0)
|
27
|
-
multi_xml (>= 0.5.2)
|
28
24
|
json (1.6.8)
|
29
25
|
method_source (0.8.2)
|
30
|
-
multi_json (1.8.0)
|
31
|
-
multi_xml (0.5.5)
|
32
26
|
pry (0.9.12.2)
|
33
27
|
coderay (~> 1.0.5)
|
34
28
|
method_source (~> 0.8)
|
35
29
|
slop (~> 3.4)
|
36
30
|
rack (1.5.2)
|
31
|
+
rack-protection (1.5.1)
|
32
|
+
rack
|
37
33
|
rack-test (0.6.2)
|
38
34
|
rack (>= 1.0)
|
39
35
|
rake (10.1.0)
|
@@ -46,22 +42,31 @@ GEM
|
|
46
42
|
rspec-expectations (2.14.2)
|
47
43
|
diff-lcs (>= 1.1.3, < 2.0)
|
48
44
|
rspec-mocks (2.14.3)
|
45
|
+
sequel (4.5.0)
|
46
|
+
sinatra (1.4.4)
|
47
|
+
rack (~> 1.4)
|
48
|
+
rack-protection (~> 1.4)
|
49
|
+
tilt (~> 1.3, >= 1.3.4)
|
49
50
|
slop (3.4.6)
|
50
|
-
|
51
|
+
sqlite3 (1.3.8)
|
52
|
+
thin (1.6.1)
|
51
53
|
daemons (>= 1.0.9)
|
52
|
-
eventmachine (>= 0.
|
54
|
+
eventmachine (>= 1.0.0)
|
53
55
|
rack (>= 1.0.0)
|
54
56
|
thor (0.18.1)
|
57
|
+
tilt (1.4.1)
|
58
|
+
webrick (1.3.1)
|
55
59
|
|
56
60
|
PLATFORMS
|
57
61
|
ruby
|
58
62
|
|
59
63
|
DEPENDENCIES
|
60
|
-
|
61
|
-
httparty
|
62
|
-
json (~> 1.6.8)
|
64
|
+
json (~> 1.6)
|
63
65
|
pact!
|
64
66
|
pry
|
65
67
|
rack (~> 1.5.2)
|
66
68
|
rake
|
67
69
|
rspec
|
70
|
+
sequel
|
71
|
+
sinatra
|
72
|
+
sqlite3
|