json_spec 0.8.1 → 1.0.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.
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