pact-support 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +29 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +8 -0
  5. data/CHANGELOG.md +4 -0
  6. data/Gemfile +4 -0
  7. data/Gemfile.lock +80 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +4 -0
  10. data/Rakefile +4 -0
  11. data/lib/pact/configuration.rb +164 -0
  12. data/lib/pact/consumer/request.rb +27 -0
  13. data/lib/pact/consumer_contract.rb +1 -0
  14. data/lib/pact/consumer_contract/consumer_contract.rb +114 -0
  15. data/lib/pact/consumer_contract/file_name.rb +19 -0
  16. data/lib/pact/consumer_contract/headers.rb +51 -0
  17. data/lib/pact/consumer_contract/interaction.rb +73 -0
  18. data/lib/pact/consumer_contract/pact_file.rb +24 -0
  19. data/lib/pact/consumer_contract/request.rb +73 -0
  20. data/lib/pact/consumer_contract/response.rb +51 -0
  21. data/lib/pact/consumer_contract/service_consumer.rb +28 -0
  22. data/lib/pact/consumer_contract/service_provider.rb +28 -0
  23. data/lib/pact/logging.rb +14 -0
  24. data/lib/pact/matchers.rb +1 -0
  25. data/lib/pact/matchers/actual_type.rb +16 -0
  26. data/lib/pact/matchers/base_difference.rb +37 -0
  27. data/lib/pact/matchers/differ.rb +153 -0
  28. data/lib/pact/matchers/difference.rb +13 -0
  29. data/lib/pact/matchers/difference_indicator.rb +26 -0
  30. data/lib/pact/matchers/embedded_diff_formatter.rb +62 -0
  31. data/lib/pact/matchers/expected_type.rb +35 -0
  32. data/lib/pact/matchers/index_not_found.rb +15 -0
  33. data/lib/pact/matchers/list_diff_formatter.rb +101 -0
  34. data/lib/pact/matchers/matchers.rb +139 -0
  35. data/lib/pact/matchers/no_diff_indicator.rb +18 -0
  36. data/lib/pact/matchers/regexp_difference.rb +13 -0
  37. data/lib/pact/matchers/type_difference.rb +16 -0
  38. data/lib/pact/matchers/unexpected_index.rb +11 -0
  39. data/lib/pact/matchers/unexpected_key.rb +11 -0
  40. data/lib/pact/matchers/unix_diff_formatter.rb +114 -0
  41. data/lib/pact/reification.rb +28 -0
  42. data/lib/pact/rspec.rb +53 -0
  43. data/lib/pact/shared/active_support_support.rb +51 -0
  44. data/lib/pact/shared/dsl.rb +76 -0
  45. data/lib/pact/shared/jruby_support.rb +18 -0
  46. data/lib/pact/shared/json_differ.rb +15 -0
  47. data/lib/pact/shared/key_not_found.rb +15 -0
  48. data/lib/pact/shared/null_expectation.rb +31 -0
  49. data/lib/pact/shared/request.rb +97 -0
  50. data/lib/pact/shared/text_differ.rb +14 -0
  51. data/lib/pact/something_like.rb +49 -0
  52. data/lib/pact/support.rb +9 -0
  53. data/lib/pact/support/version.rb +5 -0
  54. data/lib/pact/symbolize_keys.rb +12 -0
  55. data/lib/pact/term.rb +85 -0
  56. data/lib/tasks/pact.rake +29 -0
  57. data/pact-support.gemspec +35 -0
  58. data/spec/lib/pact/consumer/request_spec.rb +25 -0
  59. data/spec/lib/pact/consumer_contract/active_support_support_spec.rb +58 -0
  60. data/spec/lib/pact/consumer_contract/consumer_contract_spec.rb +141 -0
  61. data/spec/lib/pact/consumer_contract/headers_spec.rb +107 -0
  62. data/spec/lib/pact/consumer_contract/interaction_spec.rb +151 -0
  63. data/spec/lib/pact/consumer_contract/request_spec.rb +329 -0
  64. data/spec/lib/pact/consumer_contract/response_spec.rb +73 -0
  65. data/spec/lib/pact/matchers/differ_spec.rb +215 -0
  66. data/spec/lib/pact/matchers/difference_spec.rb +22 -0
  67. data/spec/lib/pact/matchers/embedded_diff_formatter_spec.rb +90 -0
  68. data/spec/lib/pact/matchers/index_not_found_spec.rb +21 -0
  69. data/spec/lib/pact/matchers/list_diff_formatter_spec.rb +120 -0
  70. data/spec/lib/pact/matchers/matchers_spec.rb +500 -0
  71. data/spec/lib/pact/matchers/regexp_difference_spec.rb +20 -0
  72. data/spec/lib/pact/matchers/type_difference_spec.rb +34 -0
  73. data/spec/lib/pact/matchers/unexpected_index_spec.rb +20 -0
  74. data/spec/lib/pact/matchers/unexpected_key_spec.rb +20 -0
  75. data/spec/lib/pact/matchers/unix_diff_formatter_spec.rb +216 -0
  76. data/spec/lib/pact/reification_spec.rb +67 -0
  77. data/spec/lib/pact/shared/dsl_spec.rb +86 -0
  78. data/spec/lib/pact/shared/json_differ_spec.rb +36 -0
  79. data/spec/lib/pact/shared/key_not_found_spec.rb +20 -0
  80. data/spec/lib/pact/shared/request_spec.rb +196 -0
  81. data/spec/lib/pact/shared/text_differ_spec.rb +54 -0
  82. data/spec/lib/pact/something_like_spec.rb +21 -0
  83. data/spec/lib/pact/term_spec.rb +89 -0
  84. data/spec/spec_helper.rb +19 -0
  85. data/spec/support/a_consumer-a_producer.json +32 -0
  86. data/spec/support/a_consumer-a_provider.json +32 -0
  87. data/spec/support/active_support_if_configured.rb +6 -0
  88. data/spec/support/case-insensitive-response-header-matching.json +21 -0
  89. data/spec/support/consumer_contract_template.json +24 -0
  90. data/spec/support/dsl_spec_support.rb +7 -0
  91. data/spec/support/factories.rb +82 -0
  92. data/spec/support/generated_index.md +4 -0
  93. data/spec/support/generated_markdown.md +55 -0
  94. data/spec/support/interaction_view_model.json +63 -0
  95. data/spec/support/interaction_view_model_with_terms.json +50 -0
  96. data/spec/support/markdown_pact.json +48 -0
  97. data/spec/support/missing_provider_states_output.txt +25 -0
  98. data/spec/support/options.json +21 -0
  99. data/spec/support/shared_examples_for_request.rb +94 -0
  100. data/spec/support/spec_support.rb +20 -0
  101. data/spec/support/stubbing.json +22 -0
  102. data/spec/support/term.json +48 -0
  103. data/spec/support/test_app_fail.json +61 -0
  104. data/spec/support/test_app_pass.json +38 -0
  105. data/spec/support/test_app_with_right_content_type_differ.json +23 -0
  106. data/tasks/spec.rake +6 -0
  107. metadata +401 -0
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+ require 'pact/shared/json_differ'
3
+
4
+ module Pact
5
+ describe JsonDiffer do
6
+
7
+ describe ".call" do
8
+
9
+ let(:expected) { {'a' => 'b'} }
10
+
11
+ subject { JsonDiffer.call(expected, actual) }
12
+
13
+ context "when the actual is valid JSON" do
14
+
15
+ let(:actual) { {'a' => 'c'} }
16
+ let(:difference) { {'a' => Pact::Matchers::Difference.new('b', 'c')} }
17
+
18
+ context "when the actual does not equal the expected" do
19
+ it "parses the JSON and returns a diff" do
20
+ expect(subject).to eq(difference)
21
+ end
22
+ end
23
+
24
+ context "when the actual equals the expected" do
25
+ let(:actual) { expected }
26
+ it "parses the JSON and returns an empty diff" do
27
+ expect(subject.any?).to be false
28
+ end
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ require 'pact/shared/key_not_found'
3
+
4
+ module Pact
5
+ describe KeyNotFound do
6
+
7
+ describe "#as_json" do
8
+ it "returns a string representation of the object" do
9
+ expect(subject.as_json).to eq subject.to_s
10
+ end
11
+ end
12
+
13
+ describe "#to_json" do
14
+ it "serialises the object to JSON" do
15
+ expect(subject.to_json).to eq "\"#{subject.to_s}\""
16
+ end
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,196 @@
1
+ require 'spec_helper'
2
+ require 'pact/shared/request'
3
+ require 'pact/shared/key_not_found'
4
+
5
+ module Pact
6
+
7
+ module Request
8
+
9
+ describe Base do
10
+
11
+ class TestRequest < Base
12
+
13
+ def self.key_not_found
14
+ Pact::KeyNotFound.new
15
+ end
16
+
17
+ end
18
+
19
+ subject { TestRequest.new("get", "/", {some: "things"}, {some: "things"} , "some=things") }
20
+
21
+ describe "#to_json" do
22
+ it "renders the keys in a sensible order" do
23
+ expect(subject.to_json).to match(/method.*path.*query.*headers.*body/)
24
+ end
25
+ end
26
+
27
+ describe "#full_path" do
28
+
29
+ subject { TestRequest.new("get", "/something", {}, {some: "things"} , query).full_path }
30
+
31
+ context "with a query that is a Pact::Term" do
32
+ let(:query) { Pact::Term.new(generate: "some=things", matcher: /some/) }
33
+ it "reifies and appends the query" do
34
+ expect(subject).to eq("/something?some=things")
35
+ end
36
+ end
37
+
38
+ context "with a query that is a string" do
39
+ let(:query) { "some=things" }
40
+ it "appends the query" do
41
+ expect(subject).to eq("/something?some=things")
42
+ end
43
+ end
44
+
45
+ context "with an empty query" do
46
+ let(:query) { "" }
47
+ it "does include a query" do
48
+ expect(subject).to eq("/something")
49
+ end
50
+ end
51
+
52
+ context "with a nil query" do
53
+ let(:query) { nil }
54
+ it "does not include a query" do
55
+ expect(subject).to eq("/something")
56
+ end
57
+ end
58
+ end
59
+
60
+ describe "#method_and_path" do
61
+ context "with an empty path" do
62
+ subject { TestRequest.new("get", "", {}, {} , "").method_and_path }
63
+
64
+ it "includes a slash" do
65
+ expect(subject).to eq("GET /")
66
+ end
67
+ end
68
+
69
+ context "with a path" do
70
+ subject { TestRequest.new("get", "/something", {}, {} , "").method_and_path }
71
+
72
+ it "includes the path" do
73
+ expect(subject).to eq("GET /something")
74
+ end
75
+ end
76
+
77
+ context "with a query" do
78
+ subject { TestRequest.new("get", "/something", {}, {} , "test=query").method_and_path }
79
+
80
+ it "includes the query" do
81
+ expect(subject).to eq("GET /something?test=query")
82
+ end
83
+ end
84
+ end
85
+
86
+ describe "#content_type" do
87
+
88
+ subject { TestRequest.new("get", "/something", headers, {} , "") }
89
+ context "when there are no expected headers" do
90
+ let(:headers) { Pact::KeyNotFound.new }
91
+ it "returns nil" do
92
+ expect(subject.send(:content_type)).to be nil
93
+ end
94
+ end
95
+ context "when there is no Content-Type header" do
96
+ let(:headers) { {} }
97
+ it "returns the content-type" do
98
+ expect(subject.send(:content_type)).to be nil
99
+ end
100
+ end
101
+ context "when there is a content-type header (" do
102
+ let(:headers) { {'content-type' => 'blah'} }
103
+ it "returns the content-type" do
104
+ expect(subject.send(:content_type)).to eq 'blah'
105
+ end
106
+ end
107
+ end
108
+
109
+ describe "modifies_resource?" do
110
+
111
+ subject { Pact::Request::Expected.from_hash(request).modifies_resource? }
112
+
113
+ shared_examples_for "may modify resource" do
114
+ context "when the request body is not specified" do
115
+ let(:request) { {method: http_method, path: '/'} }
116
+
117
+ it "returns false" do
118
+ expect(subject).to be false
119
+ end
120
+ end
121
+
122
+ context "when the request body is an empty Hash" do
123
+ let(:request) { {method: http_method, path: '/', body: {}} }
124
+
125
+ it "returns true" do
126
+ expect(subject).to be true
127
+ end
128
+ end
129
+
130
+ context "when the request body is a Hash and not empty" do
131
+ let(:request) { {method: http_method, path: '/', body: {some: 'body'}} }
132
+
133
+ it "returns true" do
134
+ expect(subject).to be true
135
+ end
136
+ end
137
+
138
+ context "when the request body is a String and not empty" do
139
+ let(:request) { {method: http_method, path: '/', body: 'some body'} }
140
+
141
+ it "returns true" do
142
+ expect(subject).to be true
143
+ end
144
+ end
145
+
146
+ context "when the request body is a String and is empty" do
147
+ let(:request) { {method: http_method, path: '/', body: ''} }
148
+
149
+ it "returns true" do
150
+ expect(subject).to be true
151
+ end
152
+ end
153
+ end
154
+
155
+ describe "when the method is PUT" do
156
+ let(:http_method) { :put }
157
+ include_examples 'may modify resource'
158
+ end
159
+
160
+ describe "when the method is POST" do
161
+ let(:http_method) { :post }
162
+ include_examples 'may modify resource'
163
+ end
164
+
165
+ describe "when the method is PATCH" do
166
+ let(:http_method) { :post }
167
+ include_examples 'may modify resource'
168
+ end
169
+
170
+ shared_examples_for "does not modify resource" do
171
+ let(:request) { {method: http_method, path: '/', body: {some: 'body'}} }
172
+
173
+ it "returns false" do
174
+ expect(subject).to be false
175
+ end
176
+ end
177
+
178
+ describe "when the method is GET" do
179
+ let(:http_method) { :get }
180
+ include_examples 'does not modify resource'
181
+ end
182
+
183
+ describe "when the method is DELETE" do
184
+ let(:http_method) { :delete }
185
+ include_examples 'does not modify resource'
186
+ end
187
+
188
+ describe "when the method is HEAD" do
189
+ let(:http_method) { :head }
190
+ include_examples 'does not modify resource'
191
+ end
192
+ end
193
+
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+ require 'pact/shared/text_differ'
3
+
4
+ module Pact
5
+ describe TextDiffer do
6
+
7
+ describe ".call" do
8
+
9
+ subject { TextDiffer.call expected, actual }
10
+
11
+ let(:expected) { "This is the string you are looking for" }
12
+
13
+ context "when the expected and actual are both strings" do
14
+
15
+ context "when they equal each other" do
16
+ let(:actual) { "This is the string you are looking for" }
17
+
18
+ it "returns an empty diff" do
19
+ expect(subject.any?).to be false
20
+ end
21
+ end
22
+
23
+ context "when they don't equal each other" do
24
+ let(:actual) { "This is not the string you are looking for" }
25
+
26
+ it "returns the diff" do
27
+ expect(subject).to eq Pact::Matchers::Difference.new(expected, actual)
28
+ end
29
+ end
30
+ end
31
+
32
+ context "when the actual is not a String" do
33
+ let(:actual) { {some: 'hash'} }
34
+ let(:difference) { Pact::Matchers::Difference.new(expected, actual)}
35
+ it "returns the diff" do
36
+ expect(subject)
37
+ end
38
+ end
39
+
40
+ context "when the expected and actual are both objects" do
41
+ let(:actual) { {some: 'hash', blah: 'blah'} }
42
+ let(:expected) { {some: 'hash'} }
43
+ let(:difference) { Pact::Matchers::Difference.new(expected, actual)}
44
+
45
+ it "returns the diff using the JSON matching logic, allowing extra keys. But should it really if the expected Content-Type isn't actually JSON?" do
46
+ expect(subject)
47
+ end
48
+
49
+ it "potentially should treat both expected and actual as Strings"
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ module Pact
4
+ describe SomethingLike do
5
+ describe 'json_create' do
6
+ let(:json) do
7
+ '
8
+ {
9
+ "json_class": "Pact::SomethingLike",
10
+ "contents" : { "thing" : "blah" }
11
+ }
12
+ '
13
+ end
14
+ subject { SomethingLike.json_create(JSON.parse(json)) }
15
+ it "creates a SomethingLike object from json" do
16
+ expect(subject).to eq(SomethingLike.new({"thing" => "blah"}))
17
+ end
18
+ end
19
+ end
20
+
21
+ end
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+
3
+ module Pact
4
+ describe Term do
5
+
6
+ describe 'initialize' do
7
+ let(:matcher) { /e/ }
8
+ let(:generate) { 'apple'}
9
+ subject { Term.new(generate: generate, matcher: matcher) }
10
+ context "when a matcher and generate are specified" do
11
+ context "when the matcher matches the generated value" do
12
+ it 'does not raise an exception' do
13
+ subject
14
+ end
15
+ end
16
+
17
+ context "when the matcher does not match the generated value" do
18
+ let(:generate) { 'banana' }
19
+ it 'raises an exception' do
20
+ expect { subject }.to raise_error /does not match/
21
+ end
22
+ end
23
+ end
24
+ context 'when a matcher is not specified' do
25
+ let(:matcher) { nil }
26
+ it 'raises an exception' do
27
+ expect { subject }.to raise_error /Please specify a matcher/
28
+ end
29
+ end
30
+ context 'when a generate is not specified' do
31
+ let(:generate) { nil }
32
+ it 'raises an exception' do
33
+ expect { subject }.to raise_error /Please specify a value/
34
+ end
35
+ end
36
+ end
37
+
38
+ describe "equality" do
39
+ context "when the matcher and generate attrs are the same" do
40
+ let(:this) { Term.new(generate: 'A', matcher: /A/) }
41
+ let(:that) { Term.new(generate: 'A', matcher: /A/) }
42
+
43
+ it "is equal" do
44
+ expect(this).to eq that
45
+ end
46
+ end
47
+
48
+ context "when the generate attrs are different" do
49
+ let(:this) { Term.new(generate: 'A', matcher: /.*/) }
50
+ let(:that) { Term.new(generate: 'B', matcher: /.*/) }
51
+
52
+ it "is not equal" do
53
+ expect(this).to_not eq that
54
+ end
55
+ end
56
+
57
+ context "when the matcher attrs are different" do
58
+ let(:this) { Term.new(matcher: /A/, generate: 'AB') }
59
+ let(:that) { Term.new(matcher: /B/, generate: 'AB') }
60
+
61
+ it "is not equal" do
62
+ expect(this).to_not eq that
63
+ end
64
+ end
65
+ end
66
+
67
+ describe 'empty?' do
68
+
69
+ subject { Term.new(generate: 'some', matcher: /some/) }
70
+
71
+ it 'should return false' do
72
+ expect(subject).to_not be_empty
73
+ end
74
+
75
+ end
76
+
77
+ describe 'unpack_regexps' do
78
+ let(:term) { Term.new(generate: 'some', matcher: /s/) }
79
+ let(:body) { [{a: [{b: term}], c:term, d: 1, e: 'blah'}] }
80
+ let(:expected) { [{:a=>[{:b=>/s/}], :c=>/s/, :d=>1, :e=>"blah"}] }
81
+
82
+ it "returns a structure with the Pact::Terms replaced by their regexps" do
83
+ expect(Term.unpack_regexps(body)).to eq expected
84
+ end
85
+
86
+ end
87
+
88
+ end
89
+ end
@@ -0,0 +1,19 @@
1
+ require 'rspec'
2
+ require 'fakefs/spec_helpers'
3
+ require 'rspec'
4
+ require 'pact/support'
5
+ require 'webmock/rspec'
6
+ require 'support/factories'
7
+ require 'support/spec_support'
8
+
9
+
10
+ WebMock.disable_net_connect!(allow_localhost: true)
11
+
12
+ require './spec/support/active_support_if_configured'
13
+
14
+ RSpec.configure do | config |
15
+ config.include(FakeFS::SpecHelpers, :fakefs => true)
16
+
17
+ config.include Pact::SpecSupport
18
+ end
19
+
@@ -0,0 +1,32 @@
1
+ {
2
+ "producer": {
3
+ "name": "an old producer"
4
+ },
5
+ "consumer": {
6
+ "name": "a consumer"
7
+ },
8
+ "interactions": [
9
+ {
10
+ "description": "request one",
11
+ "request": {
12
+ "method": "get",
13
+ "path": "/path_one"
14
+ },
15
+ "response": {
16
+ },
17
+ "producer_state": "state one"
18
+ },
19
+ {
20
+ "description": "request two",
21
+ "request": {
22
+ "method": "get",
23
+ "path": "/path_two"
24
+ },
25
+ "response": {
26
+ }
27
+ }
28
+ ],
29
+ "metadata": {
30
+ "pactSpecificationVersion": "1.0"
31
+ }
32
+ }