json_spec 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 [![Build Status](https://secure.travis-ci.org/collectiveidea/json_spec.png)](http://travis-ci.org/collectiveidea/json_spec) [![Dependency Status](https://gemnasium.com/collectiveidea/json_spec.png)](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
|
-
[![Build Status](https://secure.travis-ci.org/collectiveidea/json_spec.png)](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
|