eapi 0.1.2 → 0.2.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.
@@ -4,55 +4,56 @@ RSpec.describe Eapi do
4
4
 
5
5
  context 'basic behaviour' do
6
6
  class MyTestKlass
7
- include Eapi::Common
8
-
7
+ include Eapi::Item
9
8
  property :something
10
9
  end
11
10
 
12
- describe '#something (fluent setter/getter)' do
13
- describe '#something as getter' do
14
- it 'return the value' do
15
- eapi = MyTestKlass.new something: :hey
16
- expect(eapi.something).to eq :hey
11
+ describe MyTestKlass do
12
+ describe '#something (fluent setter/getter)' do
13
+ describe '#something as getter' do
14
+ it 'return the value' do
15
+ eapi = described_class.new something: :hey
16
+ expect(eapi.something).to eq :hey
17
+ end
17
18
  end
18
- end
19
19
 
20
- describe '#something("val")' do
21
- it 'set the value and return self' do
22
- eapi = MyTestKlass.new something: :hey
23
- res = eapi.something :other
24
- expect(eapi).to be res
25
- expect(eapi.something).to eq :other
20
+ describe '#something("val")' do
21
+ it 'set the value and return self' do
22
+ eapi = described_class.new something: :hey
23
+ res = eapi.something :other
24
+ expect(eapi).to be res
25
+ expect(eapi.something).to eq :other
26
+ end
26
27
  end
27
- end
28
28
 
29
- describe '#set_something("val")' do
30
- it 'set the value and return self' do
31
- eapi = MyTestKlass.new something: :hey
32
- res = eapi.set_something :other
33
- expect(eapi).to be res
34
- expect(eapi.something).to eq :other
29
+ describe '#set_something("val")' do
30
+ it 'set the value and return self' do
31
+ eapi = described_class.new something: :hey
32
+ res = eapi.set_something :other
33
+ expect(eapi).to be res
34
+ expect(eapi.something).to eq :other
35
+ end
35
36
  end
36
37
  end
37
- end
38
38
 
39
- describe '#get' do
40
- it 'will use the getter' do
41
- eapi = MyTestKlass.new something: :hey
42
- expect(eapi.get(:something)).to eq :hey
43
- expect(eapi.get('something')).to eq :hey
44
- end
39
+ describe '#get' do
40
+ it 'will use the getter' do
41
+ eapi = described_class.new something: :hey
42
+ expect(eapi.get(:something)).to eq :hey
43
+ expect(eapi.get('something')).to eq :hey
44
+ end
45
45
 
46
- end
46
+ end
47
47
 
48
- describe '#set' do
49
- it 'will use the fluent setter' do
50
- eapi = MyTestKlass.new
51
- expect(eapi.set(:something, :hey)).to equal eapi
52
- expect(eapi.get(:something)).to eq :hey
48
+ describe '#set' do
49
+ it 'will use the fluent setter' do
50
+ eapi = described_class.new
51
+ expect(eapi.set(:something, :hey)).to equal eapi
52
+ expect(eapi.get(:something)).to eq :hey
53
+ end
53
54
  end
54
- end
55
55
 
56
+ end
56
57
  end
57
58
 
58
59
  end
@@ -4,7 +4,7 @@ RSpec.describe Eapi do
4
4
 
5
5
  context '#definition_for' do
6
6
  class MyTestKlassDefinition
7
- include Eapi::Common
7
+ include Eapi::Item
8
8
 
9
9
  property :something, type: Hash, unrecognised_option: 1
10
10
  end
@@ -8,14 +8,14 @@ RSpec.describe Eapi do
8
8
  end
9
9
 
10
10
  class MyExtensionExternalKlass
11
- include MyExtension::Common
11
+ include MyExtension::Item
12
12
 
13
13
  property :something
14
14
  end
15
15
 
16
16
  module MyExtension
17
17
  class TestKlass
18
- include MyExtension::Common
18
+ include MyExtension::Item
19
19
 
20
20
  property :something
21
21
  end
@@ -2,63 +2,92 @@ require 'spec_helper'
2
2
 
3
3
  RSpec.describe Eapi do
4
4
 
5
- context 'function initializer' do
6
- class MyTestKlassOutside
7
- include Eapi::Common
5
+ class MyTestKlassOutside
6
+ include Eapi::Item
7
+
8
+ property :something
9
+ end
10
+
11
+ class MyTestListOutside
12
+ include Eapi::List
13
+ end
14
+
15
+ module Somewhere
16
+ class TestKlassInModule
17
+ include Eapi::Item
8
18
 
9
19
  property :something
10
20
  end
11
21
 
12
- module Somewhere
13
- class TestKlassInModule
14
- include Eapi::Common
22
+ class TestListInModule
23
+ include Eapi::List
24
+ end
25
+ end
15
26
 
16
- property :something
27
+ describe 'Eapi::Children' do
28
+ describe '#list' do
29
+ it 'returns the list of Eapi enabled classes' do
30
+ list = Eapi::Children.list
31
+ expect(list).to include(MyTestKlassOutside)
32
+ expect(list).to include(MyTestListOutside)
17
33
  end
18
34
  end
19
35
 
20
- describe 'Eapi::Children' do
21
- describe '#list' do
22
- it 'returns the list of Eapi enabled classes' do
23
- list = Eapi::Children.list
24
- expect(list).to include(MyTestKlassOutside)
25
- end
36
+ describe '#has?' do
37
+ it 'true if the given class is an Eapi enabled class' do
38
+ expect(Eapi::Children).not_to be_has('nope')
39
+ expect(Eapi::Children).to be_has(MyTestKlassOutside)
40
+ expect(Eapi::Children).to be_has('MyTestKlassOutside')
41
+ expect(Eapi::Children).to be_has('my_test_klass_outside')
42
+ expect(Eapi::Children).to be_has(MyTestListOutside)
43
+ expect(Eapi::Children).to be_has('MyTestListOutside')
44
+ expect(Eapi::Children).to be_has('my_test_list_outside')
26
45
  end
46
+ end
27
47
 
28
- describe '#has?' do
29
- it 'true if the given class is an Eapi enabled class' do
30
- expect(Eapi::Children).not_to be_has('nope')
31
- expect(Eapi::Children).to be_has(MyTestKlassOutside)
32
- expect(Eapi::Children).to be_has('MyTestKlassOutside')
33
- expect(Eapi::Children).to be_has('my_test_klass_outside')
34
- end
48
+ describe '#get' do
49
+ it 'get the given class if it is an Eapi enabled class' do
50
+ expect(Eapi::Children.get('nope')).to be_nil
51
+ expect(Eapi::Children.get(MyTestKlassOutside)).to eq MyTestKlassOutside
52
+ expect(Eapi::Children.get('MyTestKlassOutside')).to eq MyTestKlassOutside
53
+ expect(Eapi::Children.get('my_test_klass_outside')).to eq MyTestKlassOutside
54
+ expect(Eapi::Children.get(MyTestListOutside)).to eq MyTestListOutside
55
+ expect(Eapi::Children.get('MyTestListOutside')).to eq MyTestListOutside
56
+ expect(Eapi::Children.get('my_test_list_outside')).to eq MyTestListOutside
35
57
  end
58
+ end
59
+ end
36
60
 
37
- describe '#get' do
38
- it 'get the given class if it is an Eapi enabled class' do
39
- expect(Eapi::Children.get('nope')).to be_nil
40
- expect(Eapi::Children.get(MyTestKlassOutside)).to eq MyTestKlassOutside
41
- expect(Eapi::Children.get('MyTestKlassOutside')).to eq MyTestKlassOutside
42
- expect(Eapi::Children.get('my_test_klass_outside')).to eq MyTestKlassOutside
61
+ describe 'initialise using method calls to Eapi', :focus do
62
+ [
63
+ [:MyTestKlassOutside, MyTestKlassOutside],
64
+ [:my_test_klass_outside, MyTestKlassOutside],
65
+ [:Somewhere__TestKlassInModule, Somewhere::TestKlassInModule],
66
+ [:somewhere__test_klass_in_module, Somewhere::TestKlassInModule],
67
+ [:Somewhere_TestKlassInModule, Somewhere::TestKlassInModule],
68
+ [:somewhere_test_klass_in_module, Somewhere::TestKlassInModule],
69
+ ].each do |(meth, klass)|
70
+ describe "Eapi.#{meth}(...)" do
71
+ it "calls #{klass}.new" do
72
+ eapi = Eapi.send meth, something: :hey
73
+ expect(eapi).to be_a klass
74
+ expect(eapi.something).to eq :hey
43
75
  end
44
76
  end
45
77
  end
46
78
 
47
- describe 'initialise using method calls to Eapi', :focus do
48
- [
49
- [:MyTestKlassOutside, MyTestKlassOutside],
50
- [:my_test_klass_outside, MyTestKlassOutside],
51
- [:Somewhere__TestKlassInModule, Somewhere::TestKlassInModule],
52
- [:somewhere__test_klass_in_module, Somewhere::TestKlassInModule],
53
- [:Somewhere_TestKlassInModule, Somewhere::TestKlassInModule],
54
- [:somewhere_test_klass_in_module, Somewhere::TestKlassInModule],
55
- ].each do |(meth, klass)|
56
- describe "Eapi.#{meth}(...)" do
57
- it "calls #{klass}.new" do
58
- eapi = Eapi.send meth, something: :hey
59
- expect(eapi).to be_a klass
60
- expect(eapi.something).to eq :hey
61
- end
79
+ [
80
+ [:MyTestListOutside, MyTestListOutside],
81
+ [:my_test_list_outside, MyTestListOutside],
82
+ [:Somewhere__TestListInModule, Somewhere::TestListInModule],
83
+ [:somewhere__test_list_in_module, Somewhere::TestListInModule],
84
+ [:Somewhere_TestListInModule, Somewhere::TestListInModule],
85
+ [:somewhere_test_list_in_module, Somewhere::TestListInModule],
86
+ ].each do |(meth, klass)|
87
+ describe "Eapi.#{meth}(...)" do
88
+ it "calls #{klass}.new" do
89
+ eapi = Eapi.send meth
90
+ expect(eapi).to be_a klass
62
91
  end
63
92
  end
64
93
  end
@@ -0,0 +1,123 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Eapi do
4
+
5
+ context 'list elements' do
6
+ class MyTestClassValMult
7
+ include Eapi::Item
8
+
9
+ property :something, multiple: true
10
+ end
11
+
12
+ it '#add_something' do
13
+ eapi = MyTestClassValMult.new something: [1, 2]
14
+ res = eapi.add_something 3
15
+ expect(res).to be eapi
16
+ expect(eapi.something).to eq [1, 2, 3]
17
+ end
18
+
19
+ it '#init_something called on first add if element is nil' do
20
+ eapi = MyTestClassValMult.new
21
+ res = eapi.add_something :a
22
+ expect(res).to be eapi
23
+ expect(eapi.something.to_a).to eq [:a]
24
+ end
25
+
26
+ class MyTestClassValMultImpl
27
+ include Eapi::Item
28
+
29
+ property :something, type: Set
30
+ end
31
+
32
+ class MyMultiple
33
+ def self.is_multiple?
34
+ true
35
+ end
36
+
37
+ def <<(x)
38
+ @elements ||= []
39
+ @elements << x
40
+ end
41
+
42
+ def to_a
43
+ @elements.to_a
44
+ end
45
+ end
46
+
47
+ class MyTestClassValMultImpl2
48
+ include Eapi::Item
49
+
50
+ property :something, type: MyMultiple
51
+ end
52
+
53
+ class MyMultipleValueTestKlass
54
+ include Eapi::MultipleValue
55
+
56
+ def <<(x)
57
+ @elements ||= []
58
+ @elements << x
59
+ end
60
+
61
+ def to_a
62
+ @elements.to_a
63
+ end
64
+ end
65
+
66
+ class MyTestClassValMultImpl3
67
+ include Eapi::Item
68
+
69
+ property :something, type: MyMultipleValueTestKlass
70
+ end
71
+
72
+ it 'if type is Array or Set, or responds true to is_multiple?, it is multiple implicitly + uses that class to initialize the property when adding' do
73
+ [
74
+ [MyTestClassValMult, Array],
75
+ [MyTestClassValMultImpl, Set],
76
+ [MyTestClassValMultImpl2, MyMultiple],
77
+ [MyTestClassValMultImpl3, MyMultipleValueTestKlass],
78
+ ].each do |(eapi_class, type_class)|
79
+ eapi = eapi_class.new
80
+ res = eapi.add_something :a
81
+ expect(res).to be eapi
82
+ expect(eapi.something.to_a).to eq [:a]
83
+ expect(eapi.something).to be_a_kind_of type_class
84
+ end
85
+ end
86
+
87
+ describe 'element validation' do
88
+ class MyTestClassValElements
89
+ include Eapi::Item
90
+ property :something, multiple: true, element_type: Hash
91
+ property :other, multiple: true, validate_element_with: ->(record, attr, value) do
92
+ record.errors.add(attr, "element must pass my custom validation") unless value == :valid_val
93
+ end
94
+ end
95
+
96
+ describe 'using `type_element` property in definition' do
97
+ it 'will validate the type of all the elements in the list' do
98
+ eapi = MyTestClassValElements.new
99
+ eapi.add_something 1
100
+ expect(eapi).not_to be_valid
101
+ expect(eapi.errors.full_messages).to eq ["Something element must be a Hash"]
102
+ expect(eapi.errors.messages).to eq({something: ["element must be a Hash"]})
103
+
104
+ eapi.something [{a: :b}]
105
+ expect(eapi).to be_valid
106
+ end
107
+ end
108
+
109
+ describe 'using `validate_element_with` property in definition' do
110
+ it 'will run that custom validation for all the elements in the list' do
111
+ eapi = MyTestClassValElements.new
112
+ eapi.add_other 1
113
+ expect(eapi).not_to be_valid
114
+ expect(eapi.errors.full_messages).to eq ["Other element must pass my custom validation"]
115
+ expect(eapi.errors.messages).to eq({other: ["element must pass my custom validation"]})
116
+
117
+ eapi.other [:valid_val]
118
+ expect(eapi).to be_valid
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -3,122 +3,419 @@ require 'spec_helper'
3
3
  RSpec.describe Eapi do
4
4
 
5
5
  context 'list' do
6
- class MyTestClassValMult
7
- include Eapi::Common
8
6
 
9
- property :something, multiple: true
7
+ class MyListKlass
8
+ include Eapi::List
10
9
  end
11
10
 
12
- it '#add_something' do
13
- eapi = MyTestClassValMult.new something: [1, 2]
14
- res = eapi.add_something 3
15
- expect(res).to be eapi
16
- expect(eapi.something).to eq [1, 2, 3]
17
- end
18
-
19
- it '#init_something called on first add if element is nil' do
20
- eapi = MyTestClassValMult.new
21
- res = eapi.add_something :a
22
- expect(res).to be eapi
23
- expect(eapi.something.to_a).to eq [:a]
24
- end
25
-
26
- class MyTestClassValMultImpl
27
- include Eapi::Common
28
-
29
- property :something, type: Set
30
- end
11
+ describe 'list behaviour' do
12
+ subject { MyListKlass.new }
31
13
 
32
- class MyMultiple
33
- def self.is_multiple?
34
- true
14
+ context '#<<' do
15
+ it 'append element, normal behaviour' do
16
+ res = subject << :hey
17
+ expect(res).to eq [:hey]
18
+ expect(subject.to_a).to eq [:hey]
19
+ end
35
20
  end
36
21
 
37
- def <<(x)
38
- @elements ||= []
39
- @elements << x
22
+ context '#add' do
23
+ it 'fluent adder, returns self' do
24
+ res = subject.add(:hey).add(:you)
25
+ expect(res).to eq subject
26
+ expect(subject.to_a).to eq [:hey, :you]
27
+ end
40
28
  end
41
29
 
42
- def to_a
43
- @elements.to_a
30
+ context '#to_a' do
31
+ it 'executes validation' do
32
+
33
+ end
44
34
  end
45
35
  end
46
36
 
47
- class MyTestClassValMultImpl2
48
- include Eapi::Common
37
+ describe 'list methods' do
38
+ KNOWN_METHODS = {
39
+ not_supported: [:transpose, :assoc, :rassoc, :permutation, :combination, :repeated_permutation, :repeated_combination, :product, :pack],
40
+ not_same: [:pry, :to_s, :inspect, :to_a, :to_h, :hash, :eql?, :to_ary, :pretty_print, :pretty_print_cycle],
41
+ block: [:cycle, :each, :each_index, :reverse_each],
42
+ special: [:[], :[]=, :<<, :==],
43
+ other_array: [:concat, :+, :-, :&, :|, :replace, :<=>],
44
+ at: [:at, :fetch, :delete_at, :from, :to],
45
+ index: [:index, :find_index, :rindex, :delete],
46
+ push: [:push, :unshift, :append, :prepend],
47
+ insert: [:insert],
48
+ map: [:map, :map!, :collect!, :collect],
49
+ select!: [:keep_if, :select!, :reject!, :select, :delete_if, :reject, :drop_while, :take_while, :bsearch],
50
+ by_number: [:in_groups_of, :in_groups, :drop, :take, :include?, :*, :to_query, :fill],
51
+ slice: [:slice, :slice!],
52
+ sort_by: [:sort_by!],
53
+ sample: [:sample],
54
+ shuffle: [:shuffle, :shuffle!],
55
+ }
49
56
 
50
- property :something, type: MyMultiple
51
- end
57
+ SUPPORTED_METHODS = [].public_methods(false) - KNOWN_METHODS[:not_supported]
58
+ MIMIC_METHODS = [].public_methods(false) - KNOWN_METHODS.values.flatten
52
59
 
53
- class MyMultipleEapi
54
- include Eapi::Multiple
60
+ subject { MyListKlass.new.add(1).add(2).add(3) }
61
+ let(:other) { MyListKlass.new.add(1).add(2).add(3) }
62
+ let(:array) { [1, 2, 3] }
55
63
 
56
- def <<(x)
57
- @elements ||= []
58
- @elements << x
59
- end
64
+ context 'array methods' do
65
+ describe 'respond to methods' do
66
+ KNOWN_METHODS[:not_supported].each do |m|
67
+ it "does not respond to #{m}" do
68
+ expect(subject).not_to respond_to(m)
69
+ end
70
+ end
71
+
72
+ SUPPORTED_METHODS.each do |m|
73
+ it "responds to #{m}" do
74
+ expect(subject).to respond_to(m)
75
+ end
76
+ end
77
+ end
78
+
79
+ describe 'same behaviour as list array' do
80
+
81
+ describe 'to_ary' do
82
+ it { expect(subject.to_ary).to eq array }
83
+ it { expect(subject.to_ary).not_to equal subject }
84
+ it { expect(subject.to_ary).to equal subject._list }
85
+ end
86
+
87
+ describe 'method ==' do
88
+ it { expect(subject).to eq array }
89
+ it { expect(subject).to eq other }
90
+ it { expect(subject).not_to eq [3, 2, 1] }
91
+ it { expect(subject).not_to eq MyListKlass.new }
92
+ end
93
+
94
+ describe 'method []' do
95
+ it { expect(subject[2]).to eq array[2] }
96
+ end
97
+
98
+ describe 'method []=' do
99
+ it { expect(subject[2] = :paco).to eq(array[2] = :paco) }
100
+ it do
101
+ subject[2] = :paco
102
+ expect(subject[2]).to eq :paco
103
+ end
104
+ end
105
+
106
+ describe 'method <<' do
107
+ it { expect(subject << :paco).to eq(array << :paco) }
108
+ it do
109
+ subject << :paco
110
+ expect(subject.last).to eq :paco
111
+ end
112
+ end
113
+
114
+ KNOWN_METHODS[:other_array].each do |m|
115
+ describe "method #{m}" do
116
+ it { expect(subject.public_send(m, other)).to eq array.public_send(m, other._list) }
117
+ it { expect(subject.public_send(m, other._list)).to eq(array.public_send(m, other._list)) }
118
+ end
119
+ end
120
+
121
+
122
+ KNOWN_METHODS[:at].each do |m|
123
+ describe "method #{m}" do
124
+ it { expect(subject.public_send(m, 2)).to eq array.public_send(m, 2) }
125
+ end
126
+ end
127
+
128
+ KNOWN_METHODS[:index].each do |m|
129
+ describe "method #{m}" do
130
+ it { expect(subject.public_send(m, 2)).to eq array.public_send(m, 2) }
131
+ end
132
+ end
133
+
134
+ KNOWN_METHODS[:push].each do |m|
135
+ describe "method #{m}" do
136
+ it { expect(subject.public_send(m, :paco)).to eq(array.public_send(m, :paco)) }
137
+ it do
138
+ subject.public_send(m, :paco)
139
+ array.public_send(m, :paco)
140
+ expect(subject).to eq array
141
+ end
142
+ end
143
+ end
144
+
145
+ KNOWN_METHODS[:insert].each do |m|
146
+ describe "method #{m}" do
147
+ it { expect(subject.public_send(m, 1, :paco)).to eq(array.public_send(m, 1, :paco)) }
148
+ it do
149
+ subject.public_send(m, 1, :paco)
150
+ array.public_send(m, 1, :paco)
151
+ expect(subject).to eq array
152
+ end
153
+ end
154
+ end
155
+
156
+ describe "method sample" do
157
+ it do
158
+ expect(subject._list).to include(subject.sample)
159
+ end
160
+ end
161
+
162
+ describe "method shuffle" do
163
+ it do
164
+ list_before_shuffle = subject._list.dup
165
+ list_after_shuffle = subject.shuffle._list.dup
166
+ expect(list_before_shuffle.sort).to eq list_after_shuffle.sort
167
+ end
168
+ end
169
+
170
+ describe "method shuffle!" do
171
+ it do
172
+ list_before_shuffle = subject._list.dup
173
+ subject.shuffle!
174
+ list_after_shuffle = subject._list.dup
175
+ expect(list_before_shuffle.sort).to eq list_after_shuffle.sort
176
+ end
177
+ end
178
+
179
+
180
+ KNOWN_METHODS[:map].each do |m|
181
+ describe "method #{m}" do
182
+ let(:subject_applied_block) do
183
+ subject.public_send(m) { |x| x + 1 }
184
+ end
185
+
186
+ let(:array_applied_block) do
187
+ array.public_send(m) { |x| x + 1 }
188
+ end
189
+
190
+ it do
191
+ expect(subject_applied_block).to eq array_applied_block
192
+ end
193
+
194
+ it do
195
+ subject_applied_block
196
+ array_applied_block
197
+ expect(subject).to eq array
198
+ end
199
+ end
200
+ end
201
+
202
+
203
+ KNOWN_METHODS[:select!].each do |m|
204
+ describe "method #{m}" do
205
+ let(:subject_applied_block) do
206
+ subject.public_send(m) { |x| x.odd? }
207
+ end
208
+
209
+ let(:array_applied_block) do
210
+ array.public_send(m) { |x| x.odd? }
211
+ end
212
+
213
+ it do
214
+ expect(subject_applied_block).to eq array_applied_block
215
+ end
216
+
217
+ it do
218
+ subject_applied_block
219
+ array_applied_block
220
+ expect(subject).to eq array
221
+ end
222
+ end
223
+ end
224
+
225
+
226
+ KNOWN_METHODS[:by_number].each do |m|
227
+ describe "method #{m}" do
228
+ let(:subject_result) do
229
+ subject.public_send(m, 2)
230
+ end
231
+
232
+ let(:array_result) do
233
+ array.public_send(m, 2)
234
+ end
60
235
 
61
- def to_a
62
- @elements.to_a
236
+ it do
237
+ expect(subject_result).to eq array_result
238
+ end
239
+
240
+ it do
241
+ subject_result
242
+ array_result
243
+ expect(subject).to eq array
244
+ end
245
+ end
246
+ end
247
+
248
+
249
+ KNOWN_METHODS[:slice].each do |m|
250
+ describe "method #{m}" do
251
+ let(:subject_result) do
252
+ subject.public_send(m, 2)
253
+ end
254
+
255
+ let(:array_result) do
256
+ array.public_send(m, 2)
257
+ end
258
+
259
+ it do
260
+ expect(subject_result).to eq array_result
261
+ end
262
+
263
+ it do
264
+ subject_result
265
+ array_result
266
+ expect(subject).to eq array
267
+ end
268
+ end
269
+ end
270
+
271
+ describe "method sort_by!" do
272
+ let(:subject_enumerator) do
273
+ subject.sort_by!
274
+ end
275
+
276
+ let(:array_enumerator) do
277
+ array.sort_by!
278
+ end
279
+
280
+ let(:subject_with_block) do
281
+ subject.sort_by! { |x| -1 * x }
282
+ end
283
+
284
+ let(:array_with_block) do
285
+ array.sort_by! { |x| -1 * x }
286
+ end
287
+
288
+ it do
289
+ expect(subject_enumerator.to_a).to eq array_enumerator.to_a
290
+ end
291
+
292
+ it do
293
+ expect(subject_with_block.to_a).to eq array_with_block.to_a
294
+ end
295
+
296
+ it do
297
+ subject_with_block
298
+ array_with_block
299
+ expect(subject).to eq array
300
+ end
301
+ end
302
+
303
+
304
+ describe 'block methods' do
305
+ describe 'method cycle' do
306
+ it 'behaves like the method in Array' do
307
+ sl = []
308
+ al = []
309
+ subject.cycle(2) { |x| sl << (x + 1) }
310
+ array.cycle(2) { |x| al << (x + 1) }
311
+
312
+ expect(sl).to eq al
313
+ end
314
+ end
315
+ end
316
+
317
+
318
+ MIMIC_METHODS.each do |m|
319
+ describe "method #{m}" do
320
+ it 'behaves like the method in Array' do
321
+ lr = subject.public_send m
322
+ ar = array.public_send m
323
+
324
+ if ar.equal? array
325
+ expect(lr).to equal subject
326
+ else
327
+ expect(lr).to eq ar
328
+ end
329
+
330
+ expect(subject._list).to eq array
331
+ end
332
+ end
333
+ end
334
+ end
63
335
  end
64
336
  end
65
337
 
66
- class MyTestClassValMultImpl3
67
- include Eapi::Common
338
+ describe 'list definition' do
339
+ class ListDefinitionTestKlass
340
+ include Eapi::List
68
341
 
69
- property :something, type: MyMultipleEapi
70
- end
342
+ elements required: true, type: String, unique: true
343
+ end
344
+
345
+ let(:definition) { {required: true, type: String, unique: true} }
71
346
 
72
- it 'if type is Array or Set, or responds true to is_multiple?, it is multiple implicitly + uses that class to initialize the property when adding' do
73
- [
74
- [MyTestClassValMult, Array],
75
- [MyTestClassValMultImpl, Set],
76
- [MyTestClassValMultImpl2, MyMultiple],
77
- [MyTestClassValMultImpl3, MyMultipleEapi],
78
- ].each do |(eapi_class, type_class)|
79
- eapi = eapi_class.new
80
- res = eapi.add_something :a
81
- expect(res).to be eapi
82
- expect(eapi.something.to_a).to eq [:a]
83
- expect(eapi.something).to be_a_kind_of type_class
347
+ subject { ListDefinitionTestKlass.new }
348
+
349
+ context '.is_multiple?' do
350
+ it { expect(subject.class).to be_is_multiple }
84
351
  end
85
- end
86
352
 
87
- describe 'element validation' do
88
- class MyTestClassValElements
89
- include Eapi::Common
90
- property :something, multiple: true, element_type: Hash
91
- property :other, multiple: true, validate_element_with: ->(record, attr, value) do
92
- record.errors.add(attr, "element must pass my custom validation") unless value == :valid_val
353
+ context '.definition_for_elements' do
354
+ it { expect(subject.class.definition_for_elements).to eq definition }
355
+ end
356
+
357
+ context 'required' do
358
+ it 'fails if empty' do
359
+ expect(subject).not_to be_valid
360
+ subject.add "Something"
361
+ expect(subject).to be_valid
93
362
  end
94
363
  end
95
364
 
96
- describe 'using `type_element` property in definition' do
97
- it 'will validate the type of all the elements in the list' do
98
- eapi = MyTestClassValElements.new
99
- eapi.add_something 1
100
- expect(eapi).not_to be_valid
101
- expect(eapi.errors.full_messages).to eq ["Something element must be a Hash"]
102
- expect(eapi.errors.messages).to eq({something: ["element must be a Hash"]})
365
+ context 'type' do
366
+ it 'fails if any element is not of valid type' do
367
+ subject.add "Something"
368
+ subject.add :is
369
+ subject.add 1
370
+ expect(subject).not_to be_valid
371
+ subject.clear
372
+ subject.add "Just Strings"
373
+ subject.add "Many Strings"
374
+ expect(subject).to be_valid
375
+ end
376
+ end
103
377
 
104
- eapi.something [{a: :b}]
105
- expect(eapi).to be_valid
378
+ context 'unique' do
379
+ it 'fails if has any repeated elements' do
380
+ subject.add "Cramer"
381
+ subject.add "vs"
382
+ subject.add "Cramer"
383
+
384
+ expect(subject).not_to be_valid
385
+
386
+ msgs = {:_list => ["elements must be unique (repeated elements: {\"Cramer\"=>2})"]}
387
+ expect(subject.errors.messages).to eq msgs
388
+
389
+ subject.clear
390
+
391
+ subject.add "Cramer"
392
+ subject.add "vs"
393
+ subject.add "Other Guy"
394
+
395
+ expect(subject).to be_valid
106
396
  end
107
397
  end
108
398
 
109
- describe 'using `validate_element_with` property in definition' do
399
+ context 'validate_with lambda' do
400
+ class MyTestClassListValElements
401
+ include Eapi::List
402
+ elements validate_with: ->(record, attr, value) do
403
+ record.errors.add(attr, "element must pass my custom validation") unless value == :valid_val
404
+ end
405
+ end
406
+
110
407
  it 'will run that custom validation for all the elements in the list' do
111
- eapi = MyTestClassValElements.new
112
- eapi.add_other 1
408
+ eapi = MyTestClassListValElements.new
409
+ eapi.add 1
113
410
  expect(eapi).not_to be_valid
114
- expect(eapi.errors.full_messages).to eq ["Other element must pass my custom validation"]
115
- expect(eapi.errors.messages).to eq({other: ["element must pass my custom validation"]})
411
+ expect(eapi.errors.full_messages).to eq [" list element must pass my custom validation"]
412
+ expect(eapi.errors.messages).to eq({_list: ["element must pass my custom validation"]})
116
413
 
117
- eapi.other [:valid_val]
414
+ eapi.clear.add :valid_val
118
415
  expect(eapi).to be_valid
119
416
  end
120
417
  end
418
+
121
419
  end
122
420
  end
123
-
124
421
  end