rspec-resembles_json_matchers 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +16 -0
- data/Appraisals +14 -0
- data/Gemfile +4 -0
- data/Guardfile +47 -0
- data/README.md +225 -0
- data/Rakefile +6 -0
- data/examples/example_spec.rb +123 -0
- data/gemfiles/rails_42.gemfile +8 -0
- data/gemfiles/rails_42.gemfile.lock +173 -0
- data/gemfiles/rails_42_rspec_33.gemfile +8 -0
- data/gemfiles/rails_42_rspec_33.gemfile.lock +173 -0
- data/gemfiles/rails_5.gemfile +8 -0
- data/gemfiles/rails_5.gemfile.lock +184 -0
- data/lib/rspec/resembles_json_matchers.rb +57 -0
- data/lib/rspec/resembles_json_matchers/attribute_matcher.rb +85 -0
- data/lib/rspec/resembles_json_matchers/helpers.rb +29 -0
- data/lib/rspec/resembles_json_matchers/json_matcher.rb +85 -0
- data/lib/rspec/resembles_json_matchers/matcherizer.rb +25 -0
- data/lib/rspec/resembles_json_matchers/resembles_any_of_matcher.rb +61 -0
- data/lib/rspec/resembles_json_matchers/resembles_array_matcher.rb +35 -0
- data/lib/rspec/resembles_json_matchers/resembles_class_matcher.rb +29 -0
- data/lib/rspec/resembles_json_matchers/resembles_date_matcher.rb +44 -0
- data/lib/rspec/resembles_json_matchers/resembles_hash_matcher.rb +110 -0
- data/lib/rspec/resembles_json_matchers/resembles_matcher.rb +59 -0
- data/lib/rspec/resembles_json_matchers/resembles_numeric_matcher.rb +32 -0
- data/lib/rspec/resembles_json_matchers/resembles_route_matcher.rb +25 -0
- data/lib/rspec/resembles_json_matchers/resembles_string_matcher.rb +25 -0
- data/lib/rspec/resembles_json_matchers/version.rb +5 -0
- data/rspec-resembles_json_matchers.gemspec +39 -0
- metadata +226 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 85c0060d722ce75ef9a360088d85b78f095cb7c0
|
4
|
+
data.tar.gz: f51a19065d79d805b34f6745f494691379527538
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a2a0c803b0fa775e02f5077b76df085adbc1b065ffea9b11902a927c3600b2e891b44d6d256d2b6866fdcf067921f9c284ada4a2f158863d81fda0773e0c395b
|
7
|
+
data.tar.gz: 7a402c3ca3573eeff8861b557ee7587affaf5cdf2049be860cc0af04eb2c81a57ff9a8a3156ffb46f4a958eea2de47ef2b48cfb421ebed699b125cdb0e77a816
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 2.2.2
|
4
|
+
- 2.3.0
|
5
|
+
- ruby-head
|
6
|
+
before_install: gem install bundler -v 1.11.2
|
7
|
+
gemfile:
|
8
|
+
- gemfiles/rails_42.gemfile
|
9
|
+
- gemfiles/rails_42_rspec_33.gemfile
|
10
|
+
- gemfiles/rails_5.gemfile
|
11
|
+
matrix:
|
12
|
+
fast_finish: true
|
13
|
+
allow_failures:
|
14
|
+
- rvm: ruby-head
|
15
|
+
notifications:
|
16
|
+
email: false
|
data/Appraisals
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
appraise "rails-42" do
|
2
|
+
gem "rails", "~> 4.2.0"
|
3
|
+
gem "rspec", "~> 3.4.0"
|
4
|
+
end
|
5
|
+
|
6
|
+
appraise "rails-42-rspec-33" do
|
7
|
+
gem "rails", "~> 4.2.0"
|
8
|
+
gem "rspec", "~> 3.3.0"
|
9
|
+
end
|
10
|
+
|
11
|
+
appraise "rails-5" do
|
12
|
+
gem "rails", "~> 5.0.0.beta2"
|
13
|
+
gem "rspec", "~> 3.5.0.beta1"
|
14
|
+
end
|
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
## Uncomment and set this to only include directories you want to watch
|
5
|
+
# directories %w(app lib config test spec features) \
|
6
|
+
# .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
|
7
|
+
|
8
|
+
## Note: if you are using the `directories` clause above and you are not
|
9
|
+
## watching the project directory ('.'), then you will want to move
|
10
|
+
## the Guardfile to a watched dir and symlink it back, e.g.
|
11
|
+
#
|
12
|
+
# $ mkdir config
|
13
|
+
# $ mv Guardfile config/
|
14
|
+
# $ ln -s config/Guardfile .
|
15
|
+
#
|
16
|
+
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
17
|
+
|
18
|
+
# Note: The cmd option is now required due to the increasing number of ways
|
19
|
+
# rspec may be run, below are examples of the most common uses.
|
20
|
+
# * bundler: 'bundle exec rspec'
|
21
|
+
# * bundler binstubs: 'bin/rspec'
|
22
|
+
# * spring: 'bin/rspec' (This will use spring if running and you have
|
23
|
+
# installed the spring binstubs per the docs)
|
24
|
+
# * zeus: 'zeus rspec' (requires the server to be started separately)
|
25
|
+
# * 'just' rspec: 'rspec'
|
26
|
+
|
27
|
+
guard :rspec, cmd: "bundle exec rspec" do
|
28
|
+
require "guard/rspec/dsl"
|
29
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
30
|
+
|
31
|
+
# Feel free to open issues for suggestions and improvements
|
32
|
+
|
33
|
+
# RSpec files
|
34
|
+
rspec = dsl.rspec
|
35
|
+
watch(rspec.spec_helper) { rspec.spec_dir }
|
36
|
+
watch(rspec.spec_support) { rspec.spec_dir }
|
37
|
+
watch(rspec.spec_files)
|
38
|
+
|
39
|
+
# Ruby files
|
40
|
+
ruby = dsl.ruby
|
41
|
+
dsl.watch_spec_files_for(ruby.lib_files)
|
42
|
+
|
43
|
+
watch(%r{^lib/rspec/resembles_json_matchers/(.+_matcher)\.rb$}) do |m|
|
44
|
+
"spec/matchers/#{m[1]}_spec.rb"
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
data/README.md
ADDED
@@ -0,0 +1,225 @@
|
|
1
|
+
# RSpec::ResemblesJsonMatchers
|
2
|
+
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/rspec-json_api_matchers.svg)](https://badge.fury.io/rb/rspec-json_api_matchers)[![Build Status](https://travis-ci.org/paul/rspec-json_api_matchers.svg?branch=master)](https://travis-ci.org/paul/rspec-json_api_matchers)
|
4
|
+
|
5
|
+
This gem provides a set of matchers that make testing JSON documents (actually
|
6
|
+
the hashes parsed from them) simpler and more elegant.
|
7
|
+
|
8
|
+
It provides two primary matchers, `have_attribute` and `resembles`/`resembles_json`.
|
9
|
+
|
10
|
+
## `#have_attribute`
|
11
|
+
|
12
|
+
Use this matcher when you want to examine a single attribute, and optionally
|
13
|
+
match against its value.
|
14
|
+
|
15
|
+
### Example Usage
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
RSpec.describe "my hash" do
|
19
|
+
include RSpec::ResemblesJsonMatchers
|
20
|
+
|
21
|
+
subject(:response_document) do
|
22
|
+
{
|
23
|
+
author: "Paul",
|
24
|
+
gems_published: 42,
|
25
|
+
created_at: "2016-01-01T00:00:00Z"
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
# Test that the key is present, regardless of value (even nil)
|
30
|
+
it { should have_attribute :author }
|
31
|
+
|
32
|
+
# Test the value by using another matcher
|
33
|
+
it { should have_attribute :author, eq("Paul") }
|
34
|
+
it { should have_attribute :author, match(/Paul/) }
|
35
|
+
it { should have_attribute :gems_published, be > 40 }
|
36
|
+
it { should have_attribute :created_at, iso8601_timestamp }
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
It will also provide nice descriptions in the rspec doc format, and useful
|
41
|
+
failure messages:
|
42
|
+
|
43
|
+
```
|
44
|
+
my hash
|
45
|
+
should have attribute :author be present
|
46
|
+
should have attribute :author eq "Paul"
|
47
|
+
should have attribute :author match /Paul/
|
48
|
+
should have attribute :gems_published be > 40
|
49
|
+
should have attribute :created_at match /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z/
|
50
|
+
```
|
51
|
+
|
52
|
+
```
|
53
|
+
Failures:
|
54
|
+
|
55
|
+
1) my hash should have attribute :full_name be present
|
56
|
+
Failure/Error: it { should have_attribute :full_name }
|
57
|
+
Expected attribute :full_name to be present
|
58
|
+
# ./spec/examples_spec.rb:24:in `block (2 levels) in <top (required)>'
|
59
|
+
|
60
|
+
2) my hash should have attribute :author match /paul/
|
61
|
+
Failure/Error: it { should have_attribute :author, match(/paul/) }
|
62
|
+
Expected value of attribute :author to match /paul/ but it was "Paul"
|
63
|
+
# ./spec/examples_spec.rb:25:in `block (2 levels) in <top (required)>'
|
64
|
+
```
|
65
|
+
|
66
|
+
## `#resembles_json`
|
67
|
+
|
68
|
+
This matcher builds upon `#have_attribute` to let you test an entire JSON document in a single example, but still provide detailed errors about each attribute.
|
69
|
+
|
70
|
+
Additionally, it does "fuzzy" matching on the fields (unless a matcher is explicitly given), because its primary purpose it do have a clear and concise example of the API output for documentation.
|
71
|
+
|
72
|
+
See the examples folder for more.
|
73
|
+
|
74
|
+
### Example Usage
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
RSpec.describe "a basic json document" do
|
78
|
+
let(:document) do
|
79
|
+
{
|
80
|
+
"@id": "/posts/2016/test1",
|
81
|
+
"@type": "Post",
|
82
|
+
"title": "Hello World!",
|
83
|
+
"body": "lorem ipsum",
|
84
|
+
"created_at": "2016-03-01T00:03:42",
|
85
|
+
"published_at": "2016-03-10T15:35:00"
|
86
|
+
}
|
87
|
+
end
|
88
|
+
|
89
|
+
specify do
|
90
|
+
expect(document).to resemble_json(
|
91
|
+
{
|
92
|
+
"@id": "/posts/:year/:title",
|
93
|
+
"@type": eq("Post"),
|
94
|
+
"title": "Hello World!",
|
95
|
+
"body": "lorem ipsum",
|
96
|
+
"created_at": "2016-03-01T00:03:42",
|
97
|
+
"published_at": "2016-03-10T15:35:00"
|
98
|
+
}
|
99
|
+
)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
```
|
103
|
+
|
104
|
+
Again, it provides good descriptions:
|
105
|
+
|
106
|
+
```
|
107
|
+
a basic json document
|
108
|
+
should resemble json
|
109
|
+
{
|
110
|
+
"@id": /posts/:year/:title,
|
111
|
+
"@type": "Post",
|
112
|
+
"title": Hello World!,
|
113
|
+
"body": lorem ipsum,
|
114
|
+
"created_at": "2016-03-01T00:03:42",
|
115
|
+
"published_at": "2016-03-10T15:35:00"
|
116
|
+
}
|
117
|
+
```
|
118
|
+
|
119
|
+
And useful failure messages:
|
120
|
+
|
121
|
+
```
|
122
|
+
Failures:
|
123
|
+
|
124
|
+
1) The resembles json matcher a basic json document with several attributes that failed to match should resemble json
|
125
|
+
{
|
126
|
+
"@id": /posts/:year/:title,
|
127
|
+
"@type": "PostCollection",
|
128
|
+
"title": 42.0,
|
129
|
+
"body": lorem ipsum,
|
130
|
+
"created_at": "2016-03-01T00:03:42",
|
131
|
+
"published_at": "2016-03-10T15:35:00"
|
132
|
+
}
|
133
|
+
|
134
|
+
Failure/Error:
|
135
|
+
expect(document).to resemble_json(
|
136
|
+
{
|
137
|
+
"@id": "/posts/:year/:title",
|
138
|
+
"@type": eq("PostCollection"),
|
139
|
+
"title": 42.0,
|
140
|
+
"body": "lorem ipsum",
|
141
|
+
"created_at": "2016-03-01T00:03:42",
|
142
|
+
"published_at": "2016-03-10T15:35:00"
|
143
|
+
}
|
144
|
+
)
|
145
|
+
|
146
|
+
failed because
|
147
|
+
attribute "@type":
|
148
|
+
expected: "PostCollection"
|
149
|
+
got: "Post"
|
150
|
+
attribute "title":
|
151
|
+
"Hello World!" does not resemble a number
|
152
|
+
# ./examples/example_spec.rb:40:in `block (4 levels) in <top (required)>'
|
153
|
+
|
154
|
+
2) The resembles json matcher a basic json document when the matcher is missing a field that is present in the document should resemble json
|
155
|
+
{
|
156
|
+
"@id": /posts/:year/:title,
|
157
|
+
"@type": "Post",
|
158
|
+
"body": lorem ipsum,
|
159
|
+
"created_at": "2016-03-01T00:03:42",
|
160
|
+
"published_at": "2016-03-10T15:35:00"
|
161
|
+
}
|
162
|
+
|
163
|
+
Failure/Error:
|
164
|
+
expect(document).to resemble_json(
|
165
|
+
{
|
166
|
+
"@id": "/posts/:year/:title",
|
167
|
+
"@type": eq("Post"),
|
168
|
+
"body": "lorem ipsum",
|
169
|
+
"created_at": "2016-03-01T00:03:42",
|
170
|
+
"published_at": "2016-03-10T15:35:00"
|
171
|
+
}
|
172
|
+
)
|
173
|
+
|
174
|
+
failed because
|
175
|
+
attribute "title":
|
176
|
+
is present, but no matcher provided to match it
|
177
|
+
# ./examples/example_spec.rb:55:in `block (4 levels) in <top (required)>'
|
178
|
+
|
179
|
+
3) The resembles json matcher a basic json document when the document is missing a field that is present in the matcher should resemble json
|
180
|
+
{
|
181
|
+
"@id": /posts/:year/:title,
|
182
|
+
"@type": "Post",
|
183
|
+
"body": lorem ipsum,
|
184
|
+
"created_at": "2016-03-01T00:03:42",
|
185
|
+
"published_at": "2016-03-10T15:35:00"
|
186
|
+
}
|
187
|
+
|
188
|
+
Failure/Error:
|
189
|
+
expect(document).to resemble_json(
|
190
|
+
{
|
191
|
+
"@id": "/posts/:year/:title",
|
192
|
+
"@type": eq("Post"),
|
193
|
+
"body": "lorem ipsum",
|
194
|
+
"created_at": "2016-03-01T00:03:42",
|
195
|
+
"published_at": "2016-03-10T15:35:00"
|
196
|
+
}
|
197
|
+
)
|
198
|
+
|
199
|
+
failed because
|
200
|
+
attribute "title":
|
201
|
+
is present, but no matcher provided to match it
|
202
|
+
# ./examples/example_spec.rb:69:in `block (4 levels) in <top (required)>'
|
203
|
+
```
|
204
|
+
|
205
|
+
|
206
|
+
# Installation
|
207
|
+
|
208
|
+
Add this line to your application's Gemfile:
|
209
|
+
|
210
|
+
```ruby
|
211
|
+
gem 'rspec-json_api_matchers'
|
212
|
+
```
|
213
|
+
|
214
|
+
And then execute:
|
215
|
+
|
216
|
+
$ bundle
|
217
|
+
|
218
|
+
Or install it yourself as:
|
219
|
+
|
220
|
+
$ gem install rspec-json_api_matchers
|
221
|
+
|
222
|
+
# Contributing
|
223
|
+
|
224
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/paul/rspec-json_api_matchers.
|
225
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
require_relative "../spec/spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe "The resembles json matcher" do
|
4
|
+
include RSpec::ResemblesJsonMatchers
|
5
|
+
|
6
|
+
before :all do
|
7
|
+
puts <<-WARNING.strip_heredoc
|
8
|
+
NOTE: some of these are expected to fail, they are meant to demonstrate
|
9
|
+
the output generated by failing specs
|
10
|
+
WARNING
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "a basic json document" do
|
14
|
+
let(:document) do
|
15
|
+
{
|
16
|
+
"@id": "/posts/2016/test1",
|
17
|
+
"@type": "Post",
|
18
|
+
"title": "Hello World!",
|
19
|
+
"body": "lorem ipsum",
|
20
|
+
"created_at": "2016-03-01T00:03:42",
|
21
|
+
"published_at": "2016-03-10T15:35:00"
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
specify do
|
26
|
+
expect(document).to resemble_json(
|
27
|
+
{
|
28
|
+
"@id": "/posts/:year/:title",
|
29
|
+
"@type": eq("Post"),
|
30
|
+
"title": "Hello World!",
|
31
|
+
"body": "lorem ipsum",
|
32
|
+
"created_at": "2016-03-01T00:03:42",
|
33
|
+
"published_at": "2016-03-10T15:35:00"
|
34
|
+
}
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
context "with several attributes that failed to match" do
|
39
|
+
specify do
|
40
|
+
expect(document).to resemble_json(
|
41
|
+
{
|
42
|
+
"@id": "/posts/:year/:title",
|
43
|
+
"@type": eq("PostCollection"),
|
44
|
+
"title": 42.0,
|
45
|
+
"body": "lorem ipsum",
|
46
|
+
"created_at": "2016-03-01T00:03:42",
|
47
|
+
"published_at": "2016-03-10T15:35:00"
|
48
|
+
}
|
49
|
+
)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when the matcher is missing a field that is present in the document" do
|
54
|
+
specify do
|
55
|
+
expect(document).to resemble_json(
|
56
|
+
{
|
57
|
+
"@id": "/posts/:year/:title",
|
58
|
+
"@type": eq("Post"),
|
59
|
+
"body": "lorem ipsum",
|
60
|
+
"created_at": "2016-03-01T00:03:42",
|
61
|
+
"published_at": "2016-03-10T15:35:00"
|
62
|
+
}
|
63
|
+
)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "when the document is missing a field that is present in the matcher" do
|
68
|
+
specify do
|
69
|
+
expect(document).to resemble_json(
|
70
|
+
{
|
71
|
+
"@id": "/posts/:year/:title",
|
72
|
+
"@type": eq("Post"),
|
73
|
+
"body": "lorem ipsum",
|
74
|
+
"created_at": "2016-03-01T00:03:42",
|
75
|
+
"published_at": "2016-03-10T15:35:00"
|
76
|
+
}
|
77
|
+
)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "complex nested json documents" do
|
83
|
+
let(:document) do
|
84
|
+
{
|
85
|
+
"@id": "/posts",
|
86
|
+
"@type": "PostCollection",
|
87
|
+
"nextPage": "/posts?page=2",
|
88
|
+
"members": [
|
89
|
+
{
|
90
|
+
"@id": "/posts/2016/test1",
|
91
|
+
"@type": "Post",
|
92
|
+
"title": "Hello World!",
|
93
|
+
"body": "lorem ipsum",
|
94
|
+
"created_at": "2016-03-01T00:03:42",
|
95
|
+
"published_at": "2016-03-10T15:35:00"
|
96
|
+
}
|
97
|
+
]
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
specify do
|
102
|
+
expect(document).to resemble_json(
|
103
|
+
{
|
104
|
+
"@id": "/posts",
|
105
|
+
"@type": eq("PostCollection"),
|
106
|
+
"nextPage": "/posts?page=2",
|
107
|
+
"members": [
|
108
|
+
{
|
109
|
+
"@id": "/posts/:year/:title",
|
110
|
+
"@type": eq("Post"),
|
111
|
+
"title": "Hello World!",
|
112
|
+
"body": "lorem ipsum",
|
113
|
+
"created_at": "2016-03-01T00:03:42",
|
114
|
+
"published_at": "2016-03-10T15:35:00"
|
115
|
+
}
|
116
|
+
]
|
117
|
+
}
|
118
|
+
)
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|