rspec-hive 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e0ecaa7596db283e59f0ea63fbb677942e714d09
4
- data.tar.gz: ae43c8734de7c85b0551454534fc1e339a74d2f5
3
+ metadata.gz: 0b75898c0b7364fe12b80f91a36da04a54c5bab6
4
+ data.tar.gz: 86e7fcbbb5a50fc536a0954ddc27fd4cb90ef915
5
5
  SHA512:
6
- metadata.gz: 906bd8f828ba76a4646c535cee8679d60f3acf23714e8686c62789ee770d754f95f216930758d504bf57964a40c127e189b58dc17e03c674f12a283f181e83cf
7
- data.tar.gz: 6cf54197ee350b05235eb08869226dd2b26c3e63f83764ad17356c5ef842379f8d5b5b2d4a8aafe63d212d91b02c91b78d64bcd0bb729c5bb37daf8a8da05084
6
+ metadata.gz: da919d5129641e77e15c5bfeed2bef2396e3d02dd3eaa93ef61dae7af099323d6a9106a8b9b8ac02644035ab39588a88c6cbabbe40f7f53832e961d499a7244f
7
+ data.tar.gz: 2ea4738a1f9bb1d84426ed4873a33bfb2b8f2480a1b557fbb73e2b5fe8821fbb266defffe8fab57c3114558d6c10c3e0a8f9ee3d11fc0fd0c5138de884c4748c
@@ -2,28 +2,104 @@ require 'rspec/matchers'
2
2
 
3
3
  RSpec::Matchers.define :match_result_set do |expected|
4
4
  match do |actual|
5
- return false if expected.size != actual.size
5
+ @diffable_actual = []
6
6
 
7
- expected.each.with_index.all? do |expected_row, i|
7
+ @actual = actual.clone
8
+
9
+ expected.map.with_index do |expected_row, i|
8
10
  if expected_row.respond_to?(:each_pair)
9
11
  if @partial_match
10
- selected_actual_values = actual[i].values_at(*expected_row.keys)
11
- values_match?(expected_row.values, selected_actual_values)
12
+ result_set_match?(
13
+ actual[i], expected_row,
14
+ expected_transformer: ->(e) { e.values },
15
+ actual_transformer: ->(candidate) { candidate.values_at(*expected_row.keys) },
16
+ diffable_transformer: ->(candidate) { candidate.select { |k, _v| expected_row.keys.include?(k) } }
17
+ )
12
18
  else
13
- values_match?(expected_row, actual[i])
19
+ result_set_match?(actual[i], expected_row)
14
20
  end
15
21
  elsif expected_row.respond_to?(:each)
16
22
  raise ArgumentError, "Can't use partially matcher with Arrays" if @partial_match
17
- values_match?(expected_row, actual[i].values)
23
+ result_set_match?(
24
+ actual[i], expected_row,
25
+ actual_transformer: ->(candidate) { candidate.values }
26
+ )
18
27
  else
19
28
  raise ArgumentError, 'Unknown type'
20
29
  end
21
- end
30
+ end.all? && expected.size == actual.size
22
31
  end
23
32
 
24
33
  chain :partially do
25
34
  @partial_match = true
26
35
  end
27
36
 
28
- diffable
37
+ chain :unordered do
38
+ @unordered = true
39
+ end
40
+
41
+ def result_set_match?(
42
+ actual, expected_row,
43
+ expected_transformer: ->(expected) { expected },
44
+ actual_transformer: ->(candidate) { candidate },
45
+ diffable_transformer: actual_transformer
46
+ )
47
+ if @unordered
48
+ unordered_result_set_match?(expected_row, expected_transformer, actual_transformer, diffable_transformer)
49
+ else
50
+ ordered_result_set_match?(actual, expected_row, expected_transformer, actual_transformer, diffable_transformer)
51
+ end
52
+ end
53
+
54
+ def unordered_result_set_match?(expected_row, expected_transformer, actual_transformer, diffable_transformer)
55
+ found_index = @actual.find_index do |candidate|
56
+ values_match?(expected_transformer.call(expected_row), actual_transformer.call(candidate))
57
+ end
58
+ return false unless found_index
59
+ found = @actual[found_index]
60
+ @actual.delete_at(found_index)
61
+ @diffable_actual << diffable_transformer.call(found)
62
+ true
63
+ end
64
+
65
+ def ordered_result_set_match?(actual, expected_row, expected_transformer, actual_transformer, diffable_transformer)
66
+ @diffable_actual << diffable_transformer.call(actual)
67
+ values_match?(expected_transformer.call(expected_row), actual_transformer.call(actual))
68
+ end
69
+
70
+ failure_message do |actual|
71
+ "expected #{actual} to match result set #{expected}\n#{diff_message(expected)}"
72
+ end
73
+
74
+ failure_message_when_negated do |actual|
75
+ "expected #{actual} not to match result set #{expected}, but did\n#{diff_message(expected)}"
76
+ end
77
+
78
+ def diff_message(expected)
79
+ "Diff: #{differ.diff_as_object(@diffable_actual, expected)}"
80
+ end
81
+
82
+ def differ
83
+ RSpec::Support::Differ.new(
84
+ object_preparer: ->(object) { surface_descriptions_in(object) },
85
+ color: RSpec::Matchers.configuration.color?
86
+ )
87
+ end
88
+
89
+ # Copied and adapted from RSpec::Matchers::Composable
90
+ # rubocop:disable Style/CaseEquality
91
+ def surface_descriptions_in(item)
92
+ if RSpec::Matchers.is_a_describable_matcher?(item)
93
+ RSpec::Matchers::Composable::DescribableItem.new(item)
94
+ elsif Hash === item
95
+ Hash[surface_descriptions_in(item.to_a.sort)]
96
+ elsif Struct === item || unreadable_io?(item)
97
+ RSpec::Support::ObjectFormatter.format(item)
98
+ elsif should_enumerate?(item)
99
+ item.map { |subitem| surface_descriptions_in(subitem) }
100
+ else
101
+ item
102
+ end
103
+ end
104
+ # rubocop:enable Style/CaseEquality
29
105
  end
@@ -1,5 +1,5 @@
1
1
  module RSpec
2
2
  module Hive
3
- VERSION = '0.2.0'.freeze
3
+ VERSION = '0.3.0'.freeze
4
4
  end
5
5
  end
@@ -8,9 +8,24 @@ RSpec.describe 'match_result_set' do
8
8
  let(:paul) { {first_name: 'Paul', last_name: 'McCartney', age: 73} }
9
9
 
10
10
  let(:full_match) { expect(actual_rows).to match_result_set(expected_rows) }
11
+ let(:unordered_match) { expect(actual_rows).to match_result_set(expected_rows).unordered }
11
12
  let(:partial_match) { expect(actual_rows).to match_result_set(expected_rows).partially }
13
+ let(:partial_unordered_match) { expect(actual_rows).to match_result_set(expected_rows).partially.unordered }
14
+
12
15
  let(:full_match_fails) { expect(actual_rows).not_to match_result_set(expected_rows) }
16
+ let(:unordered_match_fails) { expect(actual_rows).not_to match_result_set(expected_rows).unordered }
13
17
  let(:partial_match_fails) { expect(actual_rows).not_to match_result_set(expected_rows).partially }
18
+ let(:partial_unordered_match_fails) { expect(actual_rows).not_to match_result_set(expected_rows).partially.unordered }
19
+
20
+ let(:partial_match_raises_error) do
21
+ error_message = "Can't use partially matcher with Arrays"
22
+ aggregate_failures do
23
+ expect { partial_match }.to raise_error(ArgumentError, error_message)
24
+ expect { partial_match_fails }.to raise_error(ArgumentError, error_message)
25
+ expect { partial_unordered_match }.to raise_error(ArgumentError, error_message)
26
+ expect { partial_unordered_match_fails }.to raise_error(ArgumentError, error_message)
27
+ end
28
+ end
14
29
 
15
30
  context 'when the expected set has only one row' do
16
31
  context 'but the actual set has more rows' do
@@ -20,14 +35,17 @@ RSpec.describe 'match_result_set' do
20
35
  let(:expected_rows) { [john.values] }
21
36
 
22
37
  specify { full_match_fails }
23
- specify { partial_match_fails }
38
+ specify { unordered_match_fails }
39
+ specify { partial_match_raises_error }
24
40
  end
25
41
 
26
42
  context 'when the row is given as a hash' do
27
43
  let(:expected_rows) { [john] }
28
44
 
29
45
  specify { full_match_fails }
46
+ specify { unordered_match_fails }
30
47
  specify { partial_match_fails }
48
+ specify { partial_unordered_match_fails }
31
49
  end
32
50
  end
33
51
 
@@ -39,24 +57,32 @@ RSpec.describe 'match_result_set' do
39
57
  let(:expected_rows) { [john.values << 'yoko'] }
40
58
 
41
59
  specify { full_match_fails }
60
+ specify { unordered_match_fails }
61
+ specify { partial_match_raises_error }
42
62
  end
43
63
 
44
64
  context 'when the actual and expected have are different' do
45
65
  let(:expected_rows) { [paul.values] }
46
66
 
47
67
  specify { full_match_fails }
68
+ specify { unordered_match_fails }
69
+ specify { partial_match_raises_error }
48
70
  end
49
71
 
50
72
  context 'when the actual and expected rows are equal' do
51
73
  let(:expected_rows) { [john.values] }
52
74
 
53
75
  specify { full_match }
76
+ specify { unordered_match }
77
+ specify { partial_match_raises_error }
54
78
  end
55
79
 
56
80
  context 'when the actual and expected rows are equal with rspec matchers' do
57
81
  let(:expected_rows) { [[a_string_matching('John'), a_string_matching(/lennon/i), 40]] }
58
82
 
59
83
  specify { full_match }
84
+ specify { unordered_match }
85
+ specify { partial_match_raises_error }
60
86
  end
61
87
  end
62
88
 
@@ -65,28 +91,106 @@ RSpec.describe 'match_result_set' do
65
91
  let(:expected_rows) { [john.dup.tap { |j| j[:ono] = 'yoko' }] }
66
92
 
67
93
  specify { full_match_fails }
94
+ specify { unordered_match_fails }
68
95
  specify { partial_match_fails }
96
+ specify { partial_unordered_match_fails }
69
97
  end
70
98
 
71
99
  context 'when the actual and expected have are different' do
72
100
  let(:expected_rows) { [john.dup.tap { |j| j[:first_name] = 'yoko' }] }
73
101
 
74
102
  specify { full_match_fails }
103
+ specify { unordered_match_fails }
75
104
  specify { partial_match_fails }
105
+ specify { partial_unordered_match_fails }
76
106
  end
77
107
 
78
108
  context 'when the actual and expected rows are equal' do
79
109
  let(:expected_rows) { [john] }
80
110
 
81
111
  specify { full_match }
112
+ specify { unordered_match }
82
113
  specify { partial_match }
114
+ specify { partial_unordered_match }
83
115
  end
84
116
 
85
117
  context 'when matching a subset of columns' do
86
118
  let(:expected_rows) { [{first_name: john[:first_name]}] }
87
119
 
88
120
  specify { full_match_fails }
121
+ specify { unordered_match_fails }
89
122
  specify { partial_match }
123
+ specify { partial_unordered_match }
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ context 'when the expected set has multiple rows' do
130
+ let(:ringo) { {first_name: 'Richard', last_name: 'Starkey', age: -75} }
131
+
132
+ context 'and the actual set has the same number of rows' do
133
+ let(:actual_rows) { [ringo, paul, john] }
134
+
135
+ context 'when the row is given as an array' do
136
+ context 'when rows are returned in order' do
137
+ let(:expected_rows) { [ringo.values, paul.values, john.values] }
138
+
139
+ specify { full_match }
140
+ specify { unordered_match }
141
+ specify { partial_match_raises_error }
142
+ end
143
+
144
+ context 'when rows are returned in different order' do
145
+ let(:expected_rows) { [paul.values, john.values, ringo.values] }
146
+
147
+ specify { full_match_fails }
148
+ specify { unordered_match }
149
+ specify { partial_match_raises_error }
150
+ end
151
+ end
152
+
153
+ context 'when the row is given as a hash' do
154
+ context 'when matching all columns' do
155
+ context 'when rows are returned in order' do
156
+ let(:expected_rows) { [ringo, paul, john] }
157
+
158
+ specify { full_match }
159
+ specify { unordered_match }
160
+ specify { partial_match }
161
+ specify { partial_unordered_match }
162
+ end
163
+
164
+ context 'when rows are returned in different order' do
165
+ let(:expected_rows) { [paul, john, ringo] }
166
+
167
+ specify { full_match_fails }
168
+ specify { unordered_match }
169
+ specify { partial_match_fails }
170
+ specify { partial_unordered_match }
171
+ end
172
+ end
173
+
174
+ context 'when matching a subset of columns' do
175
+ let(:expected_rows) { members.map { |member| {age: member[:age]} } }
176
+
177
+ context 'when rows are returned in order' do
178
+ let(:members) { [ringo, paul, john] }
179
+
180
+ specify { full_match_fails }
181
+ specify { unordered_match_fails }
182
+ specify { partial_match }
183
+ specify { partial_unordered_match }
184
+ end
185
+
186
+ context 'when rows are returned in different order' do
187
+ let(:members) { [john, paul, ringo] }
188
+
189
+ specify { full_match_fails }
190
+ specify { unordered_match_fails }
191
+ specify { partial_match_fails }
192
+ specify { partial_unordered_match }
193
+ end
90
194
  end
91
195
  end
92
196
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-hive
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wojtek Mielczarek
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-05-09 00:00:00.000000000 Z
12
+ date: 2016-05-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake