pact 1.0.9 → 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. data/CHANGELOG.md +20 -0
  2. data/Gemfile.lock +3 -3
  3. data/example/animal-service/Gemfile +14 -0
  4. data/example/animal-service/Gemfile.lock +67 -0
  5. data/example/animal-service/Rakefile +3 -0
  6. data/example/animal-service/spec/service_consumers/pact_helper.rb +24 -0
  7. data/example/animal-service/spec/service_consumers/provider_states_for_zoo_app.rb +9 -0
  8. data/example/zoo-app/Gemfile.lock +2 -15
  9. data/example/zoo-app/spec/pacts/zoo_app-animal_service.json +21 -6
  10. data/example/zoo-app/spec/service_providers/animal_service_spec.rb +1 -1
  11. data/lib/pact/consumer.rb +10 -11
  12. data/lib/pact/consumer/app_manager.rb +1 -0
  13. data/lib/pact/consumer/configuration.rb +179 -0
  14. data/lib/pact/consumer/interaction_builder.rb +1 -2
  15. data/lib/pact/consumer/mock_service.rb +1 -370
  16. data/lib/pact/consumer/mock_service/app.rb +70 -0
  17. data/lib/pact/consumer/mock_service/interaction_delete.rb +28 -0
  18. data/lib/pact/consumer/mock_service/interaction_list.rb +57 -0
  19. data/lib/pact/consumer/mock_service/interaction_post.rb +25 -0
  20. data/lib/pact/consumer/mock_service/interaction_replay.rb +126 -0
  21. data/lib/pact/consumer/mock_service/missing_interactions_get.rb +26 -0
  22. data/lib/pact/consumer/mock_service/rack_request_helper.rb +51 -0
  23. data/lib/pact/consumer/mock_service/startup_poll.rb +22 -0
  24. data/lib/pact/consumer/mock_service/verification_get.rb +35 -0
  25. data/lib/pact/consumer/mock_service_client.rb +3 -1
  26. data/lib/pact/consumer/mock_service_interaction_expectation.rb +33 -0
  27. data/lib/pact/consumer/request.rb +27 -0
  28. data/lib/pact/consumer/rspec.rb +1 -4
  29. data/lib/pact/consumer_contract/consumer_contract.rb +11 -8
  30. data/lib/pact/consumer_contract/interaction.rb +9 -22
  31. data/lib/pact/consumer_contract/request.rb +68 -0
  32. data/lib/pact/consumer_contract/service_consumer.rb +6 -2
  33. data/lib/pact/consumer_contract/service_provider.rb +6 -2
  34. data/lib/pact/matchers/index_not_found.rb +20 -0
  35. data/lib/pact/matchers/matchers.rb +14 -28
  36. data/lib/pact/matchers/unexpected_index.rb +17 -0
  37. data/lib/pact/matchers/unexpected_key.rb +17 -0
  38. data/lib/pact/provider.rb +1 -1
  39. data/lib/pact/provider/configuration.rb +129 -0
  40. data/lib/pact/provider/request.rb +59 -0
  41. data/lib/pact/provider/rspec.rb +4 -5
  42. data/lib/pact/provider/test_methods.rb +14 -52
  43. data/lib/pact/shared/dsl.rb +20 -0
  44. data/lib/pact/shared/key_not_found.rb +24 -0
  45. data/lib/pact/shared/null_expectation.rb +31 -0
  46. data/lib/pact/shared/request.rb +68 -0
  47. data/lib/pact/something_like.rb +7 -1
  48. data/lib/pact/symbolize_keys.rb +12 -0
  49. data/lib/pact/tasks.rb +1 -1
  50. data/lib/pact/tasks/task_helper.rb +23 -0
  51. data/lib/pact/{verification_task.rb → tasks/verification_task.rb} +4 -4
  52. data/lib/pact/version.rb +1 -1
  53. data/lib/tasks/pact.rake +5 -4
  54. data/pact.gemspec +1 -1
  55. data/spec/features/consumption_spec.rb +1 -73
  56. data/spec/features/production_spec.rb +3 -0
  57. data/spec/integration/consumer_spec.rb +170 -0
  58. data/spec/integration/pact/consumer_configuration_spec.rb +1 -1
  59. data/spec/lib/pact/consumer/{dsl_spec.rb → configuration_spec.rb} +10 -9
  60. data/spec/lib/pact/consumer/consumer_contract_builder_spec.rb +2 -2
  61. data/spec/lib/pact/consumer/interaction_builder_spec.rb +1 -1
  62. data/spec/lib/pact/consumer/mock_service/interaction_list_spec.rb +66 -0
  63. data/spec/lib/pact/consumer/mock_service/rack_request_helper_spec.rb +82 -0
  64. data/spec/lib/pact/consumer/mock_service_interaction_expectation_spec.rb +54 -0
  65. data/spec/lib/pact/consumer/request_spec.rb +24 -0
  66. data/spec/lib/pact/consumer_contract/consumer_contract_spec.rb +1 -1
  67. data/spec/lib/pact/consumer_contract/interaction_spec.rb +0 -34
  68. data/spec/lib/pact/{request_spec.rb → consumer_contract/request_spec.rb} +45 -121
  69. data/spec/lib/pact/matchers/matchers_spec.rb +29 -13
  70. data/spec/lib/pact/provider/configuration_spec.rb +163 -0
  71. data/spec/lib/pact/provider/request_spec.rb +78 -0
  72. data/spec/lib/pact/provider/test_methods_spec.rb +0 -30
  73. data/spec/lib/pact/verification_task_spec.rb +1 -1
  74. data/spec/spec_helper.rb +3 -0
  75. data/spec/support/factories.rb +5 -1
  76. data/spec/support/pact_helper.rb +6 -0
  77. data/spec/support/shared_examples_for_request.rb +83 -0
  78. data/spec/support/test_app_fail.json +3 -0
  79. data/spec/support/test_app_pass.json +18 -1
  80. metadata +68 -31
  81. data/lib/pact/consumer/dsl.rb +0 -157
  82. data/lib/pact/pact_task_helper.rb +0 -21
  83. data/lib/pact/provider/dsl.rb +0 -115
  84. data/lib/pact/request.rb +0 -167
  85. data/spec/lib/pact/consumer/mock_service_spec.rb +0 -143
  86. data/spec/lib/pact/provider/dsl_spec.rb +0 -179
data/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ ### 1.0.10 (24 September 2014)
2
+ * Removing unused requires [Beth Skurrie, 20 hours ago]
3
+ * Adding example changes [Beth Skurrie, 20 hours ago]
4
+ * Cleaning up provider configuration DSL. [Beth Skurrie, 6 days ago]
5
+ * Cleaned up consumer configuration DSL. [Beth Skurrie, 6 days ago]
6
+ * Splitting MockService request handlers into their own separate files. Divide and conquer... [Beth Skurrie, 6 days ago]
7
+ * Improving logging in mock service. [Beth Skurrie, 6 days ago]
8
+ * Cleaned up interaction list test. [Beth Skurrie, 6 days ago]
9
+ * Added better messages for matching when arrays are of different lengths. [Beth Skurrie, 6 days ago]
10
+ * Refactoring the Request world. Put each sub class of Request into it's relevant module. [Beth Skurrie, 6 days ago]
11
+ * Renaming request.match to request.matches? [Beth Skurrie, 7 days ago]
12
+ * Commenting and cleaning code. [Beth Skurrie, 7 days ago]
13
+ * Removed horrible as_json_for_mock_service method and created new class to do the same thing. [Beth Skurrie, 7 days ago]
14
+ * Moving rake task files into tasks directory. [Beth Skurrie, 7 days ago]
15
+ * Moving request file into consumer_contract folder. [Beth Skurrie, 7 days ago]
16
+ * Symbolizing keys so from_hash does not have to duplicate so much of the constructor methods. Service provider is now mandatory. [Beth Skurrie, 7 days ago]
17
+ * Removed Hashie from run time dependencies. [Beth Skurrie, 7 days ago]
18
+ * Starting to clean up mock service. Adding integration tests for failure scenarios. (Beth Skurrie, 7 days ago]
19
+ * Added RSpec fire to ensure stubbed methods exist. Pulled the recreation of a repayable request from an expected request out of the TestHelper into its own class. [Beth Skurrie, 7 days ago]
20
+
1
21
  ### 1.0.9 (16 September 2013)
2
22
 
3
23
  * Fixing pretty generate of json [Beth Skurrie]
data/Gemfile.lock CHANGED
@@ -1,10 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pact (1.0.9)
4
+ pact (1.0.10)
5
5
  awesome_print (~> 1.1.0)
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)
@@ -46,7 +45,7 @@ GEM
46
45
  rspec-expectations (~> 2.14.0)
47
46
  rspec-mocks (~> 2.14.0)
48
47
  rspec-core (2.14.5)
49
- rspec-expectations (2.14.2)
48
+ rspec-expectations (2.14.3)
50
49
  diff-lcs (>= 1.1.3, < 2.0)
51
50
  rspec-mocks (2.14.3)
52
51
  safe_yaml (0.9.5)
@@ -66,6 +65,7 @@ PLATFORMS
66
65
  DEPENDENCIES
67
66
  fakefs (~> 0.4)
68
67
  geminabox-client
68
+ hashie (~> 2.0)
69
69
  pact!
70
70
  pry
71
71
  rake (~> 10.0.3)
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'bundler', '~> 1.3.0'
4
+
5
+ group :development, :test do
6
+ gem 'rspec'
7
+ gem 'pact', path: '../../'
8
+ gem 'pry'
9
+ end
10
+
11
+ gem 'rake'
12
+ gem 'rack', '~>1.5.2'
13
+ gem 'json', '~>1.6.8'
14
+ gem 'httparty'
@@ -0,0 +1,67 @@
1
+ PATH
2
+ remote: ../../
3
+ specs:
4
+ pact (1.0.9)
5
+ awesome_print (~> 1.1.0)
6
+ find_a_port (~> 1.0.1)
7
+ hashie (~> 2.0)
8
+ json
9
+ rack-test (~> 0.6.2)
10
+ randexp (~> 0.1.7)
11
+ rspec (~> 2.12)
12
+ thin
13
+ thor
14
+
15
+ GEM
16
+ remote: https://rubygems.org/
17
+ specs:
18
+ awesome_print (1.1.0)
19
+ coderay (1.0.9)
20
+ daemons (1.1.9)
21
+ diff-lcs (1.2.4)
22
+ eventmachine (1.0.3)
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
+ json (1.6.8)
29
+ method_source (0.8.2)
30
+ multi_json (1.8.0)
31
+ multi_xml (0.5.5)
32
+ pry (0.9.12.2)
33
+ coderay (~> 1.0.5)
34
+ method_source (~> 0.8)
35
+ slop (~> 3.4)
36
+ rack (1.5.2)
37
+ rack-test (0.6.2)
38
+ rack (>= 1.0)
39
+ rake (10.1.0)
40
+ randexp (0.1.7)
41
+ rspec (2.14.1)
42
+ rspec-core (~> 2.14.0)
43
+ rspec-expectations (~> 2.14.0)
44
+ rspec-mocks (~> 2.14.0)
45
+ rspec-core (2.14.5)
46
+ rspec-expectations (2.14.2)
47
+ diff-lcs (>= 1.1.3, < 2.0)
48
+ rspec-mocks (2.14.3)
49
+ slop (3.4.6)
50
+ thin (1.5.1)
51
+ daemons (>= 1.0.9)
52
+ eventmachine (>= 0.12.6)
53
+ rack (>= 1.0.0)
54
+ thor (0.18.1)
55
+
56
+ PLATFORMS
57
+ ruby
58
+
59
+ DEPENDENCIES
60
+ bundler (~> 1.3.0)
61
+ httparty
62
+ json (~> 1.6.8)
63
+ pact!
64
+ pry
65
+ rack (~> 1.5.2)
66
+ rake
67
+ rspec
@@ -0,0 +1,3 @@
1
+ require 'pact/tasks'
2
+
3
+ :default => ['pact:verify']
@@ -0,0 +1,24 @@
1
+ require 'pact/provider/rspec'
2
+ require_relative "provider_states_for_zoo_app"
3
+
4
+
5
+ class AnimalService
6
+
7
+ def call env
8
+ response_body = {}
9
+ if env['PATH_INFO'] == '/alligators'
10
+ response_body = {'name' => 'Bob'}.to_json
11
+ end
12
+ [200, {'Content-Type' => 'application/json'}, [response_body]]
13
+ end
14
+ end
15
+
16
+ Pact.service_provider 'Animal Service' do
17
+ app do
18
+ AnimalService.new
19
+ end
20
+
21
+ honours_pact_with "Zoo App" do
22
+ pact_uri '../zoo-app/spec/pacts/zoo_app-animal_service.json'
23
+ end
24
+ end
@@ -0,0 +1,9 @@
1
+ Pact.provider_states_for "Zoo App" do
2
+ provider_state "there are alligators" do
3
+ #AlligatorRepo.save(Alligator.name("Mary"))
4
+ end
5
+
6
+ provider_state "there is not an alligator named Mary" do
7
+
8
+ end
9
+ end
@@ -1,11 +1,10 @@
1
1
  PATH
2
2
  remote: ../../
3
3
  specs:
4
- pact (0.1.37)
4
+ pact (1.0.9)
5
5
  awesome_print (~> 1.1.0)
6
- capybara (~> 2.1.0)
7
6
  find_a_port (~> 1.0.1)
8
- hashie (~> 2.0.5)
7
+ hashie (~> 2.0)
9
8
  json
10
9
  rack-test (~> 0.6.2)
11
10
  randexp (~> 0.1.7)
@@ -17,12 +16,6 @@ GEM
17
16
  remote: https://rubygems.org/
18
17
  specs:
19
18
  awesome_print (1.1.0)
20
- capybara (2.1.0)
21
- mime-types (>= 1.16)
22
- nokogiri (>= 1.3.3)
23
- rack (>= 1.0.0)
24
- rack-test (>= 0.5.4)
25
- xpath (~> 2.0)
26
19
  coderay (1.0.9)
27
20
  daemons (1.1.9)
28
21
  diff-lcs (1.2.4)
@@ -34,12 +27,8 @@ GEM
34
27
  multi_xml (>= 0.5.2)
35
28
  json (1.6.8)
36
29
  method_source (0.8.2)
37
- mime-types (1.24)
38
- mini_portile (0.5.1)
39
30
  multi_json (1.7.9)
40
31
  multi_xml (0.5.5)
41
- nokogiri (1.6.0)
42
- mini_portile (~> 0.5.0)
43
32
  pry (0.9.12.2)
44
33
  coderay (~> 1.0.5)
45
34
  method_source (~> 0.8)
@@ -63,8 +52,6 @@ GEM
63
52
  eventmachine (>= 0.12.6)
64
53
  rack (>= 1.0.0)
65
54
  thor (0.18.1)
66
- xpath (2.0.0)
67
- nokogiri (~> 1.3)
68
55
 
69
56
  PLATFORMS
70
57
  ruby
@@ -63,11 +63,9 @@
63
63
  "headers": {
64
64
  "Content-Type": "application/json"
65
65
  },
66
- "body": [
67
- {
68
- "name": "Mary"
69
- }
70
- ]
66
+ "body": {
67
+ "name": "Mary"
68
+ }
71
69
  },
72
70
  "provider_state": "there is an alligator named Mary"
73
71
  },
@@ -90,11 +88,28 @@
90
88
  }
91
89
  },
92
90
  "provider_state": "an error has occurred"
91
+ },
92
+ {
93
+ "description": "a request for alligator Mary",
94
+ "request": {
95
+ "method": "get",
96
+ "path": "/alligators/Mary",
97
+ "headers": {
98
+ "Accept": "application/json"
99
+ }
100
+ },
101
+ "response": {
102
+ "status": 404,
103
+ "headers": {
104
+ "Content-Type": "application/json"
105
+ }
106
+ },
107
+ "provider_state": "there is not an alligator named Mary"
93
108
  }
94
109
  ],
95
110
  "metadata": {
96
111
  "pact_gem": {
97
- "version": "0.1.37"
112
+ "version": "1.0.9"
98
113
  }
99
114
  }
100
115
  }
@@ -73,7 +73,7 @@ module ZooApp
73
73
 
74
74
  before do
75
75
  animal_service.
76
- given("there is an alligator named Mary").
76
+ given("there is not an alligator named Mary").
77
77
  upon_receiving("a request for alligator Mary").
78
78
  with({ method: :get, path: '/alligators/Mary', :headers => {'Accept' => 'application/json'} }).
79
79
  will_respond_with({
data/lib/pact/consumer.rb CHANGED
@@ -1,11 +1,10 @@
1
- require_relative 'consumer_contract'
2
- require_relative 'consumer/consumer_contract_builder'
3
- require_relative 'consumer/consumer_contract_builders'
4
- require_relative 'consumer/dsl'
5
- require_relative 'consumer/interaction_builder'
6
- require_relative 'consumer/mock_service'
7
- require_relative 'consumer/mock_service_client'
8
- require_relative 'consumer/app_manager'
9
- require_relative 'term'
10
- require_relative 'something_like'
11
- require_relative 'request'
1
+ require 'pact/consumer_contract'
2
+ require 'pact/consumer/configuration'
3
+ require 'pact/consumer/consumer_contract_builder'
4
+ require 'pact/consumer/consumer_contract_builders'
5
+ require 'pact/consumer/interaction_builder'
6
+ require 'pact/consumer/mock_service'
7
+ require 'pact/consumer/mock_service_client'
8
+ require 'pact/consumer/app_manager'
9
+ require 'pact/term'
10
+ require 'pact/something_like'
@@ -5,6 +5,7 @@ require 'uri'
5
5
  require 'find_a_port'
6
6
  require 'pact/logging'
7
7
  require 'pact/consumer/server'
8
+ require 'singleton'
8
9
 
9
10
  module Pact
10
11
  module Consumer
@@ -0,0 +1,179 @@
1
+ require 'pact/configuration'
2
+ require 'pact/consumer/consumer_contract_builders'
3
+ require 'pact/consumer/consumer_contract_builder'
4
+ require 'pact/shared/dsl'
5
+
6
+ module Pact::Consumer
7
+
8
+ module DSL
9
+ def service_consumer name, &block
10
+ Configuration::ServiceConsumer.build(name, &block)
11
+ end
12
+ end
13
+
14
+ module Configuration
15
+
16
+ module ConfigurationExtensions
17
+ def add_provider_verification &block
18
+ provider_verifications << block
19
+ end
20
+ def provider_verifications
21
+ @provider_verifications ||= []
22
+ end
23
+ end
24
+
25
+ class ServiceConsumer
26
+ extend Pact::DSL
27
+ attr_accessor :app, :port, :name
28
+
29
+ def initialize name
30
+ @name = name
31
+ @app = nil
32
+ @port = nil
33
+ end
34
+
35
+ dsl do
36
+ def app app
37
+ self.app = app
38
+ end
39
+
40
+ def port port
41
+ self.port = port
42
+ end
43
+
44
+ def has_pact_with service_provider_name, &block
45
+ ServiceProvider.build(service_provider_name, name, &block)
46
+ end
47
+ end
48
+
49
+ def finalize
50
+ validate
51
+ register_consumer_app if @app
52
+ end
53
+
54
+ private
55
+
56
+ def validate
57
+ raise "Please provide a consumer name" unless (name && !name.empty?)
58
+ raise "Please provide a port for the consumer app" if app && !port
59
+ end
60
+
61
+
62
+ def register_consumer_app
63
+ Pact::Consumer::AppManager.instance.register app, port
64
+ end
65
+ end
66
+
67
+
68
+ class ServiceProvider
69
+ extend Pact::DSL
70
+
71
+ attr_accessor :service, :consumer_name, :name
72
+
73
+ def initialize name, consumer_name
74
+ @name = name
75
+ @service = nil
76
+ @consumer_name = consumer_name
77
+ end
78
+
79
+ dsl do
80
+ def mock_service name, &block
81
+ self.service = MockService.build(name, consumer_name, self.name, &block)
82
+ end
83
+ end
84
+
85
+ def finalize
86
+ validate
87
+ end
88
+
89
+ private
90
+
91
+ def validate
92
+ raise "Please configure a service for #{name}" unless service
93
+ end
94
+
95
+ end
96
+
97
+ class MockService
98
+ extend Pact::DSL
99
+
100
+ attr_accessor :port, :standalone, :verify, :provider_name, :consumer_name
101
+
102
+ def initialize name, consumer_name, provider_name
103
+ @name = name
104
+ @consumer_name = consumer_name
105
+ @provider_name = provider_name
106
+ @port = nil
107
+ @standalone = false
108
+ @verify = true
109
+ end
110
+
111
+ dsl do
112
+ def port port
113
+ self.port = port
114
+ end
115
+
116
+ def standalone standalone
117
+ self.standalone = standalone
118
+ end
119
+
120
+ def verify verify
121
+ self.verify = verify
122
+ end
123
+ end
124
+
125
+ def finalize
126
+ validate
127
+ register_mock_service
128
+ configure_consumer_contract_builder
129
+ end
130
+
131
+ private
132
+
133
+ def register_mock_service
134
+ unless standalone
135
+ AppManager.instance.register_mock_service_for provider_name, "http://localhost:#{port}"
136
+ end
137
+ end
138
+
139
+ def configure_consumer_contract_builder
140
+ consumer_contract_builder = create_consumer_contract_builder
141
+ create_consumer_contract_builders_method consumer_contract_builder
142
+ setup_verification(consumer_contract_builder) if verify
143
+ consumer_contract_builder
144
+ end
145
+
146
+ def create_consumer_contract_builder
147
+ consumer_contract_builder_fields = {
148
+ :consumer_name => consumer_name,
149
+ :provider_name => provider_name,
150
+ :pactfile_write_mode => Pact.configuration.pactfile_write_mode,
151
+ :port => port
152
+ }
153
+ Pact::Consumer::ConsumerContractBuilder.new consumer_contract_builder_fields
154
+ end
155
+
156
+ def setup_verification consumer_contract_builder
157
+ Pact.configuration.add_provider_verification do | example_description |
158
+ consumer_contract_builder.verify example_description
159
+ end
160
+ end
161
+
162
+ # This makes the consumer_contract_builder available via a module method with the given identifier
163
+ # as the method name.
164
+ # I feel this should be defined somewhere else, but I'm not sure where
165
+ def create_consumer_contract_builders_method consumer_contract_builder
166
+ Pact::Consumer::ConsumerContractBuilders.send(:define_method, @name.to_sym) do
167
+ consumer_contract_builder
168
+ end
169
+ end
170
+
171
+ def validate
172
+ raise "Please provide a port for service #{name}" unless port
173
+ end
174
+ end
175
+ end
176
+ end
177
+
178
+ Pact.send(:extend, Pact::Consumer::DSL)
179
+ Pact::Configuration.send(:include, Pact::Consumer::Configuration::ConfigurationExtensions)