predicate 2.8.0 → 2.9.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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +17 -0
  3. data/lib/predicate/asserter.rb +1 -1
  4. data/lib/predicate/nodes/and.rb +22 -4
  5. data/lib/predicate/nodes/empty.rb +6 -0
  6. data/lib/predicate/nodes/eq.rb +4 -0
  7. data/lib/predicate/nodes/expr.rb +4 -0
  8. data/lib/predicate/nodes/gt.rb +6 -0
  9. data/lib/predicate/nodes/gte.rb +6 -0
  10. data/lib/predicate/nodes/in.rb +12 -0
  11. data/lib/predicate/nodes/lt.rb +6 -0
  12. data/lib/predicate/nodes/lte.rb +6 -0
  13. data/lib/predicate/nodes/neq.rb +11 -0
  14. data/lib/predicate/nodes/tautology.rb +4 -0
  15. data/lib/predicate/version.rb +1 -1
  16. data/lib/predicate.rb +16 -2
  17. data/spec/factory/shared/a_comparison_factory_method.rb +12 -4
  18. data/spec/factory/shared/a_predicate_ast_node.rb +11 -5
  19. data/spec/factory/test_${op_name}.rb.jeny +3 -1
  20. data/spec/factory/test_and.rb +6 -2
  21. data/spec/factory/test_comp.rb +27 -9
  22. data/spec/factory/test_contradiction.rb +3 -1
  23. data/spec/factory/test_empty.rb +3 -1
  24. data/spec/factory/test_factor_predicate.rb +21 -7
  25. data/spec/factory/test_from_hash.rb +21 -7
  26. data/spec/factory/test_has_size.rb +3 -1
  27. data/spec/factory/test_identifier.rb +6 -2
  28. data/spec/factory/test_literal.rb +6 -2
  29. data/spec/factory/test_match.rb +12 -4
  30. data/spec/factory/test_native.rb +6 -2
  31. data/spec/factory/test_not.rb +6 -2
  32. data/spec/factory/test_or.rb +6 -2
  33. data/spec/factory/test_qualified_identifier.rb +6 -2
  34. data/spec/factory/test_set_ops.rb +6 -2
  35. data/spec/factory/test_tautology.rb +3 -1
  36. data/spec/factory/test_var.rb +12 -4
  37. data/spec/grammar/test_match.rb +19 -19
  38. data/spec/grammar/test_sexpr.rb +49 -17
  39. data/spec/nodes/and/test_and_split.rb +30 -10
  40. data/spec/nodes/dyadic_comp/test_and_split.rb +18 -8
  41. data/spec/nodes/eq/test_and.rb +12 -4
  42. data/spec/nodes/identifier/test_and_split.rb +6 -2
  43. data/spec/nodes/identifier/test_free_variables.rb +3 -1
  44. data/spec/nodes/identifier/test_name.rb +3 -1
  45. data/spec/nodes/in/test_and.rb +18 -6
  46. data/spec/nodes/nadic_bool/test_free_variables.rb +3 -1
  47. data/spec/nodes/or/test_and_split.rb +6 -2
  48. data/spec/nodes/qualified_identifier/test_and_split.rb +6 -2
  49. data/spec/nodes/qualified_identifier/test_free_variables.rb +3 -1
  50. data/spec/nodes/qualified_identifier/test_name.rb +3 -1
  51. data/spec/nodes/qualified_identifier/test_qualifier.rb +3 -1
  52. data/spec/predicate/test_and_split.rb +48 -16
  53. data/spec/predicate/test_assert!.rb +210 -0
  54. data/spec/predicate/test_attr_split.rb +36 -12
  55. data/spec/predicate/test_bool_and.rb +7 -3
  56. data/spec/predicate/test_bool_not.rb +30 -10
  57. data/spec/predicate/test_bool_or.rb +7 -3
  58. data/spec/predicate/test_coerce.rb +19 -17
  59. data/spec/predicate/test_constants.rb +78 -26
  60. data/spec/predicate/test_free_variables.rb +3 -1
  61. data/spec/predicate/test_hash_and_equal.rb +7 -3
  62. data/spec/predicate/test_qualify.rb +8 -6
  63. data/spec/predicate/test_rename.rb +21 -11
  64. data/spec/sequel/test_to_sequel.rb +0 -1
  65. data/spec/shared/a_predicate.rb +8 -8
  66. data/spec/spec_helper.rb +1 -0
  67. data/spec/test_readme.rb +1 -1
  68. metadata +5 -5
@@ -12,13 +12,17 @@ class Predicate
12
12
  context 'when fully covered' do
13
13
  let(:list){ [:x, :y] }
14
14
 
15
- it{ should eq([predicate, tautology]) }
15
+ it {
16
+ expect(subject).to eq([predicate, tautology])
17
+ }
16
18
  end
17
19
 
18
20
  context 'when fully disjoint' do
19
21
  let(:list){ [:z] }
20
22
 
21
- it{ should eq([tautology, predicate]) }
23
+ it {
24
+ expect(subject).to eq([tautology, predicate])
25
+ }
22
26
  end
23
27
 
24
28
  end
@@ -10,13 +10,17 @@ class Predicate
10
10
  context 'when included' do
11
11
  let(:list){ [:"t.id", :name] }
12
12
 
13
- it{ should eq([predicate, tautology]) }
13
+ it {
14
+ expect(subject).to eq([predicate, tautology])
15
+ }
14
16
  end
15
17
 
16
18
  context 'when not include' do
17
19
  let(:list){ [:name] }
18
20
 
19
- it{ should eq([tautology, predicate]) }
21
+ it {
22
+ expect(subject).to eq([tautology, predicate])
23
+ }
20
24
  end
21
25
 
22
26
  end
@@ -6,7 +6,9 @@ class Predicate
6
6
 
7
7
  subject{ expr.free_variables }
8
8
 
9
- it{ should eq([:"t.id"]) }
9
+ it {
10
+ expect(subject).to eq([:"t.id"])
11
+ }
10
12
 
11
13
  end
12
14
  end
@@ -6,7 +6,9 @@ class Predicate
6
6
 
7
7
  subject{ expr.name }
8
8
 
9
- it{ should eq(:id) }
9
+ it {
10
+ expect(subject).to eq(:id)
11
+ }
10
12
 
11
13
  end
12
14
  end
@@ -6,7 +6,9 @@ class Predicate
6
6
 
7
7
  subject{ expr.qualifier }
8
8
 
9
- it{ should eq(:t) }
9
+ it {
10
+ expect(subject).to eq(:t)
11
+ }
10
12
 
11
13
  end
12
14
  end
@@ -8,97 +8,129 @@ class Predicate
8
8
  context "on tautology" do
9
9
  let(:pred){ p.tautology }
10
10
 
11
- it{ should eq([p.tautology, p.tautology]) }
11
+ it {
12
+ expect(subject).to eq([p.tautology, p.tautology])
13
+ }
12
14
  end
13
15
 
14
16
  context "on contradiction" do
15
17
  let(:pred){ p.contradiction }
16
18
 
17
- it{ should eq([p.tautology, pred]) }
19
+ it {
20
+ expect(subject).to eq([p.tautology, pred])
21
+ }
18
22
  end
19
23
 
20
24
  context "on identifier (included)" do
21
25
  let(:pred){ p.identifier(:x) }
22
26
 
23
- it{ should eq([ pred, p.tautology ]) }
27
+ it {
28
+ expect(subject).to eq([ pred, p.tautology ])
29
+ }
24
30
  end
25
31
 
26
32
  context "on identifier (excluded)" do
27
33
  let(:pred){ p.identifier(:y) }
28
34
 
29
- it{ should eq([ p.tautology, pred ]) }
35
+ it {
36
+ expect(subject).to eq([ p.tautology, pred ])
37
+ }
30
38
  end
31
39
 
32
40
  context "on not (included)" do
33
41
  let(:pred){ p.not(:x) }
34
42
 
35
- it{ should eq([ pred, p.tautology ]) }
43
+ it {
44
+ expect(subject).to eq([ pred, p.tautology ])
45
+ }
36
46
  end
37
47
 
38
48
  context "on not (excluded)" do
39
49
  let(:pred){ p.not(:y) }
40
50
 
41
- it{ should eq([ p.tautology, pred ]) }
51
+ it {
52
+ expect(subject).to eq([ p.tautology, pred ])
53
+ }
42
54
  end
43
55
 
44
56
  context "on eq (included)" do
45
57
  let(:pred){ p.eq(:x, 2) }
46
58
 
47
- it{ should eq([ pred, p.tautology ]) }
59
+ it {
60
+ expect(subject).to eq([ pred, p.tautology ])
61
+ }
48
62
  end
49
63
 
50
64
  context "on eq (excluded)" do
51
65
  let(:pred){ p.eq(:y, 2) }
52
66
 
53
- it{ should eq([ p.tautology, pred ]) }
67
+ it {
68
+ expect(subject).to eq([ p.tautology, pred ])
69
+ }
54
70
  end
55
71
 
56
72
  context "on eq with placeholder" do
57
73
  let(:pred){ p.eq(:x, p.placeholder) }
58
74
 
59
- it{ should eq([ pred, p.tautology ]) }
75
+ it {
76
+ expect(subject).to eq([ pred, p.tautology ])
77
+ }
60
78
  end
61
79
 
62
80
  context "on in with placeholder" do
63
81
  let(:pred){ p.in(:x, p.placeholder) }
64
82
 
65
- it{ should eq([ pred, p.tautology ]) }
83
+ it {
84
+ expect(subject).to eq([ pred, p.tautology ])
85
+ }
66
86
  end
67
87
 
68
88
  context "on match (included)" do
69
89
  let(:pred){ p.match(:x, "London") }
70
90
 
71
- it{ should eq([ pred, p.tautology ]) }
91
+ it {
92
+ expect(subject).to eq([ pred, p.tautology ])
93
+ }
72
94
  end
73
95
 
74
96
  context "on match (excluded)" do
75
97
  let(:pred){ p.match(:y, "London") }
76
98
 
77
- it{ should eq([ p.tautology, pred ]) }
99
+ it {
100
+ expect(subject).to eq([ p.tautology, pred ])
101
+ }
78
102
  end
79
103
 
80
104
  context "on match (included on right)" do
81
105
  let(:pred){ p.match(:y, :x) }
82
106
 
83
- it{ should eq([ pred, p.tautology ]) }
107
+ it {
108
+ expect(subject).to eq([ pred, p.tautology ])
109
+ }
84
110
  end
85
111
 
86
112
  context "on intersect" do
87
113
  let(:pred){ p.intersect(:x, [1, 2]) }
88
114
 
89
- it{ should eq([ pred, p.tautology ]) }
115
+ it {
116
+ expect(subject).to eq([ pred, p.tautology ])
117
+ }
90
118
  end
91
119
 
92
120
  context "on subset" do
93
121
  let(:pred){ p.subset(:x, [1, 2]) }
94
122
 
95
- it{ should eq([ pred, p.tautology ]) }
123
+ it {
124
+ expect(subject).to eq([ pred, p.tautology ])
125
+ }
96
126
  end
97
127
 
98
128
  context "on superset" do
99
129
  let(:pred){ p.superset(:x, [1, 2]) }
100
130
 
101
- it{ should eq([ pred, p.tautology ]) }
131
+ it {
132
+ expect(subject).to eq([ pred, p.tautology ])
133
+ }
102
134
  end
103
135
 
104
136
  end
@@ -32,6 +32,126 @@ class Predicate
32
32
  end
33
33
  end
34
34
 
35
+ describe "gt" do
36
+ let(:predicate) {
37
+ Predicate.gt(:x, 2)
38
+ }
39
+
40
+ subject{
41
+ predicate.assert!(input)
42
+ }
43
+
44
+ context "when ok" do
45
+ let(:input){
46
+ { x: 3 }
47
+ }
48
+ it 'works and returns 3' do
49
+ expect(subject).to eql(3)
50
+ end
51
+ end
52
+
53
+ context "when ko" do
54
+ let(:input){
55
+ { x: 2 }
56
+ }
57
+ it 'works and throws' do
58
+ expect{
59
+ subject
60
+ }.to raise_error(Minitest::Assertion, /Expected 2 to be > 2/)
61
+ end
62
+ end
63
+ end
64
+
65
+ describe "gte" do
66
+ let(:predicate) {
67
+ Predicate.gte(:x, 2)
68
+ }
69
+
70
+ subject{
71
+ predicate.assert!(input)
72
+ }
73
+
74
+ context "when ok" do
75
+ let(:input){
76
+ { x: 2 }
77
+ }
78
+ it 'works and returns 2' do
79
+ expect(subject).to eql(2)
80
+ end
81
+ end
82
+
83
+ context "when ko" do
84
+ let(:input){
85
+ { x: 1 }
86
+ }
87
+ it 'works and throws' do
88
+ expect{
89
+ subject
90
+ }.to raise_error(Minitest::Assertion, /Expected 1 to be >= 2/)
91
+ end
92
+ end
93
+ end
94
+
95
+ describe "lt" do
96
+ let(:predicate) {
97
+ Predicate.lt(:x, 2)
98
+ }
99
+
100
+ subject{
101
+ predicate.assert!(input)
102
+ }
103
+
104
+ context "when ok" do
105
+ let(:input){
106
+ { x: 1 }
107
+ }
108
+ it 'works and returns 1' do
109
+ expect(subject).to eql(1)
110
+ end
111
+ end
112
+
113
+ context "when ko" do
114
+ let(:input){
115
+ { x: 2 }
116
+ }
117
+ it 'works and throws' do
118
+ expect{
119
+ subject
120
+ }.to raise_error(Minitest::Assertion, /Expected 2 to be < 2/)
121
+ end
122
+ end
123
+ end
124
+
125
+ describe "lte" do
126
+ let(:predicate) {
127
+ Predicate.lte(:x, 2)
128
+ }
129
+
130
+ subject{
131
+ predicate.assert!(input)
132
+ }
133
+
134
+ context "when ok" do
135
+ let(:input){
136
+ { x: 2 }
137
+ }
138
+ it 'works and returns 2' do
139
+ expect(subject).to eql(2)
140
+ end
141
+ end
142
+
143
+ context "when ko" do
144
+ let(:input){
145
+ { x: 3 }
146
+ }
147
+ it 'works and throws' do
148
+ expect{
149
+ subject
150
+ }.to raise_error(Minitest::Assertion, /Expected 3 to be <= 2/)
151
+ end
152
+ end
153
+ end
154
+
35
155
  describe "neq" do
36
156
  let(:predicate) {
37
157
  Predicate.neq(:x, 2)
@@ -62,6 +182,96 @@ class Predicate
62
182
  end
63
183
  end
64
184
 
185
+ describe "and" do
186
+ let(:predicate) {
187
+ Predicate.eq(:x, 2) & Predicate.eq(:y, 2)
188
+ }
189
+
190
+ subject{
191
+ predicate.assert!(input)
192
+ }
193
+
194
+ context "when ok" do
195
+ let(:input){
196
+ { x: 2, y: 2 }
197
+ }
198
+ it 'works and returns true' do
199
+ expect(subject).to eql(true)
200
+ end
201
+ end
202
+
203
+ context "when ko" do
204
+ let(:input){
205
+ { x: 2, y: 3 }
206
+ }
207
+ it 'works and throws' do
208
+ expect{
209
+ subject
210
+ }.to raise_error(Minitest::Assertion, /Expected: 3\n Actual: 2/)
211
+ end
212
+ end
213
+ end
214
+
215
+ describe "empty" do
216
+ let(:predicate) {
217
+ Predicate.empty(:x)
218
+ }
219
+
220
+ subject{
221
+ predicate.assert!(input)
222
+ }
223
+
224
+ context "when ok" do
225
+ let(:input){
226
+ { x: [] }
227
+ }
228
+ it 'works and returns true' do
229
+ expect(subject).to eql([])
230
+ end
231
+ end
232
+
233
+ context "when ko" do
234
+ let(:input){
235
+ { x: [2] }
236
+ }
237
+ it 'works and throws' do
238
+ expect{
239
+ subject
240
+ }.to raise_error(Minitest::Assertion, /Expected \[2\] to be empty/)
241
+ end
242
+ end
243
+ end
244
+
245
+ describe "in" do
246
+ let(:predicate) {
247
+ Predicate.in(:x, [2, 3, 4])
248
+ }
249
+
250
+ subject{
251
+ predicate.assert!(input)
252
+ }
253
+
254
+ context "when ok" do
255
+ let(:input){
256
+ { x: 3 }
257
+ }
258
+ it 'works and returns 3' do
259
+ expect(subject).to eql(3)
260
+ end
261
+ end
262
+
263
+ context "when ko" do
264
+ let(:input){
265
+ { x: 8 }
266
+ }
267
+ it 'works and throws' do
268
+ expect{
269
+ subject
270
+ }.to raise_error(Minitest::Assertion, /Expected \[2, 3, 4\] to include 8/)
271
+ end
272
+ end
273
+ end
274
+
65
275
  end
66
276
  end
67
277
 
@@ -8,73 +8,97 @@ class Predicate
8
8
  context "on tautology" do
9
9
  let(:pred){ p.tautology }
10
10
 
11
- it{ should eq({}) }
11
+ it {
12
+ expect(subject).to eq({})
13
+ }
12
14
  end
13
15
 
14
16
  context "on contradiction" do
15
17
  let(:pred){ p.contradiction }
16
18
 
17
- it{ should eq({ nil => pred }) }
19
+ it {
20
+ expect(subject).to eq({ nil => pred })
21
+ }
18
22
  end
19
23
 
20
24
  context "on identifier" do
21
25
  let(:pred){ p.identifier(:x) }
22
26
 
23
- it{ should eq({ x: pred }) }
27
+ it {
28
+ expect(subject).to eq({ x: pred })
29
+ }
24
30
  end
25
31
 
26
32
  context "on not" do
27
33
  let(:pred){ p.not(:x) }
28
34
 
29
- it{ should eq({ x: pred }) }
35
+ it {
36
+ expect(subject).to eq({ x: pred })
37
+ }
30
38
  end
31
39
 
32
40
  context "on eq" do
33
41
  let(:pred){ p.eq(:x, 2) }
34
42
 
35
- it{ should eq({ x: pred }) }
43
+ it {
44
+ expect(subject).to eq({ x: pred })
45
+ }
36
46
  end
37
47
 
38
48
  context "on eq with placeholder" do
39
49
  let(:pred){ p.eq(:x, p.placeholder) }
40
50
 
41
- it{ should eq({ x: pred }) }
51
+ it {
52
+ expect(subject).to eq({ x: pred })
53
+ }
42
54
  end
43
55
 
44
56
  context "on in" do
45
57
  let(:pred){ p.in(:x, [2]) }
46
58
 
47
- it{ should eq({ x: pred }) }
59
+ it {
60
+ expect(subject).to eq({ x: pred })
61
+ }
48
62
  end
49
63
 
50
64
  context "on intersect" do
51
65
  let(:pred){ p.intersect(:x, [2]) }
52
66
 
53
- it{ should eq({ x: pred }) }
67
+ it {
68
+ expect(subject).to eq({ x: pred })
69
+ }
54
70
  end
55
71
 
56
72
  context "on subset" do
57
73
  let(:pred){ p.subset(:x, [2]) }
58
74
 
59
- it{ should eq({ x: pred }) }
75
+ it {
76
+ expect(subject).to eq({ x: pred })
77
+ }
60
78
  end
61
79
 
62
80
  context "on superset" do
63
81
  let(:pred){ p.superset(:x, [2]) }
64
82
 
65
- it{ should eq({ x: pred }) }
83
+ it {
84
+ expect(subject).to eq({ x: pred })
85
+ }
66
86
  end
67
87
 
68
88
  context "on match" do
69
89
  let(:pred){ p.match(:x, "London") }
70
90
 
71
- it{ should eq({ x: pred }) }
91
+ it {
92
+ expect(subject).to eq({ x: pred })
93
+ }
72
94
  end
73
95
 
74
96
  context "on match with two identifiers" do
75
97
  let(:pred){ p.match(:x, :y) }
76
98
 
77
- it{ should eq({ nil => pred }) }
99
+ it {
100
+ expect(subject).to eq({ nil => pred })
101
+ }
78
102
  end
79
103
 
80
104
  end
@@ -7,19 +7,23 @@ class Predicate
7
7
  subject{ left & right }
8
8
 
9
9
  before do
10
- subject.should be_a(Predicate)
10
+ expect(subject).to be_a(Predicate)
11
11
  end
12
12
 
13
13
  context 'with itself' do
14
14
  let(:right){ left }
15
15
 
16
- it{ should be(left) }
16
+ it {
17
+ expect(subject).to be(left)
18
+ }
17
19
  end
18
20
 
19
21
  context 'with the same expression' do
20
22
  let(:right){ Predicate.coerce(x: 2) }
21
23
 
22
- it{ should be(left) }
24
+ it {
25
+ expect(subject).to be(left)
26
+ }
23
27
  end
24
28
 
25
29
  context 'with tautology' do
@@ -7,61 +7,81 @@ class Predicate
7
7
  context "on tautology" do
8
8
  let(:pred){ Predicate.tautology }
9
9
 
10
- it{ should eq(Predicate.contradiction) }
10
+ it {
11
+ expect(subject).to eq(Predicate.contradiction)
12
+ }
11
13
  end
12
14
 
13
15
  context "on contradiction" do
14
16
  let(:pred){ Predicate.contradiction }
15
17
 
16
- it{ should eq(Predicate.tautology) }
18
+ it {
19
+ expect(subject).to eq(Predicate.tautology)
20
+ }
17
21
  end
18
22
 
19
23
  context "on not" do
20
24
  let(:pred){ Predicate.not(:x) }
21
25
 
22
- it{ should eq(Predicate.identifier(:x)) }
26
+ it {
27
+ expect(subject).to eq(Predicate.identifier(:x))
28
+ }
23
29
  end
24
30
 
25
31
  context "on comp" do
26
32
  let(:pred){ Predicate.comp(:eq, :x => 2) }
27
33
 
28
- it{ should eq(Predicate.comp(:neq, :x => 2)) }
34
+ it {
35
+ expect(subject).to eq(Predicate.comp(:neq, :x => 2))
36
+ }
29
37
  end
30
38
 
31
39
  context "on eq" do
32
40
  let(:pred){ Predicate.eq(:x => 2) }
33
41
 
34
- it{ should eq(Predicate.neq(:x => 2)) }
42
+ it {
43
+ expect(subject).to eq(Predicate.neq(:x => 2))
44
+ }
35
45
  end
36
46
 
37
47
  context "on neq" do
38
48
  let(:pred){ Predicate.neq(:x => 2) }
39
49
 
40
- it{ should eq(Predicate.eq(:x => 2)) }
50
+ it {
51
+ expect(subject).to eq(Predicate.eq(:x => 2))
52
+ }
41
53
  end
42
54
 
43
55
  context "on lt" do
44
56
  let(:pred){ Predicate.lt(:x => 2) }
45
57
 
46
- it{ should eq(Predicate.gte(:x => 2)) }
58
+ it {
59
+ expect(subject).to eq(Predicate.gte(:x => 2))
60
+ }
47
61
  end
48
62
 
49
63
  context "on lte" do
50
64
  let(:pred){ Predicate.lte(:x => 2) }
51
65
 
52
- it{ should eq(Predicate.gt(:x => 2)) }
66
+ it {
67
+ expect(subject).to eq(Predicate.gt(:x => 2))
68
+ }
53
69
  end
54
70
 
55
71
  context "on gt" do
56
72
  let(:pred){ Predicate.gt(:x => 2) }
57
73
 
58
- it{ should eq(Predicate.lte(:x => 2)) }
74
+ it {
75
+ expect(subject).to eq(Predicate.lte(:x => 2))
76
+ }
59
77
  end
60
78
 
61
79
  context "on gte" do
62
80
  let(:pred){ Predicate.gte(:x => 2) }
63
81
 
64
- it{ should eq(Predicate.lt(:x => 2)) }
82
+ it {
83
+ expect(subject).to eq(Predicate.lt(:x => 2))
84
+ }
65
85
  end
66
86
 
67
87
  end
@@ -7,19 +7,23 @@ class Predicate
7
7
  subject{ left | right }
8
8
 
9
9
  before do
10
- subject.should be_a(Predicate)
10
+ expect(subject).to be_a(Predicate)
11
11
  end
12
12
 
13
13
  context 'with itself' do
14
14
  let(:right){ left }
15
15
 
16
- it{ should be(left) }
16
+ it {
17
+ expect(subject).to be(left)
18
+ }
17
19
  end
18
20
 
19
21
  context 'with the same expression' do
20
22
  let(:right){ Predicate.coerce(x: 2) }
21
23
 
22
- it{ should be(left) }
24
+ it {
25
+ expect(subject).to be(left)
26
+ }
23
27
  end
24
28
 
25
29
  end