rspec-oj 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 +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +341 -0
- data/lib/rspec/oj/configuration.rb +33 -0
- data/lib/rspec/oj/cucumber.rb +97 -0
- data/lib/rspec/oj/errors.rb +50 -0
- data/lib/rspec/oj/exclusion.rb +29 -0
- data/lib/rspec/oj/helpers.rb +75 -0
- data/lib/rspec/oj/matchers/be_json_eql.rb +72 -0
- data/lib/rspec/oj/matchers/have_json_path.rb +36 -0
- data/lib/rspec/oj/matchers/have_json_size.rb +42 -0
- data/lib/rspec/oj/matchers/have_json_type.rb +55 -0
- data/lib/rspec/oj/matchers/include_json.rb +67 -0
- data/lib/rspec/oj/matchers.rb +37 -0
- data/lib/rspec/oj/memory.rb +23 -0
- data/lib/rspec/oj/messages.rb +12 -0
- data/lib/rspec/oj/version.rb +7 -0
- data/lib/rspec-oj.rb +18 -0
- metadata +206 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 505fa0b6ec22748476d0b3aa748f36c4b7d1c226dc87403aedadd31442a89122
|
4
|
+
data.tar.gz: aa0aab2919a98dfc9ade03e6ccee638442c059f9068927a18707282cecf55de3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ed0c980e4e0af0bf1b8174b01f5a2ebb241dcc44e5162cac15fdfe76b2720277c283ef2780f75108af9c283952c15184e4ebb9ff7e10b230374e3fb6681a69b3
|
7
|
+
data.tar.gz: 208ae97dc849e475b628976632e67cc52c2f341919c8186f7044cb75f7048ad23bd7613afeb1f2bf36c926b25d156750a6ce08f2bda2c4524284cece0e3a10be
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2020 Mikael Henriksson
|
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,341 @@
|
|
1
|
+
# rspec-oj
|
2
|
+
|
3
|
+
Easily handle JSON in RSpec and Cucumber
|
4
|
+
|
5
|
+
[](http://rubygems.org/gems/rspec-oj)
|
6
|
+
[](https://travis-ci.org/mhenrixon/rspec-oj)
|
7
|
+
[](https://codeclimate.com/github/mhenrixon/rspec-oj/maintainability)
|
8
|
+
[](https://codeclimate.com/github/mhenrixon/rspec-oj/test_coverage)
|
9
|
+
|
10
|
+
## RSpec
|
11
|
+
|
12
|
+
rspec-oj defines five new RSpec matchers:
|
13
|
+
|
14
|
+
* `be_json_eql`
|
15
|
+
* `include_json`
|
16
|
+
* `have_json_path`
|
17
|
+
* `have_json_type`
|
18
|
+
* `have_json_size`
|
19
|
+
|
20
|
+
The new matchers could be used in RSpec as follows:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
describe User do
|
24
|
+
let(:user){ User.create!(first_name: "Steve", last_name: "Richert") }
|
25
|
+
|
26
|
+
context "#to_json" do
|
27
|
+
it "includes names" do
|
28
|
+
names = { "first_name": "Steve", "last_name": "Richert" }
|
29
|
+
expect(user).to be_json_eql(names).excluding("friends")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "includes the ID" do
|
33
|
+
expect(user).to have_json_path("id")
|
34
|
+
expect(user).to have_json_type(Integer).at_path("id")
|
35
|
+
end
|
36
|
+
|
37
|
+
it "includes friends" do
|
38
|
+
expect(user).to have_json_size(0).at_path("friends")
|
39
|
+
|
40
|
+
friend = User.create!(first_name: "Catie", last_name: "Richert")
|
41
|
+
user.friends << friend
|
42
|
+
|
43
|
+
expect(user).to have_json_size(1).at_path("friends")
|
44
|
+
expect(user).to include_json(friend)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
rspec-oj also provides some useful helpers for RSpec tests:
|
51
|
+
|
52
|
+
* `parse_json`
|
53
|
+
* `normalize_json`
|
54
|
+
* `generate_normalized_json`
|
55
|
+
* `load_json`
|
56
|
+
|
57
|
+
To start using them add an include them in your RSpec configuration:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
RSpec.configure do |config|
|
61
|
+
config.include RSpec::Oj::Helpers
|
62
|
+
end
|
63
|
+
```
|
64
|
+
|
65
|
+
You can find usage examples for the helpers in [`spec/rspec/oj/helpers_spec.rb`](https://github.com/mhenrixon/rspec-oj/blob/master/spec/rspec/oj/helpers_spec.rb)
|
66
|
+
|
67
|
+
### Exclusions
|
68
|
+
|
69
|
+
rspec-oj ignores certain hash keys by default when comparing JSON:
|
70
|
+
|
71
|
+
* `id`
|
72
|
+
* `created_at`
|
73
|
+
* `updated_at`
|
74
|
+
|
75
|
+
It's oftentimes helpful when evaluating JSON representations of newly-created ActiveRecord records
|
76
|
+
so that the new ID and timestamps don't have to be known. These exclusions are globally
|
77
|
+
customizeable:
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
RSpec::Oj.configure do
|
81
|
+
exclude_keys "created_at", "updated_at"
|
82
|
+
end
|
83
|
+
```
|
84
|
+
|
85
|
+
Now, the `id` key will be included in rspec-oj's comparisons. Keys can also be excluded/included
|
86
|
+
per matcher by chaining the `excluding` or `including` methods (as shown above) which will add or
|
87
|
+
subtract from the globally excluded keys, respectively.
|
88
|
+
|
89
|
+
### Paths
|
90
|
+
|
91
|
+
Each of rspec-oj's matchers deal with JSON "paths." These are simple strings of "/" separated
|
92
|
+
hash keys and array indexes. For instance, with the following JSON:
|
93
|
+
|
94
|
+
{
|
95
|
+
"first_name": "Steve",
|
96
|
+
"last_name": "Richert",
|
97
|
+
"friends": [
|
98
|
+
{
|
99
|
+
"first_name": "Catie",
|
100
|
+
"last_name": "Richert"
|
101
|
+
}
|
102
|
+
]
|
103
|
+
}
|
104
|
+
|
105
|
+
We could access the first friend's first name with the path `"friends/0/first_name"`.
|
106
|
+
|
107
|
+
## Cucumber
|
108
|
+
|
109
|
+
rspec-oj provides Cucumber steps that utilize its RSpec matchers and that's where rspec-oj really
|
110
|
+
shines. This is perfect for testing your app's JSON API.
|
111
|
+
|
112
|
+
In order to use the Cucumber steps, in your `env.rb` you must:
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
require "rspec/oj/cucumber"
|
116
|
+
```
|
117
|
+
|
118
|
+
You also need to define a `last_json` method. If you're using Capybara, it could be as simple as:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
def last_json
|
122
|
+
page.source
|
123
|
+
end
|
124
|
+
```
|
125
|
+
|
126
|
+
Now, you can use the rspec-oj steps in your features:
|
127
|
+
|
128
|
+
```cucumber
|
129
|
+
Feature: User API
|
130
|
+
Background:
|
131
|
+
Given the following users exist:
|
132
|
+
| id | first_name | last_name |
|
133
|
+
| 1 | Steve | Richert |
|
134
|
+
| 2 | Catie | Richert |
|
135
|
+
And "Steve Richert" is friends with "Catie Richert"
|
136
|
+
|
137
|
+
Scenario: Index action
|
138
|
+
When I visit "/users.json"
|
139
|
+
Then the JSON response should have 2 users
|
140
|
+
And the JSON response at "0/id" should be 1
|
141
|
+
And the JSON response at "1/id" should be 2
|
142
|
+
|
143
|
+
Scenario: Show action
|
144
|
+
When I visit "/users/1.json"
|
145
|
+
Then the JSON response at "first_name" should be "Steve"
|
146
|
+
And the JSON response at "last_name" should be "Richert"
|
147
|
+
And the JSON response should have "created_at"
|
148
|
+
And the JSON response at "created_at" should be a string
|
149
|
+
And the JSON response at "friends" should be:
|
150
|
+
"""
|
151
|
+
[
|
152
|
+
{
|
153
|
+
"id": 2,
|
154
|
+
"first_name": "Catie",
|
155
|
+
"last_name": "Richert"
|
156
|
+
}
|
157
|
+
]
|
158
|
+
"""
|
159
|
+
```
|
160
|
+
|
161
|
+
The background steps above aren't provided by rspec-oj and the "visit" steps are provided by
|
162
|
+
Capybara. The remaining steps, rspec-oj provides. They're versatile and can be used in plenty of
|
163
|
+
different formats:
|
164
|
+
|
165
|
+
```cucumber
|
166
|
+
Then the JSON should be:
|
167
|
+
"""
|
168
|
+
{
|
169
|
+
"key": "value"
|
170
|
+
}
|
171
|
+
"""
|
172
|
+
Then the JSON at "path" should be:
|
173
|
+
"""
|
174
|
+
[
|
175
|
+
"entry",
|
176
|
+
"entry"
|
177
|
+
]
|
178
|
+
"""
|
179
|
+
|
180
|
+
Then the JSON should be {"key":"value"}
|
181
|
+
Then the JSON at "path" should be {"key":"value"}
|
182
|
+
Then the JSON should be ["entry","entry"]
|
183
|
+
Then the JSON at "path" should be ["entry","entry"]
|
184
|
+
Then the JSON at "path" should be "string"
|
185
|
+
Then the JSON at "path" should be 10
|
186
|
+
Then the JSON at "path" should be 10.0
|
187
|
+
Then the JSON at "path" should be 1e+1
|
188
|
+
Then the JSON at "path" should be true
|
189
|
+
Then the JSON at "path" should be false
|
190
|
+
Then the JSON at "path" should be null
|
191
|
+
|
192
|
+
Then the JSON should include:
|
193
|
+
"""
|
194
|
+
{
|
195
|
+
"key": "value"
|
196
|
+
}
|
197
|
+
"""
|
198
|
+
Then the JSON at "path" should include:
|
199
|
+
"""
|
200
|
+
[
|
201
|
+
"entry",
|
202
|
+
"entry"
|
203
|
+
]
|
204
|
+
"""
|
205
|
+
|
206
|
+
Then the JSON should include {"key":"value"}
|
207
|
+
Then the JSON at "path" should include {"key":"value"}
|
208
|
+
Then the JSON should include ["entry","entry"]
|
209
|
+
Then the JSON at "path" should include ["entry","entry"]
|
210
|
+
Then the JSON should include "string"
|
211
|
+
Then the JSON at "path" should include "string"
|
212
|
+
Then the JSON should include 10
|
213
|
+
Then the JSON at "path" should include 10
|
214
|
+
Then the JSON should include 10.0
|
215
|
+
Then the JSON at "path" should include 10.0
|
216
|
+
Then the JSON should include 1e+1
|
217
|
+
Then the JSON at "path" should include 1e+1
|
218
|
+
Then the JSON should include true
|
219
|
+
Then the JSON at "path" should include true
|
220
|
+
Then the JSON should include false
|
221
|
+
Then the JSON at "path" should include false
|
222
|
+
Then the JSON should include null
|
223
|
+
Then the JSON at "path" should include null
|
224
|
+
|
225
|
+
Then the JSON should have "path"
|
226
|
+
|
227
|
+
Then the JSON should be a hash
|
228
|
+
Then the JSON at "path" should be an array
|
229
|
+
Then the JSON at "path" should be a float
|
230
|
+
|
231
|
+
Then the JSON should have 1 entry
|
232
|
+
Then the JSON at "path" should have 2 entries
|
233
|
+
Then the JSON should have 3 keys
|
234
|
+
Then the JSON should have 4 whatevers
|
235
|
+
```
|
236
|
+
|
237
|
+
_All instances of "should" above could be followed by "not" and all instances of "JSON" could be downcased and/or followed by "response."_
|
238
|
+
|
239
|
+
### Table Format
|
240
|
+
|
241
|
+
Another step exists that uses Cucumber's table formatting and wraps two of the above steps:
|
242
|
+
|
243
|
+
```cucumber
|
244
|
+
Then the JSON should have the following:
|
245
|
+
| path/0 | {"key":"value"} |
|
246
|
+
| path/1 | ["entry","entry"] |
|
247
|
+
```
|
248
|
+
|
249
|
+
Any number of rows can be given. The step above is equivalent to:
|
250
|
+
|
251
|
+
```cucumber
|
252
|
+
Then the JSON at "path/0" should be {"key":"value"}
|
253
|
+
And the JSON at "path/1" should be ["entry","entry"]
|
254
|
+
```
|
255
|
+
|
256
|
+
If only one column is given:
|
257
|
+
|
258
|
+
```cucumber
|
259
|
+
Then the JSON should have the following:
|
260
|
+
| path/0 |
|
261
|
+
| path/1 |
|
262
|
+
```
|
263
|
+
|
264
|
+
This is equivalent to:
|
265
|
+
|
266
|
+
```cucumber
|
267
|
+
Then the JSON should have "path/0"
|
268
|
+
And the JSON should have "path/1"
|
269
|
+
```
|
270
|
+
|
271
|
+
### JSON Memory
|
272
|
+
|
273
|
+
There's one more Cucumber step that rspec-oj provides which hasn't been used above. It's used to
|
274
|
+
memorize JSON for reuse in later steps. You can "keep" all or a portion of the JSON by giving a
|
275
|
+
name by which to remember it.
|
276
|
+
|
277
|
+
```cucumber
|
278
|
+
Feature: User API
|
279
|
+
Scenario: Index action includes full user JSON
|
280
|
+
Given the following user exists:
|
281
|
+
| id | first_name | last_name |
|
282
|
+
| 1 | Steve | Richert |
|
283
|
+
And I visit "/users/1.json"
|
284
|
+
And I keep the JSON response as "USER_1"
|
285
|
+
When I visit "/users.json"
|
286
|
+
Then the JSON response should be:
|
287
|
+
"""
|
288
|
+
[
|
289
|
+
%{USER_1}
|
290
|
+
]
|
291
|
+
"""
|
292
|
+
```
|
293
|
+
|
294
|
+
You can memorize JSON at a path:
|
295
|
+
|
296
|
+
```cucumber
|
297
|
+
Given I keep the JSON response at "first_name" as "FIRST_NAME"
|
298
|
+
```
|
299
|
+
|
300
|
+
You can remember JSON at a path:
|
301
|
+
|
302
|
+
```cucumber
|
303
|
+
Then the JSON response at "0/first_name" should be:
|
304
|
+
"""
|
305
|
+
%{FIRST_NAME}
|
306
|
+
"""
|
307
|
+
```
|
308
|
+
|
309
|
+
You can also remember JSON inline:
|
310
|
+
|
311
|
+
```cucumber
|
312
|
+
Then the JSON response at "0/first_name" should be %{FIRST_NAME}
|
313
|
+
```
|
314
|
+
|
315
|
+
### More
|
316
|
+
|
317
|
+
Check out the [specs](https://github.com/mhenrixon/rspec-oj/blob/master/spec)
|
318
|
+
and [features](https://github.com/mhenrixon/rspec-oj/blob/master/features) to see all the
|
319
|
+
various ways you can use rspec-oj.
|
320
|
+
|
321
|
+
## Contributing
|
322
|
+
|
323
|
+
If you come across any issues, please [tell us](https://github.com/mhenrixon/rspec-oj/issues).
|
324
|
+
Pull requests (with tests) are appreciated. No pull request is too small. Please help with:
|
325
|
+
|
326
|
+
* Reporting bugs
|
327
|
+
* Suggesting features
|
328
|
+
* Writing or improving documentation
|
329
|
+
* Fixing typos
|
330
|
+
* Cleaning whitespace
|
331
|
+
* Refactoring code
|
332
|
+
* Adding tests
|
333
|
+
* Closing [issues](https://github.com/mhenrixon/rspec-oj/issues)
|
334
|
+
|
335
|
+
If you report a bug and don't include a fix, please include a failing test.
|
336
|
+
|
337
|
+
## Copyright
|
338
|
+
|
339
|
+
Copyright © 2020 Steve Richert
|
340
|
+
|
341
|
+
See [LICENSE](https://github.com/mhenrixon/rspec-oj/blob/master/LICENSE) for details.
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module RSpec
|
6
|
+
module Oj
|
7
|
+
module Configuration
|
8
|
+
DEFAULT_EXCLUDED_KEYS = %w[id created_at updated_at].freeze
|
9
|
+
|
10
|
+
attr_accessor :directory
|
11
|
+
|
12
|
+
def configure(&block)
|
13
|
+
instance_eval(&block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def excluded_keys
|
17
|
+
@excluded_keys ||= DEFAULT_EXCLUDED_KEYS
|
18
|
+
end
|
19
|
+
|
20
|
+
def excluded_keys=(keys)
|
21
|
+
@excluded_keys = keys.map(&:to_s).uniq
|
22
|
+
end
|
23
|
+
|
24
|
+
def exclude_keys(*keys)
|
25
|
+
self.excluded_keys = keys
|
26
|
+
end
|
27
|
+
|
28
|
+
def reset
|
29
|
+
instance_variables.each { |ivar| remove_instance_variable(ivar) }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rspec-oj'
|
4
|
+
|
5
|
+
World(RSpec::Oj::Helpers, RSpec::Oj::Matchers)
|
6
|
+
|
7
|
+
After do
|
8
|
+
RSpec::Oj.forget
|
9
|
+
end
|
10
|
+
|
11
|
+
When(/^(?:I )?keep the (?:JSON|json)(?: response)?(?: at "(.*)")? as "(.*)"$/) do |path, key|
|
12
|
+
RSpec::Oj.memorize(key, normalize_json(last_json, path))
|
13
|
+
end
|
14
|
+
|
15
|
+
Then(/^the (?:JSON|json)(?: response)?(?: at "(.*)")? should( not)? be:$/) do |path, negative, json|
|
16
|
+
if negative
|
17
|
+
expect(last_json).not_to be_json_eql(RSpec::Oj.remember(json)).at_path(path)
|
18
|
+
else
|
19
|
+
expect(last_json).to be_json_eql(RSpec::Oj.remember(json)).at_path(path)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
Then(/^the (?:JSON|json)(?: response)?(?: at "(.*)")? should( not)? be file "(.+)"$/) do |path, negative, file_path|
|
24
|
+
if negative
|
25
|
+
expect(last_json).not_to be_json_eql.to_file(file_path).at_path(path)
|
26
|
+
else
|
27
|
+
expect(last_json).to be_json_eql.to_file(file_path).at_path(path)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
Then(/^the (?:JSON|json)(?: response)?(?: at "(.*)")? should( not)? be (".*"|\-?\d+(?:\.\d+)?(?:[eE][\+\-]?\d+)?|\[.*\]|%?\{.*\}|true|false|null)$/) do |path, negative, value| # rubocop:disable Layout/LineLength
|
32
|
+
if negative
|
33
|
+
expect(last_json).not_to be_json_eql(RSpec::Oj.remember(value)).at_path(path)
|
34
|
+
else
|
35
|
+
expect(last_json).to be_json_eql(RSpec::Oj.remember(value)).at_path(path)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
Then(/^the (?:JSON|json)(?: response)?(?: at "(.*)")? should( not)? include:$/) do |path, negative, json|
|
40
|
+
if negative
|
41
|
+
expect(last_json).not_to include_json(RSpec::Oj.remember(json)).at_path(path)
|
42
|
+
else
|
43
|
+
expect(last_json).to include_json(RSpec::Oj.remember(json)).at_path(path)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
Then(/^the (?:JSON|json)(?: response)?(?: at "(.*)")? should( not)? include file "(.+)"$/) do |path, negative, file_path|
|
48
|
+
if negative
|
49
|
+
expect(last_json).not_to include_json.from_file(file_path).at_path(path)
|
50
|
+
else
|
51
|
+
expect(last_json).to include_json.from_file(file_path).at_path(path)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
Then(/^the (?:JSON|json)(?: response)?(?: at "(.*)")? should( not)? include (".*"|\-?\d+(?:\.\d+)?(?:[eE][\+\-]?\d+)?|\[.*\]|%?\{.*\}|true|false|null)$/) do |path, negative, value| # rubocop:disable Layout/LineLength
|
56
|
+
if negative
|
57
|
+
expect(last_json).not_to include_json(RSpec::Oj.remember(value)).at_path(path)
|
58
|
+
else
|
59
|
+
expect(last_json).to include_json(RSpec::Oj.remember(value)).at_path(path)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
Then(/^the (?:JSON|json)(?: response)?(?: at "(.*)")? should have the following:$/) do |base, table|
|
64
|
+
table.raw.each do |path, value|
|
65
|
+
path = [base, path].compact.join('/')
|
66
|
+
|
67
|
+
if value
|
68
|
+
step %(the JSON at "#{path}" should be:), value
|
69
|
+
else
|
70
|
+
step %(the JSON should have "#{path}")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
Then(/^the (?:JSON|json)(?: response)? should( not)? have "(.*)"$/) do |negative, path|
|
76
|
+
if negative
|
77
|
+
expect(last_json).not_to have_json_path(path)
|
78
|
+
else
|
79
|
+
expect(last_json).to have_json_path(path)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
Then(/^the (?:JSON|json)(?: response)?(?: at "(.*)")? should( not)? be an? (.*)$/) do |path, negative, type|
|
84
|
+
if negative
|
85
|
+
expect(last_json).not_to have_json_type(type).at_path(path)
|
86
|
+
else
|
87
|
+
expect(last_json).to have_json_type(type).at_path(path)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
Then(/^the (?:JSON|json)(?: response)?(?: at "(.*)")? should( not)? have (\d+)/) do |path, negative, size|
|
92
|
+
if negative
|
93
|
+
expect(last_json).not_to have_json_size(size.to_i).at_path(path)
|
94
|
+
else
|
95
|
+
expect(last_json).to have_json_size(size.to_i).at_path(path)
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Oj
|
5
|
+
class Error < StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
class MissingPath < Error
|
9
|
+
attr_reader :path
|
10
|
+
|
11
|
+
def initialize(path)
|
12
|
+
@path = path
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
%(Missing JSON path "#{path}")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class MissingDirectory < Error
|
21
|
+
def to_s
|
22
|
+
'No JsonSpec.directory set'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class MissingFile < Error
|
27
|
+
attr_reader :path
|
28
|
+
|
29
|
+
def initialize(path)
|
30
|
+
@path = path
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_s
|
34
|
+
"No JSON file at #{path}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class EnumerableExpected < Error
|
39
|
+
attr_reader :actual_value
|
40
|
+
|
41
|
+
def initialize(actual_value)
|
42
|
+
@actual_value = actual_value
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_s
|
46
|
+
"Enumerable expected, got #{actual_value.inspect}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Oj
|
5
|
+
module Exclusion
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def exclude_keys(ruby)
|
9
|
+
case ruby
|
10
|
+
when Hash
|
11
|
+
ruby.sort.each_with_object({}) do |(key, value), hash|
|
12
|
+
hash[key] = exclude_keys(value) unless exclude_key?(key)
|
13
|
+
end
|
14
|
+
when Array
|
15
|
+
ruby.map { |v| exclude_keys(v) }
|
16
|
+
else ruby
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def exclude_key?(key)
|
21
|
+
excluded_keys.include?(key)
|
22
|
+
end
|
23
|
+
|
24
|
+
def excluded_keys
|
25
|
+
@excluded_keys ||= Set.new(RSpec::Oj.excluded_keys)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'oj'
|
4
|
+
|
5
|
+
module RSpec
|
6
|
+
module Oj
|
7
|
+
module Helpers
|
8
|
+
extend self
|
9
|
+
|
10
|
+
def parse_json(json, path = nil)
|
11
|
+
return parse_json(generate_normalized_json(json), path) unless json.is_a?(String)
|
12
|
+
|
13
|
+
ruby = ::Oj.load("[#{json}]", mode: :compat).first
|
14
|
+
value_at_json_path(ruby, path)
|
15
|
+
rescue EncodingError
|
16
|
+
begin
|
17
|
+
::Oj.load(json)
|
18
|
+
rescue ::Oj::ParseError
|
19
|
+
json
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def normalize_json(json, path = nil)
|
24
|
+
ruby = parse_json(json, path)
|
25
|
+
generate_normalized_json(ruby)
|
26
|
+
end
|
27
|
+
|
28
|
+
def generate_normalized_json(ruby)
|
29
|
+
case ruby
|
30
|
+
when Hash, Array
|
31
|
+
::Oj.dump(ruby, mode: :compat)
|
32
|
+
else
|
33
|
+
::Oj.to_json(ruby, mode: :compat)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def load_json(relative_path)
|
38
|
+
missing_json_directory! unless RSpec::Oj.directory
|
39
|
+
path = File.join(RSpec::Oj.directory, relative_path)
|
40
|
+
missing_json_file!(path) unless File.exist?(path)
|
41
|
+
File.read(path)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def value_at_json_path(ruby, path)
|
47
|
+
return ruby unless path
|
48
|
+
|
49
|
+
path.split('/').reduce(ruby) do |memo, key|
|
50
|
+
case memo
|
51
|
+
when Hash
|
52
|
+
memo.fetch(key) { missing_json_path!(path) }
|
53
|
+
when Array
|
54
|
+
missing_json_path!(path) unless /^\d+$/.match?(key)
|
55
|
+
memo.fetch(key.to_i) { missing_json_path!(path) }
|
56
|
+
else
|
57
|
+
missing_json_path!(path)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def missing_json_path!(path)
|
63
|
+
raise RSpec::Oj::MissingPath, path
|
64
|
+
end
|
65
|
+
|
66
|
+
def missing_json_directory!
|
67
|
+
raise RSpec::Oj::MissingDirectory
|
68
|
+
end
|
69
|
+
|
70
|
+
def missing_json_file!(path)
|
71
|
+
raise RSpec::Oj::MissingFile, path
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Oj
|
5
|
+
module Matchers
|
6
|
+
class BeJsonEql
|
7
|
+
include RSpec::Oj::Helpers
|
8
|
+
include RSpec::Oj::Exclusion
|
9
|
+
include RSpec::Oj::Messages
|
10
|
+
|
11
|
+
attr_reader :expected, :actual
|
12
|
+
|
13
|
+
def diffable?
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(expected_json = nil)
|
18
|
+
@expected_json = expected_json
|
19
|
+
@path = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def matches?(actual_json)
|
23
|
+
raise 'Expected equivalent JSON not provided' if @expected_json.nil?
|
24
|
+
|
25
|
+
@actual = scrub(actual_json, @path)
|
26
|
+
@expected = scrub(@expected_json)
|
27
|
+
@actual == @expected
|
28
|
+
end
|
29
|
+
|
30
|
+
def at_path(path)
|
31
|
+
@path = path
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_file(path)
|
36
|
+
@expected_json = load_json(path)
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
def excluding(*keys)
|
41
|
+
excluded_keys.merge(keys.map(&:to_s))
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
45
|
+
def including(*keys)
|
46
|
+
excluded_keys.subtract(keys.map(&:to_s))
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
def failure_message
|
51
|
+
message_with_path('Expected equivalent JSON')
|
52
|
+
end
|
53
|
+
alias failure_message_for_should failure_message
|
54
|
+
|
55
|
+
def failure_message_when_negated
|
56
|
+
message_with_path('Expected inequivalent JSON')
|
57
|
+
end
|
58
|
+
alias failure_message_for_should_not failure_message_when_negated
|
59
|
+
|
60
|
+
def description
|
61
|
+
message_with_path('equal JSON')
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def scrub(json, path = nil)
|
67
|
+
generate_normalized_json(exclude_keys(parse_json(json, path))).chomp + "\n"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Oj
|
5
|
+
module Matchers
|
6
|
+
class HaveJsonPath
|
7
|
+
include RSpec::Oj::Helpers
|
8
|
+
|
9
|
+
def initialize(path)
|
10
|
+
@path = path
|
11
|
+
end
|
12
|
+
|
13
|
+
def matches?(json)
|
14
|
+
parse_json(json, @path)
|
15
|
+
true
|
16
|
+
rescue RSpec::Oj::MissingPath
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
def failure_message
|
21
|
+
%(Expected JSON path "#{@path}")
|
22
|
+
end
|
23
|
+
alias failure_message_for_should failure_message
|
24
|
+
|
25
|
+
def failure_message_when_negated
|
26
|
+
%(Expected no JSON path "#{@path}")
|
27
|
+
end
|
28
|
+
alias failure_message_for_should_not failure_message_when_negated
|
29
|
+
|
30
|
+
def description
|
31
|
+
%(have JSON path "#{@path}")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Oj
|
5
|
+
module Matchers
|
6
|
+
class HaveJsonSize
|
7
|
+
include RSpec::Oj::Helpers
|
8
|
+
include RSpec::Oj::Messages
|
9
|
+
|
10
|
+
def initialize(size)
|
11
|
+
@expected = size
|
12
|
+
@path = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def matches?(json)
|
16
|
+
ruby = parse_json(json, @path)
|
17
|
+
raise EnumerableExpected, ruby unless Enumerable === ruby
|
18
|
+
|
19
|
+
@actual = ruby.size
|
20
|
+
@actual == @expected
|
21
|
+
end
|
22
|
+
|
23
|
+
def at_path(path)
|
24
|
+
@path = path
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def failure_message
|
29
|
+
message_with_path("Expected JSON value size to be #{@expected}, got #{@actual}")
|
30
|
+
end
|
31
|
+
|
32
|
+
def failure_message_when_negated
|
33
|
+
message_with_path("Expected JSON value size to not be #{@expected}, got #{@actual}")
|
34
|
+
end
|
35
|
+
|
36
|
+
def description
|
37
|
+
message_with_path(%(have JSON size "#{@expected}"))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Oj
|
5
|
+
module Matchers
|
6
|
+
class HaveJsonType
|
7
|
+
include RSpec::Oj::Helpers
|
8
|
+
include RSpec::Oj::Messages
|
9
|
+
|
10
|
+
def initialize(type)
|
11
|
+
@classes = type_to_classes(type)
|
12
|
+
@path = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def matches?(json)
|
16
|
+
@ruby = parse_json(json, @path)
|
17
|
+
@classes.any? { |c| c === @ruby }
|
18
|
+
end
|
19
|
+
|
20
|
+
def at_path(path)
|
21
|
+
@path = path
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def failure_message
|
26
|
+
message_with_path("Expected JSON value type to be #{@classes.join(', ')}, got #{@ruby.class}")
|
27
|
+
end
|
28
|
+
|
29
|
+
def failure_message_when_negated
|
30
|
+
message_with_path("Expected JSON value type to not be #{@classes.join(', ')}, got #{@ruby.class}")
|
31
|
+
end
|
32
|
+
|
33
|
+
def description
|
34
|
+
message_with_path(%(have JSON type "#{@classes.join(', ')}"))
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def type_to_classes(type)
|
40
|
+
case type
|
41
|
+
when Class then [type]
|
42
|
+
when Array then type.map { |t| type_to_classes(t) }.flatten
|
43
|
+
else
|
44
|
+
case type.to_s.downcase
|
45
|
+
when 'boolean' then [TrueClass, FalseClass]
|
46
|
+
when 'object' then [Hash]
|
47
|
+
when 'nil', 'null' then [NilClass]
|
48
|
+
else [Module.const_get(type.to_s.capitalize)]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Oj
|
5
|
+
module Matchers
|
6
|
+
class IncludeJson
|
7
|
+
include RSpec::Oj::Helpers
|
8
|
+
include RSpec::Oj::Exclusion
|
9
|
+
include RSpec::Oj::Messages
|
10
|
+
|
11
|
+
def initialize(expected_json = nil)
|
12
|
+
@expected_json = expected_json
|
13
|
+
@path = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def matches?(actual_json)
|
17
|
+
raise 'Expected included JSON not provided' if @expected_json.nil?
|
18
|
+
|
19
|
+
@actual_json = actual_json
|
20
|
+
|
21
|
+
actual = parse_json(actual_json, @path)
|
22
|
+
expected = exclude_keys(parse_json(@expected_json))
|
23
|
+
case actual
|
24
|
+
when Hash then actual.values.map { |v| exclude_keys(v) }.include?(expected)
|
25
|
+
when Array then actual.map { |e| exclude_keys(e) }.include?(expected)
|
26
|
+
when String then actual.include?(expected)
|
27
|
+
else false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def at_path(path)
|
32
|
+
@path = path
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def from_file(path)
|
37
|
+
@expected_json = load_json(path)
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
def excluding(*keys)
|
42
|
+
excluded_keys.merge(keys.map(&:to_s))
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
def including(*keys)
|
47
|
+
excluded_keys.subtract(keys.map(&:to_s))
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
def failure_message
|
52
|
+
message_with_path("Expected #{@actual_json} to include #{@expected_json}")
|
53
|
+
end
|
54
|
+
alias failure_message_for_should failure_message
|
55
|
+
|
56
|
+
def failure_message_when_negated
|
57
|
+
message_with_path("Expected #{@actual_json} to not include #{@expected_json}")
|
58
|
+
end
|
59
|
+
alias failure_message_for_should_not failure_message_when_negated
|
60
|
+
|
61
|
+
def description
|
62
|
+
message_with_path('include JSON')
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rspec/oj/matchers/be_json_eql'
|
4
|
+
require 'rspec/oj/matchers/include_json'
|
5
|
+
require 'rspec/oj/matchers/have_json_path'
|
6
|
+
require 'rspec/oj/matchers/have_json_type'
|
7
|
+
require 'rspec/oj/matchers/have_json_size'
|
8
|
+
|
9
|
+
module RSpec
|
10
|
+
module Oj
|
11
|
+
module Matchers
|
12
|
+
def be_json_eql(json = nil)
|
13
|
+
RSpec::Oj::Matchers::BeJsonEql.new(json)
|
14
|
+
end
|
15
|
+
|
16
|
+
def include_json(json = nil)
|
17
|
+
RSpec::Oj::Matchers::IncludeJson.new(json)
|
18
|
+
end
|
19
|
+
|
20
|
+
def have_json_path(path) # rubocop:disable Naming/PredicateName
|
21
|
+
RSpec::Oj::Matchers::HaveJsonPath.new(path)
|
22
|
+
end
|
23
|
+
|
24
|
+
def have_json_type(type) # rubocop:disable Naming/PredicateName
|
25
|
+
RSpec::Oj::Matchers::HaveJsonType.new(type)
|
26
|
+
end
|
27
|
+
|
28
|
+
def have_json_size(size) # rubocop:disable Naming/PredicateName
|
29
|
+
RSpec::Oj::Matchers::HaveJsonSize.new(size)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
RSpec.configure do |config|
|
36
|
+
config.include RSpec::Oj::Matchers
|
37
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Oj
|
5
|
+
module Memory
|
6
|
+
def memory
|
7
|
+
@memory ||= {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def memorize(key, value)
|
11
|
+
memory[key.to_sym] = value
|
12
|
+
end
|
13
|
+
|
14
|
+
def remember(json)
|
15
|
+
memory.empty? ? json : json % memory
|
16
|
+
end
|
17
|
+
|
18
|
+
def forget
|
19
|
+
memory.clear
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/rspec-oj.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'oj'
|
4
|
+
require 'rspec'
|
5
|
+
require 'rspec/oj/errors'
|
6
|
+
require 'rspec/oj/configuration'
|
7
|
+
require 'rspec/oj/exclusion'
|
8
|
+
require 'rspec/oj/helpers'
|
9
|
+
require 'rspec/oj/messages'
|
10
|
+
require 'rspec/oj/matchers'
|
11
|
+
require 'rspec/oj/memory'
|
12
|
+
|
13
|
+
module RSpec
|
14
|
+
module Oj
|
15
|
+
extend Configuration
|
16
|
+
extend Memory
|
17
|
+
end
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,206 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rspec-oj
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mikael Henriksson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-02-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: oj
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '5.0'
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '3.0'
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '5.0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: bundler
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '2.1'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '2.1'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: gem-release
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '2.1'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '2.1'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: pry
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 0.12.2
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 0.12.2
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: rake
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '13.0'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '13.0'
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: reek
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '5.0'
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - "~>"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '5.0'
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: rubocop-mhenrixon
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - "~>"
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: 0.80.0
|
124
|
+
type: :development
|
125
|
+
prerelease: false
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - "~>"
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: 0.80.0
|
131
|
+
- !ruby/object:Gem::Dependency
|
132
|
+
name: simplecov
|
133
|
+
requirement: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - "~>"
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: 0.17.0
|
138
|
+
type: :development
|
139
|
+
prerelease: false
|
140
|
+
version_requirements: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - "~>"
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: 0.17.0
|
145
|
+
- !ruby/object:Gem::Dependency
|
146
|
+
name: simplecov-oj
|
147
|
+
requirement: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - "~>"
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: 0.18.0
|
152
|
+
type: :development
|
153
|
+
prerelease: false
|
154
|
+
version_requirements: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - "~>"
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: 0.18.0
|
159
|
+
description: RSpec matchers and Cucumber steps for testing JSON content
|
160
|
+
email:
|
161
|
+
- mikael@mhenrixon.com
|
162
|
+
executables: []
|
163
|
+
extensions: []
|
164
|
+
extra_rdoc_files: []
|
165
|
+
files:
|
166
|
+
- LICENSE.txt
|
167
|
+
- README.md
|
168
|
+
- lib/rspec-oj.rb
|
169
|
+
- lib/rspec/oj/configuration.rb
|
170
|
+
- lib/rspec/oj/cucumber.rb
|
171
|
+
- lib/rspec/oj/errors.rb
|
172
|
+
- lib/rspec/oj/exclusion.rb
|
173
|
+
- lib/rspec/oj/helpers.rb
|
174
|
+
- lib/rspec/oj/matchers.rb
|
175
|
+
- lib/rspec/oj/matchers/be_json_eql.rb
|
176
|
+
- lib/rspec/oj/matchers/have_json_path.rb
|
177
|
+
- lib/rspec/oj/matchers/have_json_size.rb
|
178
|
+
- lib/rspec/oj/matchers/have_json_type.rb
|
179
|
+
- lib/rspec/oj/matchers/include_json.rb
|
180
|
+
- lib/rspec/oj/memory.rb
|
181
|
+
- lib/rspec/oj/messages.rb
|
182
|
+
- lib/rspec/oj/version.rb
|
183
|
+
homepage: https://github.com/mhenrixon/rspec-oj
|
184
|
+
licenses:
|
185
|
+
- MIT
|
186
|
+
metadata: {}
|
187
|
+
post_install_message:
|
188
|
+
rdoc_options: []
|
189
|
+
require_paths:
|
190
|
+
- lib/rspec
|
191
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
192
|
+
requirements:
|
193
|
+
- - ">="
|
194
|
+
- !ruby/object:Gem::Version
|
195
|
+
version: '0'
|
196
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
197
|
+
requirements:
|
198
|
+
- - ">="
|
199
|
+
- !ruby/object:Gem::Version
|
200
|
+
version: '0'
|
201
|
+
requirements: []
|
202
|
+
rubygems_version: 3.1.2
|
203
|
+
signing_key:
|
204
|
+
specification_version: 4
|
205
|
+
summary: Easily handle JSON in RSpec and Cucumber
|
206
|
+
test_files: []
|