rspec-json_expectations 1.0.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 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: