drape 1.0.0.beta1

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 (181) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +27 -0
  3. data/.gitignore +18 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +1159 -0
  6. data/.travis.yml +14 -0
  7. data/.yardopts +1 -0
  8. data/CHANGELOG.md +230 -0
  9. data/CONTRIBUTING.md +20 -0
  10. data/Gemfile +16 -0
  11. data/Guardfile +26 -0
  12. data/LICENSE +7 -0
  13. data/README.md +592 -0
  14. data/Rakefile +76 -0
  15. data/drape.gemspec +31 -0
  16. data/gemfiles/5.0.gemfile +8 -0
  17. data/lib/drape.rb +63 -0
  18. data/lib/drape/automatic_delegation.rb +55 -0
  19. data/lib/drape/collection_decorator.rb +102 -0
  20. data/lib/drape/decoratable.rb +93 -0
  21. data/lib/drape/decoratable/equality.rb +26 -0
  22. data/lib/drape/decorated_association.rb +33 -0
  23. data/lib/drape/decorates_assigned.rb +44 -0
  24. data/lib/drape/decorator.rb +282 -0
  25. data/lib/drape/delegation.rb +13 -0
  26. data/lib/drape/factory.rb +91 -0
  27. data/lib/drape/finders.rb +36 -0
  28. data/lib/drape/helper_proxy.rb +43 -0
  29. data/lib/drape/helper_support.rb +5 -0
  30. data/lib/drape/lazy_helpers.rb +13 -0
  31. data/lib/drape/railtie.rb +69 -0
  32. data/lib/drape/tasks/test.rake +9 -0
  33. data/lib/drape/test/devise_helper.rb +30 -0
  34. data/lib/drape/test/minitest_integration.rb +6 -0
  35. data/lib/drape/test/rspec_integration.rb +20 -0
  36. data/lib/drape/test_case.rb +42 -0
  37. data/lib/drape/undecorate.rb +9 -0
  38. data/lib/drape/version.rb +3 -0
  39. data/lib/drape/view_context.rb +104 -0
  40. data/lib/drape/view_context/build_strategy.rb +46 -0
  41. data/lib/drape/view_helpers.rb +34 -0
  42. data/lib/generators/controller_override.rb +17 -0
  43. data/lib/generators/mini_test/decorator_generator.rb +20 -0
  44. data/lib/generators/mini_test/templates/decorator_spec.rb +4 -0
  45. data/lib/generators/mini_test/templates/decorator_test.rb +4 -0
  46. data/lib/generators/rails/decorator_generator.rb +36 -0
  47. data/lib/generators/rails/templates/decorator.rb +19 -0
  48. data/lib/generators/rspec/decorator_generator.rb +9 -0
  49. data/lib/generators/rspec/templates/decorator_spec.rb +4 -0
  50. data/lib/generators/test_unit/decorator_generator.rb +9 -0
  51. data/lib/generators/test_unit/templates/decorator_test.rb +4 -0
  52. data/spec/draper/collection_decorator_spec.rb +305 -0
  53. data/spec/draper/decoratable/equality_spec.rb +10 -0
  54. data/spec/draper/decoratable_spec.rb +203 -0
  55. data/spec/draper/decorated_association_spec.rb +85 -0
  56. data/spec/draper/decorates_assigned_spec.rb +70 -0
  57. data/spec/draper/decorator_spec.rb +828 -0
  58. data/spec/draper/factory_spec.rb +250 -0
  59. data/spec/draper/finders_spec.rb +165 -0
  60. data/spec/draper/helper_proxy_spec.rb +61 -0
  61. data/spec/draper/lazy_helpers_spec.rb +21 -0
  62. data/spec/draper/undecorate_spec.rb +19 -0
  63. data/spec/draper/view_context/build_strategy_spec.rb +116 -0
  64. data/spec/draper/view_context_spec.rb +160 -0
  65. data/spec/draper/view_helpers_spec.rb +8 -0
  66. data/spec/dummy/.gitignore +21 -0
  67. data/spec/dummy/Rakefile +6 -0
  68. data/spec/dummy/app/assets/config/manifest.js +3 -0
  69. data/spec/dummy/app/assets/images/.keep +0 -0
  70. data/spec/dummy/app/assets/javascripts/application.js +16 -0
  71. data/spec/dummy/app/assets/javascripts/cable.js +13 -0
  72. data/spec/dummy/app/assets/javascripts/channels/.keep +0 -0
  73. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  74. data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
  75. data/spec/dummy/app/channels/application_cable/connection.rb +5 -0
  76. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  77. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  78. data/spec/dummy/app/controllers/posts_controller.rb +21 -0
  79. data/spec/dummy/app/decorators/mongoid_post_decorator.rb +4 -0
  80. data/spec/dummy/app/decorators/post_decorator.rb +59 -0
  81. data/spec/dummy/app/helpers/application_helper.rb +5 -0
  82. data/spec/dummy/app/jobs/application_job.rb +2 -0
  83. data/spec/dummy/app/mailers/application_mailer.rb +4 -0
  84. data/spec/dummy/app/mailers/post_mailer.rb +18 -0
  85. data/spec/dummy/app/models/admin.rb +5 -0
  86. data/spec/dummy/app/models/application_record.rb +3 -0
  87. data/spec/dummy/app/models/concerns/.keep +0 -0
  88. data/spec/dummy/app/models/mongoid_post.rb +5 -0
  89. data/spec/dummy/app/models/post.rb +3 -0
  90. data/spec/dummy/app/models/user.rb +5 -0
  91. data/spec/dummy/app/views/layouts/application.html.erb +9 -0
  92. data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
  93. data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
  94. data/spec/dummy/app/views/post_mailer/decorated_email.html.erb +31 -0
  95. data/spec/dummy/app/views/posts/_post.html.erb +40 -0
  96. data/spec/dummy/app/views/posts/show.html.erb +1 -0
  97. data/spec/dummy/bin/bundle +3 -0
  98. data/spec/dummy/bin/rails +9 -0
  99. data/spec/dummy/bin/rake +9 -0
  100. data/spec/dummy/bin/setup +34 -0
  101. data/spec/dummy/bin/spring +15 -0
  102. data/spec/dummy/bin/update +29 -0
  103. data/spec/dummy/config.ru +5 -0
  104. data/spec/dummy/config/application.rb +21 -0
  105. data/spec/dummy/config/boot.rb +2 -0
  106. data/spec/dummy/config/cable.yml +10 -0
  107. data/spec/dummy/config/database.yml +25 -0
  108. data/spec/dummy/config/environment.rb +5 -0
  109. data/spec/dummy/config/environments/development.rb +51 -0
  110. data/spec/dummy/config/environments/production.rb +91 -0
  111. data/spec/dummy/config/environments/test.rb +42 -0
  112. data/spec/dummy/config/initializers/active_record_belongs_to_required_by_default.rb +6 -0
  113. data/spec/dummy/config/initializers/application_controller_renderer.rb +6 -0
  114. data/spec/dummy/config/initializers/assets.rb +11 -0
  115. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  116. data/spec/dummy/config/initializers/callback_terminator.rb +6 -0
  117. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  118. data/spec/dummy/config/initializers/devise.rb +3 -0
  119. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  120. data/spec/dummy/config/initializers/inflections.rb +16 -0
  121. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  122. data/spec/dummy/config/initializers/per_form_csrf_tokens.rb +4 -0
  123. data/spec/dummy/config/initializers/request_forgery_protection.rb +4 -0
  124. data/spec/dummy/config/initializers/session_store.rb +3 -0
  125. data/spec/dummy/config/initializers/ssl_options.rb +4 -0
  126. data/spec/dummy/config/initializers/to_time_preserves_timezone.rb +10 -0
  127. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  128. data/spec/dummy/config/locales/en.yml +23 -0
  129. data/spec/dummy/config/mongoid.yml +16 -0
  130. data/spec/dummy/config/puma.rb +47 -0
  131. data/spec/dummy/config/routes.rb +8 -0
  132. data/spec/dummy/config/secrets.yml +22 -0
  133. data/spec/dummy/config/spring.rb +6 -0
  134. data/spec/dummy/db/migrate/20121019115657_create_posts.rb +7 -0
  135. data/spec/dummy/db/schema.rb +19 -0
  136. data/spec/dummy/db/seeds.rb +2 -0
  137. data/spec/dummy/lib/assets/.keep +0 -0
  138. data/spec/dummy/lib/tasks/.keep +0 -0
  139. data/spec/dummy/lib/tasks/test.rake +16 -0
  140. data/spec/dummy/log/.keep +0 -0
  141. data/spec/dummy/public/404.html +67 -0
  142. data/spec/dummy/public/422.html +67 -0
  143. data/spec/dummy/public/500.html +66 -0
  144. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  145. data/spec/dummy/public/apple-touch-icon.png +0 -0
  146. data/spec/dummy/public/favicon.ico +0 -0
  147. data/spec/dummy/public/robots.txt +5 -0
  148. data/spec/dummy/spec/decorators/active_model_serializers_spec.rb +12 -0
  149. data/spec/dummy/spec/decorators/devise_spec.rb +64 -0
  150. data/spec/dummy/spec/decorators/helpers_spec.rb +21 -0
  151. data/spec/dummy/spec/decorators/post_decorator_spec.rb +66 -0
  152. data/spec/dummy/spec/decorators/spec_type_spec.rb +7 -0
  153. data/spec/dummy/spec/decorators/view_context_spec.rb +22 -0
  154. data/spec/dummy/spec/mailers/post_mailer_spec.rb +33 -0
  155. data/spec/dummy/spec/models/mongoid_post_spec.rb +8 -0
  156. data/spec/dummy/spec/models/post_spec.rb +6 -0
  157. data/spec/dummy/spec/shared_examples/decoratable.rb +26 -0
  158. data/spec/dummy/spec/spec_helper.rb +8 -0
  159. data/spec/dummy/test/controllers/.keep +0 -0
  160. data/spec/dummy/test/fixtures/.keep +0 -0
  161. data/spec/dummy/test/fixtures/files/.keep +0 -0
  162. data/spec/dummy/test/helpers/.keep +0 -0
  163. data/spec/dummy/test/integration/.keep +0 -0
  164. data/spec/dummy/test/mailers/.keep +0 -0
  165. data/spec/dummy/test/models/.keep +0 -0
  166. data/spec/dummy/test/test_helper.rb +10 -0
  167. data/spec/dummy/vendor/assets/javascripts/.keep +0 -0
  168. data/spec/dummy/vendor/assets/stylesheets/.keep +0 -0
  169. data/spec/generators/controller/controller_generator_spec.rb +24 -0
  170. data/spec/generators/decorator/decorator_generator_spec.rb +94 -0
  171. data/spec/integration/integration_spec.rb +68 -0
  172. data/spec/performance/active_record.rb +4 -0
  173. data/spec/performance/benchmark.rb +57 -0
  174. data/spec/performance/decorators.rb +41 -0
  175. data/spec/performance/models.rb +20 -0
  176. data/spec/spec_helper.rb +41 -0
  177. data/spec/support/dummy_app.rb +88 -0
  178. data/spec/support/matchers/have_text.rb +50 -0
  179. data/spec/support/shared_examples/decoratable_equality.rb +40 -0
  180. data/spec/support/shared_examples/view_helpers.rb +39 -0
  181. metadata +497 -0
@@ -0,0 +1,250 @@
1
+ require 'spec_helper'
2
+
3
+ module Drape
4
+ describe Factory do
5
+ describe '#initialize' do
6
+ it 'accepts valid options' do
7
+ valid_options = { with: Decorator, context: { foo: 'bar' } }
8
+ expect { Factory.new(valid_options) }.not_to raise_error
9
+ end
10
+
11
+ it 'rejects invalid options' do
12
+ expect { Factory.new(foo: 'bar') }.to raise_error ArgumentError, /Unknown key/
13
+ end
14
+ end
15
+
16
+ describe '#decorate' do
17
+ context 'when object is nil' do
18
+ it 'returns nil' do
19
+ factory = Factory.new
20
+
21
+ expect(factory.decorate(nil)).to be_nil
22
+ end
23
+ end
24
+
25
+ it 'calls a worker' do
26
+ factory = Factory.new
27
+ worker = ->(*) { :decorated }
28
+
29
+ Factory::Worker.should_receive(:new).and_return(worker)
30
+ expect(factory.decorate(double)).to be :decorated
31
+ end
32
+
33
+ it 'passes the object to the worker' do
34
+ factory = Factory.new
35
+ object = double
36
+
37
+ Factory::Worker.should_receive(:new).with(anything, object).and_return(->(*) {})
38
+ factory.decorate(object)
39
+ end
40
+
41
+ context 'when the :with option was given' do
42
+ it 'passes the decorator class to the worker' do
43
+ decorator_class = double
44
+ factory = Factory.new(with: decorator_class)
45
+
46
+ Factory::Worker.should_receive(:new).with(decorator_class, anything).and_return(->(*) {})
47
+ factory.decorate(double)
48
+ end
49
+ end
50
+
51
+ context 'when the :with option was omitted' do
52
+ it 'passes nil to the worker' do
53
+ factory = Factory.new
54
+
55
+ Factory::Worker.should_receive(:new).with(nil, anything).and_return(->(*) {})
56
+ factory.decorate(double)
57
+ end
58
+ end
59
+
60
+ it 'passes options to the call' do
61
+ factory = Factory.new
62
+ worker = ->(*) {}
63
+ Factory::Worker.stub new: worker
64
+ options = { foo: 'bar' }
65
+
66
+ worker.should_receive(:call).with(options)
67
+ factory.decorate(double, options)
68
+ end
69
+
70
+ context 'when the :context option was given' do
71
+ it 'sets the passed context' do
72
+ factory = Factory.new(context: { foo: 'bar' })
73
+ worker = ->(*) {}
74
+ Factory::Worker.stub new: worker
75
+
76
+ worker.should_receive(:call).with(baz: 'qux', context: { foo: 'bar' })
77
+ factory.decorate(double, { baz: 'qux' })
78
+ end
79
+
80
+ it 'is overridden by explicitly-specified context' do
81
+ factory = Factory.new(context: { foo: 'bar' })
82
+ worker = ->(*) {}
83
+ Factory::Worker.stub new: worker
84
+
85
+ worker.should_receive(:call).with(context: { baz: 'qux' })
86
+ factory.decorate(double, context: { baz: 'qux' })
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ describe Factory::Worker do
93
+ describe '#call' do
94
+ it 'calls the decorator method' do
95
+ object = double
96
+ options = { foo: 'bar' }
97
+ worker = Factory::Worker.new(double, object)
98
+ decorator = ->(*) {}
99
+ allow(worker).to receive(:decorator) { decorator }
100
+
101
+ decorator.should_receive(:call).with(object, options).and_return(:decorated)
102
+ expect(worker.call(options)).to be :decorated
103
+ end
104
+
105
+ context 'when the :context option is callable' do
106
+ it 'calls it' do
107
+ worker = Factory::Worker.new(double, double)
108
+ decorator = ->(*) {}
109
+ worker.stub decorator: decorator
110
+ context = { foo: 'bar' }
111
+
112
+ decorator.should_receive(:call).with(anything, context: context)
113
+ worker.call(context: -> { context })
114
+ end
115
+
116
+ it 'receives arguments from the :context_args option' do
117
+ worker = Factory::Worker.new(double, double)
118
+ worker.stub decorator: ->(*) {}
119
+ context = -> {}
120
+
121
+ context.should_receive(:call).with(:foo, :bar)
122
+ worker.call(context: context, context_args: [:foo, :bar])
123
+ end
124
+
125
+ it 'wraps non-arrays passed to :context_args' do
126
+ worker = Factory::Worker.new(double, double)
127
+ worker.stub decorator: ->(*) {}
128
+ context = -> {}
129
+ hash = { foo: 'bar' }
130
+
131
+ context.should_receive(:call).with(hash)
132
+ worker.call(context: context, context_args: hash)
133
+ end
134
+ end
135
+
136
+ context 'when the :context option is not callable' do
137
+ it "doesn't call it" do
138
+ worker = Factory::Worker.new(double, double)
139
+ decorator = ->(*) {}
140
+ worker.stub decorator: decorator
141
+ context = { foo: 'bar' }
142
+
143
+ decorator.should_receive(:call).with(anything, context: context)
144
+ worker.call(context: context)
145
+ end
146
+ end
147
+
148
+ it 'does not pass the :context_args option to the decorator' do
149
+ worker = Factory::Worker.new(double, double)
150
+ decorator = ->(*) {}
151
+ worker.stub decorator: decorator
152
+
153
+ decorator.should_receive(:call).with(anything, foo: 'bar')
154
+ worker.call(foo: 'bar', context_args: [])
155
+ end
156
+ end
157
+
158
+ describe '#decorator' do
159
+ context 'for a singular object' do
160
+ context 'when decorator_class is specified' do
161
+ it 'returns the .decorate method from the decorator' do
162
+ decorator_class = Class.new(Decorator)
163
+ worker = Factory::Worker.new(decorator_class, double)
164
+
165
+ expect(worker.decorator).to eq decorator_class.method(:decorate)
166
+ end
167
+ end
168
+
169
+ context 'when decorator_class is unspecified' do
170
+ context 'and the object is decoratable' do
171
+ it "returns the object's #decorate method" do
172
+ object = double
173
+ options = { foo: 'bar' }
174
+ worker = Factory::Worker.new(nil, object)
175
+
176
+ object.should_receive(:decorate).with(options).and_return(:decorated)
177
+ expect(worker.decorator.call(object, options)).to be :decorated
178
+ end
179
+ end
180
+
181
+ context 'and the object is not decoratable' do
182
+ it 'raises an error' do
183
+ object = double
184
+ worker = Factory::Worker.new(nil, object)
185
+
186
+ expect { worker.decorator }.to raise_error UninferrableDecoratorError
187
+ end
188
+ end
189
+ end
190
+
191
+ context 'when the object is a struct' do
192
+ it 'returns a singular decorator' do
193
+ object = Struct.new(:stuff).new('things')
194
+
195
+ decorator_class = Class.new(Decorator)
196
+ worker = Factory::Worker.new(decorator_class, object)
197
+
198
+ expect(worker.decorator).to eq decorator_class.method(:decorate)
199
+ end
200
+ end
201
+ end
202
+
203
+ context 'for a collection object' do
204
+ context 'when decorator_class is a CollectionDecorator' do
205
+ it 'returns the .decorate method from the collection decorator' do
206
+ decorator_class = Class.new(CollectionDecorator)
207
+ worker = Factory::Worker.new(decorator_class, [])
208
+
209
+ expect(worker.decorator).to eq decorator_class.method(:decorate)
210
+ end
211
+ end
212
+
213
+ context 'when decorator_class is a Decorator' do
214
+ it 'returns the .decorate_collection method from the decorator' do
215
+ decorator_class = Class.new(Decorator)
216
+ worker = Factory::Worker.new(decorator_class, [])
217
+
218
+ expect(worker.decorator).to eq decorator_class.method(:decorate_collection)
219
+ end
220
+ end
221
+
222
+ context 'when decorator_class is unspecified' do
223
+ context 'and the object is decoratable' do
224
+ it "returns the .decorate_collection method from the object's decorator" do
225
+ object = []
226
+ decorator_class = Class.new(Decorator)
227
+ allow(object).to receive(:decorator_class) { decorator_class }
228
+ allow(object).to receive(:decorate) { nil }
229
+ worker = Factory::Worker.new(nil, object)
230
+
231
+ decorator_class
232
+ .should_receive(:decorate_collection).with(object, foo: 'bar', with: nil)
233
+ .and_return(:decorated)
234
+
235
+ expect(worker.decorator.call(object, foo: 'bar')).to be :decorated
236
+ end
237
+ end
238
+
239
+ context 'and the object is not decoratable' do
240
+ it 'returns the .decorate method from CollectionDecorator' do
241
+ worker = Factory::Worker.new(nil, [])
242
+
243
+ expect(worker.decorator).to eq CollectionDecorator.method(:decorate)
244
+ end
245
+ end
246
+ end
247
+ end
248
+ end
249
+ end
250
+ end
@@ -0,0 +1,165 @@
1
+ require 'spec_helper'
2
+
3
+ module Drape
4
+ describe Finders do
5
+ protect_class ProductDecorator
6
+ before { ProductDecorator.decorates_finders }
7
+
8
+ describe '.find' do
9
+ it 'proxies to the model class' do
10
+ Product.should_receive(:find).with(1)
11
+ ProductDecorator.find(1)
12
+ end
13
+
14
+ it 'decorates the result' do
15
+ found = Product.new
16
+ Product.stub(:find).and_return(found)
17
+ decorator = ProductDecorator.find(1)
18
+ expect(decorator).to be_a ProductDecorator
19
+ expect(decorator.object).to be found
20
+ end
21
+
22
+ it 'passes context to the decorator' do
23
+ Product.stub(:find)
24
+ context = { some: 'context' }
25
+ decorator = ProductDecorator.find(1, context: context)
26
+
27
+ expect(decorator.context).to be context
28
+ end
29
+ end
30
+
31
+ describe '.find_by_(x)' do
32
+ it 'proxies to the model class' do
33
+ Product.should_receive(:find_by_name).with('apples')
34
+ ProductDecorator.find_by_name('apples')
35
+ end
36
+
37
+ it 'decorates the result' do
38
+ found = Product.new
39
+ Product.stub(:find_by_name).and_return(found)
40
+ decorator = ProductDecorator.find_by_name('apples')
41
+ expect(decorator).to be_a ProductDecorator
42
+ expect(decorator.object).to be found
43
+ end
44
+
45
+ it 'proxies complex ProductDecorators' do
46
+ Product.should_receive(:find_by_name_and_size).with('apples', 'large')
47
+ ProductDecorator.find_by_name_and_size('apples', 'large')
48
+ end
49
+
50
+ it 'proxies find_last_by_(x) ProductDecorators' do
51
+ Product.should_receive(:find_last_by_name_and_size).with('apples', 'large')
52
+ ProductDecorator.find_last_by_name_and_size('apples', 'large')
53
+ end
54
+
55
+ it 'proxies find_or_initialize_by_(x) ProductDecorators' do
56
+ Product.should_receive(:find_or_initialize_by_name_and_size).with('apples', 'large')
57
+ ProductDecorator.find_or_initialize_by_name_and_size('apples', 'large')
58
+ end
59
+
60
+ it 'proxies find_or_create_by_(x) ProductDecorators' do
61
+ Product.should_receive(:find_or_create_by_name_and_size).with('apples', 'large')
62
+ ProductDecorator.find_or_create_by_name_and_size('apples', 'large')
63
+ end
64
+
65
+ it 'passes context to the decorator' do
66
+ Product.stub(:find_by_name_and_size)
67
+ context = { some: 'context' }
68
+ decorator = ProductDecorator.find_by_name_and_size('apples', 'large', context: context)
69
+
70
+ expect(decorator.context).to be context
71
+ end
72
+ end
73
+
74
+ describe '.find_all_by_' do
75
+ it 'proxies to the model class' do
76
+ Product.should_receive(:find_all_by_name_and_size).with('apples', 'large').and_return([])
77
+ ProductDecorator.find_all_by_name_and_size('apples', 'large')
78
+ end
79
+
80
+ it 'decorates the result' do
81
+ found = [Product.new, Product.new]
82
+ Product.stub(:find_all_by_name).and_return(found)
83
+ decorator = ProductDecorator.find_all_by_name('apples')
84
+
85
+ expect(decorator).to be_a Drape::CollectionDecorator
86
+ expect(decorator.decorator_class).to be ProductDecorator
87
+ expect(decorator).to eq found
88
+ end
89
+
90
+ it 'passes context to the decorator' do
91
+ Product.stub(:find_all_by_name)
92
+ context = { some: 'context' }
93
+ decorator = ProductDecorator.find_all_by_name('apples', context: context)
94
+
95
+ expect(decorator.context).to be context
96
+ end
97
+ end
98
+
99
+ describe '.all' do
100
+ it 'returns a decorated collection' do
101
+ found = [Product.new, Product.new]
102
+ Product.stub all: found
103
+ decorator = ProductDecorator.all
104
+
105
+ expect(decorator).to be_a Drape::CollectionDecorator
106
+ expect(decorator.decorator_class).to be ProductDecorator
107
+ expect(decorator).to eq found
108
+ end
109
+
110
+ it 'passes context to the decorator' do
111
+ Product.stub(:all)
112
+ context = { some: 'context' }
113
+ decorator = ProductDecorator.all(context: context)
114
+
115
+ expect(decorator.context).to be context
116
+ end
117
+ end
118
+
119
+ describe '.first' do
120
+ it 'proxies to the model class' do
121
+ Product.should_receive(:first)
122
+ ProductDecorator.first
123
+ end
124
+
125
+ it 'decorates the result' do
126
+ first = Product.new
127
+ Product.stub(:first).and_return(first)
128
+ decorator = ProductDecorator.first
129
+ expect(decorator).to be_a ProductDecorator
130
+ expect(decorator.object).to be first
131
+ end
132
+
133
+ it 'passes context to the decorator' do
134
+ Product.stub(:first)
135
+ context = { some: 'context' }
136
+ decorator = ProductDecorator.first(context: context)
137
+
138
+ expect(decorator.context).to be context
139
+ end
140
+ end
141
+
142
+ describe '.last' do
143
+ it 'proxies to the model class' do
144
+ Product.should_receive(:last)
145
+ ProductDecorator.last
146
+ end
147
+
148
+ it 'decorates the result' do
149
+ last = Product.new
150
+ Product.stub(:last).and_return(last)
151
+ decorator = ProductDecorator.last
152
+ expect(decorator).to be_a ProductDecorator
153
+ expect(decorator.object).to be last
154
+ end
155
+
156
+ it 'passes context to the decorator' do
157
+ Product.stub(:last)
158
+ context = { some: 'context' }
159
+ decorator = ProductDecorator.last(context: context)
160
+
161
+ expect(decorator.context).to be context
162
+ end
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ module Drape
4
+ describe HelperProxy do
5
+ describe '#initialize' do
6
+ it 'sets the view context' do
7
+ view_context = double
8
+ helper_proxy = HelperProxy.new(view_context)
9
+
10
+ expect(helper_proxy.send(:view_context)).to be view_context
11
+ end
12
+ end
13
+
14
+ describe '#method_missing' do
15
+ protect_class HelperProxy
16
+
17
+ it 'proxies methods to the view context' do
18
+ view_context = double
19
+ helper_proxy = HelperProxy.new(view_context)
20
+
21
+ view_context.stub(:foo) { |arg| arg }
22
+ expect(helper_proxy.foo(:passed)).to be :passed
23
+ end
24
+
25
+ it 'passes blocks' do
26
+ view_context = double
27
+ helper_proxy = HelperProxy.new(view_context)
28
+
29
+ view_context.stub(:foo) { |&block| block.call }
30
+ expect(helper_proxy.foo { :yielded }).to be :yielded
31
+ end
32
+
33
+ it 'defines the method for better performance' do
34
+ helper_proxy = HelperProxy.new(double(foo: 'bar'))
35
+
36
+ expect(HelperProxy.instance_methods).not_to include :foo
37
+ helper_proxy.foo
38
+ expect(HelperProxy.instance_methods).to include :foo
39
+ end
40
+ end
41
+
42
+ describe '#respond_to_missing?' do
43
+ it 'allows #method to be called on the view context' do
44
+ helper_proxy = HelperProxy.new(double(foo: 'bar'))
45
+
46
+ expect(helper_proxy.respond_to?(:foo)).to be_truthy
47
+ end
48
+ end
49
+
50
+ describe 'proxying methods which are overriding' do
51
+ it 'proxies :capture' do
52
+ view_context = double
53
+ helper_proxy = HelperProxy.new(view_context)
54
+
55
+ allow(view_context).to receive(:capture) { |*args, &block| [*args, block.call] }
56
+ expect(helper_proxy.capture(:first_arg, :second_arg) { :yielded })
57
+ .to be_eql [:first_arg, :second_arg, :yielded]
58
+ end
59
+ end
60
+ end
61
+ end