rspec-json_expectations 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8d3da7374ac61ca45bda7f28a31cd3343e11576e
4
+ data.tar.gz: 0ff730addd56dc7fc87021b5c358c8b399645c8b
5
+ SHA512:
6
+ metadata.gz: 9a7aad7424c140606260fbc15bb5e67e61e99e724c2cc0eeb87b8fe6d9f52abf332b4b3ffd7f6d17862d92fd059ed2406583b2e7ab7e9b6faa79aeb002f4c7c7
7
+ data.tar.gz: 22c5a1adf525eec9cf4d6e77aeaede263a34db007b47d4212cabb9607e8f06a56caf723cd7631659b88d1dce2a16a1297918702aaa26b72c4468efa91f6d9dea
data/.gitignore ADDED
@@ -0,0 +1,24 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ gemfiles/*.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
19
+ *.bundle
20
+ *.so
21
+ *.o
22
+ *.a
23
+ mkmf.log
24
+ /dummy
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ script: bundle exec cucumber
2
+ language: ruby
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1.2
7
+ gemfile:
8
+ - gemfiles/rspec-2
9
+ - gemfiles/rspec-3
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Alexey Fedorov
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,103 @@
1
+ # RSpec::JsonExpectations
2
+
3
+ [![Build Status](https://travis-ci.org/waterlink/rspec-json_expectations.svg?branch=master)](https://travis-ci.org/waterlink/rspec-json_expectations)
4
+
5
+ Set of matchers and helpers to allow you test your APIs responses like a pro.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'rspec-json_expectations'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install rspec-json_expectations
20
+
21
+ ## Setup
22
+
23
+ Simply add this line at the top of your spec helper:
24
+
25
+ ```ruby
26
+ require "rspec/json_expectations"
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ Simple example:
32
+
33
+ ```ruby
34
+ require "spec_helper"
35
+
36
+ RSpec.describe "User API" do
37
+ subject { api_get :user }
38
+
39
+ it "has basic info about user" do
40
+ expect(subject).to include_json(
41
+ id: 25,
42
+ email: "john.smith@example.com",
43
+ name: "John"
44
+ )
45
+ end
46
+
47
+ it "has some additional info about user" do
48
+ expect(subject).to include_json(
49
+ premium: "gold",
50
+ gamification_score: 79
51
+ )
52
+ end
53
+ end
54
+ ```
55
+
56
+ And the output when I run it is:
57
+
58
+ ```
59
+ FF
60
+
61
+ Failures:
62
+
63
+ 1) User API has basic info about user
64
+ Failure/Error: expect(subject).to include_json(
65
+
66
+ json atom at path "id" is not equal to expected value:
67
+
68
+ expected: 25
69
+ got: 37
70
+
71
+ json atom at path "name" is not equal to expected value:
72
+
73
+ expected: "John"
74
+ got: "Smith J."
75
+
76
+ # ./spec/user_api_spec.rb:18:in `block (2 levels) in <top (required)>'
77
+
78
+ 2) User API has some additional info about user
79
+ Failure/Error: expect(subject).to include_json(
80
+
81
+ json atom at path "premium" is not equal to expected value:
82
+
83
+ expected: "gold"
84
+ got: "silver"
85
+
86
+ # ./spec/user_api_spec.rb:26:in `block (2 levels) in <top (required)>'
87
+
88
+ Finished in 0.00102 seconds (files took 0.0853 seconds to load)
89
+ 2 examples, 2 failures
90
+
91
+ Failed examples:
92
+
93
+ rspec ./spec/user_api_spec.rb:17 # User API has basic info about user
94
+ rspec ./spec/user_api_spec.rb:25 # User API has some additional info about user
95
+ ```
96
+
97
+ ## Contributing
98
+
99
+ 1. Fork it ( https://github.com/waterlink/rspec-json_expectations/fork )
100
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
101
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
102
+ 4. Push to the branch (`git push origin my-new-feature`)
103
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/bin/build ADDED
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+
3
+ bin/with-rspec-2 install && bin/with-rspec-3 install && bin/with-rspec-2 exec cucumber && bin/with-rspec-3 exec cucumber && echo "SUCCESS" || echo "FAILED"
data/bin/with-rspec-2 ADDED
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+
3
+ BUNDLE_GEMFILE=gemfiles/rspec-2 bundle $*
data/bin/with-rspec-3 ADDED
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+
3
+ BUNDLE_GEMFILE=gemfiles/rspec-3 bundle $*
@@ -0,0 +1,210 @@
1
+ Feature: Array matching support for include_json matcher
2
+
3
+ As a developer extensively testing my APIs
4
+ I want to be able to match json parts with array
5
+
6
+ Background:
7
+ Given a file "spec/spec_helper.rb" with:
8
+ """ruby
9
+ require "rspec/json_expectations"
10
+ """
11
+ And a local "JSON_WITH_ARRAY" with:
12
+ """json
13
+ {
14
+ "per_page": 3,
15
+ "count": 17,
16
+ "page": 2,
17
+ "page_count": 6,
18
+ "results": [
19
+ {
20
+ "id": 25,
21
+ "email": "john.smith@example.com",
22
+ "badges": ["first flight", "day & night"],
23
+ "name": "John"
24
+ },
25
+ {
26
+ "id": 26,
27
+ "email": "john.smith@example.com",
28
+ "badges": ["first flight"],
29
+ "name": "John"
30
+ },
31
+ {
32
+ "id": 27,
33
+ "email": "john.smith@example.com",
34
+ "badges": ["day & night"],
35
+ "name": "John"
36
+ }
37
+ ]
38
+ }
39
+ """
40
+ And a local "JSON_WITH_ROOT_ARRAY" with:
41
+ """json
42
+ [
43
+ "first flight",
44
+ "day & night"
45
+ ]
46
+ """
47
+
48
+ Scenario: Expecting json string to fully include json with arrays
49
+ Given a file "spec/nested_example_spec.rb" with:
50
+ """ruby
51
+ require "spec_helper"
52
+
53
+ RSpec.describe "A json response" do
54
+ subject { '%{JSON_WITH_ARRAY}' }
55
+
56
+ it "has basic info about user" do
57
+ expect(subject).to include_json(
58
+ results: [
59
+ { id: 25, badges: ["first flight", "day & night"] },
60
+ { id: 26, badges: ["first flight"] },
61
+ { id: 27, badges: ["day & night"] }
62
+ ]
63
+ )
64
+ end
65
+ end
66
+ """
67
+ When I run "rspec spec/nested_example_spec.rb"
68
+ Then I see:
69
+ """
70
+ 1 example, 0 failures
71
+ """
72
+
73
+ Scenario: Expecting wrong json string to fully include json with arrays
74
+ Given a file "spec/nested_example_spec.rb" with:
75
+ """ruby
76
+ require "spec_helper"
77
+
78
+ RSpec.describe "A json response" do
79
+ subject { '%{JSON_WITH_ARRAY}' }
80
+
81
+ it "has basic info about user" do
82
+ expect(subject).to include_json(
83
+ results: [
84
+ { id: 24, badges: [] },
85
+ { id: 25, badges: ["first flight", "day & night"] },
86
+ { id: 26, badges: ["first flight"] },
87
+ { id: 27, badges: ["day & night"] }
88
+ ]
89
+ )
90
+ end
91
+ end
92
+ """
93
+ When I run "rspec spec/nested_example_spec.rb"
94
+ Then I see:
95
+ """
96
+ json atom at path "results/0/id" is not equal to expected value:
97
+ """
98
+ And I see:
99
+ """
100
+ json atom at path "results/1/id" is not equal to expected value:
101
+ """
102
+ And I see:
103
+ """
104
+ json atom at path "results/1/badges/1" is missing
105
+ """
106
+ And I see:
107
+ """
108
+ json atom at path "results/2/id" is not equal to expected value:
109
+ """
110
+ And I see:
111
+ """
112
+ json atom at path "results/2/badges/0" is not equal to expected value:
113
+ """
114
+ And I see:
115
+ """
116
+ expected: "first flight"
117
+ got: "day & night"
118
+ """
119
+ And I see:
120
+ """
121
+ json atom at path "results/3" is missing
122
+ """
123
+
124
+ Scenario: Expecting json string to partially include json with arrays
125
+ Given a file "spec/nested_example_spec.rb" with:
126
+ """ruby
127
+ require "spec_helper"
128
+
129
+ RSpec.describe "A json response" do
130
+ subject { '%{JSON_WITH_ARRAY}' }
131
+
132
+ it "has basic info about user" do
133
+ expect(subject).to include_json(
134
+ results: {
135
+ 2 => { id: 27, badges: ["day & night"] }
136
+ }
137
+ )
138
+ end
139
+ end
140
+ """
141
+ When I run "rspec spec/nested_example_spec.rb"
142
+ Then I see:
143
+ """
144
+ 1 example, 0 failures
145
+ """
146
+
147
+ Scenario: Expecting wrong json string to partially include json with arrays
148
+ Given a file "spec/nested_example_spec.rb" with:
149
+ """ruby
150
+ require "spec_helper"
151
+
152
+ RSpec.describe "A json response" do
153
+ subject { '%{JSON_WITH_ARRAY}' }
154
+
155
+ it "has basic info about user" do
156
+ expect(subject).to include_json(
157
+ results: {
158
+ 2 => { id: 28, badges: ["day & night"] }
159
+ }
160
+ )
161
+ end
162
+ end
163
+ """
164
+ When I run "rspec spec/nested_example_spec.rb"
165
+ Then I see:
166
+ """
167
+ json atom at path "results/2/id" is not equal to expected value:
168
+ """
169
+
170
+ Scenario: Expecting json string with array at root to fully include json with arrays
171
+ Given a file "spec/nested_example_spec.rb" with:
172
+ """ruby
173
+ require "spec_helper"
174
+
175
+ RSpec.describe "A json response" do
176
+ subject { '%{JSON_WITH_ROOT_ARRAY}' }
177
+
178
+ it "has basic info about user" do
179
+ expect(subject).to include_json(
180
+ [ "first flight", "day & night" ]
181
+ )
182
+ end
183
+ end
184
+ """
185
+ When I run "rspec spec/nested_example_spec.rb"
186
+ Then I see:
187
+ """
188
+ 1 example, 0 failures
189
+ """
190
+
191
+ Scenario: Expecting wrong json string with array at root to fully include json with arrays
192
+ Given a file "spec/nested_example_spec.rb" with:
193
+ """ruby
194
+ require "spec_helper"
195
+
196
+ RSpec.describe "A json response" do
197
+ subject { '%{JSON_WITH_ROOT_ARRAY}' }
198
+
199
+ it "has basic info about user" do
200
+ expect(subject).to include_json(
201
+ [ "first flight", "day & night", "super hero" ]
202
+ )
203
+ end
204
+ end
205
+ """
206
+ When I run "rspec spec/nested_example_spec.rb"
207
+ Then I see:
208
+ """
209
+ json atom at path "2" is missing
210
+ """
@@ -0,0 +1,116 @@
1
+ Feature: include_json matcher
2
+
3
+ As a developer extensively testing my APIs with RSpec
4
+ I want to have a suitable tool to test my API responses
5
+ And I want to use simple ruby hashes to describe the parts of response
6
+ For that I need a custom matcher
7
+
8
+ Background:
9
+ Given a file "spec/spec_helper.rb" with:
10
+ """ruby
11
+ require "rspec/json_expectations"
12
+ """
13
+ And a local "SIMPLE_JSON" with:
14
+ """json
15
+ {
16
+ "id": 25,
17
+ "email": "john.smith@example.com",
18
+ "name": "John"
19
+ }
20
+ """
21
+ And a local "BIG_JSON" with:
22
+ """json
23
+ {
24
+ "id": 25,
25
+ "email": "john.smith@example.com",
26
+ "password_hash": "super_md5_hash_that_is_unbreakable",
27
+ "name": "John",
28
+ "profile_id": 39,
29
+ "role": "admin"
30
+ }
31
+ """
32
+
33
+ Scenario: Expecting json string to include simple json
34
+ Given a file "spec/simple_example_spec.rb" with:
35
+ """ruby
36
+ require "spec_helper"
37
+
38
+ RSpec.describe "A json response" do
39
+ subject { '%{SIMPLE_JSON}' }
40
+
41
+ it "has basic info about user" do
42
+ expect(subject).to include_json(
43
+ id: 25,
44
+ email: "john.smith@example.com",
45
+ name: "John"
46
+ )
47
+ end
48
+ end
49
+ """
50
+ When I run "rspec spec/simple_example_spec.rb"
51
+ Then I see:
52
+ """
53
+ 1 example, 0 failures
54
+ """
55
+
56
+ Scenario: Expecting wrong json string to include simple json
57
+ Given a file "spec/simple_with_fail_spec.rb" with:
58
+ """ruby
59
+ require "spec_helper"
60
+
61
+ RSpec.describe "A json response" do
62
+ subject { '%{SIMPLE_JSON}' }
63
+
64
+ it "has basic info about user" do
65
+ expect(subject).to include_json(
66
+ id: 37,
67
+ email: "john.smith@example.com",
68
+ name: "Smith"
69
+ )
70
+ end
71
+ end
72
+ """
73
+ When I run "rspec spec/simple_with_fail_spec.rb"
74
+ Then I see:
75
+ """
76
+ 1 example, 1 failure
77
+ """
78
+ And I see:
79
+ """
80
+ expected: 37
81
+ got: 25
82
+ """
83
+ And I see:
84
+ """
85
+ expected: "Smith"
86
+ got: "John"
87
+ """
88
+ And I see:
89
+ """ruby
90
+ # ./spec/simple_with_fail_spec.rb
91
+ """
92
+
93
+ Scenario: Expecting json response with excessive fields to include 'smaller' json
94
+ Given a file "spec/excessive_fields_spec.rb" with:
95
+ """ruby
96
+ require "spec_helper"
97
+
98
+ RSpec.describe "A json response" do
99
+ subject { '%{BIG_JSON}' }
100
+
101
+ it "has basic info about user" do
102
+ expect(subject).to include_json(
103
+ id: 25,
104
+ name: "John",
105
+ profile_id: 39,
106
+ role: "admin"
107
+ )
108
+ end
109
+ end
110
+ """
111
+ When I run "rspec spec/excessive_fields_spec.rb"
112
+ Then I see:
113
+ """
114
+ 1 example, 0 failures
115
+ """
116
+
@@ -0,0 +1,78 @@
1
+ Feature: negation matching for include_json matcher
2
+
3
+ As a developer extensively testing my APIs
4
+ I want to be able to check if JSON response does not include some json part
5
+ For that I need appropriate negation matching mechanism
6
+ Where all json paths specified by include_json matcher should fail for
7
+ expectation to succeed
8
+
9
+ Background:
10
+ Given a file "spec/spec_helper.rb" with:
11
+ """ruby
12
+ require "rspec/json_expectations"
13
+ """
14
+ And a local "SIMPLE_JSON" with:
15
+ """json
16
+ {
17
+ "id": 25,
18
+ "email": "john.smith@example.com",
19
+ "name": "John"
20
+ }
21
+ """
22
+
23
+ Scenario: Expecting json string not to incldue simple json
24
+ Given a file "spec/simple_example_spec.rb" with:
25
+ """ruby
26
+ require "spec_helper"
27
+
28
+ RSpec.describe "A json response" do
29
+ subject { '%{SIMPLE_JSON}' }
30
+
31
+ it "has basic info about user" do
32
+ expect(subject).not_to include_json(
33
+ id: 26,
34
+ email: "sarah@example.org",
35
+ name: "Sarah C.",
36
+ missing: "field"
37
+ )
38
+ end
39
+ end
40
+ """
41
+ When I run "rspec spec/simple_example_spec.rb"
42
+ Then I see:
43
+ """
44
+ 1 example, 0 failures
45
+ """
46
+
47
+ Scenario: Expecting json string not to incldue simple json, when it is partially included
48
+ Given a file "spec/simple_example_spec.rb" with:
49
+ """ruby
50
+ require "spec_helper"
51
+
52
+ RSpec.describe "A json response" do
53
+ subject { '%{SIMPLE_JSON}' }
54
+
55
+ it "has basic info about user" do
56
+ expect(subject).not_to include_json(
57
+ id: 26,
58
+ email: /john.*@example.com/,
59
+ name: "John",
60
+ missing: "field"
61
+ )
62
+ end
63
+ end
64
+ """
65
+ When I run "rspec spec/simple_example_spec.rb"
66
+ Then I see:
67
+ """
68
+ 1 example, 1 failure
69
+ """
70
+ And I see:
71
+ """
72
+ json atom at path "email" should not match expected regex:
73
+ """
74
+ And I see:
75
+ """
76
+ json atom at path "name" should not equal to expected value:
77
+ """
78
+
@@ -0,0 +1,63 @@
1
+ Feature: nested json support with include_json matcher
2
+
3
+ As a developer extensively testing my APIs
4
+ I want to be able to easily test nested JSON responses
5
+
6
+ Background:
7
+ Given a file "spec/spec_helper.rb" with:
8
+ """ruby
9
+ require "rspec/json_expectations"
10
+ """
11
+ And a local "NESTED_JSON" with:
12
+ """json
13
+ {
14
+ "id": 25,
15
+ "email": "john.smith@example.com",
16
+ "gamification": {
17
+ "rating": 93,
18
+ "score": 397
19
+ },
20
+ "name": "John"
21
+ }
22
+ """
23
+
24
+ Scenario: Expecting json string to include nested json
25
+ Given a file "spec/nested_example_spec.rb" with:
26
+ """ruby
27
+ require "spec_helper"
28
+
29
+ RSpec.describe "A json response" do
30
+ subject { '%{NESTED_JSON}' }
31
+
32
+ it "has basic info about user" do
33
+ expect(subject).to include_json(
34
+ id: 25,
35
+ email: "john.smith@example.com",
36
+ name: "John"
37
+ )
38
+ end
39
+
40
+ it "has gamification info for user" do
41
+ expect(subject).to include_json(
42
+ gamification: {
43
+ rating: 93,
44
+ score: 355
45
+ }
46
+ )
47
+ end
48
+ end
49
+ """
50
+ When I run "rspec spec/nested_example_spec.rb"
51
+ Then I see:
52
+ """
53
+ 2 examples, 1 failure
54
+ """
55
+ And I see:
56
+ """
57
+ json atom at path "gamification/score" is not equal to expected value:
58
+ """
59
+ And I see:
60
+ """
61
+ expected: 355
62
+ got: 397
63
+ """
@@ -0,0 +1,94 @@
1
+ Feature: regular expressions support with include_json matcher
2
+
3
+ As a developer extensively testing my APIs
4
+ I want to be able to match string values by regex
5
+
6
+ Background:
7
+ Given a file "spec/spec_helper.rb" with:
8
+ """ruby
9
+ require "rspec/json_expectations"
10
+ """
11
+ And a local "SIMPLE_JSON" with:
12
+ """json
13
+ {
14
+ "id": 25,
15
+ "email": "john.smith@example.com",
16
+ "name": "John",
17
+ "code": "5wmsx6ae7p",
18
+ "url": "https://test.example.org/api/v5/users/5wmsx6ae7p.json"
19
+ }
20
+ """
21
+ And a local "WRONG_JSON" with:
22
+ """json
23
+ {
24
+ "id": 25,
25
+ "email": "john.smith@example.com",
26
+ "name": "John",
27
+ "code": "5wmsx6ae7psome-trash",
28
+ "url": "https://test.example.org/api/v6/users/5wmsx6ae7p.json"
29
+ }
30
+ """
31
+
32
+ Scenario: Expecting json string to include simple json with regex
33
+ Given a file "spec/simple_example_spec.rb" with:
34
+ """ruby
35
+ require "spec_helper"
36
+
37
+ RSpec.describe "A json response" do
38
+ subject { '%{SIMPLE_JSON}' }
39
+
40
+ it "has basic info about user" do
41
+ expect(subject).to include_json(
42
+ id: 25,
43
+ email: "john.smith@example.com",
44
+ name: "John",
45
+ code: /^[a-z0-9]{10}$/,
46
+ url: %%r{api/v5/users/[a-z0-9]{10}.json}
47
+ )
48
+ end
49
+ end
50
+ """
51
+ When I run "rspec spec/simple_example_spec.rb"
52
+ Then I see:
53
+ """
54
+ 1 example, 0 failures
55
+ """
56
+
57
+ Scenario: Expecting wrong json string to include simple json with regex
58
+ Given a file "spec/simple_example_spec.rb" with:
59
+ """ruby
60
+ require "spec_helper"
61
+
62
+ RSpec.describe "A json response" do
63
+ subject { '%{WRONG_JSON}' }
64
+
65
+ it "has basic info about user" do
66
+ expect(subject).to include_json(
67
+ id: 25,
68
+ email: "john.smith@example.com",
69
+ name: "John",
70
+ code: /^[a-z0-9]{10}$/,
71
+ url: %%r{api/v5/users/[a-z0-9]{10}.json}
72
+ )
73
+ end
74
+ end
75
+ """
76
+ When I run "rspec spec/simple_example_spec.rb"
77
+ Then I see:
78
+ """
79
+ json atom at path "code" does not match expected regex:
80
+ """
81
+ And I see:
82
+ """
83
+ expected: /^[a-z0-9]{10}$/
84
+ got: "5wmsx6ae7psome-trash"
85
+ """
86
+ And I see:
87
+ """
88
+ json atom at path "url" does not match expected regex:
89
+ """
90
+ And I see:
91
+ """
92
+ expected: /api\/v5\/users\/[a-z0-9]{10}.json/
93
+ got: "https://test.example.org/api/v6/users/5wmsx6ae7p.json"
94
+ """
@@ -0,0 +1,32 @@
1
+ DUMMY_FOLDER = "dummy"
2
+
3
+ def init
4
+ `mkdir -p #{DUMMY_FOLDER}`
5
+ `cp -r gemfiles #{DUMMY_FOLDER}`
6
+ `cp *.gemspec #{DUMMY_FOLDER}`
7
+ `cp -r lib #{DUMMY_FOLDER}`
8
+ end
9
+
10
+ init
11
+
12
+ Given(/^a file "(.*?)" with:$/) do |filename, contents|
13
+ @locals ||= {}
14
+ full_path = File.join(DUMMY_FOLDER, filename)
15
+ `mkdir -p #{File.dirname(full_path)}`
16
+ File.open(full_path, 'w') { |f| f.write(contents % @locals) }
17
+ end
18
+
19
+ Given(/^a local "(.*?)" with:$/) do |key, value|
20
+ @locals ||= {}
21
+ @locals[key.to_sym] = value
22
+ end
23
+
24
+ When(/^I run "(.*?)"$/) do |command|
25
+ @output = `cd #{DUMMY_FOLDER}; #{command}`
26
+ puts @output
27
+ end
28
+
29
+ Then(/^I see:$/) do |what|
30
+ @output ||= ""
31
+ expect(@output).to include(what)
32
+ end
@@ -0,0 +1,3 @@
1
+ require 'rspec/expectations'
2
+
3
+ World(RSpec::Expectations)
data/gemfiles/rspec-2 ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rspec-json_expectations.gemspec
4
+ gemspec path: '..'
5
+
6
+ group :test do
7
+ gem 'cucumber'
8
+ gem 'rspec', '~> 2.14.0'
9
+ end
10
+
data/gemfiles/rspec-3 ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rspec-json_expectations.gemspec
4
+ gemspec path: '..'
5
+
6
+ group :test do
7
+ gem 'cucumber'
8
+ gem 'rspec', '~> 3.0'
9
+ end
10
+
@@ -0,0 +1,11 @@
1
+ require "rspec"
2
+ require "rspec/json_expectations/version"
3
+ require "rspec/json_expectations/json_traverser"
4
+ require "rspec/json_expectations/failure_presenter"
5
+ require "rspec/json_expectations/matchers"
6
+
7
+ module RSpec
8
+ module JsonExpectations
9
+ # Your code goes here...
10
+ end
11
+ end
@@ -0,0 +1,55 @@
1
+ module RSpec
2
+ module JsonExpectations
3
+ # Allows to present failures in a nice way for each json path
4
+ class FailurePresenter
5
+ class << self
6
+ def render(errors)
7
+ negate = errors[:_negate]
8
+ errors.map { |path, error| render_error(path, error, negate) }.join
9
+ end
10
+
11
+ private
12
+
13
+ def render_error(path, error, negate=false)
14
+ [
15
+ render_no_key(path, error, negate),
16
+ render_not_eq(path, error, negate),
17
+ render_not_match(path, error, negate)
18
+ ].select { |e| e }.first
19
+ end
20
+
21
+ def render_no_key(path, error, negate=false)
22
+ %{
23
+ json atom at path "#{path}" is missing
24
+ } if error == :no_key
25
+ end
26
+
27
+ def render_not_eq(path, error, negate=false)
28
+ %{
29
+ json atom at path "#{path}" #{negate ? "should" : "is"} not equal to expected value:
30
+
31
+ expected: #{error[:expected].inspect}
32
+ got: #{error[:actual].inspect}
33
+ } if error_is_not_eq?(error)
34
+ end
35
+
36
+ def render_not_match(path, error, negate=false)
37
+ %{
38
+ json atom at path "#{path}" #{negate ? "should" : "does"} not match expected regex:
39
+
40
+ expected: #{error[:expected].inspect}
41
+ got: #{error[:actual].inspect}
42
+ } if error_is_not_match?(error)
43
+ end
44
+
45
+ def error_is_not_eq?(error)
46
+ error.is_a?(Hash) && error.has_key?(:expected) && !error[:expected].is_a?(Regexp)
47
+ end
48
+
49
+ def error_is_not_match?(error)
50
+ error.is_a?(Hash) && error.has_key?(:expected) && error[:expected].is_a?(Regexp)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,112 @@
1
+ require "json"
2
+
3
+ module RSpec
4
+ module JsonExpectations
5
+ # This class allows to traverse a json actual value along
6
+ # with json expected value for inclusion and check if they
7
+ # match. Errors are accumulated in errors hash for each
8
+ # json atom paths.
9
+ class JsonTraverser
10
+ SUPPORTED_VALUES = [Hash, String, Numeric, Regexp, Array]
11
+
12
+ class << self
13
+ def traverse(errors, expected, actual, negate=false, prefix=[])
14
+ [
15
+ handle_hash(errors, expected, actual, negate, prefix),
16
+ handle_array(errors, expected, actual, negate, prefix),
17
+ handle_value(errors, expected, actual, negate, prefix),
18
+ handle_regex(errors, expected, actual, negate, prefix),
19
+ handle_unsupported(expected)
20
+ ].any?
21
+ end
22
+
23
+ private
24
+
25
+ def handle_keyvalue(errors, expected, actual, negate=false, prefix=[])
26
+ expected.map do |key, value|
27
+ new_prefix = prefix + [key]
28
+ if has_key?(actual, key)
29
+ traverse(errors, value, fetch(actual, key), negate, new_prefix)
30
+ else
31
+ errors[new_prefix.join("/")] = :no_key unless negate
32
+ conditionally_negate(false, negate)
33
+ end
34
+ end.all? || false
35
+ end
36
+
37
+ def handle_hash(errors, expected, actual, negate=false, prefix=[])
38
+ return nil unless expected.is_a?(Hash)
39
+
40
+ handle_keyvalue(errors, expected, actual, negate, prefix)
41
+ end
42
+
43
+ def handle_array(errors, expected, actual, negate=false, prefix=[])
44
+ return nil unless expected.is_a?(Array)
45
+
46
+ transformed_expected = expected.each_with_index.map { |v, k| [k, v] }
47
+ handle_keyvalue(errors, transformed_expected, actual, negate, prefix)
48
+ end
49
+
50
+ def handle_value(errors, expected, actual, negate=false, prefix=[])
51
+ return nil unless expected.is_a?(String) || expected.is_a?(Numeric)
52
+
53
+ if conditionally_negate(actual == expected, negate)
54
+ true
55
+ else
56
+ errors[prefix.join("/")] = {
57
+ actual: actual,
58
+ expected: expected
59
+ }
60
+ false
61
+ end
62
+ end
63
+
64
+ def handle_regex(errors, expected, actual, negate=false, prefix=[])
65
+ return nil unless expected.is_a?(Regexp)
66
+
67
+ if conditionally_negate(!!expected.match(actual), negate)
68
+ true
69
+ else
70
+ errors[prefix.join("/")] = {
71
+ actual: actual,
72
+ expected: expected
73
+ }
74
+ false
75
+ end
76
+ end
77
+
78
+ def handle_unsupported(expected)
79
+ unless SUPPORTED_VALUES.any? { |type| expected.is_a?(type) }
80
+ raise NotImplementedError,
81
+ "#{expected} expectation is not supported"
82
+ end
83
+ end
84
+
85
+ def has_key?(actual, key)
86
+ if actual.is_a?(Hash)
87
+ actual.has_key?(key.to_s)
88
+ elsif actual.is_a?(Array)
89
+ actual.count > key
90
+ else
91
+ false
92
+ end
93
+ end
94
+
95
+ def fetch(actual, key, default=nil)
96
+ if actual.is_a?(Hash)
97
+ actual[key.to_s]
98
+ elsif actual.is_a?(Array)
99
+ actual[key]
100
+ else
101
+ default
102
+ end
103
+ end
104
+
105
+ def conditionally_negate(value, negate=false)
106
+ value ^ negate
107
+ end
108
+
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,51 @@
1
+ RSpec::Matchers.define :include_json do |expected|
2
+
3
+ # RSpec 2 vs 3
4
+ if respond_to?(:failure_message)
5
+ match do |actual|
6
+ traverse(expected, actual, false)
7
+ end
8
+
9
+ match_when_negated do |actual|
10
+ traverse(expected, actual, true)
11
+ end
12
+
13
+ failure_message do |actual|
14
+ RSpec::JsonExpectations::FailurePresenter.render(@include_json_errors)
15
+ end
16
+
17
+ failure_message_when_negated do |actual|
18
+ RSpec::JsonExpectations::FailurePresenter.render(@include_json_errors)
19
+ end
20
+ else
21
+ match_for_should do |actual|
22
+ traverse(expected, actual, false)
23
+ end
24
+
25
+ match_for_should_not do |actual|
26
+ traverse(expected, actual, true)
27
+ end
28
+
29
+ failure_message_for_should do |actual|
30
+ RSpec::JsonExpectations::FailurePresenter.render(@include_json_errors)
31
+ end
32
+
33
+ failure_message_for_should_not do |actual|
34
+ RSpec::JsonExpectations::FailurePresenter.render(@include_json_errors)
35
+ end
36
+ end
37
+
38
+ def traverse(expected, actual, negate=false)
39
+ unless expected.is_a?(Hash) || expected.is_a?(Array)
40
+ raise ArgumentError,
41
+ "Expected value must be a json for include_json matcher"
42
+ end
43
+
44
+ RSpec::JsonExpectations::JsonTraverser.traverse(
45
+ @include_json_errors = { _negate: negate },
46
+ expected,
47
+ JSON.parse(actual),
48
+ negate
49
+ )
50
+ end
51
+ end
@@ -0,0 +1,5 @@
1
+ module RSpec
2
+ module JsonExpectations
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
data/local_env.rb ADDED
@@ -0,0 +1,3 @@
1
+ After do |s|
2
+ Cucumber.wants_to_quit = true if s.failed?
3
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rspec/json_expectations/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rspec-json_expectations"
8
+ spec.version = RSpec::JsonExpectations::VERSION
9
+ spec.authors = ["Alexey Fedorov"]
10
+ spec.email = ["alexey.fedorov@wimdu.com"]
11
+ spec.summary = %q{Set of matchers and helpers to allow you test your APIs responses like a pro.}
12
+ spec.description = ""
13
+ spec.homepage = "https://github.com/waterlink/rspec-json_expectations"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.6"
22
+ spec.add_development_dependency "rake"
23
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rspec-json_expectations
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Alexey Fedorov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: ''
42
+ email:
43
+ - alexey.fedorov@wimdu.com
44
+ executables:
45
+ - build
46
+ - with-rspec-2
47
+ - with-rspec-3
48
+ extensions: []
49
+ extra_rdoc_files: []
50
+ files:
51
+ - ".gitignore"
52
+ - ".travis.yml"
53
+ - LICENSE.txt
54
+ - README.md
55
+ - Rakefile
56
+ - bin/build
57
+ - bin/with-rspec-2
58
+ - bin/with-rspec-3
59
+ - features/rspec/json_expectations/array_support.feature
60
+ - features/rspec/json_expectations/include_json_matcher.feature
61
+ - features/rspec/json_expectations/negation_matching.feature
62
+ - features/rspec/json_expectations/nested_json_support.feature
63
+ - features/rspec/json_expectations/regular_expressions_support.feature
64
+ - features/step_definitions/steps.rb
65
+ - features/support/env.rb
66
+ - gemfiles/rspec-2
67
+ - gemfiles/rspec-3
68
+ - lib/rspec/json_expectations.rb
69
+ - lib/rspec/json_expectations/failure_presenter.rb
70
+ - lib/rspec/json_expectations/json_traverser.rb
71
+ - lib/rspec/json_expectations/matchers.rb
72
+ - lib/rspec/json_expectations/version.rb
73
+ - local_env.rb
74
+ - rspec-json_expectations.gemspec
75
+ homepage: https://github.com/waterlink/rspec-json_expectations
76
+ licenses:
77
+ - MIT
78
+ metadata: {}
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubyforge_project:
95
+ rubygems_version: 2.2.2
96
+ signing_key:
97
+ specification_version: 4
98
+ summary: Set of matchers and helpers to allow you test your APIs responses like a
99
+ pro.
100
+ test_files:
101
+ - features/rspec/json_expectations/array_support.feature
102
+ - features/rspec/json_expectations/include_json_matcher.feature
103
+ - features/rspec/json_expectations/negation_matching.feature
104
+ - features/rspec/json_expectations/nested_json_support.feature
105
+ - features/rspec/json_expectations/regular_expressions_support.feature
106
+ - features/step_definitions/steps.rb
107
+ - features/support/env.rb
108
+ has_rdoc: