jsontest 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 (51) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.travis.yml +21 -0
  4. data/CHANGELOG.md +8 -0
  5. data/Gemfile +8 -0
  6. data/LICENSE.txt +20 -0
  7. data/README.md +343 -0
  8. data/Rakefile +18 -0
  9. data/features/equivalence.feature +286 -0
  10. data/features/files.feature +89 -0
  11. data/features/inclusion.feature +154 -0
  12. data/features/memory.feature +221 -0
  13. data/features/paths.feature +74 -0
  14. data/features/sizes.feature +38 -0
  15. data/features/step_definitions/steps.rb +7 -0
  16. data/features/support/env.rb +9 -0
  17. data/features/types.feature +24 -0
  18. data/gemfiles/rspec2.gemfile +10 -0
  19. data/gemfiles/rspec3.gemfile +10 -0
  20. data/jsontest.gemspec +22 -0
  21. data/lib/jsontest.rb +14 -0
  22. data/lib/jsontest/configuration.rb +30 -0
  23. data/lib/jsontest/cucumber.rb +95 -0
  24. data/lib/jsontest/errors.rb +46 -0
  25. data/lib/jsontest/exclusion.rb +26 -0
  26. data/lib/jsontest/helpers.rb +62 -0
  27. data/lib/jsontest/matchers.rb +33 -0
  28. data/lib/jsontest/matchers/be_json_eql.rb +66 -0
  29. data/lib/jsontest/matchers/have_json_path.rb +32 -0
  30. data/lib/jsontest/matchers/have_json_size.rb +39 -0
  31. data/lib/jsontest/matchers/have_json_type.rb +52 -0
  32. data/lib/jsontest/matchers/include_json.rb +63 -0
  33. data/lib/jsontest/memory.rb +19 -0
  34. data/lib/jsontest/messages.rb +8 -0
  35. data/spec/jsontest/configuration_spec.rb +62 -0
  36. data/spec/jsontest/helpers_spec.rb +111 -0
  37. data/spec/jsontest/matchers/be_json_eql_spec.rb +111 -0
  38. data/spec/jsontest/matchers/have_json_path_spec.rb +29 -0
  39. data/spec/jsontest/matchers/have_json_size_spec.rb +61 -0
  40. data/spec/jsontest/matchers/have_json_type_spec.rb +92 -0
  41. data/spec/jsontest/matchers/include_json_spec.rb +96 -0
  42. data/spec/jsontest/matchers_spec.rb +77 -0
  43. data/spec/jsontest/memory_spec.rb +32 -0
  44. data/spec/spec_helper.rb +23 -0
  45. data/spec/support/files/one.json +1 -0
  46. data/spec/support/files/project/one.json +1 -0
  47. data/spec/support/files/project/two.json +18 -0
  48. data/spec/support/files/project/version/one.json +1 -0
  49. data/spec/support/files/project/version/two.json +3 -0
  50. data/spec/support/files/two.json +24 -0
  51. metadata +182 -0
@@ -0,0 +1,111 @@
1
+ require "spec_helper"
2
+
3
+ describe JsonTest::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
+ %("jsontest").should be_json_eql(%("jsontest"))
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
+ JsonTest.excluded_keys.should_not be_empty
30
+
31
+ actual = expected = { "json" => "spec" }
32
+ JsonTest.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
+ JsonTest.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
+ JsonTest.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
+ JsonTest.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
+ JsonTest.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
+ JsonTest.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
+ JsonTest.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
+ JsonTest.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
+ JsonTest.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
+ JsonTest.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 "provides 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 "provides 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 do |error|
103
+ error.message.should == "Expected equivalent JSON not provided"
104
+ end
105
+ end
106
+
107
+ it "matches file contents" do
108
+ JsonTest.directory = files_path
109
+ %({ "value" : "from_file" }).should be_json_eql.to_file("one.json")
110
+ end
111
+ end
@@ -0,0 +1,29 @@
1
+ require "spec_helper"
2
+
3
+ describe JsonTest::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 "provides 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,61 @@
1
+ require "spec_helper"
2
+
3
+ describe JsonTest::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" do
25
+ matcher = have_json_size(3)
26
+ matcher.matches?(%([1,2]))
27
+ matcher.failure_message.should eq "Expected JSON value size to be 3, got 2"
28
+ matcher.failure_message_for_should.should eq "Expected JSON value size to be 3, got 2" # RSpec 2 interface
29
+ end
30
+
31
+ it "provides a failure message for negation" do
32
+ matcher = have_json_size(3)
33
+ matcher.matches?(%([1,2,3]))
34
+ matcher.failure_message_when_negated.should eq "Expected JSON value size to not be 3, got 3"
35
+ matcher.failure_message_for_should_not.should eq "Expected JSON value size to not be 3, got 3" # RSpec 2 interface
36
+ end
37
+
38
+ it "provides a description message" do
39
+ matcher = have_json_size(1)
40
+ matcher.matches?(%({"id":1,"json":["spec"]}))
41
+ matcher.description.should eq %(have JSON size "1")
42
+ end
43
+
44
+ it "provides a description message with path" do
45
+ matcher = have_json_size(1).at_path("json")
46
+ matcher.matches?(%({"id":1,"json":["spec"]}))
47
+ matcher.description.should eq %(have JSON size "1" at path "json")
48
+ end
49
+
50
+ it "provides an error when parsing nil" do
51
+ matcher = have_json_size(0).at_path("json")
52
+ expect { matcher.matches?(%({"id":1,"json":null})) }.to raise_error(JsonTest::EnumerableExpected,
53
+ "Enumerable expected, got nil")
54
+ end
55
+
56
+ it "provides an error when parsing non-enumerables" do
57
+ matcher = have_json_size(0).at_path("json")
58
+ expect { matcher.matches?(%({"id":1,"json":12345})) }.to raise_error(JsonTest::EnumerableExpected,
59
+ "Enumerable expected, got 12345")
60
+ end
61
+ end
@@ -0,0 +1,92 @@
1
+ require "spec_helper"
2
+
3
+ describe JsonTest::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
+ %(["jsontest"]).should have_json_type(String).at_path("0")
20
+ end
21
+
22
+ it "matches a valid JSON value, yet invalid JSON document" do
23
+ %("jsontest").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" do
50
+ matcher = have_json_type(Numeric)
51
+ matcher.matches?(%("foo"))
52
+ matcher.failure_message.should eq "Expected JSON value type to be Numeric, got String"
53
+ matcher.failure_message_for_should.should eq "Expected JSON value type to be Numeric, got String" # RSpec 2 interface
54
+ end
55
+
56
+ it "provides a failure message for negation" do
57
+ matcher = have_json_type(Numeric)
58
+ matcher.matches?(%(10.0))
59
+
60
+ matcher.failure_message_when_negated.should eq "Expected JSON value type to not be Numeric, got Float"
61
+ matcher.failure_message_for_should_not.should eq "Expected JSON value type to not be Numeric, got Float" # RSpec 2 interface
62
+ end
63
+
64
+ it "provides a description message" do
65
+ matcher = have_json_type(String)
66
+ matcher.matches?(%({"id":1,"json":"spec"}))
67
+ matcher.description.should eq %(have JSON type "String")
68
+ end
69
+
70
+ it "provides a description message with path" do
71
+ matcher = have_json_type(String).at_path("json")
72
+ matcher.matches?(%({"id":1,"json":"spec"}))
73
+ matcher.description.should eq %(have JSON type "String" at path "json")
74
+ end
75
+
76
+ context "somewhat uselessly" do
77
+ it "matches true" do
78
+ %(true).should have_json_type(TrueClass)
79
+ end
80
+
81
+ it "matches false" do
82
+ %(false).should have_json_type(FalseClass)
83
+ end
84
+
85
+ it "matches null" do
86
+ null = %(null)
87
+ null.should have_json_type(NilClass)
88
+ null.should have_json_type(:nil)
89
+ null.should have_json_type(:null)
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,96 @@
1
+ require "spec_helper"
2
+
3
+ describe JsonTest::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 included 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 a substring" do
49
+ json = %("json")
50
+ json.should include_json(%("js"))
51
+ json.should include_json(%("json"))
52
+ end
53
+
54
+ it "matches at a path" do
55
+ %({"one":{"two":[3,4]}}).should include_json(%([3,4])).at_path("one")
56
+ end
57
+
58
+ it "ignores excluded keys" do
59
+ %([{"id":1,"two":3}]).should include_json(%({"two":3}))
60
+ end
61
+
62
+ it "provides a description message" do
63
+ matcher = include_json(%({"json":"spec"}))
64
+ matcher.matches?(%({"id":1,"json":"spec"}))
65
+ matcher.description.should == "include JSON"
66
+ end
67
+
68
+ it "provides a description message with path" do
69
+ matcher = include_json(%("spec")).at_path("json/0")
70
+ matcher.matches?(%({"id":1,"json":["spec"]}))
71
+ matcher.description.should == %(include JSON at path "json/0")
72
+ end
73
+
74
+ it "provides a useful failure message for should" do
75
+ matcher = include_json(%([4,5,6]))
76
+ matcher.matches?(%([1,2,3]))
77
+ matcher.failure_message_for_should.should == "Expected [1,2,3] to include [4,5,6]"
78
+ end
79
+
80
+ it "provides a useful failure message for should not" do
81
+ matcher = include_json(%(3))
82
+ matcher.matches?(%([1,2,3]))
83
+ matcher.failure_message_for_should_not.should == "Expected [1,2,3] to not include 3"
84
+ end
85
+
86
+ it "raises an error when not given expected JSON" do
87
+ expect{ %([{"id":1,"two":3}]).should include_json }.to raise_error do |error|
88
+ error.message.should == "Expected included JSON not provided"
89
+ end
90
+ end
91
+
92
+ it "matches file contents" do
93
+ JsonTest.directory = files_path
94
+ %({"one":{"value":"from_file"},"four":{"five":6}}).should include_json.from_file("one.json")
95
+ end
96
+ end
@@ -0,0 +1,77 @@
1
+ require "spec_helper"
2
+
3
+ describe JsonTest::Matchers do
4
+ let(:environment) do
5
+ klass = Class.new
6
+ klass.send(:include, JsonTest::Matchers)
7
+ klass.new
8
+ end
9
+
10
+ let(:json){ %({"json":"spec"}) }
11
+
12
+ context "be_json_eql" do
13
+ it "instantiates its matcher" do
14
+ JsonTest::Matchers::BeJsonEql.should_receive(:new).with(json)
15
+ environment.be_json_eql(json)
16
+ end
17
+
18
+ it "returns its matcher" do
19
+ matcher = environment.be_json_eql(json)
20
+ matcher.should be_a(JsonTest::Matchers::BeJsonEql)
21
+ end
22
+ end
23
+
24
+ context "include_json" do
25
+ it "instantiates its matcher" do
26
+ JsonTest::Matchers::IncludeJson.should_receive(:new).with(json)
27
+ environment.include_json(json)
28
+ end
29
+
30
+ it "returns its matcher" do
31
+ matcher = environment.include_json(json)
32
+ matcher.should be_a(JsonTest::Matchers::IncludeJson)
33
+ end
34
+ end
35
+
36
+ context "have_json_path" do
37
+ let(:path){ "json" }
38
+
39
+ it "instantiates its matcher" do
40
+ JsonTest::Matchers::HaveJsonPath.should_receive(:new).with(path)
41
+ environment.have_json_path(path)
42
+ end
43
+
44
+ it "returns its matcher" do
45
+ matcher = environment.have_json_path(path)
46
+ matcher.should be_a(JsonTest::Matchers::HaveJsonPath)
47
+ end
48
+ end
49
+
50
+ context "have_json_type" do
51
+ let(:type){ Hash }
52
+
53
+ it "instantiates its matcher" do
54
+ JsonTest::Matchers::HaveJsonType.should_receive(:new).with(type)
55
+ environment.have_json_type(type)
56
+ end
57
+
58
+ it "returns its matcher" do
59
+ matcher = environment.have_json_type(type)
60
+ matcher.should be_a(JsonTest::Matchers::HaveJsonType)
61
+ end
62
+ end
63
+
64
+ context "have_json_size" do
65
+ let(:size){ 1 }
66
+
67
+ it "instantiates its matcher" do
68
+ JsonTest::Matchers::HaveJsonSize.should_receive(:new).with(size)
69
+ environment.have_json_size(size)
70
+ end
71
+
72
+ it "returns its matcher" do
73
+ matcher = environment.have_json_size(size)
74
+ matcher.should be_a(JsonTest::Matchers::HaveJsonSize)
75
+ end
76
+ end
77
+ end