eq_json 1.0.2 → 2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9ec463196fe5607b1e9b24b069a789c237c4dd28
4
- data.tar.gz: aa249d10540740c92146fc97766617812409cefa
3
+ metadata.gz: 54c360affa2fa9e451be2b9c0765921b6e47d8cf
4
+ data.tar.gz: 287c476265ac3839bd51f65f3a4457d5b21bc02f
5
5
  SHA512:
6
- metadata.gz: 2a431e39d5628ab69001a5fde73f84713227395baac64f038cf7d29ed443c758ae492397637e053836bbf4564ba810408ae31ef0b2e76eda70ffe2762a5883e0
7
- data.tar.gz: 17f55e32ef6021a364cae492e213fd50b733114234fa74067891dfcb4888ac2672fde88b82c917f157e3c173d37c834e737de0366f73ab9a27e1130f19360f71
6
+ metadata.gz: ce546a2c31702fe243970f867241ebf234c5897b997bb6c226068f348e6c071a45892d921d6f1e3a047f84acf9fa1966bb7f1d1d261945a0826f83f570ad4f03
7
+ data.tar.gz: 252d2b5eb57a2bdea5ad22cf2eab566edcc11e8248143e184bf352fe692bb00907f6a975d096a7ecfd0a515a6de9a4dfdbeb0afe5f565e20a8399baad6ce311c
data/.gitignore CHANGED
@@ -14,3 +14,4 @@ mkmf.log
14
14
  .idea
15
15
  *.iml
16
16
  *.gem
17
+ out
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  <!-- [![Build Status](https://travis-ci.org/jadekler/eq_wo_order.svg?branch=master)](https://travis-ci.org/jadekler/eq_wo_order) -->
4
4
 
5
- RSpec equality matcher that JSON. Outputs meaningful failure messages.
5
+ RSpec equality matcher that is JSON aware. Outputs meaningful failure messages.
6
6
 
7
7
 
8
8
  ## Installation
@@ -56,8 +56,58 @@ expected = {
56
56
  }
57
57
  }
58
58
 
59
- expect(expected).to eq_json(actual)
59
+ expect(actual).to eq_json(expected)
60
60
  ```
61
+
62
+ There is also a special json array matcher. This is used to match json arrays which are arrays of JSON
63
+ objects which have a key. The key is used to compare objects in the array. The matcher looks for items in
64
+ the actual using the key. It then compares the expected item and actual item that it found via the key.
65
+ The key is passed in to the matcher with the expected value. In the example
66
+ below a JSON array of book objects is being compared. Each book has a bookId which is used by the matcher to
67
+ do the compare of expected and actual
68
+ ```ruby
69
+ actualArray = [
70
+ {
71
+ bookId: "1",
72
+ name: "Harry Potter and the Sorcerer's Stone",
73
+ author: "J.K. Rowling"
74
+ },
75
+ {
76
+ bookId: "2",
77
+ name: "Eragon",
78
+ author: "Christopher Paolini",
79
+ },
80
+ {
81
+ bookId: "3",
82
+ name: "The Fellowship of the Ring",
83
+ author: "J.R.R. Tolkien"
84
+
85
+ }
86
+ ]
87
+
88
+ expectedArray = [
89
+ {
90
+ bookId: "3",
91
+ name: "The Fellowship of the Ring",
92
+ author: "J.R.R. Tolkien"
93
+
94
+ },
95
+ {
96
+ bookId: "1",
97
+ name: "Harry Potter and the Sorcerer's Stone",
98
+ author: "J.K. Rowling"
99
+ },
100
+ {
101
+ bookId: "2",
102
+ name: "Eragon",
103
+ author: "Christopher Paolini"
104
+ }
105
+ ]
106
+
107
+ expect(actualArray).to eq_json_array_with_key(expectedArray, :bookId)
108
+
109
+ ```
110
+
61
111
  # More Documentation
62
112
  [Keynote Slides](https://github.com/davidmrhodes/eq_json/blob/master/doc/eqJsonPresentation.key)
63
113
 
data/TODO.txt CHANGED
@@ -1,31 +1,19 @@
1
- 1) Implement array equals
2
- a) make sure to test that arrays with same objects but different number of
3
- same objects is not equal. Must test with same number of total objects in
4
- array
5
1
 
6
- 2) Document that did not use matcher DSL. Easier to test if just used class.
7
-
8
- 3) Look to see on diff what should get actual is green or red?
2
+ 1) Look to see on diff what should get actual is green or red?
9
3
  Answer: expected is - in red
10
4
 
11
- 4) If object is a string and is multi line use differ in failure_message
5
+ 2) If object is a string and is multi line use differ in failure_message
12
6
 
13
- 5) test for json object combinations of (do for actual also)
7
+ 3) test for json object combinations of (do for actual also)
14
8
  first key in map not in expected
15
9
  middle key in map not in expected
16
10
  last key in map not in expected
17
11
 
18
- 6) Do I need to check expected and actual are valid josn?
19
-
12
+ 4) Do I need to check expected and actual are valid josn?
20
13
 
21
- 7) Add comparable function with an selection criteria for and id to compare arrays
22
14
 
23
- 8) If objects are large write them to a files in temp
24
- Could be done via configuration to find if configuration exists:
15
+ 5) Add comparable function with an selection criteria for and id to compare arrays
25
16
 
26
- if RSpec.configuration.methods.include? :json_debug_config
27
- puts "json_debug_config #{RSpec.configuration.json_debug_config}"
28
- end
17
+ 6) Had suggestion to make color brighter red
29
18
 
30
- Then put this in spec_helper:
31
- c.json_debug_config=true
19
+ 7) Had suggestion to print out sorted json in debug mode.
data/eq_json.gemspec CHANGED
@@ -1,8 +1,8 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'eq_json'
3
- s.version = '1.0.2'
4
- s.date = '2016-02-29'
5
- s.summary = 'RSpec equality matcher that to compare JSON'
3
+ s.version = '2.0.0'
4
+ s.date = '2017-05-12'
5
+ s.summary = 'RSpec equality matcher that compares JSON'
6
6
  s.description = 'RSpec equality matcher that deeply compares JSON. Examples at github.com/davidmrhodes/eq_json'
7
7
  s.authors = ['David M. Rhodes']
8
8
  s.email = 'barnaby71@gmail.com'
@@ -15,6 +15,7 @@ Gem::Specification.new do |s|
15
15
  s.require_paths = ['lib']
16
16
 
17
17
  s.add_runtime_dependency 'rspec', '~> 3.0'
18
+ s.add_runtime_dependency 'json', '~> 1.7'
18
19
  s.add_development_dependency 'bundler', '~> 1.7'
19
20
  s.add_development_dependency 'rake', '~> 10.0'
20
21
  end
@@ -0,0 +1,54 @@
1
+ require 'colorizer'
2
+
3
+ class ArrayWithKeyMessageGen
4
+
5
+ def initialize(matcher)
6
+ @matcher = matcher
7
+ @colorizer = EqJsonColorizer.new
8
+ end
9
+
10
+ def generateFailureMessage(expectedItem, eqFailureMessage)
11
+ return "#{@matcher.key} #{expectedItem[@matcher.key]}\n" +
12
+ eqFailureMessage
13
+ end
14
+
15
+ def generateExpectedNotInActual(expectedItem)
16
+ return "#{@matcher.key} #{expectedItem[@matcher.key]} not found in actual\n" +
17
+ "Expected: #{expectedItem.to_json}\n"
18
+ end
19
+
20
+ def generateExpectedItemMissingKey(expectedItem)
21
+ return "Tester error expected item does not have key #{@matcher.key}.\n" +
22
+ "Expected item: #{expectedItem.to_json}\n"
23
+ end
24
+
25
+
26
+ def generateDifferentSizeArrays()
27
+ objectsNotInExpected = getObjectsNotIn(@matcher.actual, @matcher.expected);
28
+ objectsNotInActual = getObjectsNotIn(@matcher.expected, @matcher.actual);
29
+
30
+ jsonErrorInfo = "Array size does not match. Expected #{@matcher.expected.length} actual #{@matcher.actual.length}\n"
31
+
32
+ unless objectsNotInExpected.empty?
33
+ jsonErrorInfo << "expected does not contain #{@matcher.key}s #{objectsNotInExpected}\n"
34
+ end
35
+
36
+ unless objectsNotInActual.empty?
37
+ jsonErrorInfo << "actual does not contain #{@matcher.key}s #{objectsNotInActual}\n"
38
+ end
39
+
40
+ return jsonErrorInfo
41
+ end
42
+
43
+ def getObjectsNotIn(array1, array2)
44
+ missing = []
45
+ array1.each do |item1|
46
+ item2 = array2.find {|item| item[@matcher.key] == item1[@matcher.key]}
47
+ if item2.nil?
48
+ missing.push(item1[@matcher.key])
49
+ end
50
+ end
51
+ return missing
52
+ end
53
+ end
54
+
@@ -0,0 +1,22 @@
1
+ require 'tmpdir'
2
+
3
+ class EqJsonDebugDumper
4
+
5
+ def initialize(matcher)
6
+ @matcher = matcher
7
+ end
8
+
9
+ def dump
10
+ dumpToFile('expected', @matcher.expected)
11
+ dumpToFile('actual', @matcher.actual)
12
+ dumpToFile('currentExpectedObj', @matcher.currentExpectedObj)
13
+ dumpToFile('currentActualObj', @matcher.currentActualObj)
14
+ end
15
+
16
+ def dumpToFile(baseName, jsonHash)
17
+ fileName = Dir.tmpdir() + File::SEPARATOR + "#{baseName}.json"
18
+ File.open(fileName, "w") do |file|
19
+ file.print JSON.pretty_generate(jsonHash)
20
+ end
21
+ end
22
+ end
data/lib/eq_json.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  require 'pp'
2
2
  require 'message_generator'
3
3
  require 'eq_json_array'
4
+ require 'debug_dumper'
4
5
 
5
- class EqualWithOutOrderJson
6
+ class EqualJson
6
7
 
7
8
  attr_accessor :actual, :expected, :jsonPath, :jsonPathRoot, :currentActualObj,
8
9
  :currentExpectedObj, :currentJsonKey
@@ -21,6 +22,12 @@ class EqualWithOutOrderJson
21
22
  end
22
23
 
23
24
  def failure_message
25
+ if RSpec.configuration.methods.include? :json_debug_config
26
+ if RSpec.configuration.json_debug_config?
27
+ debugDumper = EqJsonDebugDumper.new(self)
28
+ debugDumper.dump()
29
+ end
30
+ end
24
31
  return @failureMessage
25
32
  end
26
33
 
@@ -138,5 +145,7 @@ class EqualWithOutOrderJson
138
145
  end
139
146
 
140
147
  def eq_json(*args)
141
- EqualWithOutOrderJson.new(*args)
148
+ EqualJson.new(*args)
142
149
  end
150
+
151
+
@@ -0,0 +1,59 @@
1
+ require 'pp'
2
+ require 'message_generator'
3
+ require 'debug_dumper'
4
+ require 'eq_json'
5
+ require 'array_with_key_message_gen'
6
+
7
+ class EqualJsonArrayWithKey
8
+
9
+ attr_accessor :actual, :expected, :key
10
+
11
+ def initialize(expected, key)
12
+ unless key.is_a? Symbol
13
+ raise "Key should be a symbol"
14
+ end
15
+ @expected = expected
16
+ @key = key
17
+ @messageGenerator = ArrayWithKeyMessageGen.new(self)
18
+ end
19
+
20
+ def matches?(actual)
21
+ @actual = actual
22
+
23
+ unless actual.length == expected.length
24
+ @failureMessage = @messageGenerator.generateDifferentSizeArrays()
25
+ return false
26
+ end
27
+
28
+ @expected.each() do |expectedItem|
29
+ puts "expectedItem[key] #{expectedItem[@key]}"
30
+ if expectedItem[@key].nil?
31
+ puts "got here dmr"
32
+ @failureMessage = @messageGenerator.generateExpectedItemMissingKey(expectedItem)
33
+ return false
34
+ end
35
+
36
+ actualItem = actual.find {|item| item[@key] == expectedItem[@key]}
37
+ if actualItem.nil?
38
+ @failureMessage = @messageGenerator.generateExpectedNotInActual(expectedItem)
39
+ return false;
40
+ end
41
+ @eqJsonMatcher=EqualJson.new(expectedItem)
42
+ if !@eqJsonMatcher.matches?(actualItem)
43
+ @failureMessage = @messageGenerator.generateFailureMessage(expectedItem, @eqJsonMatcher.failure_message)
44
+ return false;
45
+ end
46
+ end
47
+
48
+ return true;
49
+ end
50
+
51
+ def failure_message
52
+ return @failureMessage
53
+ end
54
+
55
+ end
56
+
57
+ def eq_json_array_with_key(*args)
58
+ EqualJsonArrayWithKey.new(*args)
59
+ end
@@ -18,7 +18,7 @@ describe 'test objects not same type' do
18
18
 
19
19
  actualJson=actual.to_json
20
20
 
21
- customMatcher=EqualWithOutOrderJson.new(expected)
21
+ customMatcher=EqualJson.new(expected)
22
22
 
23
23
  expect(customMatcher.matches?(actual)).to eq(false)
24
24
 
@@ -75,7 +75,7 @@ describe 'test single level json objects' do
75
75
  author: 'J.K. Rowling'
76
76
  }
77
77
 
78
- customMatcher=EqualWithOutOrderJson.new(expected)
78
+ customMatcher=EqualJson.new(expected)
79
79
 
80
80
  expect(customMatcher.matches?(actual)).to eq(false)
81
81
 
@@ -107,7 +107,7 @@ describe 'test single level json objects' do
107
107
  name: 'Harry Potter and the Sorcerer\'s Stone',
108
108
  }
109
109
 
110
- customMatcher=EqualWithOutOrderJson.new(expected)
110
+ customMatcher=EqualJson.new(expected)
111
111
 
112
112
  expect(customMatcher.matches?(actual)).to eq(false)
113
113
 
@@ -140,7 +140,7 @@ describe 'test single level json objects' do
140
140
  name: 'Harry Potter and the Sorcerer\'s Stone',
141
141
  }
142
142
 
143
- customMatcher=EqualWithOutOrderJson.new(expected)
143
+ customMatcher=EqualJson.new(expected)
144
144
 
145
145
  expect(customMatcher.matches?(actual)).to eq(false)
146
146
 
@@ -175,7 +175,7 @@ describe 'test single level json objects' do
175
175
  }
176
176
 
177
177
 
178
- customMatcher=EqualWithOutOrderJson.new(expected)
178
+ customMatcher=EqualJson.new(expected)
179
179
 
180
180
  expect(customMatcher.matches?(actual)).to eq(false)
181
181
 
@@ -210,7 +210,7 @@ describe 'test single level json objects' do
210
210
  author: 'J.K. Rowling'
211
211
  }
212
212
 
213
- customMatcher=EqualWithOutOrderJson.new(expected)
213
+ customMatcher=EqualJson.new(expected)
214
214
 
215
215
  expect(customMatcher.matches?(actual)).to eq(false)
216
216
 
@@ -0,0 +1,208 @@
1
+ require 'json'
2
+ require 'eq_json_array_with_key'
3
+ require 'spec_helper.rb'
4
+
5
+ describe 'test arrays not the same size' do
6
+
7
+ it 'actual contains more items than expected' do
8
+
9
+ actual = {
10
+ bookSeller: "amazon",
11
+ bookWholeSellers: {
12
+ publisherInfo: {
13
+ name: "ACME Publisher Inc.",
14
+ publishDate: {
15
+ month: 3,
16
+ day: 23,
17
+ year: 2015
18
+ },
19
+ products: {
20
+ books: [
21
+ {
22
+ bookId: "1",
23
+ name: "Harry Potter and the Sorcerer's Stone",
24
+ author: "J.K. Rowling"
25
+ },
26
+ {
27
+ bookId: "2",
28
+ name: "Eragon",
29
+ author: "Christopher Paolini",
30
+ },
31
+ {
32
+ bookId: "4",
33
+ name: "Effective Java",
34
+ authoer: "Cannot Remember"
35
+ },
36
+ {
37
+ bookId: "5",
38
+ name: "The HP Way",
39
+ authoer: "Bill and Dave"
40
+ },
41
+ {
42
+ bookId: "3",
43
+ name: "The Fellowship of the Ring",
44
+ author: "J.R.R. Tolkien"
45
+
46
+ }
47
+ ]
48
+ }
49
+ }
50
+ },
51
+ url: "www.amazon.com"
52
+
53
+ }
54
+ actualArray = actual[:bookWholeSellers][:publisherInfo][:products][:books]
55
+
56
+ expected = {
57
+ bookSeller: "amazon",
58
+ bookWholeSellers: {
59
+ publisherInfo: {
60
+ name: "ACME Publisher Inc.",
61
+ publishDate: {
62
+ month: 3,
63
+ day: 23,
64
+ year: 2015
65
+ },
66
+ products: {
67
+ books: [
68
+ {
69
+ bookId: "3",
70
+ name: "The Fellowship of the Ring",
71
+ author: "J.R.R. Tolkien"
72
+
73
+ },
74
+ {
75
+ bookId: "1",
76
+ name: "Harry Potter and the Sorcerer's Stone",
77
+ author: "J.K. Rowling"
78
+ },
79
+ {
80
+ bookId: "2",
81
+ name: "Eragon",
82
+ author: "Christopher Paolini"
83
+ }
84
+ ]
85
+ }
86
+ }
87
+ },
88
+ url: "www.amazon.com"
89
+ }
90
+
91
+ expectedArray = expected[:bookWholeSellers][:publisherInfo][:products][:books]
92
+
93
+
94
+ customMatcher=EqualJsonArrayWithKey.new(expectedArray, :bookId)
95
+
96
+ expect(customMatcher.matches?(actualArray)).to eq(false)
97
+
98
+ expectedJson=expected.to_json;
99
+ actualJson=actual.to_json;
100
+
101
+ String expectedErrorMessage= "Array size does not match. Expected 3 actual 5\n" +
102
+ "expected does not contain bookIds [\"4\", \"5\"]\n"
103
+
104
+ expect(customMatcher.failure_message).to eq(expectedErrorMessage)
105
+
106
+ expect(actualArray).not_to eq_json_array_with_key(expectedArray, :bookId)
107
+
108
+ end
109
+
110
+ it 'expected contains more items than actual' do
111
+
112
+ actual = {
113
+ bookSeller: "amazon",
114
+ bookWholeSellers: {
115
+ publisherInfo: {
116
+ name: "ACME Publisher Inc.",
117
+ publishDate: {
118
+ month: 3,
119
+ day: 23,
120
+ year: 2015
121
+ },
122
+ products: {
123
+ books: [
124
+ {
125
+ bookId: "1",
126
+ name: "Harry Potter and the Sorcerer's Stone",
127
+ author: "J.K. Rowling"
128
+ },
129
+ {
130
+ bookId: "2",
131
+ name: "Eragon",
132
+ author: "Christopher Paolini",
133
+ },
134
+ {
135
+ bookId: "3",
136
+ name: "The Fellowship of the Ring",
137
+ author: "J.R.R. Tolkien"
138
+
139
+ }
140
+ ]
141
+ }
142
+ }
143
+ },
144
+ url: "www.amazon.com"
145
+
146
+ }
147
+ actualArray = actual[:bookWholeSellers][:publisherInfo][:products][:books]
148
+
149
+ expected = {
150
+ bookSeller: "amazon",
151
+ bookWholeSellers: {
152
+ publisherInfo: {
153
+ name: "ACME Publisher Inc.",
154
+ publishDate: {
155
+ month: 3,
156
+ day: 23,
157
+ year: 2015
158
+ },
159
+ products: {
160
+ books: [
161
+ {
162
+ bookId: "3",
163
+ name: "The Fellowship of the Ring",
164
+ author: "J.R.R. Tolkien"
165
+
166
+ },
167
+ {
168
+ bookId: "1",
169
+ name: "Harry Potter and the Sorcerer's Stone",
170
+ author: "J.K. Rowling"
171
+ },
172
+ {
173
+ bookId: "2",
174
+ name: "Eragon",
175
+ author: "Christopher Paolini"
176
+ },
177
+ {
178
+ bookId: "5",
179
+ name: "The HP Way",
180
+ authoer: "Bill and Dave"
181
+ }
182
+ ]
183
+ }
184
+ }
185
+ },
186
+ url: "www.amazon.com"
187
+ }
188
+
189
+ expectedArray = expected[:bookWholeSellers][:publisherInfo][:products][:books]
190
+
191
+
192
+ customMatcher=EqualJsonArrayWithKey.new(expectedArray, :bookId)
193
+
194
+ expect(customMatcher.matches?(actualArray)).to eq(false)
195
+
196
+ expectedJson=expected.to_json;
197
+ actualJson=actual.to_json;
198
+
199
+ String expectedErrorMessage= "Array size does not match. Expected 4 actual 3\n" +
200
+ "actual does not contain bookIds [\"5\"]\n"
201
+
202
+ expect(customMatcher.failure_message).to eq(expectedErrorMessage)
203
+
204
+ expect(actualArray).not_to eq_json_array_with_key(expectedArray, :bookId)
205
+
206
+ end
207
+
208
+ end