rspec-oj 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://img.shields.io/gem/v/rspec-oj.svg?style=flat)](http://rubygems.org/gems/rspec-oj)
|
6
|
+
[![Build Status](https://img.shields.io/travis/mhenrixon/rspec-oj/master.svg?style=flat)](https://travis-ci.org/mhenrixon/rspec-oj)
|
7
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/e05efd6949d820a0db09/maintainability)](https://codeclimate.com/github/mhenrixon/rspec-oj/maintainability)
|
8
|
+
[![Test Coverage](https://api.codeclimate.com/v1/badges/e05efd6949d820a0db09/test_coverage)](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: []
|