json_spec 0.7.0 → 0.8.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.
- data/.travis.yml +1 -3
- data/README.md +16 -5
- data/json_spec.gemspec +2 -2
- data/lib/json_spec.rb +1 -1
- data/lib/json_spec/cucumber.rb +3 -3
- data/lib/json_spec/matchers.rb +196 -143
- data/lib/json_spec/version.rb +1 -1
- metadata +91 -49
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
json_spec
|
1
|
+
json_spec [](http://travis-ci.org/collectiveidea/json_spec) [](https://gemnasium.com/collectiveidea/json_spec)
|
2
2
|
========
|
3
|
+
|
3
4
|
Easily handle JSON in RSpec and Cucumber
|
4
5
|
|
5
6
|
Installation
|
@@ -16,10 +17,6 @@ Please help write documentation!
|
|
16
17
|
|
17
18
|
[http://rdoc.info/gems/json_spec](http://rdoc.info/gems/json_spec)
|
18
19
|
|
19
|
-
Continuous Integration
|
20
|
-
----------------------
|
21
|
-
[](http://travis-ci.org/collectiveidea/json_spec)
|
22
|
-
|
23
20
|
RSpec
|
24
21
|
--------------
|
25
22
|
json_spec defines five new RSpec matchers:
|
@@ -56,6 +53,20 @@ The new matchers could be used in RSpec as follows:
|
|
56
53
|
end
|
57
54
|
end
|
58
55
|
|
56
|
+
Also json_spec provides some useful helpers for RSpec tests:
|
57
|
+
|
58
|
+
* `parse_json`
|
59
|
+
* `normalize_json`
|
60
|
+
* `generate_normalized_json`
|
61
|
+
|
62
|
+
To start using them add include statement in your Rspec.configure at spec_helper.rb file:
|
63
|
+
|
64
|
+
RSpec.configure do |config|
|
65
|
+
config.include JsonSpec::Helpers
|
66
|
+
end
|
67
|
+
|
68
|
+
Examples of usage this methods you can find in spec/json_spec/helpers_spec.rb
|
69
|
+
|
59
70
|
### Exclusions
|
60
71
|
|
61
72
|
json_spec ignores certain hash keys by default when comparing JSON:
|
data/json_spec.gemspec
CHANGED
@@ -18,9 +18,9 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{|f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
-
s.add_dependency "multi_json", "~> 1.0
|
21
|
+
s.add_dependency "multi_json", "~> 1.0"
|
22
22
|
s.add_dependency "rspec", "~> 2.0"
|
23
23
|
|
24
24
|
s.add_development_dependency "rake", "~> 0.9"
|
25
|
-
s.add_development_dependency "cucumber", "~> 1.
|
25
|
+
s.add_development_dependency "cucumber", "~> 1.1", ">= 1.1.1"
|
26
26
|
end
|
data/lib/json_spec.rb
CHANGED
data/lib/json_spec/cucumber.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.expand_path("../../json_spec", __FILE__)
|
2
2
|
|
3
|
-
World(JsonSpec::Helpers)
|
3
|
+
World(JsonSpec::Helpers, JsonSpec::Matchers)
|
4
4
|
|
5
5
|
After do
|
6
6
|
JsonSpec.forget
|
@@ -47,9 +47,9 @@ Then /^the (?:JSON|json)(?: response)?(?: at "(.*)")? should have the following:
|
|
47
47
|
path = [base, path].compact.join("/")
|
48
48
|
|
49
49
|
if value
|
50
|
-
|
50
|
+
step %(the JSON at "#{path}" should be:), value
|
51
51
|
else
|
52
|
-
|
52
|
+
step %(the JSON should have "#{path}")
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
data/lib/json_spec/matchers.rb
CHANGED
@@ -1,161 +1,214 @@
|
|
1
1
|
require "json"
|
2
2
|
require "rspec"
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
4
|
+
module JsonSpec
|
5
|
+
module Matchers
|
6
|
+
class BeJsonEql
|
7
|
+
include JsonSpec::Helpers
|
8
|
+
include JsonSpec::Exclusion
|
9
|
+
|
10
|
+
attr_reader :expected, :actual
|
11
|
+
|
12
|
+
def diffable?
|
13
|
+
true
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(expected_json)
|
17
|
+
@expected_json = expected_json
|
18
|
+
end
|
19
|
+
|
20
|
+
def matches?(actual_json)
|
21
|
+
@actual, @expected = scrub(actual_json, @path), scrub(@expected_json)
|
22
|
+
@actual == @expected
|
23
|
+
end
|
24
|
+
|
25
|
+
def at_path(path)
|
26
|
+
@path = path
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def excluding(*keys)
|
31
|
+
excluded_keys.merge(keys.map{|k| k.to_s })
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def including(*keys)
|
36
|
+
excluded_keys.subtract(keys.map{|k| k.to_s })
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
def failure_message_for_should
|
41
|
+
message = "Expected equivalent JSON"
|
42
|
+
message << %( at path "#{@path}") if @path
|
43
|
+
message
|
44
|
+
end
|
45
|
+
|
46
|
+
def failure_message_for_should_not
|
47
|
+
message = "Expected inequivalent JSON"
|
48
|
+
message << %( at path "#{@path}") if @path
|
49
|
+
message
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
def scrub(json, path = nil)
|
54
|
+
generate_normalized_json(exclude_keys(parse_json(json, path))).chomp + "\n"
|
55
|
+
end
|
55
56
|
end
|
56
|
-
end
|
57
|
-
|
58
|
-
chain :at_path do |path|
|
59
|
-
@path = path
|
60
|
-
end
|
61
|
-
|
62
|
-
chain :excluding do |*keys|
|
63
|
-
excluded_keys.merge(*keys.map{|k| k.to_s })
|
64
|
-
end
|
65
|
-
|
66
|
-
chain :including do |*keys|
|
67
|
-
excluded_keys.subtract(keys.map{|k| k.to_s })
|
68
|
-
end
|
69
|
-
|
70
|
-
failure_message_for_should do
|
71
|
-
message = "Expected included JSON"
|
72
|
-
message << %( at path "#{@path}") if @path
|
73
|
-
message
|
74
|
-
end
|
75
|
-
|
76
|
-
failure_message_for_should_not do
|
77
|
-
message = "Expected excluded JSON"
|
78
|
-
message << %( at path "#{@path}") if @path
|
79
|
-
message
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
RSpec::Matchers.define :have_json_path do |path|
|
84
|
-
include JsonSpec::Helpers
|
85
57
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
58
|
+
class IncludeJson
|
59
|
+
include JsonSpec::Helpers
|
60
|
+
include JsonSpec::Exclusion
|
61
|
+
|
62
|
+
def initialize(expected_json)
|
63
|
+
@expected_json = expected_json
|
64
|
+
end
|
65
|
+
|
66
|
+
def matches?(actual_json)
|
67
|
+
actual = parse_json(actual_json, @path)
|
68
|
+
expected = exclude_keys(parse_json(@expected_json))
|
69
|
+
case actual
|
70
|
+
when Hash then actual.values.map{|v| exclude_keys(v) }.include?(expected)
|
71
|
+
when Array then actual.map{|e| exclude_keys(e) }.include?(expected)
|
72
|
+
else false
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def at_path(path)
|
77
|
+
@path = path
|
78
|
+
self
|
79
|
+
end
|
80
|
+
|
81
|
+
def excluding(*keys)
|
82
|
+
excluded_keys.merge(keys.map{|k| k.to_s })
|
83
|
+
self
|
84
|
+
end
|
85
|
+
|
86
|
+
def including(*keys)
|
87
|
+
excluded_keys.subtract(keys.map{|k| k.to_s })
|
88
|
+
self
|
89
|
+
end
|
90
|
+
|
91
|
+
def failure_message_for_should
|
92
|
+
message = "Expected included JSON"
|
93
|
+
message << %( at path "#{@path}") if @path
|
94
|
+
message
|
95
|
+
end
|
96
|
+
|
97
|
+
def failure_message_for_should_not
|
98
|
+
message = "Expected excluded JSON"
|
99
|
+
message << %( at path "#{@path}") if @path
|
100
|
+
message
|
101
|
+
end
|
92
102
|
end
|
93
|
-
end
|
94
103
|
|
95
|
-
|
96
|
-
|
97
|
-
|
104
|
+
class HaveJsonPath
|
105
|
+
include JsonSpec::Helpers
|
106
|
+
|
107
|
+
def initialize(path)
|
108
|
+
@path = path
|
109
|
+
end
|
110
|
+
|
111
|
+
def matches?(json)
|
112
|
+
begin
|
113
|
+
parse_json(json, @path)
|
114
|
+
true
|
115
|
+
rescue JsonSpec::MissingPathError
|
116
|
+
false
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def failure_message_for_should
|
121
|
+
%(Expected JSON path "#{@path}")
|
122
|
+
end
|
123
|
+
|
124
|
+
def failure_message_for_should_not
|
125
|
+
%(Expected no JSON path "#{@path}")
|
126
|
+
end
|
127
|
+
end
|
98
128
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
129
|
+
class HaveJsonType
|
130
|
+
include JsonSpec::Helpers
|
131
|
+
|
132
|
+
def initialize(klass)
|
133
|
+
@klass = klass
|
134
|
+
end
|
135
|
+
|
136
|
+
def matches?(json)
|
137
|
+
@ruby = parse_json(json, @path)
|
138
|
+
@ruby.is_a?(@klass)
|
139
|
+
end
|
140
|
+
|
141
|
+
def at_path(path)
|
142
|
+
@path = path
|
143
|
+
self
|
144
|
+
end
|
145
|
+
|
146
|
+
def failure_message_for_should
|
147
|
+
message = "Expected JSON value type to be #{@klass}, got #{@ruby.class}"
|
148
|
+
message << %( at path "#{@path}") if @path
|
149
|
+
message
|
150
|
+
end
|
151
|
+
|
152
|
+
def failure_message_for_should_not
|
153
|
+
message = "Expected JSON value type to not be #{@klass}, got #{@ruby.class}"
|
154
|
+
message << %( at path "#{@path}") if @path
|
155
|
+
message
|
156
|
+
end
|
157
|
+
end
|
103
158
|
|
104
|
-
|
105
|
-
|
159
|
+
class HaveJsonSize
|
160
|
+
include JsonSpec::Helpers
|
161
|
+
|
162
|
+
def initialize(size)
|
163
|
+
@expected = size
|
164
|
+
end
|
165
|
+
|
166
|
+
def matches?(json)
|
167
|
+
ruby = parse_json(json, @path)
|
168
|
+
@actual = ruby.is_a?(Enumerable) ? ruby.size : 1
|
169
|
+
@actual == @expected
|
170
|
+
end
|
171
|
+
|
172
|
+
def at_path(path)
|
173
|
+
@path = path
|
174
|
+
self
|
175
|
+
end
|
176
|
+
|
177
|
+
def failure_message_for_should
|
178
|
+
message = "Expected JSON value size to be #{@expected}, got #{@actual}"
|
179
|
+
message << %( at path "#{@path}") if @path
|
180
|
+
message
|
181
|
+
end
|
182
|
+
|
183
|
+
def failure_message_for_should_not
|
184
|
+
message = "Expected JSON value size to not be #{@expected}, got #{@actual}"
|
185
|
+
message << %( at path "#{@path}") if @path
|
186
|
+
message
|
187
|
+
end
|
188
|
+
end
|
106
189
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
end
|
190
|
+
def be_json_eql(json)
|
191
|
+
JsonSpec::Matchers::BeJsonEql.new(json)
|
192
|
+
end
|
111
193
|
|
112
|
-
|
113
|
-
|
114
|
-
|
194
|
+
def include_json(json)
|
195
|
+
JsonSpec::Matchers::IncludeJson.new(json)
|
196
|
+
end
|
115
197
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
message
|
120
|
-
end
|
198
|
+
def have_json_path(path)
|
199
|
+
JsonSpec::Matchers::HaveJsonPath.new(path)
|
200
|
+
end
|
121
201
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
message
|
126
|
-
end
|
202
|
+
def have_json_type(klass)
|
203
|
+
JsonSpec::Matchers::HaveJsonType.new(klass)
|
204
|
+
end
|
127
205
|
|
128
|
-
|
129
|
-
|
206
|
+
def have_json_size(size)
|
207
|
+
JsonSpec::Matchers::HaveJsonSize.new(size)
|
208
|
+
end
|
130
209
|
end
|
131
210
|
end
|
132
211
|
|
133
|
-
RSpec
|
134
|
-
include JsonSpec::
|
135
|
-
|
136
|
-
match do |json|
|
137
|
-
@json = json
|
138
|
-
actual_size == expected_size
|
139
|
-
end
|
140
|
-
|
141
|
-
chain :at_path do |path|
|
142
|
-
@path = path
|
143
|
-
end
|
144
|
-
|
145
|
-
failure_message_for_should do
|
146
|
-
message = "Expected JSON value size to be #{expected_size}, got #{actual_size}"
|
147
|
-
message << %( at path "#{@path}") if @path
|
148
|
-
message
|
149
|
-
end
|
150
|
-
|
151
|
-
failure_message_for_should_not do
|
152
|
-
message = "Expected JSON value size to not be #{expected_size}, got #{actual_size}"
|
153
|
-
message << %( at path "#{@path}") if @path
|
154
|
-
message
|
155
|
-
end
|
156
|
-
|
157
|
-
def actual_size
|
158
|
-
ruby = parse_json(@json, @path)
|
159
|
-
ruby.is_a?(Enumerable) ? ruby.size : 1
|
160
|
-
end
|
212
|
+
RSpec.configure do |config|
|
213
|
+
config.include JsonSpec::Matchers
|
161
214
|
end
|
data/lib/json_spec/version.rb
CHANGED
metadata
CHANGED
@@ -1,67 +1,100 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: json_spec
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 63
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 8
|
9
|
+
- 0
|
10
|
+
version: 0.8.0
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Steve Richert
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
|
18
|
+
date: 2012-01-22 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
15
21
|
name: multi_json
|
16
|
-
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
17
24
|
none: false
|
18
|
-
requirements:
|
25
|
+
requirements:
|
19
26
|
- - ~>
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 15
|
29
|
+
segments:
|
30
|
+
- 1
|
31
|
+
- 0
|
32
|
+
version: "1.0"
|
22
33
|
type: :runtime
|
23
|
-
|
24
|
-
|
25
|
-
- !ruby/object:Gem::Dependency
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
26
36
|
name: rspec
|
27
|
-
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
28
39
|
none: false
|
29
|
-
requirements:
|
40
|
+
requirements:
|
30
41
|
- - ~>
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 2
|
46
|
+
- 0
|
47
|
+
version: "2.0"
|
33
48
|
type: :runtime
|
34
|
-
|
35
|
-
|
36
|
-
- !ruby/object:Gem::Dependency
|
49
|
+
version_requirements: *id002
|
50
|
+
- !ruby/object:Gem::Dependency
|
37
51
|
name: rake
|
38
|
-
|
52
|
+
prerelease: false
|
53
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
39
54
|
none: false
|
40
|
-
requirements:
|
55
|
+
requirements:
|
41
56
|
- - ~>
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
hash: 25
|
59
|
+
segments:
|
60
|
+
- 0
|
61
|
+
- 9
|
62
|
+
version: "0.9"
|
44
63
|
type: :development
|
45
|
-
|
46
|
-
|
47
|
-
- !ruby/object:Gem::Dependency
|
64
|
+
version_requirements: *id003
|
65
|
+
- !ruby/object:Gem::Dependency
|
48
66
|
name: cucumber
|
49
|
-
|
67
|
+
prerelease: false
|
68
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
50
69
|
none: false
|
51
|
-
requirements:
|
70
|
+
requirements:
|
52
71
|
- - ~>
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
hash: 13
|
74
|
+
segments:
|
75
|
+
- 1
|
76
|
+
- 1
|
77
|
+
version: "1.1"
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
hash: 17
|
81
|
+
segments:
|
82
|
+
- 1
|
83
|
+
- 1
|
84
|
+
- 1
|
85
|
+
version: 1.1.1
|
55
86
|
type: :development
|
56
|
-
|
57
|
-
version_requirements: *70258292710140
|
87
|
+
version_requirements: *id004
|
58
88
|
description: Easily handle JSON in RSpec and Cucumber
|
59
|
-
email:
|
89
|
+
email:
|
60
90
|
- steve.richert@gmail.com
|
61
91
|
executables: []
|
92
|
+
|
62
93
|
extensions: []
|
94
|
+
|
63
95
|
extra_rdoc_files: []
|
64
|
-
|
96
|
+
|
97
|
+
files:
|
65
98
|
- .gitignore
|
66
99
|
- .travis.yml
|
67
100
|
- Gemfile
|
@@ -93,29 +126,38 @@ files:
|
|
93
126
|
- spec/spec_helper.rb
|
94
127
|
homepage: https://github.com/collectiveidea/json_spec
|
95
128
|
licenses: []
|
129
|
+
|
96
130
|
post_install_message:
|
97
131
|
rdoc_options: []
|
98
|
-
|
132
|
+
|
133
|
+
require_paths:
|
99
134
|
- lib
|
100
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
135
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
101
136
|
none: false
|
102
|
-
requirements:
|
103
|
-
- -
|
104
|
-
- !ruby/object:Gem::Version
|
105
|
-
|
106
|
-
|
137
|
+
requirements:
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
hash: 3
|
141
|
+
segments:
|
142
|
+
- 0
|
143
|
+
version: "0"
|
144
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
145
|
none: false
|
108
|
-
requirements:
|
109
|
-
- -
|
110
|
-
- !ruby/object:Gem::Version
|
111
|
-
|
146
|
+
requirements:
|
147
|
+
- - ">="
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
hash: 3
|
150
|
+
segments:
|
151
|
+
- 0
|
152
|
+
version: "0"
|
112
153
|
requirements: []
|
154
|
+
|
113
155
|
rubyforge_project: json_spec
|
114
|
-
rubygems_version: 1.8.
|
156
|
+
rubygems_version: 1.8.15
|
115
157
|
signing_key:
|
116
158
|
specification_version: 3
|
117
159
|
summary: Easily handle JSON in RSpec and Cucumber
|
118
|
-
test_files:
|
160
|
+
test_files:
|
119
161
|
- features/equivalence.feature
|
120
162
|
- features/inclusion.feature
|
121
163
|
- features/memory.feature
|