radiant-shop_packages-extension 0.0.1

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 (56) hide show
  1. data/.gitignore +2 -0
  2. data/README +3 -0
  3. data/Rakefile +138 -0
  4. data/VERSION +1 -0
  5. data/app/controllers/.DS_Store +0 -0
  6. data/app/controllers/admin/shop/packages/packings_controller.rb +90 -0
  7. data/app/controllers/admin/shop/packages_controller.rb +63 -0
  8. data/app/datasets/shop_packages.rb +25 -0
  9. data/app/models/shop_package.rb +79 -0
  10. data/app/models/shop_packing.rb +22 -0
  11. data/app/views/admin/shop/packages/edit.html.haml +11 -0
  12. data/app/views/admin/shop/packages/edit/_foot.html.haml +17 -0
  13. data/app/views/admin/shop/packages/edit/_form.html.haml +15 -0
  14. data/app/views/admin/shop/packages/edit/_head.html.haml +4 -0
  15. data/app/views/admin/shop/packages/edit/_inputs.html.haml +2 -0
  16. data/app/views/admin/shop/packages/edit/_meta.html.haml +8 -0
  17. data/app/views/admin/shop/packages/edit/_parts.html.haml +9 -0
  18. data/app/views/admin/shop/packages/edit/_popups.html.haml +4 -0
  19. data/app/views/admin/shop/packages/edit/buttons/_browse_products.html.haml +1 -0
  20. data/app/views/admin/shop/packages/edit/inputs/_name.html.haml +3 -0
  21. data/app/views/admin/shop/packages/edit/inputs/_price.html.haml +3 -0
  22. data/app/views/admin/shop/packages/edit/meta/_sku.html.haml +5 -0
  23. data/app/views/admin/shop/packages/edit/parts/_description.html.haml +1 -0
  24. data/app/views/admin/shop/packages/edit/parts/_products.html.haml +3 -0
  25. data/app/views/admin/shop/packages/edit/popups/_browse_products.html.haml +7 -0
  26. data/app/views/admin/shop/packages/edit/shared/_product.html.haml +8 -0
  27. data/app/views/admin/shop/packages/index.html.haml +13 -0
  28. data/app/views/admin/shop/packages/index/_foot.html.haml +8 -0
  29. data/app/views/admin/shop/packages/index/_head.html.haml +2 -0
  30. data/app/views/admin/shop/packages/index/_package.html.haml +9 -0
  31. data/app/views/admin/shop/packages/index/buttons/_new_package.html.haml +1 -0
  32. data/app/views/admin/shop/packages/new.html.haml +11 -0
  33. data/app/views/admin/shop/packages/remove.html.haml +12 -0
  34. data/config/locales/en.yml +11 -0
  35. data/config/routes.rb +13 -0
  36. data/cucumber.yml +1 -0
  37. data/db/migrate/20101015161749_setup_shop_packages.rb +27 -0
  38. data/lib/shop_packages/interface/packages.rb +34 -0
  39. data/lib/shop_packages/models/shop_packageable.rb +15 -0
  40. data/lib/shop_packages/tags/helpers.rb +41 -0
  41. data/lib/shop_packages/tags/package.rb +94 -0
  42. data/lib/tasks/shop_packages_extension_tasks.rake +55 -0
  43. data/public/javascripts/admin/extensions/shop/packages/edit.js +109 -0
  44. data/public/stylesheets/sass/admin/extensions/shop/packages/edit.sass +162 -0
  45. data/radiant-shop_packages-extension.gemspec +104 -0
  46. data/shop_packages_extension.rb +37 -0
  47. data/spec/controllers/admin/shop/packages/packings_controller_spec.rb +188 -0
  48. data/spec/controllers/admin/shop/packages_controller_spec.rb +32 -0
  49. data/spec/datasets/shop_packages.rb +23 -0
  50. data/spec/lib/shop_packages/tags/package_spec.rb +348 -0
  51. data/spec/models/shop_package_spec.rb +117 -0
  52. data/spec/models/shop_packing_spec.rb +67 -0
  53. data/spec/models/shop_product_spec.rb +25 -0
  54. data/spec/spec.opts +4 -0
  55. data/spec/spec_helper.rb +23 -0
  56. metadata +141 -0
@@ -0,0 +1,188 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe Admin::Shop::Packages::PackingsController do
4
+
5
+ dataset :users
6
+
7
+ before(:each) do
8
+ login_as :admin
9
+
10
+ @shop_package = ShopPackage.new
11
+ @shop_packages = [ @shop_package ]
12
+
13
+ @shop_product = ShopProduct.new
14
+ @shop_products = [ @shop_product ]
15
+
16
+ @shop_packing = ShopPacking.new
17
+ @shop_packings = [ @shop_packing ]
18
+
19
+ stub(@shop_package).id { 1 }
20
+ stub(@shop_package).packings { @shop_packings }
21
+ end
22
+
23
+ describe '#sort' do
24
+ before :each do
25
+ @packings = [
26
+ 'package_products[]=2',
27
+ 'package_products[]=1'
28
+ ].join('&')
29
+ end
30
+
31
+ context 'packings are not passed' do
32
+ context 'js' do
33
+ it 'should return an error string and failure status' do
34
+ put :sort, :package_id => 1, :format => 'js'
35
+
36
+ response.should_not be_success
37
+ response.body.should === "Could not sort products."
38
+ end
39
+ end
40
+ end
41
+
42
+ context 'categories are passed' do
43
+ context 'could not sort' do
44
+ before :each do
45
+ mock(ShopPacking).find('2').stub!.update_attributes!({:position,1}) { raise ActiveRecord::RecordNotSaved }
46
+ end
47
+
48
+ context 'js' do
49
+ it 'should return an error string and failure status' do
50
+ put :sort, :package_id => 1, :packings => @packings, :format => 'js'
51
+
52
+ response.should_not be_success
53
+ response.body.should === 'Could not sort products.'
54
+ end
55
+ end
56
+ end
57
+
58
+ context 'successfully sorted' do
59
+ before :each do
60
+ mock(ShopPacking).find('2').stub!.update_attributes!({:position,1}) { true }
61
+ mock(ShopPacking).find('1').stub!.update_attributes!({:position,2}) { true }
62
+ end
63
+
64
+ context 'js' do
65
+ it 'should return success string and success status' do
66
+ put :sort, :package_id => 1, :packings => @packings, :format => 'js'
67
+
68
+ response.should be_success
69
+ response.body.should === 'Products successfully sorted.'
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ describe '#create' do
77
+ before :each do
78
+ mock(ShopPackage).find('1') { @shop_package }
79
+ mock(ShopProduct).find('1') { @shop_product }
80
+ mock(ShopPacking).new { @shop_packing }
81
+ end
82
+ context 'packing could not be created' do
83
+ before :each do
84
+ mock(@shop_packing).save! { raise ActiveRecord::RecordNotSaved }
85
+ end
86
+
87
+ context 'js' do
88
+ it 'should return error notice and failure status' do
89
+ post :create, :package_id => 1, :product_id => 1, :format => 'js'
90
+
91
+ response.body.should === 'Could not attach product.'
92
+ response.should_not be_success
93
+ end
94
+ end
95
+ end
96
+
97
+ context 'packing successfully created' do
98
+ before :each do
99
+ mock(@shop_packing).save! { true }
100
+ end
101
+
102
+ context 'js' do
103
+ it 'should render the collection partial and success status' do
104
+ post :create, :package_id => 1, :product_id => 1, :format => 'js'
105
+
106
+ response.should be_success
107
+ assigns(:shop_packing).should === @shop_packing
108
+ response.should render_template('admin/shop/packages/edit/shared/_product')
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ describe '#update' do
115
+ before :each do
116
+ mock(ShopPacking).find('1') { @shop_packing }
117
+ end
118
+ context 'packing could not be created' do
119
+ before :each do
120
+ mock(@shop_packing).update_attributes!({ :quantity => '1' }) { raise ActiveRecord::RecordNotSaved }
121
+ end
122
+
123
+ context 'js' do
124
+ it 'should return error notice and failure status' do
125
+ put :update, :package_id => 1, :id => 1, :quantity => 1, :format => 'js'
126
+
127
+ response.should_not be_success
128
+ response.body.should === 'Could not update Product Quantity.'
129
+ end
130
+ end
131
+ end
132
+
133
+ context 'packing successfully created' do
134
+ before :each do
135
+ mock(@shop_packing).update_attributes!({ :quantity => '1' }) { true }
136
+ end
137
+
138
+ context 'js' do
139
+ it 'should render the collection partial and success status' do
140
+ put :update, :package_id => 1, :id => 1, :quantity => 1, :format => 'js'
141
+
142
+ response.should be_success
143
+ response.body.should === 'Product Quantity successfully updated.'
144
+
145
+ end
146
+ end
147
+ end
148
+ end
149
+
150
+ describe '#destroy' do
151
+ before :each do
152
+ mock(ShopPacking).find('1') { @shop_packing }
153
+ stub(@shop_packing).product { nil }
154
+ stub(@shop_packing).package { nil }
155
+ end
156
+
157
+ context 'product not destroyed' do
158
+ before :each do
159
+ stub(@shop_packing).destroy { raise ActiveRecord::RecordNotFound }
160
+ end
161
+
162
+ context 'js' do
163
+ it 'should render an error and failure status' do
164
+ delete :destroy, :package_id => 1, :id => 1, :format => 'js'
165
+
166
+ response.should_not be_success
167
+ response.body.should === 'Could not remove product.'
168
+ end
169
+ end
170
+ end
171
+
172
+ context 'product successfully destroyed' do
173
+ before :each do
174
+ stub(@shop_packing).destroy { true }
175
+ end
176
+
177
+ context 'js' do
178
+ it 'should render success message and success status' do
179
+ delete :destroy, :package_id => 1, :id => 1, :format => 'js'
180
+
181
+ response.should be_success
182
+ response.should render_template('admin/shop/packages/edit/shared/_product')
183
+ end
184
+ end
185
+ end
186
+ end
187
+
188
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe Admin::Shop::PackagesController do
4
+
5
+ dataset :users, :shop_packages
6
+
7
+ before(:each) do
8
+ login_as :admin
9
+ @package = shop_packages(:all_bread)
10
+ end
11
+
12
+ describe '#new' do
13
+ it 'should assign global instance variables' do
14
+ get :new
15
+
16
+ assigns(:meta).should === ['sku']
17
+ assigns(:buttons).should === []
18
+ assigns(:parts).should === ['description']
19
+ end
20
+ end
21
+
22
+ describe '#edit' do
23
+ it 'should assign global instance variables' do
24
+ get :edit, :id => @package.id
25
+
26
+ assigns(:meta).should === ['sku']
27
+ assigns(:buttons).should === ['browse_products']
28
+ assigns(:parts).should === ['description','products']
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,23 @@
1
+ class ShopPackagesDataset < Dataset::Base
2
+ uses :shop_products
3
+
4
+ def load
5
+ packages = {
6
+ :bread => [ :soft, :crusty, :warm ]
7
+ }
8
+ packages.each do |package, products|
9
+ create_record :shop_package, "all_#{package.to_s}".to_sym,
10
+ :name => "all #{package.to_s}",
11
+ :sku => "all_#{package.to_s}",
12
+ :price => 1 * 10
13
+
14
+ products.each_with_index do |product, i|
15
+ create_record :shop_packing, "#{product.to_s}_bread".to_s.to_sym,
16
+ :quantity => 1,
17
+ :position => 1,
18
+ :package => shop_packages("all_#{package.to_s}".to_sym),
19
+ :product => shop_products("#{product.to_s}_bread".to_sym)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,348 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe ShopPackages::Tags::Package do
4
+
5
+ dataset :pages, :shop_packages
6
+
7
+ it 'should describe these tags' do
8
+ ShopPackages::Tags::Package.tags.sort.should == [
9
+ 'shop:packages',
10
+ 'shop:packages:if_packages',
11
+ 'shop:packages:unless_packages',
12
+ 'shop:packages:each',
13
+ 'shop:package',
14
+ 'shop:package:id',
15
+ 'shop:package:name',
16
+ 'shop:package:sku',
17
+ 'shop:package:description',
18
+ 'shop:package:price',
19
+ 'shop:package:value',
20
+ 'shop:package:if_products',
21
+ 'shop:package:unless_products',
22
+ 'shop:package:products',
23
+ 'shop:package:products:each',
24
+ 'shop:package:product:quantity'].sort
25
+ end
26
+
27
+ before :all do
28
+ @page = pages(:home)
29
+ end
30
+
31
+ before :each do
32
+ @package = shop_packages(:all_bread)
33
+ end
34
+
35
+ context 'outside a package' do
36
+ describe '<r:shop:packages>' do
37
+ context 'packages' do
38
+ it 'should render' do
39
+ tag = %{<r:shop:packages>success</r:shop:packages>}
40
+ exp = %{success}
41
+
42
+ @page.should render(tag).as(exp)
43
+ end
44
+ end
45
+ context 'no packages' do
46
+ it 'should render' do
47
+ tag = %{<r:shop:packages>success</r:shop:packages>}
48
+ exp = %{success}
49
+
50
+ @page.should render(tag).as(exp)
51
+ end
52
+ end
53
+ end
54
+
55
+ describe '<r:shop:packages:if_packages>' do
56
+ context 'success' do
57
+ it 'should render' do
58
+ tag = %{<r:shop:packages:if_packages>success</r:shop:packages:if_packages>}
59
+ exp = %{success}
60
+
61
+ @page.should render(tag).as(exp)
62
+ end
63
+ end
64
+ context 'failure' do
65
+ it 'should render' do
66
+ mock(ShopPackages::Tags::Helpers).current_packages(anything) { [] }
67
+ tag = %{<r:shop:packages:if_packages>failure</r:shop:packages:if_packages>}
68
+ exp = %{}
69
+
70
+ @page.should render(tag).as(exp)
71
+ end
72
+ end
73
+ end
74
+
75
+ describe '<r:shop:packages:unless_packages>' do
76
+ context 'success' do
77
+ it 'should not render' do
78
+ mock(ShopPackages::Tags::Helpers).current_packages(anything) { [] }
79
+
80
+ tag = %{<r:shop:packages:unless_packages>success</r:shop:packages:unless_packages>}
81
+ exp = %{success}
82
+
83
+ @page.should render(tag).as(exp)
84
+ end
85
+ end
86
+ context 'failure' do
87
+ it 'should render' do
88
+ mock(ShopPackages::Tags::Helpers).current_packages(anything) { ShopPackage.all }
89
+
90
+ tag = %{<r:shop:packages:unless_packages>failure</r:shop:packages:unless_packages>}
91
+ exp = %{}
92
+
93
+ @page.should render(tag).as(exp)
94
+ end
95
+ end
96
+ end
97
+
98
+ describe '<r:shop:packages:each>' do
99
+ context 'success' do
100
+ it 'should render' do
101
+ mock(ShopPackages::Tags::Helpers).current_packages(anything) { ShopPackage.all }
102
+
103
+ tag = %{<r:shop:packages:each>.a.</r:shop:packages:each>}
104
+ exp = ShopPackage.all.map{ '.a.' }.join('')
105
+
106
+ @page.should render(tag).as(exp)
107
+ end
108
+ end
109
+
110
+ context 'failure' do
111
+ it 'should not render' do
112
+ mock(ShopPackages::Tags::Helpers).current_packages(anything) { [] }
113
+
114
+ tag = %{<r:shop:packages:each>failure</r:shop:packages:each>}
115
+ exp = %{}
116
+
117
+ @page.should render(tag).as(exp)
118
+ end
119
+ end
120
+ end
121
+
122
+ describe '<r:shop:package>' do
123
+ context 'success' do
124
+ it 'should render' do
125
+ mock(ShopPackages::Tags::Helpers).current_package(anything) { @package }
126
+
127
+ tag = %{<r:shop:package>success</r:shop:package>}
128
+ exp = %{success}
129
+
130
+ @page.should render(tag).as(exp)
131
+ end
132
+ end
133
+
134
+ context 'failure' do
135
+ it 'should not render' do
136
+ mock(ShopPackages::Tags::Helpers).current_package(anything) { nil }
137
+
138
+ tag = %{<r:shop:package>failure</r:shop:package>}
139
+ exp = %{}
140
+
141
+ @page.should render(tag).as(exp)
142
+ end
143
+ end
144
+ end
145
+
146
+ end
147
+
148
+ context 'within a package' do
149
+
150
+ before :each do
151
+ mock(ShopPackages::Tags::Helpers).current_package(anything) { @package }
152
+ end
153
+
154
+ context 'simple attributes' do
155
+ describe '<r:shop:package:id />' do
156
+ it 'should render the id' do
157
+ tag = %{<r:shop:package:id />}
158
+ exp = @package.id.to_s
159
+
160
+ @page.should render(tag).as(exp)
161
+ end
162
+ end
163
+
164
+ describe '<r:shop:package:name />' do
165
+ it 'should render the name' do
166
+ tag = %{<r:shop:package:name />}
167
+ exp = @package.name.to_s
168
+
169
+ @page.should render(tag).as(exp)
170
+ end
171
+ end
172
+
173
+ describe '<r:shop:package:sku />' do
174
+ it 'should render the sku' do
175
+ tag = %{<r:shop:package:sku />}
176
+ exp = @package.sku.to_s
177
+
178
+ @page.should render(tag).as(exp)
179
+ end
180
+ end
181
+ end
182
+
183
+ describe '<r:package:description />' do
184
+ it 'should render a textile filtered result' do
185
+ @package.description = '*bold*'
186
+
187
+ tag = %{<r:shop:package:description />}
188
+ exp = %{<p><strong>bold</strong></p>}
189
+
190
+ @page.should render(tag).as(exp)
191
+ end
192
+ end
193
+
194
+ context 'currency attributes' do
195
+ before :each do
196
+ Radiant::Config['shop.price_unit'] = '$'
197
+ Radiant::Config['shop.price_precision'] = 2
198
+ Radiant::Config['shop.price_separator'] = '.'
199
+ Radiant::Config['shop.price_delimiter'] = ','
200
+ end
201
+ describe '<r:shop:package:price />' do
202
+ before :each do
203
+ @package.price = 1234.34567890
204
+ end
205
+
206
+ it 'should render a standard price' do
207
+ tag = %{<r:shop:package:price />}
208
+ exp = %{$1,234.35}
209
+ @page.should render(tag).as(exp)
210
+ end
211
+
212
+ it 'should render a high precision price' do
213
+ tag = %{<r:shop:package:price precision="8"/>}
214
+ exp = %{$1,234.34567890}
215
+
216
+ @page.should render(tag).as(exp)
217
+ end
218
+
219
+ it 'should render a custom format' do
220
+ tag = %{<r:shop:package:price unit="%" separator="-" delimiter="+" />}
221
+ exp = %{%1+234-35}
222
+
223
+ @page.should render(tag).as(exp)
224
+ end
225
+ end
226
+
227
+ describe '<r:shop:package:value />' do
228
+ before :each do
229
+ stub(@package).value { 1234.34567890 }
230
+ end
231
+
232
+ it 'should render a standard price' do
233
+ tag = %{<r:shop:package:value />}
234
+ exp = %{$1,234.35}
235
+
236
+ @page.should render(tag).as(exp)
237
+ end
238
+
239
+ it 'should render a high precision price' do
240
+ tag = %{<r:shop:package:value precision="8"/>}
241
+ exp = %{$1,234.34567890}
242
+
243
+ @page.should render(tag).as(exp)
244
+ end
245
+
246
+ it 'should render a custom format' do
247
+ tag = %{<r:shop:package:value unit="%" separator="-" delimiter="+" />}
248
+ exp = %{%1+234-35}
249
+
250
+ @page.should render(tag).as(exp)
251
+ end
252
+ end
253
+ end
254
+
255
+ end
256
+
257
+ context 'products in a package' do
258
+
259
+ before :each do
260
+ mock(ShopPackages::Tags::Helpers).current_package(anything) { @package }
261
+ end
262
+
263
+ describe '<r:shop:package:if_products>' do
264
+ context 'success' do
265
+ it 'should render' do
266
+ tag = %{<r:shop:package:if_products>success</r:shop:package:if_products>}
267
+ exp = %{success}
268
+
269
+ @page.should render(tag).as(exp)
270
+ end
271
+ end
272
+
273
+ context 'failure' do
274
+ it 'should not render' do
275
+ stub(@package).products { [] }
276
+
277
+ tag = %{<r:shop:package:if_products>failure</r:shop:package:if_products>}
278
+ exp = %{}
279
+
280
+ @page.should render(tag).as(exp)
281
+ end
282
+ end
283
+ end
284
+
285
+ describe '<r:shop:package:unless_products>' do
286
+ context 'success' do
287
+ it 'should render' do
288
+ stub(@package).products { [] }
289
+ tag = %{<r:shop:package:unless_products>success</r:shop:package:unless_products>}
290
+ exp = %{success}
291
+
292
+ @page.should render(tag).as(exp)
293
+ end
294
+ end
295
+
296
+ context 'failure' do
297
+ it 'should not render' do
298
+ tag = %{<r:shop:package:unless_products>failure</r:shop:package:unless_products>}
299
+ exp = %{}
300
+
301
+ @page.should render(tag).as(exp)
302
+ end
303
+ end
304
+ end
305
+
306
+ describe '<r:shop:package:products>' do
307
+ it 'should render' do
308
+ tag = %{<r:shop:package:products>success</r:shop:package:products>}
309
+ exp = %{success}
310
+
311
+ @page.should render(tag).as(exp)
312
+ end
313
+ end
314
+
315
+ describe '<r:shop:package:products:each>' do
316
+ context 'success' do
317
+ it 'should render' do
318
+ tag = %{<r:shop:package:products:each>.a.</r:shop:package:products:each>}
319
+ exp = @package.products.map{'.a.'}.join('')
320
+
321
+ @page.should render(tag).as(exp)
322
+ end
323
+ end
324
+
325
+ context 'failure' do
326
+ it 'should not render' do
327
+ stub(@package).packings { [] }
328
+
329
+ tag = %{<r:shop:package:products:each>failure</r:shop:package:products:each>}
330
+ exp = %{}
331
+
332
+ @page.should render(tag).as(exp)
333
+ end
334
+ end
335
+ end
336
+
337
+ describe '<r:shop:package:product:quantity>' do
338
+ it 'should render the quantity of the current packing' do
339
+ tag = %{<r:shop:package:products:each:product:quantity />}
340
+ exp = @package.packings.map{|p| p.quantity}.join('')
341
+
342
+ @page.should render(tag).as(exp)
343
+ end
344
+ end
345
+
346
+ end
347
+
348
+ end