pact 1.3.3 → 1.4.0.rc2

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 (110) hide show
  1. data/CHANGELOG.md +16 -1
  2. data/Gemfile +5 -0
  3. data/Gemfile.lock +34 -13
  4. data/README.md +3 -2
  5. data/example/animal-service/lib/animal_service/api.rb +1 -0
  6. data/example/zoo-app/lib/zoo_app/animal_service_client.rb +0 -9
  7. data/example/zoo-app/lib/zoo_app/models/alligator.rb +2 -0
  8. data/lib/pact.rb +6 -5
  9. data/lib/pact/cli.rb +0 -26
  10. data/lib/pact/consumer/configuration.rb +0 -1
  11. data/lib/pact/consumer/configuration/configuration_extensions.rb +51 -0
  12. data/lib/pact/consumer/consumer_contract_builder.rb +1 -2
  13. data/lib/pact/consumer/interaction_builder.rb +2 -4
  14. data/lib/pact/doc/interaction_view_model.rb +9 -6
  15. data/lib/pact/doc/sort_interactions.rb +1 -1
  16. data/lib/pact/provider/rspec.rb +11 -9
  17. data/lib/pact/version.rb +1 -1
  18. data/pact.gemspec +5 -0
  19. data/spec/lib/pact/consumer/interaction_builder_spec.rb +4 -8
  20. data/spec/support/case-insensitive-response-header-matching.json +21 -0
  21. data/spec/support/case-insensitive-response-header-matching.rb +15 -0
  22. data/tasks/pact-test.rake +5 -0
  23. metadata +42 -122
  24. data/lib/pact/configuration.rb +0 -195
  25. data/lib/pact/consumer/app_manager.rb +0 -158
  26. data/lib/pact/consumer/interactions_filter.rb +0 -48
  27. data/lib/pact/consumer/mock_service.rb +0 -2
  28. data/lib/pact/consumer/mock_service/app.rb +0 -82
  29. data/lib/pact/consumer/mock_service/interaction_delete.rb +0 -33
  30. data/lib/pact/consumer/mock_service/interaction_list.rb +0 -76
  31. data/lib/pact/consumer/mock_service/interaction_mismatch.rb +0 -73
  32. data/lib/pact/consumer/mock_service/interaction_post.rb +0 -31
  33. data/lib/pact/consumer/mock_service/interaction_replay.rb +0 -139
  34. data/lib/pact/consumer/mock_service/log_get.rb +0 -28
  35. data/lib/pact/consumer/mock_service/missing_interactions_get.rb +0 -30
  36. data/lib/pact/consumer/mock_service/mock_service_administration_endpoint.rb +0 -31
  37. data/lib/pact/consumer/mock_service/pact_post.rb +0 -33
  38. data/lib/pact/consumer/mock_service/rack_request_helper.rb +0 -51
  39. data/lib/pact/consumer/mock_service/verification_get.rb +0 -68
  40. data/lib/pact/consumer/mock_service_client.rb +0 -65
  41. data/lib/pact/consumer/mock_service_interaction_expectation.rb +0 -37
  42. data/lib/pact/consumer/request.rb +0 -27
  43. data/lib/pact/consumer/server.rb +0 -90
  44. data/lib/pact/consumer_contract.rb +0 -1
  45. data/lib/pact/consumer_contract/consumer_contract.rb +0 -115
  46. data/lib/pact/consumer_contract/consumer_contract_writer.rb +0 -84
  47. data/lib/pact/consumer_contract/file_name.rb +0 -19
  48. data/lib/pact/consumer_contract/headers.rb +0 -51
  49. data/lib/pact/consumer_contract/interaction.rb +0 -67
  50. data/lib/pact/consumer_contract/pact_file.rb +0 -24
  51. data/lib/pact/consumer_contract/request.rb +0 -73
  52. data/lib/pact/consumer_contract/service_consumer.rb +0 -28
  53. data/lib/pact/consumer_contract/service_provider.rb +0 -28
  54. data/lib/pact/logging.rb +0 -14
  55. data/lib/pact/matchers.rb +0 -1
  56. data/lib/pact/matchers/actual_type.rb +0 -16
  57. data/lib/pact/matchers/base_difference.rb +0 -37
  58. data/lib/pact/matchers/differ.rb +0 -153
  59. data/lib/pact/matchers/difference.rb +0 -13
  60. data/lib/pact/matchers/difference_indicator.rb +0 -26
  61. data/lib/pact/matchers/embedded_diff_formatter.rb +0 -62
  62. data/lib/pact/matchers/expected_type.rb +0 -35
  63. data/lib/pact/matchers/index_not_found.rb +0 -15
  64. data/lib/pact/matchers/list_diff_formatter.rb +0 -101
  65. data/lib/pact/matchers/matchers.rb +0 -139
  66. data/lib/pact/matchers/no_diff_indicator.rb +0 -18
  67. data/lib/pact/matchers/regexp_difference.rb +0 -13
  68. data/lib/pact/matchers/type_difference.rb +0 -16
  69. data/lib/pact/matchers/unexpected_index.rb +0 -11
  70. data/lib/pact/matchers/unexpected_key.rb +0 -11
  71. data/lib/pact/matchers/unix_diff_formatter.rb +0 -114
  72. data/lib/pact/reification.rb +0 -28
  73. data/lib/pact/rspec.rb +0 -53
  74. data/lib/pact/shared/active_support_support.rb +0 -51
  75. data/lib/pact/shared/dsl.rb +0 -76
  76. data/lib/pact/shared/jruby_support.rb +0 -18
  77. data/lib/pact/shared/json_differ.rb +0 -15
  78. data/lib/pact/shared/key_not_found.rb +0 -15
  79. data/lib/pact/shared/null_expectation.rb +0 -31
  80. data/lib/pact/shared/request.rb +0 -80
  81. data/lib/pact/shared/text_differ.rb +0 -14
  82. data/lib/pact/something_like.rb +0 -49
  83. data/lib/pact/symbolize_keys.rb +0 -12
  84. data/lib/pact/term.rb +0 -85
  85. data/spec/lib/pact/consumer/request_spec.rb +0 -24
  86. data/spec/lib/pact/consumer_contract/active_support_support_spec.rb +0 -58
  87. data/spec/lib/pact/consumer_contract/consumer_contract_spec.rb +0 -180
  88. data/spec/lib/pact/consumer_contract/headers_spec.rb +0 -107
  89. data/spec/lib/pact/consumer_contract/interaction_spec.rb +0 -107
  90. data/spec/lib/pact/consumer_contract/request_spec.rb +0 -329
  91. data/spec/lib/pact/matchers/differ_spec.rb +0 -214
  92. data/spec/lib/pact/matchers/difference_spec.rb +0 -22
  93. data/spec/lib/pact/matchers/embedded_diff_formatter_spec.rb +0 -90
  94. data/spec/lib/pact/matchers/index_not_found_spec.rb +0 -21
  95. data/spec/lib/pact/matchers/list_diff_formatter_spec.rb +0 -114
  96. data/spec/lib/pact/matchers/matchers_spec.rb +0 -500
  97. data/spec/lib/pact/matchers/regexp_difference_spec.rb +0 -20
  98. data/spec/lib/pact/matchers/type_difference_spec.rb +0 -34
  99. data/spec/lib/pact/matchers/unexpected_index_spec.rb +0 -20
  100. data/spec/lib/pact/matchers/unexpected_key_spec.rb +0 -20
  101. data/spec/lib/pact/matchers/unix_diff_formatter_spec.rb +0 -216
  102. data/spec/lib/pact/reification_spec.rb +0 -67
  103. data/spec/lib/pact/shared/dsl_spec.rb +0 -86
  104. data/spec/lib/pact/shared/json_differ_spec.rb +0 -36
  105. data/spec/lib/pact/shared/key_not_found_spec.rb +0 -20
  106. data/spec/lib/pact/shared/request_spec.rb +0 -111
  107. data/spec/lib/pact/shared/text_differ_spec.rb +0 -54
  108. data/spec/lib/pact/something_like_spec.rb +0 -21
  109. data/spec/lib/pact/term_spec.rb +0 -89
  110. data/spec/support/dsl_spec_support.rb +0 -7
@@ -1,12 +0,0 @@
1
- module Pact
2
- module SymbolizeKeys
3
-
4
- def self.included(base)
5
- base.extend(self)
6
- end
7
-
8
- def symbolize_keys hash
9
- hash.inject({}) { |memo, (k,v)| memo[k.to_sym] = v; memo }
10
- end
11
- end
12
- end
data/lib/pact/term.rb DELETED
@@ -1,85 +0,0 @@
1
- require 'pact/shared/active_support_support'
2
- require 'json/add/regexp'
3
-
4
- module Pact
5
- class Term
6
-
7
- include Pact::ActiveSupportSupport
8
-
9
- attr_reader :generate, :matcher
10
-
11
- def self.json_create(obj)
12
- new(generate: obj['data']['generate'], matcher: obj['data']['matcher'])
13
- end
14
-
15
- def self.unpack_regexps source
16
- case source
17
- when Pact::Term then source.matcher
18
- when Array then unpack_regexps_from_array source
19
- when Hash then unpack_regexps_from_hash source
20
- else
21
- source
22
- end
23
- end
24
-
25
- def initialize(attributes = {})
26
- @generate = attributes[:generate]
27
- @matcher = attributes[:matcher]
28
- raise "Please specify a matcher for the Term" unless @matcher != nil
29
- raise "Please specify a value to generate for the Term" unless @generate != nil
30
- raise "Value to generate \"#{@generate}\" does not match regular expression #{@matcher}" unless @generate =~ @matcher
31
- end
32
-
33
- def to_hash
34
- { json_class: self.class.name, data: { generate: generate, matcher: fix_regexp(matcher)} }
35
- end
36
-
37
- def as_json(options = {})
38
- to_hash
39
- end
40
-
41
-
42
- def to_json(options = {})
43
- as_json.to_json(options)
44
- end
45
-
46
- def match(literal)
47
- literal.respond_to?(:to_s) ? matcher.match(literal.to_s) : nil
48
- end
49
-
50
- def ==(other)
51
- return false unless other.respond_to?(:generate) && other.respond_to?(:matcher)
52
- generate == other.generate && matcher == other.matcher
53
- end
54
-
55
- def to_s
56
- "Pact::Term matcher: #{matcher.inspect}" + (generate.nil? ? "" : " generate: \"#{generate}\"")
57
- end
58
-
59
- def diff_with_actual(actual)
60
- match(actual) ? nil : {
61
- expected: self,
62
- actual: actual
63
- }
64
- end
65
-
66
- def empty?
67
- false
68
- end
69
-
70
- private
71
-
72
- def self.unpack_regexps_from_array source
73
- source.each_with_object([]) do | item, destination |
74
- destination << unpack_regexps(item)
75
- end
76
- end
77
-
78
- def self.unpack_regexps_from_hash source
79
- source.keys.each_with_object({}) do | key, destination |
80
- destination[key] = unpack_regexps source[key]
81
- end
82
- end
83
-
84
- end
85
- end
@@ -1,24 +0,0 @@
1
- require 'spec_helper'
2
- require 'support/shared_examples_for_request'
3
-
4
- module Pact
5
- describe Consumer::Request::Actual do
6
- it_behaves_like "a request"
7
-
8
- let(:raw_request) do
9
- {
10
- 'method' => 'get',
11
- 'path' => '/mallory'
12
- }
13
- end
14
-
15
- describe "from_hash" do
16
- context "when field are not defined" do
17
- subject { described_class.from_hash(raw_request) }
18
- it "raises an error" do
19
- expect{subject}.to raise_error KeyError
20
- end
21
- end
22
- end
23
- end
24
- end
@@ -1,58 +0,0 @@
1
- require 'spec_helper'
2
- require 'pact/shared/active_support_support'
3
-
4
- module Pact
5
- describe ActiveSupportSupport do
6
-
7
- include ActiveSupportSupport
8
-
9
-
10
- describe "fix_regexp" do
11
- let(:regexp) { /moose/ }
12
-
13
- subject { fix_regexp regexp }
14
-
15
- it "returns the original regexp" do
16
- expect(subject).to be(regexp)
17
- end
18
-
19
- it "fixes the as_json method for Regexp that ActiveSupport tramples beneath its destructive hooves of destruction" do
20
- expect(subject.to_json).to eq("{\"json_class\":\"Regexp\",\"o\":0,\"s\":\"moose\"}")
21
- end
22
- end
23
-
24
- describe "fix_all_the_things" do
25
- let(:hash) do
26
- { 'body' => Pact::Term.new(matcher: /a*b/, generate: 'abba'), array: [/blah/], thing: /alligator/ }
27
- end
28
-
29
- subject { fix_all_the_things(hash) }
30
-
31
- it "returns the original object" do
32
- expect(subject).to be(hash)
33
- end
34
-
35
- it "finds all the Regexp objects in hashes or Pact class attributes and fixes the as_json method" do
36
- json = subject.to_json
37
- expect(json).to include("{\"json_class\":\"Regexp\",\"o\":0,\"s\":\"a*b\"}")
38
- expect(json).to include("{\"json_class\":\"Regexp\",\"o\":0,\"s\":\"blah\"}")
39
- expect(json).to include("{\"json_class\":\"Regexp\",\"o\":0,\"s\":\"alligator\"}")
40
- end
41
- end
42
-
43
- describe "fix_json_formatting" do
44
- let(:active_support_affected_pretty_generated_json) { "{\"json_class\":\"Regexp\",\"o\":0,\"s\":\"a*b\"}" }
45
- let(:pretty_generated_json) do
46
- '{
47
- "json_class": "Regexp",
48
- "o": 0,
49
- "s": "a*b"
50
- }'
51
- end
52
-
53
- it "pretty formats the json that has been not pretty formatted because of ActiveSupport" do
54
- expect(fix_json_formatting(active_support_affected_pretty_generated_json)).to eq (pretty_generated_json.strip)
55
- end
56
- end
57
- end
58
- end
@@ -1,180 +0,0 @@
1
- require 'spec_helper'
2
- require 'pact/consumer_contract'
3
-
4
- module Pact
5
- describe ConsumerContract do
6
- describe "as_json" do
7
-
8
- class MockInteraction
9
- def as_json(options ={})
10
- {:mock => "interaction"}
11
- end
12
- end
13
-
14
- before do
15
- allow(DateTime).to receive(:now).and_return(DateTime.strptime("2013-08-15T13:27:13+10:00"))
16
- end
17
-
18
- let(:service_consumer) { double('ServiceConsumer', :as_json => {:a => 'consumer'}) }
19
- let(:service_provider) { double('ServiceProvider', :as_json => {:a => 'provider'}) }
20
- let(:pact) { ConsumerContract.new({:interactions => [MockInteraction.new], :consumer => service_consumer, :provider => service_provider }) }
21
- let(:expected_as_json) { {:provider=>{:a=>"provider"}, :consumer=>{:a=>"consumer"}, :interactions=>[{:mock=>"interaction"}], :metadata=>{:pactSpecificationVersion=> "1.0.0" }} }
22
-
23
- it "should return a hash representation of the Pact" do
24
- expect(pact.as_json).to eq expected_as_json
25
- end
26
-
27
- end
28
-
29
- describe ".from_json" do
30
- let(:loaded_pact) { ConsumerContract.from_json(string) }
31
- context "when the top level object is a ConsumerContract" do
32
- let(:string) { '{"interactions":[{"request": {"path":"/path", "method" : "get"}}], "consumer": {"name" : "Bob"} , "provider": {"name" : "Mary"} }' }
33
-
34
- it "should create a Pact" do
35
- expect(loaded_pact).to be_instance_of ConsumerContract
36
- end
37
-
38
- it "should have interactions" do
39
- expect(loaded_pact.interactions).to be_instance_of Array
40
- end
41
-
42
- it "should have a consumer" do
43
- expect(loaded_pact.consumer).to be_instance_of Pact::ServiceConsumer
44
- end
45
-
46
- it "should have a provider" do
47
- expect(loaded_pact.provider).to be_instance_of Pact::ServiceProvider
48
- end
49
- end
50
-
51
- context "with old 'producer' key" do
52
- let(:string) { File.read('./spec/support/a_consumer-a_producer.json')}
53
- it "should create a Pact" do
54
- expect(loaded_pact).to be_instance_of ConsumerContract
55
- end
56
-
57
- it "should have interactions" do
58
- expect(loaded_pact.interactions).to be_instance_of Array
59
- end
60
-
61
- it "should have a consumer" do
62
- expect(loaded_pact.consumer).to be_instance_of Pact::ServiceConsumer
63
- end
64
-
65
- it "should have a provider" do
66
- expect(loaded_pact.provider).to be_instance_of Pact::ServiceProvider
67
- expect(loaded_pact.provider.name).to eq "an old producer"
68
- end
69
-
70
- it "should have a provider_state" do
71
- expect(loaded_pact.interactions.first.provider_state).to eq 'state one'
72
- end
73
- end
74
- end
75
-
76
- describe "find_interactions" do
77
- let(:consumer) { double('Pact::ServiceConsumer', :name => 'Consumer')}
78
- let(:provider) { double('Pact::ServiceProvider', :name => 'Provider')}
79
- let(:interaction) { double('Pact::Interaction') }
80
- subject { ConsumerContract.new(:interactions => [interaction], :consumer => consumer, :provider => provider) }
81
- let(:criteria) { {:description => /blah/} }
82
- before do
83
- expect(interaction).to receive(:matches_criteria?).with(criteria).and_return(matches)
84
- end
85
- context "by description" do
86
- context "when no interactions are found" do
87
- let(:matches) { false }
88
- it "returns an empty array" do
89
- expect(subject.find_interactions(criteria)).to eql []
90
- end
91
- end
92
- context "when interactions are found" do
93
- let(:matches) { true }
94
- it "returns an array of the matching interactions" do
95
- expect(subject.find_interactions(criteria)).to eql [interaction]
96
- end
97
- end
98
- end
99
- end
100
-
101
- describe "find_interaction" do
102
- let(:consumer) { double('Pact::ServiceConsumer', :name => 'Consumer')}
103
- let(:provider) { double('Pact::ServiceProvider', :name => 'Provider')}
104
- let(:interaction1) { double('Pact::Interaction') }
105
- let(:interaction2) { double('Pact::Interaction') }
106
- let(:criteria) { {:description => /blah/} }
107
-
108
- before do
109
- expect(interaction1).to receive(:matches_criteria?).with(criteria).and_return(matches1)
110
- expect(interaction2).to receive(:matches_criteria?).with(criteria).and_return(matches2)
111
- end
112
-
113
- subject { ConsumerContract.new(:interactions => [interaction1, interaction2], :consumer => consumer, :provider => provider) }
114
- context "by description" do
115
- context "when a match is found" do
116
- let(:matches1) { true }
117
- let(:matches2) { false }
118
-
119
- it "returns the interaction" do
120
- expect(subject.find_interaction criteria).to eql interaction1
121
- end
122
- end
123
- context "when more than one match is found" do
124
- let(:matches1) { true }
125
- let(:matches2) { true }
126
- it "raises an error" do
127
- expect{ subject.find_interaction(criteria) }.to raise_error "Found more than 1 interaction matching {:description=>/blah/} in pact file between Consumer and Provider."
128
- end
129
- end
130
- context "when a match is not found" do
131
- let(:matches1) { false }
132
- let(:matches2) { false }
133
- it "raises an error" do
134
- expect{ subject.find_interaction(criteria) }.to raise_error "Could not find interaction matching {:description=>/blah/} in pact file between Consumer and Provider."
135
- end
136
- end
137
- end
138
- end
139
-
140
- describe "update_pactfile" do
141
- let(:pacts_dir) { Pathname.new("./tmp/pactfiles") }
142
- let(:expected_pact_path) { pacts_dir + "test_consumer-test_service.json" }
143
- let(:expected_pact_string) do <<-eos
144
- {
145
- "provider": {
146
- "name": "test_service"
147
- },
148
- "consumer": {
149
- "name": "test_consumer"
150
- },
151
- "interactions": [
152
- "something"
153
- ],
154
- "metadata": {
155
- "pactSpecificationVersion": "1.0.0"
156
- }
157
- }
158
- eos
159
- end
160
- let(:consumer) { Pact::ServiceConsumer.new(:name => 'test_consumer')}
161
- let(:provider) { Pact::ServiceProvider.new(:name => 'test_service')}
162
- let(:interactions) { [double("interaction", as_json: "something")]}
163
- subject { ConsumerContract.new(:consumer => consumer, :provider => provider, :interactions => interactions) }
164
- before do
165
- allow(Pact.configuration).to receive(:pact_dir).and_return(Pathname.new("./tmp/pactfiles"))
166
- FileUtils.rm_rf pacts_dir
167
- FileUtils.mkdir_p pacts_dir
168
- subject.update_pactfile
169
- end
170
-
171
- it "should write to a file specified by the consumer and provider name" do
172
- expect(File.exist?(expected_pact_path)).to eq true
173
- end
174
-
175
- it "should write the interactions to the file" do
176
- expect(File.read(expected_pact_path)).to eql expected_pact_string.strip
177
- end
178
- end
179
- end
180
- end
@@ -1,107 +0,0 @@
1
- require 'spec_helper'
2
- require 'pact/consumer_contract/headers'
3
-
4
- module Pact
5
- describe Headers do
6
-
7
- describe "initialize" do
8
-
9
- context "with duplicate headers" do
10
-
11
- subject { Headers.new('Content-Type' => 'application/hippo', 'CONTENT-TYPE' => 'application/giraffe') }
12
-
13
- it "raises an error" do
14
- expect { subject }.to raise_error DuplicateHeaderError, /Content\-Type.*CONTENT\-TYPE/
15
- end
16
-
17
- end
18
-
19
- context "with a symbol as a header name" do
20
-
21
- subject { Headers.new(:'content-type' => 'application/hippo') }
22
-
23
- it "converts the header name to a String" do
24
- expect( subject.to_hash ).to eq 'content-type' => 'application/hippo'
25
- end
26
-
27
- end
28
-
29
- context "with a nil header name" do
30
-
31
- subject { Headers.new(nil => 'application/hippo') }
32
-
33
- it "raises an error" do
34
- expect{ subject }.to raise_error InvalidHeaderNameTypeError
35
- end
36
-
37
- end
38
-
39
- context "with a boolean header name" do
40
-
41
- subject { Headers.new(false => 'application/hippo') }
42
-
43
- it "raises an error" do
44
- expect{ subject }.to raise_error InvalidHeaderNameTypeError
45
- end
46
-
47
- end
48
-
49
- end
50
-
51
- describe "[]" do
52
-
53
- subject { Headers.new 'Content-Type' => 'application/hippo' }
54
-
55
- it "is case insensitive as HTTP headers are case insensitive" do
56
- expect(subject['Content-Type']).to eq('application/hippo')
57
- expect(subject['CONTENT-TYPE']).to eq('application/hippo')
58
- expect(subject['content-type']).to eq('application/hippo')
59
- end
60
-
61
- end
62
-
63
- describe "fetch" do
64
-
65
- subject { Headers.new 'Content-Type' => 'application/hippo' }
66
-
67
- it "is case insensitive as HTTP headers are case insensitive" do
68
- expect(subject.fetch('Content-Type')).to eq('application/hippo')
69
- expect(subject.fetch('CONTENT-TYPE')).to eq('application/hippo')
70
- expect(subject.fetch('content-type')).to eq('application/hippo')
71
- expect(subject.fetch('Content-Length','1')).to eq('1')
72
- expect { subject.fetch('Content-Length')}.to raise_error KeyError
73
- end
74
-
75
- end
76
-
77
- describe "key?" do
78
-
79
- subject { Headers.new 'Content-Type' => 'application/hippo' }
80
-
81
- it "is case insensitive as HTTP headers are case insensitive" do
82
- expect(subject.key?('CONTENT-TYPE')).to be true
83
- expect(subject.key?('CONTENT-LENGTH')).to be false
84
- end
85
- end
86
-
87
- describe "has_key?" do
88
-
89
- subject { Headers.new 'Content-Type' => 'application/hippo' }
90
-
91
- it "is case insensitive as HTTP headers are case insensitive" do
92
- expect(subject.has_key?('CONTENT-TYPE')).to be true
93
- expect(subject.has_key?('CONTENT-LENGTH')).to be false
94
- end
95
- end
96
-
97
- describe "[]=" do
98
-
99
- subject { Headers.new }
100
-
101
- it "does not allow modification" do
102
- expect{ subject['Content-Type'] = 'application/hippo' }.to raise_error /frozen/
103
- end
104
-
105
- end
106
- end
107
- end