api_matchers 0.3.0 → 0.4.0

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
- YTM2MmZhOGZkNjQ4N2Q1M2ZjMTU0ODhmZjE1ZDBiMjljZTE1YTk4NA==
5
- data.tar.gz: !binary |-
6
- ZGQzMDNiNTQ2YmI2YmU1YWQzZjlkZmZmODk2OTVkZGFmODE1NDc0MA==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- Y2RhNTE5NzdmYTkwMjE0ZTVlM2EwZmM0ZjY2Y2U3MWQ2ZjA5OWIwMjY2NGVh
10
- MmMzNGZhYmE0MzA0OGQ2NjQxYTgyNTJkMDI4YjhmNDJhZmM0NGNmMjAxZjQw
11
- ZTRjM2NlNjI4ZDc5ZjYwZTM2ZTY0ZWIwYTQ1MzRiNmNlOGQ2ZDg=
12
- data.tar.gz: !binary |-
13
- MzIyNmE0NmIwOGQxODRhMmJkN2ZmNmZkMTllOTFjMGJjMzc1MjQ3ZGY4MWZl
14
- NWJjMGFiNjA3ZGRmYjZhMzBkOTAxNzgxM2JkOWQyNzUxNmI5NGRkYWRlMDA1
15
- NTI4MWEzNDY1MGY0YzI2NzYzMGYxYzEwZDAwNDQyZGUyZTg3NjQ=
2
+ SHA1:
3
+ metadata.gz: 55a5fba1fb8dd8e0534a451e2db5af8662312b0e
4
+ data.tar.gz: dfe3690699a99aeffe353d50c7401a5eb741e084
5
+ SHA512:
6
+ metadata.gz: 8a28c82e8bfeede2915149c45e89f0698c9c1600dfeaefb4ddda8e06ad0e88649144a59dd0f40cbe4f2b6b2465b5ea5ca0b205d41bcf8110a416354691d12582
7
+ data.tar.gz: 0d594066a2ba47024bb9cd1126578e0cef31f81a6b97ad009d8f7161f7290384a7a641127b35639b02043662f8b56f44acfeba49c14ed73f75999a6db521c443
data/.travis.yml ADDED
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0
5
+ - jruby
6
+ before_install:
7
+ - export DISPLAY=:99.0
8
+ - sh -e /etc/init.d/xvfb start
9
+ script:
10
+ - bundle exec rspec
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source 'https://rubygems.org'
1
+ source 'http://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in api_matchers.gemspec
4
4
  gemspec
data/README.markdown CHANGED
@@ -1,30 +1,40 @@
1
- # API Matchers
1
+ # API Matchers [![Build Status](https://travis-ci.org/tomas-stefano/api_matchers.png?branch=master)](https://travis-ci.org/tomas-stefano/api_matchers)
2
2
 
3
- Collection of RSpec matchers for create your API.
3
+ Collection of RSpec matchers for your API.
4
4
 
5
5
  ## Response Body Matchers
6
6
 
7
- * have_node
8
- * have_json_node
9
- * have_xml_node
7
+ * `have_node`
8
+ * `have_json_node`
9
+ * `have_xml_node`
10
+ * `have_json`
10
11
 
11
- # Response Status Matchers
12
+ ## Response Status Matchers
12
13
 
13
- * be_ok_
14
- * create_resource
15
- * be_a_bad_request
16
- * be_unauthorized
17
- * be_internal_server_error
18
- * be_not_found
14
+ * `be_ok`
15
+ * `create_resource`
16
+ * `be_a_bad_request`
17
+ * `be_unauthorized`
18
+ * `be_internal_server_error`
19
+ * `be_not_found`
19
20
 
20
- # Other Matcher
21
+ ## Other Matchers
21
22
 
22
- * be_in_xml
23
- * be_a_json
23
+ * `be_in_xml`
24
+ * `be_in_json`
24
25
 
25
26
  ## Install
26
27
 
27
- gem install api_matchers
28
+ Include the gem to your test group in you Gemfile:
29
+
30
+ ```ruby
31
+ group :test do
32
+ gem 'api_matchers'
33
+ # other gems
34
+ end
35
+ ```
36
+
37
+ Or install it manually: `gem install api_matchers`.
28
38
 
29
39
  ## Usage
30
40
 
@@ -33,9 +43,9 @@ Collection of RSpec matchers for create your API.
33
43
  To include all this matchers you need to include the APIMatchers::RSpecMatchers module:
34
44
 
35
45
  ```ruby
36
- RSpec.configure do |config|
37
- config.include APIMatchers::RSpecMatchers
38
- end
46
+ RSpec.configure do |config|
47
+ config.include APIMatchers::RSpecMatchers
48
+ end
39
49
  ```
40
50
 
41
51
  ### Have Node Matcher
@@ -46,33 +56,33 @@ The have_node matcher parse the actual and see if have the expcted node with the
46
56
  You can verify if node exists:
47
57
 
48
58
  ```ruby
49
- '{ "transaction": { "id": 54, "status": "paid" } }'.should have_node(:transaction)
59
+ '{ "transaction": { "id": 54, "status": "paid" } }'.should have_node(:transaction)
50
60
  ```
51
61
 
52
62
  Or if node exist with a value:
53
63
 
54
64
  ```ruby
55
- '{ "transaction": { "id": 54, "status": "paid" } }'.should have_node(:id).with(54)
65
+ '{ "transaction": { "id": 54, "status": "paid" } }'.should have_node(:id).with(54)
56
66
  ```
57
67
 
58
68
  ```ruby
59
- '{ "error": "not_authorized" }'.should have_node(:error).with('not_authorized')
69
+ '{ "error": "not_authorized" }'.should have_node(:error).with('not_authorized')
60
70
  ```
61
71
 
62
72
  ```ruby
63
- '{"parcels":1 }'.should have_node(:parcels).with(1)
73
+ '{"parcels":1 }'.should have_node(:parcels).with(1)
64
74
  ```
65
75
 
66
76
  To see the json node and see if include a text, you can do this:
67
77
 
68
78
  ```ruby
69
- '{"error": "Transaction error: Name cant be blank"}'.should have_node(:error).including_text("Transaction error")
79
+ '{"error": "Transaction error: Name cant be blank"}'.should have_node(:error).including_text("Transaction error")
70
80
  ```
71
81
 
72
82
  You can verify boolean values too:
73
83
 
74
84
  ```ruby
75
- '{"creditcard":true}'.should have_node(:creditcard).with(true)
85
+ '{"creditcard":true}'.should have_node(:creditcard).with(true)
76
86
  ```
77
87
 
78
88
  ### HAVE NODE Matcher Configuration
@@ -80,65 +90,67 @@ You can verify boolean values too:
80
90
  You can configure if you want xml (JSON is the default):
81
91
 
82
92
  ```ruby
83
- APIMatchers.setup do |config|
84
- config.content_type = :xml
85
- end
93
+ APIMatchers.setup do |config|
94
+ config.content_type = :xml
95
+ end
86
96
  ```
87
97
 
88
98
  ```ruby
89
- '<transaction><id>200</id><status>paid</status></transaction>'.should have_node(:status)
99
+ '<transaction><id>200</id><status>paid</status></transaction>'.should have_node(:status)
90
100
  ```
91
101
 
92
- Using the with method:
102
+ Using the `with` method:
93
103
 
94
104
  ```ruby
95
- '<transaction><id>200</id><status>paid</status></transaction>'.should have_node(:status).with('paid')
105
+ '<transaction><id>200</id><status>paid</status></transaction>'.should have_node(:status).with('paid')
96
106
  ```
97
107
 
98
- Or you can use the **have_xml_node** matcher:
108
+ Or you can use the `have_xml_node` matcher:
99
109
 
100
110
  ```ruby
101
- "<error>Transaction error: Name can't be blank</error>".should have_xml_node(:error).with("Transaction error: Name can't be blank")
111
+ "<error>Transaction error: Name can't be blank</error>".should have_xml_node(:error).with("Transaction error: Name can't be blank")
102
112
  ```
103
113
 
104
114
  To see the xml node and see if include a text, you can do this:
105
115
 
106
116
  ```ruby
107
- "<error>Transaction error: Name can't be blank</error>".should have_xml_node(:error).including_text("Transaction error")
117
+ "<error>Transaction error: Name can't be blank</error>".should have_xml_node(:error).including_text("Transaction error")
108
118
  ```
109
119
 
110
- **If you work with xml and json in the same API, I recommend that you check the have_json_node and have_xml_node matchers.**
120
+ **If you work with xml and json in the same API, check the have_json_node and have_xml_node matchers.**
111
121
 
112
- You can configure the name of the method for example:
122
+ You can configure the name of the method and then you will be able to use *without* the **#body** method, for example:
113
123
 
114
124
  ```ruby
115
- ## Instead of this
116
- response.body.should have_node(:foo)
125
+ APIMatchers.setup do |config|
126
+ config.response_body_method = :body
127
+ end
128
+
129
+ response.should have_node(:foo).with('bar')
117
130
  ```
118
131
 
119
- ```ruby
120
- ## YOU can do this
121
- APIMatchers.setup do |config|
122
- config.response_body_method = :body
123
- end
132
+ # Instead of:
133
+ response.body.should have_node(:foo)
124
134
  ```
125
135
 
126
- Then you can use *without* call the **#body** method:
136
+ ### Have JSON Node Matcher
127
137
 
128
138
  ```ruby
129
- response.should have_node(:foo).with('bar')
139
+ '{ "transaction": { "id": 54, "status": "paid" } }'.should have_json_node(:id).with(54)
130
140
  ```
131
141
 
132
- ### Have JSON Node Matcher
142
+ ### Have XML Node Matcher
133
143
 
134
144
  ```ruby
135
- '{ "transaction": { "id": 54, "status": "paid" } }'.should have_json_node(:id).with(54)
145
+ "<product><name>gateway</name></product>".should have_xml_node(:name).with('gateway')
136
146
  ```
137
147
 
138
- ### Have XML Node Matcher
148
+ ### Have JSON Matcher
149
+
150
+ Sometimes, you want to compare the entire JSON structure:
139
151
 
140
152
  ```ruby
141
- "<product><name>gateway</name></product>".should have_xml_node(:name).with('gateway')
153
+ "['Foo', 'Bar', 'Baz']".should have_json(['Foo', 'Bar', 'Baz'])
142
154
  ```
143
155
 
144
156
  ### Create Resource Matcher
@@ -146,7 +158,7 @@ Then you can use *without* call the **#body** method:
146
158
  This matchers see the HTTP STATUS CODE is equal to 201.
147
159
 
148
160
  ```ruby
149
- response.status.should create_resource
161
+ response.status.should create_resource
150
162
  ```
151
163
 
152
164
  ### BAD REQUEST Matcher
@@ -154,8 +166,8 @@ This matchers see the HTTP STATUS CODE is equal to 201.
154
166
  This BAD REQUEST is a matcher that see if the HTTP STATUS code is equal to 400.
155
167
 
156
168
  ```ruby
157
- response.status.should be_a_bad_request
158
- response.status.should be_bad_request
169
+ response.status.should be_a_bad_request
170
+ response.status.should be_bad_request
159
171
  ```
160
172
 
161
173
  ### UNAUTHORIZED Matcher
@@ -163,8 +175,8 @@ This BAD REQUEST is a matcher that see if the HTTP STATUS code is equal to 400.
163
175
  This UNAUTHORIZED is a matcher that see if the HTTP STATUS code is equal to 401.
164
176
 
165
177
  ```ruby
166
- response.status.should be_unauthorized
167
- response.body.should have_node(:message).with('Invalid Credentials')
178
+ response.status.should be_unauthorized
179
+ response.body.should have_node(:message).with('Invalid Credentials')
168
180
  ```
169
181
 
170
182
  ### INTERNAL SERVER ERROR Matcher
@@ -172,8 +184,8 @@ This UNAUTHORIZED is a matcher that see if the HTTP STATUS code is equal to 401.
172
184
  This INTERNAL SERVER Error is a matcher that see if the HTTP STATUS code is equal to 500.
173
185
 
174
186
  ```ruby
175
- response.status.should be_internal_server_error
176
- response.body.should have_node(:message).with('An Internal Error Occurs in our precious app. :S')
187
+ response.status.should be_internal_server_error
188
+ response.body.should have_node(:message).with('An Internal Error Occurs in our precious app. :S')
177
189
  ```
178
190
 
179
191
  ### HTTP STATUS CODE Configuration
@@ -181,32 +193,32 @@ This INTERNAL SERVER Error is a matcher that see if the HTTP STATUS code is equa
181
193
  You can configure the name method to call the http status code:
182
194
 
183
195
  ```ruby
184
- APIMatchers.setup do |config|
185
- config.http_status_method = :status
186
- end
196
+ APIMatchers.setup do |config|
197
+ config.http_status_method = :status
198
+ end
187
199
  ```
188
200
 
189
201
  Then you can use without call the **#status** method:
190
202
 
191
203
  ```ruby
192
- response.should create_resource
204
+ response.should create_resource
193
205
  ```
194
206
 
195
207
  This configurations affects this matchers:
196
208
 
197
- * be_ok
198
- * create_resource
199
- * be_a_bad_request
200
- * be_internal_server_error
201
- * be_unauthorized
202
- * be_not_found
209
+ * `be_ok`
210
+ * `create_resource`
211
+ * `be_a_bad_request`
212
+ * `be_internal_server_error`
213
+ * `be_unauthorized`
214
+ * `be_not_found`
203
215
 
204
216
  ### Be in XML Matcher
205
217
 
206
218
  This is a matcher that see if the content type is xml:
207
219
 
208
220
  ```ruby
209
- response.headers['Content-Type'].should be_in_xml
221
+ response.headers['Content-Type'].should be_in_xml
210
222
  ```
211
223
 
212
224
  ### Be in JSON Matcher
@@ -214,7 +226,7 @@ This is a matcher that see if the content type is xml:
214
226
  This is a matcher that see if the content type is in JSON:
215
227
 
216
228
  ```ruby
217
- response.headers['Content-Type'].should be_in_json
229
+ response.headers['Content-Type'].should be_in_json
218
230
  ```
219
231
 
220
232
  ### Headers Configuration
@@ -222,17 +234,17 @@ This is a matcher that see if the content type is in JSON:
222
234
  You can configure the name method to call the headers and content type:
223
235
 
224
236
  ```ruby
225
- APIMatchers.setup do |config|
226
- config.header_method = :headers
227
- config.header_content_type_key = 'Content-Type'
228
- end
237
+ APIMatchers.setup do |config|
238
+ config.header_method = :headers
239
+ config.header_content_type_key = 'Content-Type'
240
+ end
229
241
  ```
230
242
 
231
- Then you can use without call the **#headers** calling the **#['Content-Type']** method:
243
+ And then you will be able to use without call the **#headers** calling the **#['Content-Type']** method:
232
244
 
233
245
  ```ruby
234
- response.should be_in_json
235
- response.should be_in_xml
246
+ response.should be_in_json
247
+ response.should be_in_xml
236
248
  ```
237
249
 
238
250
  ### Acknowlegments
@@ -242,3 +254,4 @@ Then you can use without call the **#headers** calling the **#['Content-Type']**
242
254
  ### Contributors
243
255
 
244
256
  * Stephen Orens
257
+ * Lucas Caton
@@ -20,7 +20,6 @@ module APIMatchers
20
20
  expected_value = expected_value.to_datetime.to_s
21
21
  end
22
22
  end
23
-
24
23
  return value if value == expected_value or expected_value.nil?
25
24
  end
26
25
 
@@ -4,17 +4,26 @@ module APIMatchers
4
4
  module ResponseBody
5
5
  class HaveXmlNode < Base
6
6
  def matches?(actual)
7
+ value = false
7
8
  @actual = actual
8
9
  xml = Nokogiri::XML(response_body)
9
- node = xml.xpath("//#{@expected_node}").text
10
10
 
11
- if @with_value
12
- node == @with_value.to_s
13
- elsif @expected_including_text
14
- node.to_s.include?(@expected_including_text)
15
- else
16
- node.present?
11
+ node_set = xml.xpath("//#{@expected_node}")
12
+ if node_set
13
+ node_set.each do |node|
14
+ if @with_value
15
+ value = (node.text == @with_value.to_s)
16
+ elsif @expected_including_text
17
+ value = (node.text.to_s.include?(@expected_including_text))
18
+ else
19
+ value = node.text.present?
20
+ end
21
+ # if value is true, time to return
22
+ return value if value
23
+ end
17
24
  end
25
+ # at this point, it failed to match
26
+ return value
18
27
  end
19
28
  end
20
29
  end
@@ -1,3 +1,3 @@
1
1
  module APIMatchers
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -6,6 +6,10 @@ describe APIMatchers::ResponseBody::HaveJson do
6
6
  it 'equal json' do
7
7
  ['Petshop', 'Dogs'].to_json.should have_json(['Petshop', 'Dogs'])
8
8
  end
9
+
10
+ it 'compares with Hash too' do
11
+ { 'offers' => [10, 90] }.to_json.should have_json({ 'offers' => [10,90] })
12
+ end
9
13
  end
10
14
 
11
15
  context 'when fails' do
@@ -63,6 +63,33 @@ describe APIMatchers::ResponseBody::HaveXmlNode do
63
63
  }.to fail_with(%Q{expected to have node called: 'message' including text: 'Fox on the run'. Got: '<error><message>Transaction error: Name can't be blank</message></error>'})
64
64
  end
65
65
  end
66
+
67
+ context "find matching node when multiple records" do
68
+ it "should pass when the expected is included in the actual (1 level)" do
69
+ %{<messages>
70
+ <message><id>4</id></message>
71
+ <message><id>2</id></message>
72
+ </messages>}.should have_xml_node(:id).with(2)
73
+ end
74
+ it "should fail when the expected is not included in the actual (1 level)" do
75
+ %{<messages>
76
+ <message><id>4</id></message>
77
+ <message><id>2</id></message>
78
+ </messages>}.should_not have_xml_node(:id).with(3)
79
+ end
80
+ it "should pass when the expected is included in the actual (2 levels)" do
81
+ %{<messages>
82
+ <message><header><id>4</id></header></message>
83
+ <message><header><id>2</id></header></message>
84
+ </messages>}.should have_xml_node(:id).with(2)
85
+ end
86
+ it "should fail when the expected is not included in the actual (2 levels)" do
87
+ %{<messages>
88
+ <message><header><id>4</id></header></message>
89
+ <message><header><id>2</id></header></message>
90
+ </messages>}.should_not have_xml_node(:id).with(3)
91
+ end
92
+ end
66
93
  end
67
94
 
68
95
  describe "actual.should_not have_xml_node" do
metadata CHANGED
@@ -1,55 +1,55 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: api_matchers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomas D'Stefano
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-25 00:00:00.000000000 Z
11
+ date: 2013-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ! '>='
17
+ - - '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: 2.10.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ! '>='
24
+ - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: 2.10.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activesupport
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ! '>='
31
+ - - '>='
32
32
  - !ruby/object:Gem::Version
33
33
  version: 3.2.5
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ! '>='
38
+ - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: 3.2.5
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: nokogiri
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ! '>='
45
+ - - '>='
46
46
  - !ruby/object:Gem::Version
47
47
  version: 1.5.2
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ! '>='
52
+ - - '>='
53
53
  - !ruby/object:Gem::Version
54
54
  version: 1.5.2
55
55
  description: Collection of RSpec matchers for create your API.
@@ -61,6 +61,7 @@ extra_rdoc_files: []
61
61
  files:
62
62
  - .gitignore
63
63
  - .rvmrc.example
64
+ - .travis.yml
64
65
  - Gemfile
65
66
  - History.markdown
66
67
  - LICENSE
@@ -117,17 +118,17 @@ require_paths:
117
118
  - lib
118
119
  required_ruby_version: !ruby/object:Gem::Requirement
119
120
  requirements:
120
- - - ! '>='
121
+ - - '>='
121
122
  - !ruby/object:Gem::Version
122
123
  version: '0'
123
124
  required_rubygems_version: !ruby/object:Gem::Requirement
124
125
  requirements:
125
- - - ! '>='
126
+ - - '>='
126
127
  - !ruby/object:Gem::Version
127
128
  version: '0'
128
129
  requirements: []
129
130
  rubyforge_project:
130
- rubygems_version: 2.0.3
131
+ rubygems_version: 2.1.10
131
132
  signing_key:
132
133
  specification_version: 4
133
134
  summary: Collection of RSpec matchers for create your API.