pact-support 0.0.2 → 0.0.3

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.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- NWE0OThiMTk0ZTVjOTU1YWE5MGZmODZiZDM2MjIzNTc3M2YwYTZhYw==
5
- data.tar.gz: !binary |-
6
- NGE1ZmFlOGY4M2NjZTUyMTMxODhhYzNkODU0YmU4ZjY2OGNiYWEwMw==
2
+ SHA1:
3
+ metadata.gz: c22fbc42f806850fdf59aae86c0ab60221e53b31
4
+ data.tar.gz: d861be0013364c930b5d092caa37fab70a3d9c5c
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- M2QzYmJlY2M5MzJjMWQwY2RiOTRlNDBhMWRkYTc2MDc4Mjk3MjY4NDIzZWYw
10
- Zjc3ODE5OWJhN2JiYzk5MDU0NzI2YWI0Mjg4YmUwMmQ0NjhhZWVmMTEwZDI2
11
- NDNlOTYzYjI2NmQ4YWM4YTVlMTQ2NDlmMWFkOTE5OTAzOWVhYWY=
12
- data.tar.gz: !binary |-
13
- YTBlNGY3YWQ2MzViNjgwNTdiODI2YzM0MzNiMGJiOTAxNTkyOTVmNzAzZTQw
14
- OWY4YTA5YTAwYmZjNTZhZWQ4MmU3Y2NkZmNlNjJkZjcxYWUyNWY4NmUxNzY3
15
- ODFkODcxNjkxYjZiZjhkNTFmZTJlOWM0NThjZDAyYTEzZGUyMWI=
6
+ metadata.gz: ce97bbeb237b4ed9dd74251120aab5a1ad6a452057c0fdf4f7236c811fe35a944bc3a89263983782bbc304104ea2e2f36b37a2b40c0455cf8c647ad26e0c249e
7
+ data.tar.gz: 92b643e2648be79ccf6e7221d7d3a30e3a735fe6cc04f0cede398a7ac6bc720a3d0564d8da9ade013003d616c87b39ae1bff815bb7d8dbb5346f8cb3764b4d0c
@@ -2,6 +2,10 @@ Do this to generate your change history
2
2
 
3
3
  git log --pretty=format:' * %h - %s (%an, %ad)'
4
4
 
5
+ ### 0.0.3 (17 October 2014)
6
+
7
+ * bab0b34 - Added possibility to provide queries as Hash. Then order of parameters in the query is not longer relevant. (André Allavena, Tue Oct 14 00:24:38 2014 +1000)
8
+
5
9
  ### 0.0.2 (12 October 2014)
6
10
 
7
11
  * e7080fe - Added a QueryString class in preparation for a QueryHash class (Beth, Sun Oct 12 14:32:15 2014 +1100)
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pact-support (0.0.2)
4
+ pact-support (0.0.3)
5
5
  awesome_print (~> 1.1)
6
6
  find_a_port (~> 1.0.1)
7
7
  json
@@ -46,7 +46,7 @@ GEM
46
46
  rspec-core (~> 3.1.0)
47
47
  rspec-expectations (~> 3.1.0)
48
48
  rspec-mocks (~> 3.1.0)
49
- rspec-core (3.1.6)
49
+ rspec-core (3.1.7)
50
50
  rspec-support (~> 3.1.0)
51
51
  rspec-expectations (3.1.2)
52
52
  diff-lcs (>= 1.2.0, < 2.0)
@@ -0,0 +1,16 @@
1
+ require_relative 'query_hash'
2
+ require_relative 'query_string'
3
+
4
+ module Pact
5
+ class Query
6
+
7
+ def self.create query
8
+ if query.is_a? Hash
9
+ Pact::QueryHash.new(query)
10
+ else
11
+ Pact::QueryString.new(query)
12
+ end
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,55 @@
1
+ require 'pact/shared/active_support_support'
2
+ require 'pact/matchers'
3
+ require 'pact/symbolize_keys'
4
+
5
+ module Pact
6
+ class QueryHash
7
+
8
+ include ActiveSupportSupport
9
+ include Pact::Matchers
10
+ include SymbolizeKeys
11
+
12
+ def initialize query
13
+ @hash = query.nil? ? query : convert_to_hash_of_arrays(query)
14
+ end
15
+
16
+ def convert_to_hash_of_arrays query
17
+ symbolize_keys(query).inject({}) {|h,(k,v)| h[k] = v.is_a?(Array) ? v : [v] ; h }
18
+ end
19
+
20
+ def as_json opts = {}
21
+ @hash
22
+ end
23
+
24
+ def to_json opts = {}
25
+ as_json(opts).to_json(opts)
26
+ end
27
+
28
+ def eql? other
29
+ self == other
30
+ end
31
+
32
+ def == other
33
+ QueryHash === other && other.query == query
34
+ end
35
+
36
+ # other will always be a QueryString, not a QueryHash, as it will have ben created
37
+ # from the actual query string.
38
+ def difference(other)
39
+ diff(query, symbolize_keys(CGI::parse(other.query)))
40
+ end
41
+
42
+ def query
43
+ @hash
44
+ end
45
+
46
+ def to_s
47
+ @hash.inspect
48
+ end
49
+
50
+ def empty?
51
+ @hash && @hash.empty?
52
+ end
53
+
54
+ end
55
+ end
@@ -1,30 +1,38 @@
1
1
  require 'randexp'
2
-
2
+ require 'rack/utils'
3
+ # reqiore 'active_support/core_ext/object/to_param'
3
4
  module Pact
4
5
  module Reification
6
+ include ActiveSupportSupport
5
7
 
6
8
  def self.from_term(term)
7
9
  case term
8
10
  when Pact::Term, Regexp, Pact::SomethingLike
9
- term.generate
11
+ term.generate
10
12
  when Hash
11
13
  term.inject({}) do |mem, (key,term)|
12
14
  mem[key] = from_term(term)
13
- mem
14
- end
15
- when Array
16
- term.inject([]) do |mem, term|
17
- mem << from_term(term)
18
15
  mem
19
16
  end
17
+ when Array
18
+ term.map{ |t| from_term(t)}
20
19
  when Pact::Request::Base
21
20
  from_term(term.to_hash)
22
21
  when Pact::QueryString
23
22
  from_term(term.query)
23
+ when Pact::QueryHash
24
+ term.query.map { |k, v|
25
+ if v.nil?
26
+ k
27
+ elsif v.is_a?(Array) #For cases where there are multiple instance of the same parameter
28
+ v.map { |x| "#{k}=#{from_term(x)}"}.join('&')
29
+ else
30
+ "#{k}=#{from_term(v)}"
31
+ end
32
+ }.join('&')
24
33
  else
25
34
  term
26
35
  end
27
36
  end
28
-
29
37
  end
30
38
  end
@@ -1,7 +1,7 @@
1
1
  require 'pact/matchers'
2
2
  require 'pact/symbolize_keys'
3
3
  require 'pact/consumer_contract/headers'
4
- require 'pact/consumer_contract/query_string'
4
+ require 'pact/consumer_contract/query'
5
5
 
6
6
  module Pact
7
7
 
@@ -19,7 +19,7 @@ module Pact
19
19
  @path = path.chomp('/')
20
20
  @headers = Hash === headers ? Headers.new(headers) : headers # Could be a NullExpectation - TODO make this more elegant
21
21
  @body = body
22
- @query = is_unspecified?(query) ? query : Pact::QueryString.new(query)
22
+ @query = is_unspecified?(query) ? query : Pact::Query.create(query)
23
23
  end
24
24
 
25
25
  def to_json(options = {})
@@ -1,5 +1,5 @@
1
1
  module Pact
2
2
  module Support
3
- VERSION = "0.0.2"
3
+ VERSION = "0.0.3"
4
4
  end
5
5
  end
@@ -299,7 +299,117 @@ module Pact
299
299
  end
300
300
  end
301
301
 
302
- context "when a string is expected, but a number is found" do
302
+ context 'when a query is specified' do
303
+ context 'when the queries are defined by hashes, order does not matter' do
304
+ let(:expected_query) { { params: 'hello', params2: 'world', params3: 'small' } }
305
+ let(:actual_query) { 'params3=small&params2=world&params=hello' }
306
+
307
+ it "does match" do
308
+ expect(subject.matches? actual_request).to be true
309
+ end
310
+ end
311
+
312
+ context 'when the queries are defined by hashes, order does not matter but content does' do
313
+ let(:expected_query) { { params: 'hello', params2: 'world', params3: 'small' } }
314
+ let(:actual_query) { 'params3=big&params2=world&params=hello' }
315
+
316
+ it "does not match" do
317
+ expect(subject.matches? actual_request).to be false
318
+ end
319
+ end
320
+
321
+ context 'when the queries are defined by hashes, with extra unmatched parameters' do
322
+ let(:expected_query) { { params: 'hello', params2: 'world', params3: 'small' } }
323
+ let(:actual_query) { 'params2=world&params=hello' }
324
+
325
+ it "does not match" do
326
+ expect(subject.matches? actual_request).to be false
327
+ end
328
+ end
329
+
330
+ context 'when the queries are defined by hashes holding Pact Terms, order does not matter but content does' do
331
+ let(:expected_query) { { params: 'hello', params2: Term.new(generate: 'world', matcher: /w\w+/), params3: 'small' } }
332
+ let(:actual_query) { 'params3=small&params=hello&params2=wroom'}
333
+
334
+ it "does match" do
335
+ expect(subject.matches? actual_request).to be true
336
+ end
337
+ end
338
+
339
+ context 'when the queries are defined by hashes holding Pact Terms and the regex does not match' do
340
+ let(:expected_query) { { params: 'hello', params2: Term.new(generate: 'world', matcher: /w\w+/), params3: 'small' } }
341
+ let(:actual_query) { 'params3=small&params=hello&params2=bonjour'}
342
+
343
+ it "does not match" do
344
+ expect(subject.matches? actual_request).to be false
345
+ end
346
+ end
347
+
348
+ context 'when the query is a hash containing arrays, to denote multiple parameters with the same name' do
349
+ let(:expected_query) {
350
+ { simple_param: "hi",
351
+ double_param: ["hello", "world"],
352
+ simple2: "bye",
353
+ }
354
+ }
355
+ context 'when the multipe terms are in the correct order - order 1' do
356
+ let(:actual_query) {['simple_param=hi', 'double_param=hello', 'double_param=world', 'simple2=bye'].join('&')}
357
+ it "does match" do
358
+ expect(subject.matches? actual_request).to be true
359
+ end
360
+ end
361
+ context 'when the multipe terms are in the correct order - order 2' do
362
+ let(:actual_query) {['simple_param=hi', 'double_param=hello', 'simple2=bye', 'double_param=world'].join('&')}
363
+ it "does match" do
364
+ expect(subject.matches? actual_request).to be true
365
+ end
366
+ end
367
+ context 'when the multipe terms are in the correct order - order 3' do
368
+ let(:actual_query) {['simple2=bye', 'double_param=hello', 'double_param=world', 'simple_param=hi'].join('&')}
369
+ it "does match" do
370
+ expect(subject.matches? actual_request).to be true
371
+ end
372
+ end
373
+ context 'when the multiple terms are in incorrect order' do
374
+ let(:actual_query) {['simple2=bye', 'double_param=world', 'double_param=hello', 'simple_param=hi'].join('&')}
375
+ it "does not match" do
376
+ expect(subject.matches? actual_request).to be false
377
+ end
378
+ end
379
+ context 'when the first of the multiple terms is missing' do
380
+ let(:actual_query) {['simple_param=hi', 'double_param=world', 'simple2=bye', ].join('&')}
381
+ it "does not match" do
382
+ expect(subject.matches? actual_request).to be false
383
+ end
384
+ end
385
+ context 'when the last of the multiple terms is missing' do
386
+ let(:actual_query) {['simple_param=hi', 'double_param=hello', 'simple2=bye', ].join('&')}
387
+ it "does not match" do
388
+ expect(subject.matches? actual_request).to be false
389
+ end
390
+ end
391
+ end
392
+
393
+ context 'when the query does not contain multiple params of the same name, but the request does' do
394
+ let(:expected_query) { {param1: 'hi', param2: 'there'} }
395
+ context 'when the param is duplicated' do
396
+ let(:actual_query) { 'param1=hi&param2=there&param2=there'}
397
+ it "does not match" do
398
+ expect(subject.matches? actual_request).to be false
399
+ end
400
+ end
401
+ context 'when the duplicated param has different values' do
402
+ let(:actual_query) { 'param1=hi&param2=there&param2=overthere' }
403
+ it "does not match" do
404
+ expect(subject.matches? actual_request).to be false
405
+ end
406
+ end
407
+ end
408
+ end
409
+
410
+
411
+
412
+ context "when in the body a string is expected, but a number is found" do
303
413
  let(:actual_body) { { thing: 123} }
304
414
  let(:expected_body) { { thing: "123" } }
305
415
 
@@ -75,5 +75,39 @@ module Pact
75
75
 
76
76
  end
77
77
 
78
+ context "when Hash Query" do
79
+
80
+ subject { Reification.from_term(query)}
81
+
82
+ let(:query) { QueryHash.new( {param: 'hello', extra: 'world'})}
83
+
84
+ it "returns the hash in the natural order" do
85
+ expect(subject).to eq("param=hello&extra=world")
86
+ end
87
+ end
88
+
89
+ context "when Hash Query with embeded terms" do
90
+
91
+ subject { Reification.from_term(query)}
92
+
93
+ let(:query) { QueryHash.new( {param: 'hello', extra: Pact::Term.new(generate: "wonderworld", matcher: /\w+world/)})}
94
+
95
+ it "returns the hash in the natural order, and fills in Terms appropriately" do
96
+ expect(subject).to eq("param=hello&extra=wonderworld")
97
+ end
98
+
99
+ end
100
+ context "when Hash Query with Arrays and multiple params with the same name" do
101
+
102
+ subject { Reification.from_term(query)}
103
+
104
+ let(:query) { QueryHash.new( {param: 'hello', double: [Pact::Term.new(generate: "wonder", matcher: /\w+/), 'world'], simple: 'bye'})}
105
+
106
+ it "returns the hash in the natural order, and fills in Terms appropriately" do
107
+ expect(subject).to eq("param=hello&double=wonder&double=world&simple=bye")
108
+ end
109
+
110
+ end
111
+
78
112
  end
79
113
  end
@@ -42,6 +42,13 @@ module Pact
42
42
  end
43
43
  end
44
44
 
45
+ context "with a query that is a hash" do
46
+ let(:query) { { params: 'hello', params2: Term.new(generate: 'world', matcher: /w\w+/), params3: 'small' } }
47
+ it "appends the query" do
48
+ expect(subject).to eq("/something?params=hello&params2=world&params3=small")
49
+ end
50
+ end
51
+
45
52
  context "with an empty query" do
46
53
  let(:query) { "" }
47
54
  it "does include a query" do
@@ -41,6 +41,39 @@ shared_examples "a request" do
41
41
  expect(subject.full_path).to eq "/path?a"
42
42
  end
43
43
  end
44
+ context "with a path and a query that is a QueryString" do
45
+ subject { described_class.from_hash({:path => '/path', :method => 'get', :headers => {}, :query => Pact::Term.new(generate: 'a', matcher: /a/)}) }
46
+ it "returns the full path with reified path" do
47
+ expect(subject.full_path).to eq "/path?a"
48
+ end
49
+ end
50
+ context "with a path and a query that is a QueryHash" do
51
+ subject { described_class.from_hash({:path => '/path', :method => 'get', :headers => {}, :query => {param: 'hello', extra: 'world'}}) }
52
+ it "returns the full path with reified path" do
53
+ expect(subject.full_path).to eq "/path?param=hello&extra=world"
54
+ end
55
+ end
56
+ context "with a path and a query that is a QueryHash with an embeded Term" do
57
+ subject { described_class.from_hash({:path => '/path', :method => 'get', :headers => {},
58
+ :query => {param: 'hello', extra: Pact::Term.new(generate: "wonderworld", matcher: /\w+world/)}}) }
59
+ it "returns the full path with reified path" do
60
+ expect(subject.full_path).to eq "/path?param=hello&extra=wonderworld"
61
+ end
62
+ end
63
+ context "with a path and a query that has multiple terms" do
64
+ subject { described_class.from_hash({:path => '/path', :method => 'get', :headers => {},
65
+ :query => {param: 'hello', simple: 'hi', double: [ 'hello', 'world'], last: 'gone'}}) }
66
+ it "returns the full path with reified path" do
67
+ expect(subject.full_path).to eq "/path?param=hello&simple=hi&double=hello&double=world&last=gone"
68
+ end
69
+ end
70
+ context "with a path and a query that has multiple terms including terms" do
71
+ subject { described_class.from_hash({:path => '/path', :method => 'get', :headers => {},
72
+ :query => {param: 'hello', simple: 'hi', double: [ 'hello', Pact::Term.new(generate: "wonderworld", matcher: /\w+world/)], last: 'gone'}}) }
73
+ it "returns the full path with reified path" do
74
+ expect(subject.full_path).to eq "/path?param=hello&simple=hi&double=hello&double=wonderworld&last=gone"
75
+ end
76
+ end
44
77
  end
45
78
 
46
79
  describe "building from a hash" do
@@ -71,10 +104,15 @@ shared_examples "a request" do
71
104
  expect(subject.body).to eq 'hello mallory'
72
105
  end
73
106
 
74
- it "extracts the query" do
107
+ it "extracts the string query" do
75
108
  expect(subject.query).to eq Pact::QueryString.new('query')
76
109
  end
77
110
 
111
+ it "extracts the hash query" do
112
+ raw_request['query']= {param: 'hello', extra: 'world'}
113
+ expect(subject.query).to eq Pact::QueryHash.new( {param: 'hello', extra: 'world'})
114
+ end
115
+
78
116
  it "blows up if method is absent" do
79
117
  raw_request.delete 'method'
80
118
  expect { described_class.from_hash(raw_request) }.to raise_error
@@ -91,4 +129,4 @@ shared_examples "a request" do
91
129
  end
92
130
 
93
131
  end
94
- end
132
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pact-support
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Fraser
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2014-10-12 00:00:00.000000000 Z
15
+ date: 2014-10-17 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: randexp
@@ -32,14 +32,14 @@ dependencies:
32
32
  name: rspec
33
33
  requirement: !ruby/object:Gem::Requirement
34
34
  requirements:
35
- - - ! '>='
35
+ - - '>='
36
36
  - !ruby/object:Gem::Version
37
37
  version: '2.14'
38
38
  type: :runtime
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
41
41
  requirements:
42
- - - ! '>='
42
+ - - '>='
43
43
  - !ruby/object:Gem::Version
44
44
  version: '2.14'
45
45
  - !ruby/object:Gem::Dependency
@@ -74,14 +74,14 @@ dependencies:
74
74
  name: json
75
75
  requirement: !ruby/object:Gem::Requirement
76
76
  requirements:
77
- - - ! '>='
77
+ - - '>='
78
78
  - !ruby/object:Gem::Version
79
79
  version: '0'
80
80
  type: :runtime
81
81
  prerelease: false
82
82
  version_requirements: !ruby/object:Gem::Requirement
83
83
  requirements:
84
- - - ! '>='
84
+ - - '>='
85
85
  - !ruby/object:Gem::Version
86
86
  version: '0'
87
87
  - !ruby/object:Gem::Dependency
@@ -116,14 +116,14 @@ dependencies:
116
116
  name: thor
117
117
  requirement: !ruby/object:Gem::Requirement
118
118
  requirements:
119
- - - ! '>='
119
+ - - '>='
120
120
  - !ruby/object:Gem::Version
121
121
  version: '0'
122
122
  type: :runtime
123
123
  prerelease: false
124
124
  version_requirements: !ruby/object:Gem::Requirement
125
125
  requirements:
126
- - - ! '>='
126
+ - - '>='
127
127
  - !ruby/object:Gem::Version
128
128
  version: '0'
129
129
  - !ruby/object:Gem::Dependency
@@ -158,14 +158,14 @@ dependencies:
158
158
  name: pry
159
159
  requirement: !ruby/object:Gem::Requirement
160
160
  requirements:
161
- - - ! '>='
161
+ - - '>='
162
162
  - !ruby/object:Gem::Version
163
163
  version: '0'
164
164
  type: :development
165
165
  prerelease: false
166
166
  version_requirements: !ruby/object:Gem::Requirement
167
167
  requirements:
168
- - - ! '>='
168
+ - - '>='
169
169
  - !ruby/object:Gem::Version
170
170
  version: '0'
171
171
  - !ruby/object:Gem::Dependency
@@ -200,14 +200,14 @@ dependencies:
200
200
  name: activesupport
201
201
  requirement: !ruby/object:Gem::Requirement
202
202
  requirements:
203
- - - ! '>='
203
+ - - '>='
204
204
  - !ruby/object:Gem::Version
205
205
  version: '0'
206
206
  type: :development
207
207
  prerelease: false
208
208
  version_requirements: !ruby/object:Gem::Requirement
209
209
  requirements:
210
- - - ! '>='
210
+ - - '>='
211
211
  - !ruby/object:Gem::Version
212
212
  version: '0'
213
213
  description:
@@ -238,6 +238,8 @@ files:
238
238
  - lib/pact/consumer_contract/headers.rb
239
239
  - lib/pact/consumer_contract/interaction.rb
240
240
  - lib/pact/consumer_contract/pact_file.rb
241
+ - lib/pact/consumer_contract/query.rb
242
+ - lib/pact/consumer_contract/query_hash.rb
241
243
  - lib/pact/consumer_contract/query_string.rb
242
244
  - lib/pact/consumer_contract/request.rb
243
245
  - lib/pact/consumer_contract/response.rb
@@ -338,17 +340,17 @@ require_paths:
338
340
  - lib
339
341
  required_ruby_version: !ruby/object:Gem::Requirement
340
342
  requirements:
341
- - - ! '>='
343
+ - - '>='
342
344
  - !ruby/object:Gem::Version
343
345
  version: '0'
344
346
  required_rubygems_version: !ruby/object:Gem::Requirement
345
347
  requirements:
346
- - - ! '>='
348
+ - - '>='
347
349
  - !ruby/object:Gem::Version
348
350
  version: '0'
349
351
  requirements: []
350
352
  rubyforge_project:
351
- rubygems_version: 2.1.11
353
+ rubygems_version: 2.0.14
352
354
  signing_key:
353
355
  specification_version: 4
354
356
  summary: Shared code for Pact gems