magicka 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -0
  3. data/README.md +3 -3
  4. data/config/check_specs.yml +0 -2
  5. data/config/yardstick.yml +8 -2
  6. data/lib/magicka/aggregator/method_builder.rb +35 -28
  7. data/lib/magicka/aggregator.rb +16 -8
  8. data/lib/magicka/display.rb +1 -1
  9. data/lib/magicka/element/class_methods.rb +2 -0
  10. data/lib/magicka/element.rb +4 -2
  11. data/lib/magicka/helper/aggregator_options.rb +64 -0
  12. data/lib/magicka/helper/class_methods.rb +10 -2
  13. data/lib/magicka/helper/method_builder.rb +10 -6
  14. data/lib/magicka/helper.rb +12 -6
  15. data/lib/magicka/version.rb +1 -1
  16. data/magicka.gemspec +1 -1
  17. data/spec/dummy/app/controllers/application_controller.rb +1 -0
  18. data/spec/dummy/app/controllers/documents_controller.rb +9 -0
  19. data/spec/dummy/app/models/document.rb +5 -0
  20. data/spec/dummy/app/models/magicka/data_entry.rb +7 -0
  21. data/spec/dummy/app/models/magicka/data_table.rb +6 -0
  22. data/spec/dummy/app/views/documents/show.html.erb +6 -0
  23. data/spec/dummy/app/views/templates/display/_data_entry.html.erb +2 -0
  24. data/spec/dummy/config/environments/development.rb +1 -0
  25. data/spec/dummy/config/initializers/magicka.rb +7 -0
  26. data/spec/dummy/config/routes.rb +1 -0
  27. data/spec/dummy/db/schema.rb +5 -0
  28. data/spec/integration/yard/magicka/helper_spec.rb +33 -0
  29. data/spec/lib/magicka/aggregator/class_methods_spec.rb +352 -0
  30. data/spec/lib/magicka/aggregator/method_builder_spec.rb +29 -0
  31. data/spec/lib/magicka/aggregator_spec.rb +0 -221
  32. data/spec/lib/magicka/helper/aggregator_options_spec.rb +99 -0
  33. data/spec/lib/magicka/helper/class_methods_spec.rb +101 -0
  34. data/spec/lib/magicka/helper_spec.rb +2 -18
  35. data/spec/support/factories/document.rb +7 -0
  36. data/spec/support/factory_bot.rb +7 -0
  37. data/spec/support/models/custom_aggregator.rb +12 -0
  38. data/spec/support/models/my_element.rb +6 -0
  39. metadata +21 -4
@@ -0,0 +1,352 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Magicka::Aggregator::ClassMethods do
6
+ subject(:aggregator) { aggregator_class.new(renderer, model) }
7
+
8
+ let(:aggregator_class) { Class.new(Magicka::Aggregator) }
9
+ let(:model) { :my_model }
10
+ let(:renderer) { instance_double('renderer') }
11
+ let(:template) { 'templates/forms/input' }
12
+ let(:locals) { {} }
13
+
14
+ describe '.type' do
15
+ let(:type) { %w[form display other].sample }
16
+
17
+ it 'sets aggregator type' do
18
+ expect { aggregator_class.type(type) }
19
+ .to change(aggregator_class, :type)
20
+ .from(nil).to(type.to_sym)
21
+ end
22
+
23
+ context 'when type has not been set' do
24
+ let(:aggregator_class) do
25
+ Class.new(Magicka::Aggregator) do
26
+ def self.name
27
+ 'Magicka::MyClass'
28
+ end
29
+ end
30
+ end
31
+
32
+ it 'Uses class name as type' do
33
+ expect(aggregator_class.type)
34
+ .to eq(:my_class)
35
+ end
36
+ end
37
+ end
38
+
39
+ describe '.with_element' do
40
+ let(:element_class) { Magicka::Input }
41
+
42
+ context 'when seeting element class only' do
43
+ it do
44
+ expect { aggregator_class.with_element(element_class) }
45
+ .to add_method(:input)
46
+ .to(aggregator)
47
+ end
48
+
49
+ context 'when built method is called' do
50
+ let(:template) { 'templates/forms/input' }
51
+ let(:field) { :field }
52
+ let(:label) { 'Label' }
53
+ let(:placeholder) { 'Value' }
54
+
55
+ let(:locals) do
56
+ {
57
+ field: field,
58
+ label: label,
59
+ ng_errors: 'my_model.errors.field',
60
+ ng_model: 'my_model.field',
61
+ placeholder: placeholder
62
+ }
63
+ end
64
+
65
+ let(:arguments) do
66
+ {
67
+ label: label,
68
+ placeholder: placeholder
69
+ }
70
+ end
71
+
72
+ before do
73
+ aggregator_class.with_element(element_class)
74
+
75
+ allow(renderer)
76
+ .to receive(:render)
77
+ .with(partial: template, locals: locals)
78
+ end
79
+
80
+ it 'renders an input' do
81
+ aggregator.input(field, **arguments)
82
+
83
+ expect(renderer).to have_received(:render)
84
+ end
85
+
86
+ context 'when passing a custom model' do
87
+ let(:locals) do
88
+ {
89
+ field: field,
90
+ label: label,
91
+ ng_errors: 'my_custom_model.errors.field',
92
+ ng_model: 'my_custom_model.field',
93
+ placeholder: placeholder
94
+ }
95
+ end
96
+
97
+ it 'renders an input' do
98
+ aggregator.input(field, model: 'my_custom_model', **arguments)
99
+
100
+ expect(renderer).to have_received(:render)
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+ context 'when seeting element class and method' do
107
+ it do
108
+ expect { aggregator_class.with_element(element_class, :my_input) }
109
+ .to add_method(:my_input)
110
+ .to(aggregator)
111
+ end
112
+
113
+ context 'when built method is called' do
114
+ let(:template) { 'templates/forms/input' }
115
+ let(:field) { :field }
116
+ let(:label) { 'Label' }
117
+ let(:placeholder) { 'Value' }
118
+
119
+ let(:locals) do
120
+ {
121
+ field: field,
122
+ label: label,
123
+ ng_errors: 'my_model.errors.field',
124
+ ng_model: 'my_model.field',
125
+ placeholder: placeholder
126
+ }
127
+ end
128
+
129
+ let(:arguments) do
130
+ {
131
+ label: label,
132
+ placeholder: placeholder
133
+ }
134
+ end
135
+
136
+ before do
137
+ aggregator_class.with_element(element_class, :my_input)
138
+
139
+ allow(renderer)
140
+ .to receive(:render)
141
+ .with(partial: template, locals: locals)
142
+ end
143
+
144
+ it 'renders an input' do
145
+ aggregator.my_input(field, **arguments)
146
+
147
+ expect(renderer).to have_received(:render)
148
+ end
149
+
150
+ context 'when passing a custom model' do
151
+ let(:locals) do
152
+ {
153
+ field: field,
154
+ label: label,
155
+ ng_errors: 'my_custom_model.errors.field',
156
+ ng_model: 'my_custom_model.field',
157
+ placeholder: placeholder
158
+ }
159
+ end
160
+
161
+ it 'renders an input' do
162
+ aggregator.my_input(field, model: 'my_custom_model', **arguments)
163
+
164
+ expect(renderer).to have_received(:render)
165
+ end
166
+ end
167
+ end
168
+ end
169
+
170
+ context 'when setting element class and template' do
171
+ it do
172
+ expect do
173
+ aggregator_class.with_element(element_class, template: template)
174
+ end
175
+ .to add_method(:input)
176
+ .to(aggregator)
177
+ end
178
+
179
+ context 'when built method is called' do
180
+ let(:template) { 'my_templates/my_input' }
181
+ let(:field) { :field }
182
+ let(:label) { 'Label' }
183
+ let(:placeholder) { 'Value' }
184
+
185
+ let(:locals) do
186
+ {
187
+ field: field,
188
+ label: label,
189
+ ng_errors: 'my_model.errors.field',
190
+ ng_model: 'my_model.field',
191
+ placeholder: placeholder
192
+ }
193
+ end
194
+
195
+ let(:arguments) do
196
+ {
197
+ label: label,
198
+ placeholder: placeholder
199
+ }
200
+ end
201
+
202
+ before do
203
+ aggregator_class.with_element(element_class, template: template)
204
+
205
+ allow(renderer)
206
+ .to receive(:render)
207
+ .with(partial: template, locals: locals)
208
+ end
209
+
210
+ it 'renders an input' do
211
+ aggregator.input(field, **arguments)
212
+
213
+ expect(renderer).to have_received(:render)
214
+ end
215
+
216
+ context 'when passing a custom model' do
217
+ let(:locals) do
218
+ {
219
+ field: field,
220
+ label: label,
221
+ ng_errors: 'my_custom_model.errors.field',
222
+ ng_model: 'my_custom_model.field',
223
+ placeholder: placeholder
224
+ }
225
+ end
226
+
227
+ it 'renders an input' do
228
+ aggregator.input(field, model: 'my_custom_model', **arguments)
229
+
230
+ expect(renderer).to have_received(:render)
231
+ end
232
+ end
233
+ end
234
+ end
235
+
236
+ context 'when element class is defined with a string' do
237
+ let(:element_class) { 'Magicka::Input' }
238
+
239
+ it do
240
+ expect { aggregator_class.with_element(element_class) }
241
+ .to add_method(:input)
242
+ .to(aggregator)
243
+ end
244
+
245
+ context 'when built method is called' do
246
+ let(:template) { 'templates/forms/input' }
247
+ let(:field) { :field }
248
+ let(:label) { 'Label' }
249
+ let(:placeholder) { 'Value' }
250
+
251
+ let(:locals) do
252
+ {
253
+ field: field,
254
+ label: label,
255
+ ng_errors: 'my_model.errors.field',
256
+ ng_model: 'my_model.field',
257
+ placeholder: placeholder
258
+ }
259
+ end
260
+
261
+ let(:arguments) do
262
+ {
263
+ label: label,
264
+ placeholder: placeholder
265
+ }
266
+ end
267
+
268
+ before do
269
+ aggregator_class.with_element(element_class)
270
+
271
+ allow(renderer)
272
+ .to receive(:render)
273
+ .with(partial: template, locals: locals)
274
+ end
275
+
276
+ it 'renders an input' do
277
+ aggregator.input(field, **arguments)
278
+
279
+ expect(renderer).to have_received(:render)
280
+ end
281
+
282
+ context 'when passing a custom model' do
283
+ let(:locals) do
284
+ {
285
+ field: field,
286
+ label: label,
287
+ ng_errors: 'my_custom_model.errors.field',
288
+ ng_model: 'my_custom_model.field',
289
+ placeholder: placeholder
290
+ }
291
+ end
292
+
293
+ it 'renders an input' do
294
+ aggregator.input(field, model: 'my_custom_model', **arguments)
295
+
296
+ expect(renderer).to have_received(:render)
297
+ end
298
+ end
299
+ end
300
+ end
301
+
302
+ context 'when element class is defined with a string and the element loaded later' do
303
+ let(:element_class) { 'Magicka::SpecDefinedInput' }
304
+
305
+ it do
306
+ expect { aggregator_class.with_element(element_class, :input) }
307
+ .to add_method(:input)
308
+ .to(aggregator)
309
+ end
310
+
311
+ context 'when built method is called' do
312
+ let(:template) { 'templates/forms/my_input' }
313
+ let(:field) { :field }
314
+ let(:label) { 'Label' }
315
+ let(:placeholder) { 'Value' }
316
+
317
+ let(:locals) do
318
+ {
319
+ field: field,
320
+ label: label,
321
+ ng_errors: 'my_model.errors.field',
322
+ ng_model: 'my_model.field',
323
+ placeholder: placeholder
324
+ }
325
+ end
326
+
327
+ let(:arguments) do
328
+ {
329
+ label: label,
330
+ placeholder: placeholder
331
+ }
332
+ end
333
+
334
+ before do
335
+ aggregator_class.with_element(element_class, :input, template: template)
336
+
337
+ Magicka.const_set(:SpecDefinedInput, Class.new(Magicka::Input))
338
+
339
+ allow(renderer)
340
+ .to receive(:render)
341
+ .with(partial: template, locals: locals)
342
+ end
343
+
344
+ it 'renders an input' do
345
+ aggregator.input(field, **arguments)
346
+
347
+ expect(renderer).to have_received(:render)
348
+ end
349
+ end
350
+ end
351
+ end
352
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Magicka::Aggregator::MethodBuilder do
6
+ subject(:builder) do
7
+ aggregator_class.new(aggregator_class, element_class_arg)
8
+ end
9
+
10
+ let(:aggregator_class) { Class.new(described_class) }
11
+ let(:element_class_arg) { element_class }
12
+ let(:element_class) { Magicka::MyElement }
13
+
14
+ describe '#element_class' do
15
+ context 'when passing an element class' do
16
+ it do
17
+ expect(builder.element_class).to eq(element_class)
18
+ end
19
+ end
20
+
21
+ context 'when passing an element class name' do
22
+ let(:element_class_arg) { element_class.to_s }
23
+
24
+ it do
25
+ expect(builder.element_class).to eq(element_class)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -11,227 +11,6 @@ describe Magicka::Aggregator do
11
11
  let(:template) { 'templates/forms/input' }
12
12
  let(:locals) { {} }
13
13
 
14
- describe '.type' do
15
- let(:type) { %w[form display other].sample }
16
-
17
- it 'sets aggregator type' do
18
- expect { aggregator_class.type(type) }
19
- .to change(aggregator_class, :type)
20
- .from(nil).to(type.to_sym)
21
- end
22
-
23
- context 'when type has not been set' do
24
- let(:aggregator_class) do
25
- Class.new(described_class) do
26
- def self.name
27
- 'Magicka::MyClass'
28
- end
29
- end
30
- end
31
-
32
- it 'Uses class name as type' do
33
- expect(aggregator_class.type)
34
- .to eq(:my_class)
35
- end
36
- end
37
- end
38
-
39
- describe '.with_element' do
40
- context 'when seeting element class only' do
41
- it do
42
- expect { aggregator_class.with_element(Magicka::Input) }
43
- .to add_method(:input)
44
- .to(aggregator)
45
- end
46
-
47
- context 'when built method is called' do
48
- let(:template) { 'templates/forms/input' }
49
- let(:field) { :field }
50
- let(:label) { 'Label' }
51
- let(:placeholder) { 'Value' }
52
-
53
- let(:locals) do
54
- {
55
- field: field,
56
- label: label,
57
- ng_errors: 'my_model.errors.field',
58
- ng_model: 'my_model.field',
59
- placeholder: placeholder
60
- }
61
- end
62
-
63
- let(:arguments) do
64
- {
65
- label: label,
66
- placeholder: placeholder
67
- }
68
- end
69
-
70
- before do
71
- aggregator_class.with_element(Magicka::Input)
72
-
73
- allow(renderer)
74
- .to receive(:render)
75
- .with(partial: template, locals: locals)
76
- end
77
-
78
- it 'renders an input' do
79
- aggregator.input(field, **arguments)
80
-
81
- expect(renderer).to have_received(:render)
82
- end
83
-
84
- context 'when passing a custom model' do
85
- let(:locals) do
86
- {
87
- field: field,
88
- label: label,
89
- ng_errors: 'my_custom_model.errors.field',
90
- ng_model: 'my_custom_model.field',
91
- placeholder: placeholder
92
- }
93
- end
94
-
95
- it 'renders an input' do
96
- aggregator.input(field, model: 'my_custom_model', **arguments)
97
-
98
- expect(renderer).to have_received(:render)
99
- end
100
- end
101
- end
102
- end
103
-
104
- context 'when seeting element class and method' do
105
- it do
106
- expect { aggregator_class.with_element(Magicka::Input, :my_input) }
107
- .to add_method(:my_input)
108
- .to(aggregator)
109
- end
110
-
111
- context 'when built method is called' do
112
- let(:template) { 'templates/forms/input' }
113
- let(:field) { :field }
114
- let(:label) { 'Label' }
115
- let(:placeholder) { 'Value' }
116
-
117
- let(:locals) do
118
- {
119
- field: field,
120
- label: label,
121
- ng_errors: 'my_model.errors.field',
122
- ng_model: 'my_model.field',
123
- placeholder: placeholder
124
- }
125
- end
126
-
127
- let(:arguments) do
128
- {
129
- label: label,
130
- placeholder: placeholder
131
- }
132
- end
133
-
134
- before do
135
- aggregator_class.with_element(Magicka::Input, :my_input)
136
-
137
- allow(renderer)
138
- .to receive(:render)
139
- .with(partial: template, locals: locals)
140
- end
141
-
142
- it 'renders an input' do
143
- aggregator.my_input(field, **arguments)
144
-
145
- expect(renderer).to have_received(:render)
146
- end
147
-
148
- context 'when passing a custom model' do
149
- let(:locals) do
150
- {
151
- field: field,
152
- label: label,
153
- ng_errors: 'my_custom_model.errors.field',
154
- ng_model: 'my_custom_model.field',
155
- placeholder: placeholder
156
- }
157
- end
158
-
159
- it 'renders an input' do
160
- aggregator.my_input(field, model: 'my_custom_model', **arguments)
161
-
162
- expect(renderer).to have_received(:render)
163
- end
164
- end
165
- end
166
- end
167
-
168
- context 'when seeting element class and template' do
169
- it do
170
- expect do
171
- aggregator_class.with_element(Magicka::Input, template: template)
172
- end
173
- .to add_method(:input)
174
- .to(aggregator)
175
- end
176
-
177
- context 'when built method is called' do
178
- let(:template) { 'my_templates/my_input' }
179
- let(:field) { :field }
180
- let(:label) { 'Label' }
181
- let(:placeholder) { 'Value' }
182
-
183
- let(:locals) do
184
- {
185
- field: field,
186
- label: label,
187
- ng_errors: 'my_model.errors.field',
188
- ng_model: 'my_model.field',
189
- placeholder: placeholder
190
- }
191
- end
192
-
193
- let(:arguments) do
194
- {
195
- label: label,
196
- placeholder: placeholder
197
- }
198
- end
199
-
200
- before do
201
- aggregator_class.with_element(Magicka::Input, template: template)
202
-
203
- allow(renderer)
204
- .to receive(:render)
205
- .with(partial: template, locals: locals)
206
- end
207
-
208
- it 'renders an input' do
209
- aggregator.input(field, **arguments)
210
-
211
- expect(renderer).to have_received(:render)
212
- end
213
-
214
- context 'when passing a custom model' do
215
- let(:locals) do
216
- {
217
- field: field,
218
- label: label,
219
- ng_errors: 'my_custom_model.errors.field',
220
- ng_model: 'my_custom_model.field',
221
- placeholder: placeholder
222
- }
223
- end
224
-
225
- it 'renders an input' do
226
- aggregator.input(field, model: 'my_custom_model', **arguments)
227
-
228
- expect(renderer).to have_received(:render)
229
- end
230
- end
231
- end
232
- end
233
- end
234
-
235
14
  describe '#with_model' do
236
15
  let(:expected_aggregator) do
237
16
  aggregator_class.new(renderer, 'my_model.inner')
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Magicka::Helper::AggregatorOptions do
6
+ subject(:options) { described_class.new(options_hash) }
7
+
8
+ let(:options_hash) do
9
+ {
10
+ aggregator: aggregator,
11
+ type: type,
12
+ config_block: config_block
13
+ }
14
+ end
15
+
16
+ let(:aggregator_class) { Class.new(Magicka::Aggregator) }
17
+ let(:aggregator) { aggregator_class }
18
+ let(:type) { :my_aggregator }
19
+ let(:config_block) do
20
+ proc { with_element(Magicka::Input) }
21
+ end
22
+
23
+ describe '#configured_aggregator' do
24
+ let(:renderer) { instance_double(ActionView::OutputBuffer) }
25
+ let(:model) { Object.new }
26
+ let(:element_class) { Magicka::Input }
27
+
28
+ before do
29
+ allow(element_class).to receive(:render).with(
30
+ renderer: renderer,
31
+ field: :name,
32
+ model: model,
33
+ template: nil
34
+ )
35
+ end
36
+
37
+ context 'when aggregator is a class' do
38
+ context 'when config block is given' do
39
+ it 'returns the given aggregator class' do
40
+ expect(options.configured_aggregator)
41
+ .to be(aggregator)
42
+ end
43
+
44
+ it 'configure the aggregator' do
45
+ options.configured_aggregator.new(renderer, model)
46
+ .input(:name)
47
+
48
+ expect(element_class).to have_received(:render)
49
+ end
50
+ end
51
+
52
+ context 'when config block is not given' do
53
+ let(:config_block) { nil }
54
+
55
+ it 'returns the given aggregator class' do
56
+ expect(options.configured_aggregator)
57
+ .to be(aggregator)
58
+ end
59
+ end
60
+ end
61
+
62
+ context 'when aggregator is a String' do
63
+ let(:aggregator) { "Magicka::#{aggregator_name}" }
64
+ let(:aggregator_name) { :CustomAggregator }
65
+
66
+ before { Magicka.const_set(aggregator_name, aggregator_class) }
67
+
68
+ context 'when config block is given' do
69
+ let(:aggregator_name) { :CustomAggregator1 }
70
+
71
+ it 'returns the given aggregator class' do
72
+ expect(options.configured_aggregator)
73
+ .to be(aggregator_class)
74
+ end
75
+ end
76
+
77
+ context 'when config block is given and is called' do
78
+ let(:aggregator_name) { :CustomAggregator2 }
79
+
80
+ it 'configure the aggregator' do
81
+ options.configured_aggregator.new(renderer, model)
82
+ .input(:name)
83
+
84
+ expect(element_class).to have_received(:render)
85
+ end
86
+ end
87
+
88
+ context 'when config block is not given' do
89
+ let(:aggregator_name) { :CustomAggregator3 }
90
+ let(:config_block) { nil }
91
+
92
+ it 'returns the given aggregator class' do
93
+ expect(options.configured_aggregator)
94
+ .to be(aggregator_class)
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end