rspec_structure_matcher 0.0.7 → 0.0.8

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: 193cd69f56ffdd252aaf2737ff554fed0b3ae767
4
- data.tar.gz: e103d7eee610617d6b33bbeac712f1ff8ce2f678
3
+ metadata.gz: b806804c4a8f7c07e794d2d08d314fed04b2a7c3
4
+ data.tar.gz: c7add716e2fb93116eca59247d69ab20c4e94d56
5
5
  SHA512:
6
- metadata.gz: 99823fa6ba3e1b747e2487af5ccb9858df3dbb0985a33a056d045be6fc44d4d911742a789cc91b51ab4106758e7e9f87c0267c3b2ce1a4bbecbeb4b1bd5e798c
7
- data.tar.gz: 3c48db7cb3414c6f6a824ee45409250e51c090b50eedef1a7d94c264f96d790564932edef9004e95656537e33407e079f7395b2f2ddfb29f96867087e64895c7
6
+ metadata.gz: 89dc486be69a92be0e6084c803fbc3f3187edc62c44ddb80785c831eec1440efb31168ebd71f8b91347516ddceebee176453a4b5ee1e3f506becdffa66b7ee0d
7
+ data.tar.gz: 78157d392b7b7d48bbe1374b1518fe1c0a01c093fcf73a53e7dfa99b223278f2cdaaa1960e24ebf0e00a551fcc4fb015b9d9b4f7fff0a2f8c00d165113751454
data/README.md CHANGED
@@ -57,6 +57,27 @@ Callable proc/lambda
57
57
  Exact match
58
58
  : Other values will be compared directly with `==`.
59
59
 
60
+ ### Testing arrays
61
+
62
+ You often want to match each item in an array of objects against the same structure. To do so, simply define your structure with a single item in the array. This item will be matched against all items in the array you are testing.
63
+
64
+ expected_structure = {
65
+ items: [
66
+ {
67
+ name: String
68
+ }
69
+ ]
70
+ }
71
+
72
+ actual_object = {
73
+ items: [
74
+ { name: 'Bob' },
75
+ { name: 'Jane' }
76
+ ]
77
+ }
78
+
79
+ expect(actual_object).to have_structure(expected_structure) # true
80
+
60
81
  ### Testing Optional Values
61
82
 
62
83
  As mentioned above, you can use `optionally` to test optional values, so that the test will pass even if the response contains a `null`. `optionally` is nothing more than a helpful lambda generation method, much like the proc/lambda that you can write yourself.
@@ -1,6 +1,6 @@
1
1
  require 'pp'
2
2
 
3
- RSpec::Matchers.define :have_structure do |expected, opts|
3
+ RSpec::Matchers.define :have_structure do |expected|
4
4
  match do |actual|
5
5
  HaveStructureMatcher.match?(actual, expected)
6
6
  end
@@ -10,8 +10,20 @@ module HaveStructureMatcher
10
10
  end
11
11
 
12
12
  def self.build_diff(actual, expected)
13
- return expected unless actual.is_a?(Hash)
13
+ if actual.is_a?(Array) && expected.is_a?(Array)
14
+ build_array_diff(actual, expected)
15
+ elsif actual.is_a?(Hash) && expected.is_a?(Hash)
16
+ build_hash_diff(actual, expected)
17
+ elsif actual.is_a?(Hash)
18
+ expected
19
+ elsif value_match?(actual, expected)
20
+ actual
21
+ else
22
+ expected
23
+ end
24
+ end
14
25
 
26
+ def self.build_hash_diff(actual, expected)
15
27
  keys = actual.keys | expected.keys
16
28
 
17
29
  keys.each_with_object({}) do |key, memo|
@@ -22,7 +34,7 @@ module HaveStructureMatcher
22
34
  if expected_value.is_a?(Hash)
23
35
  memo[key] = build_diff(actual_value, expected_value)
24
36
  elsif expected_value.is_a?(Array)
25
- memo[key] = expected_value.zip(actual_value).map { |(e,a)| build_diff(a, e) }
37
+ memo[key] = build_array_diff(actual_value, expected_value)
26
38
  elsif value_match?(actual_value, expected_value)
27
39
  memo[key] = actual_value
28
40
  else
@@ -35,6 +47,14 @@ module HaveStructureMatcher
35
47
  end
36
48
  end
37
49
 
50
+ def self.build_array_diff(actual_value, expected_value)
51
+ if expected_value.length == 1 && actual_value.is_a?(Array)
52
+ actual_value.map { |a| build_diff(a, expected_value[0]) }
53
+ else
54
+ expected_value.zip(actual_value).map { |(e,a)| build_diff(a, e) }
55
+ end
56
+ end
57
+
38
58
  def self.print_expected_value(expected_value)
39
59
  if expected_value.respond_to?(:call)
40
60
  "Proc [#{expected_value.source_location.join(':')}]"
data/lib/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module RspecStructureMatcher
2
- VERSION = "0.0.7"
2
+ VERSION = "0.0.8"
3
3
  end
@@ -1,5 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'rspec_structure_matcher'
3
2
 
4
3
  describe 'have_structure' do
5
4
  let(:expected_structure) {
@@ -19,7 +18,7 @@ describe 'have_structure' do
19
18
  it 'raises the correct error' do
20
19
  expect {
21
20
  expect(structure).to have_structure(expected_structure)
22
- }.to raise_error(RSpec::Expectations::ExpectationNotMetError, /-"bar" => String/)
21
+ }.to raise_error(RSpec::Expectations::ExpectationNotMetError, Regexp.new('-{"foo"=>"baz", "bar"=>String}'))
23
22
  end
24
23
  end
25
24
 
@@ -35,7 +34,10 @@ describe 'have_structure' do
35
34
  it 'raises the correct error' do
36
35
  expect {
37
36
  expect(structure).to have_structure(expected_structure)
38
- }.to raise_error(RSpec::Expectations::ExpectationNotMetError, /\+"bam" => "baz"/)
37
+ }.to raise_error(
38
+ RSpec::Expectations::ExpectationNotMetError,
39
+ Regexp.new(Regexp.escape('+{"foo"=>"baz", "bar"=>"baz", "bam"=>"baz"}'))
40
+ )
39
41
  end
40
42
  end
41
43
 
@@ -50,7 +52,10 @@ describe 'have_structure' do
50
52
  it 'raises the correct error' do
51
53
  expect {
52
54
  expect(structure).to have_structure(expected_structure)
53
- }.to raise_error(RSpec::Expectations::ExpectationNotMetError, /-"foo" => String/)
55
+ }.to raise_error(
56
+ RSpec::Expectations::ExpectationNotMetError,
57
+ Regexp.new(Regexp.escape('+{"foo"=>1, "bar"=>"baz"}'))
58
+ )
54
59
  end
55
60
  end
56
61
 
@@ -80,7 +85,10 @@ describe 'have_structure' do
80
85
  it 'fails validation' do
81
86
  expect {
82
87
  expect(structure).to have_structure(expected_structure)
83
- }.to raise_error(RSpec::Expectations::ExpectationNotMetError, /-"foo" => String/)
88
+ }.to raise_error(
89
+ RSpec::Expectations::ExpectationNotMetError,
90
+ Regexp.new(Regexp.escape('+{:foo=>"baz", "bar"=>"baz"}'))
91
+ )
84
92
  end
85
93
  end
86
94
 
@@ -118,7 +126,10 @@ describe 'have_structure' do
118
126
  it 'fails validation' do
119
127
  expect {
120
128
  expect(structure).to have_structure(expected_structure)
121
- }.to raise_error(RSpec::Expectations::ExpectationNotMetError, /-"foo" => 2/)
129
+ }.to raise_error(
130
+ RSpec::Expectations::ExpectationNotMetError,
131
+ Regexp.new(Regexp.escape('+{"foo"=>1, "bar"=>"baz"}'))
132
+ )
122
133
  end
123
134
  end
124
135
  end
@@ -148,7 +159,10 @@ describe 'have_structure' do
148
159
  it 'fails validation' do
149
160
  expect {
150
161
  expect(structure).to have_structure(expected_structure)
151
- }.to raise_error(RSpec::Expectations::ExpectationNotMetError, /\+"foo" => 100/)
162
+ }.to raise_error(
163
+ RSpec::Expectations::ExpectationNotMetError,
164
+ Regexp.new(Regexp.quote('+{"foo"=>100}'))
165
+ )
152
166
  end
153
167
  end
154
168
  end
@@ -179,6 +193,17 @@ describe 'have_structure' do
179
193
  }.not_to raise_error
180
194
  end
181
195
  end
196
+
197
+ context 'regular expression' do
198
+ let(:expected_structure) { {'foo' => optionally(/\w+/)} }
199
+ let(:structure) { {'foo' => 'hello'} }
200
+
201
+ it 'raises no error' do
202
+ expect {
203
+ expect(structure).to have_structure(expected_structure)
204
+ }.not_to raise_error
205
+ end
206
+ end
182
207
  end
183
208
 
184
209
  context "with nested structure" do
@@ -219,9 +244,49 @@ describe 'have_structure' do
219
244
  it 'fails validation' do
220
245
  expect {
221
246
  expect(structure).to have_structure(expected_structure)
222
- }.to raise_error(RSpec::Expectations::ExpectationNotMetError, /\+"bar" => "a"/)
247
+ }.to raise_error(
248
+ RSpec::Expectations::ExpectationNotMetError,
249
+ Regexp.new(Regexp.quote('+{"foo"=>1, "bar"=>"a"}'))
250
+ )
223
251
  end
224
252
  end
253
+ end
254
+
255
+ context "matching against an array of objects" do
256
+ let(:expected_structure) do
257
+ {
258
+ 'items' => [
259
+ {
260
+ 'name' => String
261
+ }
262
+ ]
263
+ }
264
+ end
265
+
266
+ let(:structure) do
267
+ {
268
+ 'items' => [
269
+ { 'name' => 'Bob' },
270
+ { 'name' => 'Jane' }
271
+ ]
272
+ }
273
+ end
225
274
 
275
+ it 'passes validation' do
276
+ expect {
277
+ expect(structure).to have_structure(expected_structure)
278
+ }.not_to raise_error
279
+ end
280
+ end
281
+
282
+ context "matching two arrays" do
283
+ let(:expected_structure) { [Integer] }
284
+ let(:structure) { [10, 20, 30] }
285
+
286
+ it 'passes validation' do
287
+ expect {
288
+ expect(structure).to have_structure(expected_structure)
289
+ }.not_to raise_error
290
+ end
226
291
  end
227
292
  end
data/spec/spec_helper.rb CHANGED
@@ -2,3 +2,8 @@ require "bundler/setup"
2
2
  Bundler.setup
3
3
 
4
4
  require "pry-byebug"
5
+ require "rspec_structure_matcher"
6
+
7
+ RSpec.configure do |config|
8
+ config.include HaveStructureMatcher::Methods
9
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec_structure_matcher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Marklove
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-11 00:00:00.000000000 Z
11
+ date: 2017-05-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec