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.
Files changed (39) hide show
  1. data/.travis.yml +2 -4
  2. data/Gemfile +1 -1
  3. data/{LICENSE.md → LICENSE} +0 -0
  4. data/README.md +221 -210
  5. data/features/files.feature +89 -0
  6. data/features/support/env.rb +3 -0
  7. data/features/types.feature +7 -1
  8. data/json_spec.gemspec +16 -20
  9. data/lib/json_spec/configuration.rb +10 -2
  10. data/lib/json_spec/cucumber.rb +18 -3
  11. data/lib/json_spec/errors.rb +22 -1
  12. data/lib/json_spec/helpers.rb +17 -2
  13. data/lib/json_spec/matchers/be_json_eql.rb +63 -0
  14. data/lib/json_spec/matchers/have_json_path.rb +30 -0
  15. data/lib/json_spec/matchers/have_json_size.rb +35 -0
  16. data/lib/json_spec/matchers/have_json_type.rb +49 -0
  17. data/lib/json_spec/matchers/include_json.rb +57 -0
  18. data/lib/json_spec/matchers.rb +9 -218
  19. data/lib/json_spec/memory.rb +2 -3
  20. data/lib/json_spec/messages.rb +8 -0
  21. data/lib/json_spec.rb +3 -1
  22. data/spec/json_spec/configuration_spec.rb +10 -0
  23. data/spec/json_spec/helpers_spec.rb +33 -1
  24. data/spec/json_spec/matchers/be_json_eql_spec.rb +109 -0
  25. data/spec/json_spec/matchers/have_json_path_spec.rb +29 -0
  26. data/spec/json_spec/matchers/have_json_size_spec.rb +47 -0
  27. data/spec/json_spec/matchers/have_json_type_spec.rb +89 -0
  28. data/spec/json_spec/matchers/include_json_spec.rb +76 -0
  29. data/spec/json_spec/matchers_spec.rb +43 -287
  30. data/spec/json_spec/memory_spec.rb +8 -3
  31. data/spec/spec_helper.rb +4 -0
  32. data/spec/support/files/one.json +1 -0
  33. data/spec/support/files/project/one.json +1 -0
  34. data/spec/support/files/project/two.json +18 -0
  35. data/spec/support/files/project/version/one.json +1 -0
  36. data/spec/support/files/project/version/two.json +3 -0
  37. data/spec/support/files/two.json +24 -0
  38. metadata +49 -20
  39. 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::MissingPathError)
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