json_spec 0.8.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +2 -4
- data/Gemfile +1 -1
- data/{LICENSE.md → LICENSE} +0 -0
- data/README.md +221 -210
- data/features/files.feature +89 -0
- data/features/support/env.rb +3 -0
- data/features/types.feature +7 -1
- data/json_spec.gemspec +16 -20
- data/lib/json_spec/configuration.rb +10 -2
- data/lib/json_spec/cucumber.rb +18 -3
- data/lib/json_spec/errors.rb +22 -1
- data/lib/json_spec/helpers.rb +17 -2
- data/lib/json_spec/matchers/be_json_eql.rb +63 -0
- data/lib/json_spec/matchers/have_json_path.rb +30 -0
- data/lib/json_spec/matchers/have_json_size.rb +35 -0
- data/lib/json_spec/matchers/have_json_type.rb +49 -0
- data/lib/json_spec/matchers/include_json.rb +57 -0
- data/lib/json_spec/matchers.rb +9 -218
- data/lib/json_spec/memory.rb +2 -3
- data/lib/json_spec/messages.rb +8 -0
- data/lib/json_spec.rb +3 -1
- data/spec/json_spec/configuration_spec.rb +10 -0
- data/spec/json_spec/helpers_spec.rb +33 -1
- data/spec/json_spec/matchers/be_json_eql_spec.rb +109 -0
- data/spec/json_spec/matchers/have_json_path_spec.rb +29 -0
- data/spec/json_spec/matchers/have_json_size_spec.rb +47 -0
- data/spec/json_spec/matchers/have_json_type_spec.rb +89 -0
- data/spec/json_spec/matchers/include_json_spec.rb +76 -0
- data/spec/json_spec/matchers_spec.rb +43 -287
- data/spec/json_spec/memory_spec.rb +8 -3
- data/spec/spec_helper.rb +4 -0
- data/spec/support/files/one.json +1 -0
- data/spec/support/files/project/one.json +1 -0
- data/spec/support/files/project/two.json +18 -0
- data/spec/support/files/project/version/one.json +1 -0
- data/spec/support/files/project/version/two.json +3 -0
- data/spec/support/files/two.json +24 -0
- metadata +49 -20
- data/lib/json_spec/version.rb +0 -3
@@ -49,4 +49,14 @@ describe JsonSpec::Configuration do
|
|
49
49
|
JsonSpec.reset
|
50
50
|
JsonSpec.excluded_keys.should == original
|
51
51
|
end
|
52
|
+
|
53
|
+
it "resets its directory" do
|
54
|
+
JsonSpec.directory.should be_nil
|
55
|
+
|
56
|
+
JsonSpec.directory = "/"
|
57
|
+
JsonSpec.directory.should_not be_nil
|
58
|
+
|
59
|
+
JsonSpec.reset
|
60
|
+
JsonSpec.directory.should be_nil
|
61
|
+
end
|
52
62
|
end
|
@@ -25,7 +25,7 @@ describe JsonSpec::Helpers do
|
|
25
25
|
it "raises an error for a missing path" do
|
26
26
|
json = %({"json":["spec"]})
|
27
27
|
%w(spec json/1).each do |path|
|
28
|
-
expect{ parse_json(json, path) }.to raise_error(JsonSpec::
|
28
|
+
expect{ parse_json(json, path) }.to raise_error(JsonSpec::MissingPath)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
@@ -71,4 +71,36 @@ describe JsonSpec::Helpers do
|
|
71
71
|
generate_normalized_json(nil).should == %(null)
|
72
72
|
end
|
73
73
|
end
|
74
|
+
|
75
|
+
context "load_json_file" do
|
76
|
+
it "raises an error when no directory is set" do
|
77
|
+
expect{ load_json("one.json") }.to raise_error(JsonSpec::MissingDirectory)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "returns JSON when the file exists" do
|
81
|
+
JsonSpec.directory = files_path
|
82
|
+
load_json("one.json").should == %({"value":"from_file"})
|
83
|
+
end
|
84
|
+
|
85
|
+
it "ignores extra slashes" do
|
86
|
+
JsonSpec.directory = "/#{files_path}/"
|
87
|
+
load_json("one.json").should == %({"value":"from_file"})
|
88
|
+
end
|
89
|
+
|
90
|
+
it "raises an error when the file doesn't exist" do
|
91
|
+
JsonSpec.directory = files_path
|
92
|
+
expect{ load_json("bogus.json") }.to raise_error(JsonSpec::MissingFile)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "raises an error when the directory doesn't exist" do
|
96
|
+
JsonSpec.directory = "#{files_path}_bogus"
|
97
|
+
expect{ load_json("one.json") }.to raise_error(JsonSpec::MissingFile)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "finds nested files" do
|
101
|
+
JsonSpec.directory = files_path
|
102
|
+
load_json("project/one.json").should == %({"nested":"inside_folder"})
|
103
|
+
load_json("project/version/one.json").should == %({"nested":"deeply"})
|
104
|
+
end
|
105
|
+
end
|
74
106
|
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe JsonSpec::Matchers::BeJsonEql do
|
4
|
+
it "matches identical JSON" do
|
5
|
+
%({"json":"spec"}).should be_json_eql(%({"json":"spec"}))
|
6
|
+
end
|
7
|
+
|
8
|
+
it "matches differently-formatted JSON" do
|
9
|
+
%({"json": "spec"}).should be_json_eql(%({"json":"spec"}))
|
10
|
+
end
|
11
|
+
|
12
|
+
it "matches out-of-order hashes" do
|
13
|
+
%({"laser":"lemon","json":"spec"}).should be_json_eql(%({"json":"spec","laser":"lemon"}))
|
14
|
+
end
|
15
|
+
|
16
|
+
it "doesn't match out-of-order arrays" do
|
17
|
+
%(["json","spec"]).should_not be_json_eql(%(["spec","json"]))
|
18
|
+
end
|
19
|
+
|
20
|
+
it "matches valid JSON values, yet invalid JSON documents" do
|
21
|
+
%("json_spec").should be_json_eql(%("json_spec"))
|
22
|
+
end
|
23
|
+
|
24
|
+
it "matches at a path" do
|
25
|
+
%({"json":["spec"]}).should be_json_eql(%("spec")).at_path("json/0")
|
26
|
+
end
|
27
|
+
|
28
|
+
it "ignores excluded-by-default hash keys" do
|
29
|
+
JsonSpec.excluded_keys.should_not be_empty
|
30
|
+
|
31
|
+
actual = expected = {"json" => "spec"}
|
32
|
+
JsonSpec.excluded_keys.each{|k| actual[k] = k }
|
33
|
+
actual.to_json.should be_json_eql(expected.to_json)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "ignores custom excluded hash keys" do
|
37
|
+
JsonSpec.exclude_keys("ignore")
|
38
|
+
%({"json":"spec","ignore":"please"}).should be_json_eql(%({"json":"spec"}))
|
39
|
+
end
|
40
|
+
|
41
|
+
it "ignores nested, excluded hash keys" do
|
42
|
+
JsonSpec.exclude_keys("ignore")
|
43
|
+
%({"json":"spec","please":{"ignore":"this"}}).should be_json_eql(%({"json":"spec","please":{}}))
|
44
|
+
end
|
45
|
+
|
46
|
+
it "ignores hash keys when included in the expected value" do
|
47
|
+
JsonSpec.exclude_keys("ignore")
|
48
|
+
%({"json":"spec","ignore":"please"}).should be_json_eql(%({"json":"spec","ignore":"this"}))
|
49
|
+
end
|
50
|
+
|
51
|
+
it "doesn't match Ruby-equivalent, JSON-inequivalent values" do
|
52
|
+
%({"one":1}).should_not be_json_eql(%({"one":1.0}))
|
53
|
+
end
|
54
|
+
|
55
|
+
it "matches different looking, JSON-equivalent values" do
|
56
|
+
%({"ten":10.0}).should be_json_eql(%({"ten":1e+1}))
|
57
|
+
end
|
58
|
+
|
59
|
+
it "excludes extra hash keys per matcher" do
|
60
|
+
JsonSpec.excluded_keys = %w(ignore)
|
61
|
+
%({"id":1,"json":"spec","ignore":"please"}).should be_json_eql(%({"id":2,"json":"spec","ignore":"this"})).excluding("id")
|
62
|
+
end
|
63
|
+
|
64
|
+
it "excludes extra hash keys given as symbols" do
|
65
|
+
JsonSpec.excluded_keys = []
|
66
|
+
%({"id":1,"json":"spec"}).should be_json_eql(%({"id":2,"json":"spec"})).excluding(:id)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "excludes multiple keys" do
|
70
|
+
JsonSpec.excluded_keys = []
|
71
|
+
%({"id":1,"json":"spec"}).should be_json_eql(%({"id":2,"json":"different"})).excluding(:id, :json)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "includes globally-excluded hash keys per matcher" do
|
75
|
+
JsonSpec.excluded_keys = %w(id ignore)
|
76
|
+
%({"id":1,"json":"spec","ignore":"please"}).should_not be_json_eql(%({"id":2,"json":"spec","ignore":"this"})).including("id")
|
77
|
+
end
|
78
|
+
|
79
|
+
it "includes globally-included hash keys given as symbols" do
|
80
|
+
JsonSpec.excluded_keys = %w(id)
|
81
|
+
%({"id":1,"json":"spec"}).should_not be_json_eql(%({"id":2,"json":"spec"})).including(:id)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "includes multiple keys" do
|
85
|
+
JsonSpec.excluded_keys = %w(id json)
|
86
|
+
%({"id":1,"json":"spec"}).should_not be_json_eql(%({"id":2,"json":"different"})).including(:id, :json)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "provide a description message" do
|
90
|
+
matcher = be_json_eql(%({"id":2,"json":"spec"}))
|
91
|
+
matcher.matches?(%({"id":1,"json":"spec"}))
|
92
|
+
matcher.description.should == "equal JSON"
|
93
|
+
end
|
94
|
+
|
95
|
+
it "provide a description message with path" do
|
96
|
+
matcher = be_json_eql(%({"id":1,"json":["spec"]})).at_path("json/0")
|
97
|
+
matcher.matches?(%({"id":1,"json":["spec"]}))
|
98
|
+
matcher.description.should == %(equal JSON at path "json/0")
|
99
|
+
end
|
100
|
+
|
101
|
+
it "raises an error when not given expected JSON" do
|
102
|
+
expect{ %({"id":1,"json":"spec"}).should be_json_eql }.to raise_error
|
103
|
+
end
|
104
|
+
|
105
|
+
it "matches file contents" do
|
106
|
+
JsonSpec.directory = files_path
|
107
|
+
%({ "value" : "from_file" }).should be_json_eql.to_file("one.json")
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe JsonSpec::Matchers::HaveJsonPath do
|
4
|
+
it "matches hash keys" do
|
5
|
+
%({"one":{"two":{"three":4}}}).should have_json_path("one/two/three")
|
6
|
+
end
|
7
|
+
|
8
|
+
it "doesn't match values" do
|
9
|
+
%({"one":{"two":{"three":4}}}).should_not have_json_path("one/two/three/4")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "matches array indexes" do
|
13
|
+
%([1,[1,2,[1,2,3,4]]]).should have_json_path("1/2/3")
|
14
|
+
end
|
15
|
+
|
16
|
+
it "respects null array values" do
|
17
|
+
%([null,[null,null,[null,null,null,null]]]).should have_json_path("1/2/3")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "matches hash keys and array indexes" do
|
21
|
+
%({"one":[1,2,{"three":4}]}).should have_json_path("one/2/three")
|
22
|
+
end
|
23
|
+
|
24
|
+
it "provide a description message" do
|
25
|
+
matcher = have_json_path("json")
|
26
|
+
matcher.matches?(%({"id":1,"json":"spec"}))
|
27
|
+
matcher.description.should == %(have JSON path "json")
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe JsonSpec::Matchers::HaveJsonSize do
|
4
|
+
it "counts array entries" do
|
5
|
+
%([1,2,3]).should have_json_size(3)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "counts null array entries" do
|
9
|
+
%([1,null,3]).should have_json_size(3)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "counts hash key/value pairs" do
|
13
|
+
%({"one":1,"two":2,"three":3}).should have_json_size(3)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "counts null hash values" do
|
17
|
+
%({"one":1,"two":null,"three":3}).should have_json_size(3)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "matches at a path" do
|
21
|
+
%({"one":[1,2,3]}).should have_json_size(3).at_path("one")
|
22
|
+
end
|
23
|
+
|
24
|
+
it "provides a failure message for should" do
|
25
|
+
matcher = have_json_size(3)
|
26
|
+
matcher.matches?(%([1,2]))
|
27
|
+
matcher.failure_message_for_should.should == "Expected JSON value size to be 3, got 2"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "provides a failure message for should not" do
|
31
|
+
matcher = have_json_size(3)
|
32
|
+
matcher.matches?(%([1,2,3]))
|
33
|
+
matcher.failure_message_for_should_not.should == "Expected JSON value size to not be 3, got 3"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "provide a description message" do
|
37
|
+
matcher = have_json_size(1)
|
38
|
+
matcher.matches?(%({"id":1,"json":["spec"]}))
|
39
|
+
matcher.description.should == %(have JSON size "1")
|
40
|
+
end
|
41
|
+
|
42
|
+
it "provide a description message with path" do
|
43
|
+
matcher = have_json_size(1).at_path("json")
|
44
|
+
matcher.matches?(%({"id":1,"json":["spec"]}))
|
45
|
+
matcher.description.should == %(have JSON size "1" at path "json")
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe JsonSpec::Matchers::HaveJsonType do
|
4
|
+
it "matches hashes" do
|
5
|
+
hash = %({})
|
6
|
+
hash.should have_json_type(Hash)
|
7
|
+
hash.should have_json_type(:object)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "matches arrays" do
|
11
|
+
%([]).should have_json_type(Array)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "matches at a path" do
|
15
|
+
%({"root":[]}).should have_json_type(Array).at_path("root")
|
16
|
+
end
|
17
|
+
|
18
|
+
it "matches strings" do
|
19
|
+
%(["json_spec"]).should have_json_type(String).at_path("0")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "matches a valid JSON value, yet invalid JSON document" do
|
23
|
+
%("json_spec").should have_json_type(String)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "matches empty strings" do
|
27
|
+
%("").should have_json_type(String)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "matches integers" do
|
31
|
+
%(10).should have_json_type(Integer)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "matches floats" do
|
35
|
+
%(10.0).should have_json_type(Float)
|
36
|
+
%(1e+1).should have_json_type(Float)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "matches booleans" do
|
40
|
+
%(true).should have_json_type(:boolean)
|
41
|
+
%(false).should have_json_type(:boolean)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "matches ancestor classes" do
|
45
|
+
%(10).should have_json_type(Numeric)
|
46
|
+
%(10.0).should have_json_type(Numeric)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "provides a failure message for should" do
|
50
|
+
matcher = have_json_type(Numeric)
|
51
|
+
matcher.matches?(%("foo"))
|
52
|
+
matcher.failure_message_for_should.should == "Expected JSON value type to be Numeric, got String"
|
53
|
+
end
|
54
|
+
|
55
|
+
it "provides a failure message for should not" do
|
56
|
+
matcher = have_json_type(Numeric)
|
57
|
+
matcher.matches?(%(10))
|
58
|
+
matcher.failure_message_for_should_not.should == "Expected JSON value type to not be Numeric, got Fixnum"
|
59
|
+
end
|
60
|
+
|
61
|
+
it "provide a description message" do
|
62
|
+
matcher = have_json_type(String)
|
63
|
+
matcher.matches?(%({"id":1,"json":"spec"}))
|
64
|
+
matcher.description.should == %(have JSON type "String")
|
65
|
+
end
|
66
|
+
|
67
|
+
it "provide a description message with path" do
|
68
|
+
matcher = have_json_type(String).at_path("json")
|
69
|
+
matcher.matches?(%({"id":1,"json":"spec"}))
|
70
|
+
matcher.description.should == %(have JSON type "String" at path "json")
|
71
|
+
end
|
72
|
+
|
73
|
+
context "somewhat uselessly" do
|
74
|
+
it "matches true" do
|
75
|
+
%(true).should have_json_type(TrueClass)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "matches false" do
|
79
|
+
%(false).should have_json_type(FalseClass)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "matches null" do
|
83
|
+
null = %(null)
|
84
|
+
null.should have_json_type(NilClass)
|
85
|
+
null.should have_json_type(:nil)
|
86
|
+
null.should have_json_type(:null)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe JsonSpec::Matchers::IncludeJson do
|
4
|
+
it "matches included array elements" do
|
5
|
+
json = %(["one",1,1.0,true,false,null])
|
6
|
+
json.should include_json(%("one"))
|
7
|
+
json.should include_json(%(1))
|
8
|
+
json.should include_json(%(1.0))
|
9
|
+
json.should include_json(%(true))
|
10
|
+
json.should include_json(%(false))
|
11
|
+
json.should include_json(%(null))
|
12
|
+
end
|
13
|
+
|
14
|
+
it "matches an array included in an array" do
|
15
|
+
json = %([[1,2,3],[4,5,6]])
|
16
|
+
json.should include_json(%([1,2,3]))
|
17
|
+
json.should include_json(%([4,5,6]))
|
18
|
+
end
|
19
|
+
|
20
|
+
it "matches a hash included in an array" do
|
21
|
+
json = %([{"one":1},{"two":2}])
|
22
|
+
json.should include_json(%({"one":1}))
|
23
|
+
json.should include_json(%({"two":2}))
|
24
|
+
end
|
25
|
+
|
26
|
+
it "matches include hash values" do
|
27
|
+
json = %({"string":"one","integer":1,"float":1.0,"true":true,"false":false,"null":null})
|
28
|
+
json.should include_json(%("one"))
|
29
|
+
json.should include_json(%(1))
|
30
|
+
json.should include_json(%(1.0))
|
31
|
+
json.should include_json(%(true))
|
32
|
+
json.should include_json(%(false))
|
33
|
+
json.should include_json(%(null))
|
34
|
+
end
|
35
|
+
|
36
|
+
it "matches a hash included in a hash" do
|
37
|
+
json = %({"one":{"two":3},"four":{"five":6}})
|
38
|
+
json.should include_json(%({"two":3}))
|
39
|
+
json.should include_json(%({"five":6}))
|
40
|
+
end
|
41
|
+
|
42
|
+
it "matches an array included in a hash" do
|
43
|
+
json = %({"one":[2,3],"four":[5,6]})
|
44
|
+
json.should include_json(%([2,3]))
|
45
|
+
json.should include_json(%([5,6]))
|
46
|
+
end
|
47
|
+
|
48
|
+
it "matches at a path" do
|
49
|
+
%({"one":{"two":[3,4]}}).should include_json(%([3,4])).at_path("one")
|
50
|
+
end
|
51
|
+
|
52
|
+
it "ignores excluded keys" do
|
53
|
+
%([{"id":1,"two":3}]).should include_json(%({"two":3}))
|
54
|
+
end
|
55
|
+
|
56
|
+
it "provide a description message" do
|
57
|
+
matcher = include_json(%({"json":"spec"}))
|
58
|
+
matcher.matches?(%({"id":1,"json":"spec"}))
|
59
|
+
matcher.description.should == "include JSON"
|
60
|
+
end
|
61
|
+
|
62
|
+
it "provide a description message with path" do
|
63
|
+
matcher = include_json(%("spec")).at_path("json/0")
|
64
|
+
matcher.matches?(%({"id":1,"json":["spec"]}))
|
65
|
+
matcher.description.should == %(include JSON at path "json/0")
|
66
|
+
end
|
67
|
+
|
68
|
+
it "raises an error when not given expected JSON" do
|
69
|
+
expect{ %([{"id":1,"two":3}]).should include_json }.to raise_error
|
70
|
+
end
|
71
|
+
|
72
|
+
it "matches file contents" do
|
73
|
+
JsonSpec.directory = files_path
|
74
|
+
%({"one":{"value":"from_file"},"four":{"five":6}}).should include_json.from_file("one.json")
|
75
|
+
end
|
76
|
+
end
|