radiant-shop-extension 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (160) hide show
  1. data/.gitignore +6 -0
  2. data/Gemfile +26 -0
  3. data/Gemfile.lock +75 -0
  4. data/HISTORY.md +77 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.md +26 -0
  7. data/Rakefile +141 -0
  8. data/VERSION +1 -0
  9. data/app/.DS_Store +0 -0
  10. data/app/controllers/admin/shop/categories_controller.rb +206 -0
  11. data/app/controllers/admin/shop/customers_controller.rb +137 -0
  12. data/app/controllers/admin/shop/orders_controller.rb +171 -0
  13. data/app/controllers/admin/shop/products/images_controller.rb +144 -0
  14. data/app/controllers/admin/shop/products_controller.rb +217 -0
  15. data/app/controllers/admin/shops_controller.rb +9 -0
  16. data/app/controllers/shop/categories_controller.rb +49 -0
  17. data/app/controllers/shop/line_items_controller.rb +165 -0
  18. data/app/controllers/shop/orders_controller.rb +16 -0
  19. data/app/controllers/shop/products_controller.rb +48 -0
  20. data/app/models/form_checkout.rb +245 -0
  21. data/app/models/shop_address.rb +13 -0
  22. data/app/models/shop_addressable.rb +11 -0
  23. data/app/models/shop_category.rb +85 -0
  24. data/app/models/shop_category_page.rb +7 -0
  25. data/app/models/shop_customer.rb +27 -0
  26. data/app/models/shop_line_item.rb +32 -0
  27. data/app/models/shop_order.rb +108 -0
  28. data/app/models/shop_payment.rb +6 -0
  29. data/app/models/shop_payment_method.rb +5 -0
  30. data/app/models/shop_product.rb +87 -0
  31. data/app/models/shop_product_attachment.rb +30 -0
  32. data/app/models/shop_product_page.rb +7 -0
  33. data/app/views/.DS_Store +0 -0
  34. data/app/views/admin/.DS_Store +0 -0
  35. data/app/views/admin/pages/_shop_category.html.haml +4 -0
  36. data/app/views/admin/pages/_shop_product.html.haml +4 -0
  37. data/app/views/admin/shop/categories/edit.html.haml +12 -0
  38. data/app/views/admin/shop/categories/edit/_fields.html.haml +28 -0
  39. data/app/views/admin/shop/categories/edit/_head.html.haml +2 -0
  40. data/app/views/admin/shop/categories/edit/_meta.html.haml +7 -0
  41. data/app/views/admin/shop/categories/edit/_part.html.haml +3 -0
  42. data/app/views/admin/shop/categories/edit/_popup.html.haml +3 -0
  43. data/app/views/admin/shop/categories/edit/meta/_handle.html.haml +5 -0
  44. data/app/views/admin/shop/categories/edit/meta/_layouts.html.haml +10 -0
  45. data/app/views/admin/shop/categories/edit/parts/_description.html.haml +1 -0
  46. data/app/views/admin/shop/categories/index/_category.html.haml +16 -0
  47. data/app/views/admin/shop/categories/new.html.haml +10 -0
  48. data/app/views/admin/shop/categories/remove.html.haml +12 -0
  49. data/app/views/admin/shop/customers/index.html.haml +36 -0
  50. data/app/views/admin/shop/orders/index.html.haml +33 -0
  51. data/app/views/admin/shop/products/edit.html.haml +14 -0
  52. data/app/views/admin/shop/products/edit/_fields.html.haml +38 -0
  53. data/app/views/admin/shop/products/edit/_head.html.haml +2 -0
  54. data/app/views/admin/shop/products/edit/_image.html.haml +12 -0
  55. data/app/views/admin/shop/products/edit/_meta.html.haml +8 -0
  56. data/app/views/admin/shop/products/edit/_part.html.haml +3 -0
  57. data/app/views/admin/shop/products/edit/_popup.html.haml +3 -0
  58. data/app/views/admin/shop/products/edit/buttons/_browse_images.html.haml +1 -0
  59. data/app/views/admin/shop/products/edit/buttons/_new_image.html.haml +1 -0
  60. data/app/views/admin/shop/products/edit/meta/_category.html.haml +5 -0
  61. data/app/views/admin/shop/products/edit/meta/_sku.html.haml +5 -0
  62. data/app/views/admin/shop/products/edit/parts/_description.html.haml +1 -0
  63. data/app/views/admin/shop/products/edit/parts/_images.html.haml +5 -0
  64. data/app/views/admin/shop/products/edit/popups/_browse_images.html.haml +6 -0
  65. data/app/views/admin/shop/products/edit/popups/_new_image.html.haml +18 -0
  66. data/app/views/admin/shop/products/index.html.haml +10 -0
  67. data/app/views/admin/shop/products/index/_bottom.html.haml +5 -0
  68. data/app/views/admin/shop/products/index/_product.html.haml +13 -0
  69. data/app/views/admin/shop/products/new.html.haml +10 -0
  70. data/app/views/admin/shop/products/remove.html.haml +12 -0
  71. data/app/views/shop/categories/show.html.haml +1 -0
  72. data/app/views/shop/orders/show.html.haml +1 -0
  73. data/app/views/shop/products/index.html.haml +1 -0
  74. data/app/views/shop/products/show.html.haml +1 -0
  75. data/config/locales/en.yml +50 -0
  76. data/config/routes.rb +38 -0
  77. data/config/shop_cart.yml +16 -0
  78. data/cucumber.yml +1 -0
  79. data/db/migrate/20100311053701_initial.rb +153 -0
  80. data/db/migrate/20100520033059_create_layouts.rb +119 -0
  81. data/db/migrate/20100903122123_create_forms.rb +44 -0
  82. data/db/migrate/20100908063639_create_snippets.rb +22 -0
  83. data/features/support/env.rb +16 -0
  84. data/features/support/paths.rb +14 -0
  85. data/lib/shop/controllers/application_controller.rb +39 -0
  86. data/lib/shop/controllers/site_controller.rb +12 -0
  87. data/lib/shop/interface/products.rb +49 -0
  88. data/lib/shop/models/image.rb +14 -0
  89. data/lib/shop/models/page.rb +14 -0
  90. data/lib/shop/tags/address.rb +40 -0
  91. data/lib/shop/tags/cart.rb +49 -0
  92. data/lib/shop/tags/category.rb +83 -0
  93. data/lib/shop/tags/core.rb +12 -0
  94. data/lib/shop/tags/helpers.rb +142 -0
  95. data/lib/shop/tags/item.rb +109 -0
  96. data/lib/shop/tags/product.rb +109 -0
  97. data/lib/shop/tags/responses.rb +34 -0
  98. data/lib/tasks/shop_extension_tasks.rake +54 -0
  99. data/mockups/balsamiq/products-retro_fun_tshirt-more.bmml +0 -0
  100. data/mockups/balsamiq/products-retro_fun_tshirt.bmml +0 -0
  101. data/public/images/admin/extensions/shop/products/sort.png +0 -0
  102. data/public/javascripts/admin/extensions/shop/products/edit.js +115 -0
  103. data/public/javascripts/admin/extensions/shop/products/index.js +65 -0
  104. data/public/stylesheets/sass/admin/extensions/shop/edit.sass +86 -0
  105. data/public/stylesheets/sass/admin/extensions/shop/products/edit.sass +158 -0
  106. data/public/stylesheets/sass/admin/extensions/shop/products/index.sass +129 -0
  107. data/radiant-shop-extension.gemspec +245 -0
  108. data/shop_extension.rb +62 -0
  109. data/spec/controllers/admin/shop/categories_controller_spec.rb +443 -0
  110. data/spec/controllers/admin/shop/products/images_controller_spec.rb +477 -0
  111. data/spec/controllers/admin/shop/products_controller_spec.rb +394 -0
  112. data/spec/controllers/admin/shops_controller_spec.rb +19 -0
  113. data/spec/controllers/shop/categories_controller_spec.rb +42 -0
  114. data/spec/controllers/shop/line_items_controller_spec.rb +256 -0
  115. data/spec/controllers/shop/orders_controller_specs.rb +37 -0
  116. data/spec/controllers/shop/products_controller_spec.rb +51 -0
  117. data/spec/datasets/forms.rb +153 -0
  118. data/spec/datasets/images.rb +13 -0
  119. data/spec/datasets/shop_addresses.rb +27 -0
  120. data/spec/datasets/shop_categories.rb +13 -0
  121. data/spec/datasets/shop_line_items.rb +9 -0
  122. data/spec/datasets/shop_orders.rb +21 -0
  123. data/spec/datasets/shop_products.rb +34 -0
  124. data/spec/helpers/nested_tag_helper.rb +33 -0
  125. data/spec/lib/shop/models/image_spec.rb +28 -0
  126. data/spec/lib/shop/models/page_spec.rb +38 -0
  127. data/spec/lib/shop/tags/address_spec.rb +196 -0
  128. data/spec/lib/shop/tags/cart_spec.rb +169 -0
  129. data/spec/lib/shop/tags/category_spec.rb +201 -0
  130. data/spec/lib/shop/tags/core_spec.rb +16 -0
  131. data/spec/lib/shop/tags/helpers_spec.rb +381 -0
  132. data/spec/lib/shop/tags/item_spec.rb +313 -0
  133. data/spec/lib/shop/tags/product_spec.rb +334 -0
  134. data/spec/matchers/comparison.rb +72 -0
  135. data/spec/matchers/render_matcher.rb +33 -0
  136. data/spec/models/form_checkout_spec.rb +376 -0
  137. data/spec/models/shop_category_page_spec.rb +10 -0
  138. data/spec/models/shop_category_spec.rb +58 -0
  139. data/spec/models/shop_line_item_spec.rb +42 -0
  140. data/spec/models/shop_order_spec.rb +228 -0
  141. data/spec/models/shop_product_attachment_spec.rb +72 -0
  142. data/spec/models/shop_product_page_spec.rb +10 -0
  143. data/spec/models/shop_product_spec.rb +135 -0
  144. data/spec/spec.opts +6 -0
  145. data/spec/spec_helper.rb +22 -0
  146. data/vendor/plugins/acts_as_list/README +23 -0
  147. data/vendor/plugins/acts_as_list/init.rb +3 -0
  148. data/vendor/plugins/acts_as_list/lib/active_record/acts/list.rb +256 -0
  149. data/vendor/plugins/acts_as_list/test/list_test.rb +332 -0
  150. data/vendor/plugins/json_fields/.gitignore +3 -0
  151. data/vendor/plugins/json_fields/MIT-LICENSE +20 -0
  152. data/vendor/plugins/json_fields/README.rdoc +65 -0
  153. data/vendor/plugins/json_fields/Rakefile +55 -0
  154. data/vendor/plugins/json_fields/init.rb +2 -0
  155. data/vendor/plugins/json_fields/lib/json_fields.rb +99 -0
  156. data/vendor/plugins/json_fields/spec/lib/json_fields_spec.rb +124 -0
  157. data/vendor/plugins/json_fields/spec/spec.opts +6 -0
  158. data/vendor/plugins/json_fields/spec/spec_helper.rb +29 -0
  159. data/vendor/plugins/json_fields/spec/test_models.rb +12 -0
  160. metadata +324 -0
@@ -0,0 +1,256 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe Shop::LineItemsController do
4
+ before :each do
5
+ request.env["HTTP_REFERER"] = '/back'
6
+
7
+ @order = Object.new
8
+ stub(@order).id { '1' }
9
+
10
+ @line_item = Object.new
11
+ stub(@line_item).id { '1' }
12
+
13
+ @attr_hash = {
14
+ :include => :product,
15
+ :only => ShopLineItem.params
16
+ }
17
+ end
18
+
19
+ describe '#index' do
20
+ before :each do
21
+ @line_items = Object.new
22
+ mock(controller).find_or_create_shop_order.mock!.line_items.mock!.all { @line_items }
23
+ end
24
+
25
+ it 'should list all items' do
26
+ get :index
27
+ response.should be_success
28
+ response.should render_template(:index)
29
+ end
30
+
31
+ it 'should list all items in js' do
32
+ get :index, :format => 'js'
33
+ response.should be_success
34
+ response.should render_template('/shop/line_items/_line_item')
35
+ end
36
+
37
+ it 'should list all items in json' do
38
+ get :index, :format => 'json'
39
+ response.should be_success
40
+ response.body.should == @line_items.to_json(@attr_hash)
41
+ end
42
+ end
43
+
44
+ describe '#show' do
45
+ before :each do
46
+ @line_items = Object.new
47
+ mock(controller).find_or_create_shop_order.mock!.line_items.mock!.find(@line_item.id.to_s) { @line_items }
48
+ end
49
+
50
+ it 'should list all items' do
51
+ get :show, :id => @line_item.id
52
+ response.should be_success
53
+ response.should render_template(:show)
54
+ end
55
+
56
+ it 'should list all items in js' do
57
+ get :show, :format => 'js', :id => @line_item.id
58
+ response.should be_success
59
+ response.should render_template('/shop/line_items/_line_item')
60
+ end
61
+
62
+ it 'should list all items in json' do
63
+ get :show, :format => 'json', :id => @line_item.id
64
+ response.should be_success
65
+ response.body.should == @line_item.to_json(@attr_hash)
66
+ end
67
+ end
68
+
69
+ describe '#create' do
70
+ context 'success' do
71
+ context 'defined quantity' do
72
+ it 'should assign the custom quantity' do
73
+ mock(controller).find_or_create_shop_order.mock!.add!(1, 5, nil) { @line_item }
74
+
75
+ post :create, :line_item => { :item_id => 1, :quantity => 5 }
76
+ end
77
+ end
78
+ context 'no quantity defined' do
79
+ it 'should assign a quantity of 1' do
80
+ mock(controller).find_or_create_shop_order.mock!.add!(1, nil, nil) { @line_item }
81
+
82
+ post :create, :line_item => { :item_id => 1}
83
+ end
84
+ end
85
+ context 'defined type' do
86
+ it 'should redirect back' do
87
+ mock(controller).find_or_create_shop_order.mock!.add!(1, nil, 'ShopPackage') { @line_item }
88
+
89
+ post :create, :line_item => { :item_id => 1, :item_type => 'ShopPackage' }
90
+ end
91
+ end
92
+ context 'no type defined' do
93
+ it 'should not assign a type and redirect back' do
94
+ mock(controller).find_or_create_shop_order.mock!.add!(1, nil, nil) { @line_item }
95
+
96
+ post :create, :line_item => { :item_id => 1 }
97
+ end
98
+ end
99
+
100
+ context 'responses' do
101
+ before :each do
102
+ mock(controller).find_or_create_shop_order.mock!.add!(1, nil, nil) { @line_item }
103
+ end
104
+ it 'HTML should assign a notice and redirect' do
105
+ post :create, :line_item => { :item_id => 1 }
106
+
107
+ flash.now[:notice] === 'Item added to Cart.'
108
+ response.should redirect_to('/back')
109
+ end
110
+ it 'JS should list all items in' do
111
+ post :create, :line_item => { :item_id => 1 }, :format => 'js'
112
+
113
+ response.should be_success
114
+ response.should render_template('/shop/line_items/_line_item')
115
+ end
116
+
117
+ it 'JSON should list all items in' do
118
+ post :create, :line_item => { :item_id => 1 }, :format => 'json'
119
+
120
+ response.should be_success
121
+ response.body.should === @line_item.to_json(@attr_hash)
122
+ end
123
+ end
124
+ end
125
+
126
+ context 'failure' do
127
+ before :each do
128
+ mock(controller).find_or_create_shop_order.mock!.add!(1, 1, nil) { raise ActiveRecord::RecordNotSaved }
129
+ end
130
+ it 'should list all items' do
131
+ post :create, :line_item => { :item_id => 1, :quantity => 1 }
132
+
133
+ flash.now[:error].should === 'Could not add Item to Cart.'
134
+ response.should redirect_to('/back')
135
+ end
136
+
137
+ it 'should list all items in js' do
138
+ post :create, :line_item => { :item_id => 1, :quantity => 1 }, :format => 'js'
139
+
140
+ response.should_not be_success
141
+ response.body.should === 'Could not add Item to Cart.'
142
+ end
143
+
144
+ it 'should list all items in json' do
145
+ post :create, :line_item => { :item_id => 1, :quantity => 1 }, :format => 'json'
146
+
147
+ response.should_not be_success
148
+ JSON.parse(response.body)['error'].should === 'Could not add Item to Cart.'
149
+ end
150
+ end
151
+ end
152
+
153
+ describe '#update' do
154
+ context 'success' do
155
+ before :each do
156
+ mock(controller).find_or_create_shop_order.mock!.update!(@line_item.id, 1) { @line_item }
157
+ end
158
+
159
+ it 'should redirect back' do
160
+ put :update, :id => 'x', :line_item => { :id => @line_item.id }
161
+
162
+ flash.now[:notice].should === 'Item updated successfully.'
163
+ response.should redirect_to('/back')
164
+ end
165
+
166
+ it 'should list all items in js' do
167
+ put :update, :id => 'x', :line_item => { :id => @line_item.id }, :format => 'js'
168
+
169
+ response.should be_success
170
+ response.should render_template('/shop/line_items/_line_item')
171
+ end
172
+
173
+ it 'should list all items in json' do
174
+ put :update, :id => 'x', :line_item => { :id => @line_item.id }, :format => 'json'
175
+
176
+ response.should be_success
177
+ response.body.should === @line_item.to_json(@attr_hash)
178
+ end
179
+ end
180
+
181
+ context 'failure' do
182
+ before :each do
183
+ mock(controller).find_or_create_shop_order.mock!.update!(@line_item.id, 1) { raise ActiveRecord::RecordNotSaved }
184
+ end
185
+
186
+ it 'HTML should list all items' do
187
+ put :update, :id => 'x', :line_item => { :id => @line_item.id }
188
+ flash.now[:error].should === 'Could not update Item.'
189
+ response.should redirect_to('/back')
190
+ end
191
+
192
+ it 'JS should list all items' do
193
+ put :update, :id => 'x', :line_item => { :id => @line_item.id }, :format => 'js'
194
+ response.should_not be_success
195
+ response.body.should === 'Could not update Item.'
196
+ end
197
+
198
+ it 'JSON should list all items' do
199
+ put :update, :id => 'x', :line_item => { :id => @line_item.id }, :format => 'json'
200
+ response.should_not be_success
201
+ JSON.parse(response.body)['error'].should === 'Could not update Item.'
202
+ end
203
+ end
204
+ end
205
+
206
+ describe '#destroy' do
207
+ context 'success' do
208
+ before :each do
209
+ mock(controller).find_or_create_shop_order.mock!.remove!(@line_item.id) { true }
210
+ end
211
+
212
+ it 'should redirect back' do
213
+ delete :destroy, :id => @line_item.id
214
+ flash.now[:notice].should === 'Item removed from Cart.'
215
+ response.should redirect_to('/back')
216
+ end
217
+
218
+ it 'should list all items in js' do
219
+ delete :destroy, :id => @line_item.id, :format => 'js'
220
+ response.should be_success
221
+ response.body.should === 'Item removed from Cart.'
222
+ end
223
+
224
+ it 'should list all items in json' do
225
+ delete :destroy, :id => @line_item.id, :format => 'json'
226
+ response.should be_success
227
+ JSON.parse(response.body)['notice'].should === 'Item removed from Cart.'
228
+ end
229
+ end
230
+
231
+ context 'failure' do
232
+ before :each do
233
+ mock(controller).find_or_create_shop_order.mock!.remove!(@line_item.id.to_s) { raise ActiveRecord::RecordNotFound }
234
+ end
235
+
236
+ it 'should list all items' do
237
+ delete :destroy, :id => @line_item.id
238
+ flash.now[:error].should === 'Could not remove Item from Cart.'
239
+ response.should redirect_to('/back')
240
+ end
241
+
242
+ it 'should list all items in js' do
243
+ delete :destroy, :format => 'js', :id => @line_item.id
244
+ response.should_not be_success
245
+ response.body.should === 'Could not remove Item from Cart.'
246
+ end
247
+
248
+ it 'should list all items in json' do
249
+ delete :destroy, :format => 'json', :id => @line_item.id
250
+ response.should_not be_success
251
+ JSON.parse(response.body)['error'].should === 'Could not remove Item from Cart.'
252
+ end
253
+ end
254
+ end
255
+
256
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe Shop::OrdersController do
4
+
5
+ dataset :shop_orders
6
+
7
+ before(:each) do
8
+ @order = shop_orders(:one_item)
9
+ end
10
+
11
+ describe '#finalize' do
12
+ context 'paid order' do
13
+ it 'should redirect to the thanks page' do
14
+ stub(@order).new? { false }
15
+ mock(controller).current_shop_order { @order }
16
+
17
+ get :finalize
18
+
19
+ response.should redirect_to("/#{Radiant::Config['shop.cart_thanks_path']}")
20
+ end
21
+ it 'should set the session shop_order to nil'
22
+ end
23
+
24
+ context 'new order' do
25
+ it 'should redirect to the cart page' do
26
+ stub(@order).new? { true }
27
+ mock(controller).current_shop_order { @order }
28
+
29
+ get :finalize
30
+
31
+ response.should redirect_to("/#{Radiant::Config['shop.cart_path']}")
32
+ end
33
+ it 'should not touch the session shop_order'
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe Shop::ProductsController do
4
+ before(:each) do
5
+ @shop_product = ShopProduct.new
6
+ @shop_category = ShopCategory.new
7
+
8
+ stub(@shop_product).sku { 'a' }
9
+ stub(@shop_product).name { 'Bob' }
10
+ stub(@shop_product).category { @shop_category }
11
+
12
+ stub(@shop_category).handle { 'b' }
13
+ stub(@shop_category).product_layout.stub!.name { 'Layout' }
14
+
15
+ @shop_products = [ @shop_product ]
16
+ end
17
+
18
+ describe '#index' do
19
+ it 'should expose products list' do
20
+ mock(ShopProduct).search(nil) { @shop_products }
21
+ get :index
22
+
23
+ response.should be_success
24
+ assigns(:shop_products).should === @shop_products
25
+ end
26
+ end
27
+
28
+ describe '#show' do
29
+ it 'should expose product' do
30
+ mock(ShopProduct).find(:first, :conditions => { :sku => @shop_product.sku }) { @shop_product }
31
+
32
+ get :show, :sku => @shop_product.sku, :handle => @shop_category.handle
33
+
34
+ response.should be_success
35
+ assigns(:shop_product).should === @shop_product
36
+ assigns(:shop_category).should == @shop_product.category
37
+ assigns(:radiant_layout).should == 'Layout'
38
+ assigns(:title).should === 'Bob'
39
+ end
40
+
41
+ it 'should return 404 if product empty' do
42
+ mock(ShopProduct).find(:first, :conditions => { :sku => @shop_product.sku }) { false }
43
+
44
+ get :show, :sku => @shop_product.sku, :handle => @shop_category.handle
45
+
46
+ response.should render_template('site/not_found')
47
+ response.should_not be_success
48
+ end
49
+ end
50
+
51
+ end
@@ -0,0 +1,153 @@
1
+ class FormsDataset < Dataset::Base
2
+ def load
3
+ create_record :form, :checkout,
4
+ :title => 'Checkout',
5
+ :body => body,
6
+ :content => content,
7
+ :config => config
8
+ end
9
+
10
+ def body
11
+ <<-BODY
12
+ <r:shop:cart>
13
+ <ul class="items">
14
+ <r:items:each:item>
15
+ <li class="item"><r:quantity /> x <r:name /></li>
16
+ </r:items:each:item>
17
+ </ul>
18
+ <div class="addresses">
19
+ <ol class="billing">
20
+ <li>
21
+ <r:label for='billing[name]'>Name</r:label>
22
+ <r:text name='billing[name]' />
23
+ </li>
24
+ <li>
25
+ <r:label for='billing[unit]'>Unit</r:label>
26
+ <r:text name='billing[unit]' />
27
+ </li>
28
+ <li>
29
+ <r:label for='billing[street]'>Street</r:label>
30
+ <r:text name='billing[street]' />
31
+ </li>
32
+ <li>
33
+ <r:label for='billing[suburb]'>Suburb</r:label>
34
+ <r:text name='billing[suburb]' />
35
+ </li>
36
+ <li>
37
+ <r:label for='billing[state]'>State</r:label>
38
+ <r:text name='billing[state]' />
39
+ </li>
40
+ <li>
41
+ <r:label for='billing[postcode]'>Postcode</r:label>
42
+ <r:text name='billing[postcode]' />
43
+ </li>
44
+ <li>
45
+ <r:label for='billing[country]'>Country</r:label>
46
+ <r:text name='billing[country]' />
47
+ </li>
48
+ </ol>
49
+ <ol class="shipping">
50
+ <li>
51
+ <r:label for='shipping[name]'>Name</r:label>
52
+ <r:text name='shipping[name]' />
53
+ </li>
54
+ <li>
55
+ <r:label for='shipping[unit]'>Unit</r:label>
56
+ <r:text name='shipping[unit]' />
57
+ </li>
58
+ <li>
59
+ <r:label for='shipping[street]'>Street</r:label>
60
+ <r:text name='shipping[street]' />
61
+ </li>
62
+ <li>
63
+ <r:label for='shipping[suburb]'>Suburb</r:label>
64
+ <r:text name='shipping[suburb]' />
65
+ </li>
66
+ <li>
67
+ <r:label for='shipping[state]'>State</r:label>
68
+ <r:text name='shipping[state]' />
69
+ </li>
70
+ <li>
71
+ <r:label for='shipping[postcode]'>Postcode</r:label>
72
+ <r:text name='shipping[postcode]' />
73
+ </li>
74
+ <li>
75
+ <r:label for='shipping[country]'>Country</r:label>
76
+ <r:text name='shipping[country]' />
77
+ </li>
78
+ </ol>
79
+ </div>
80
+ <ol class="card">
81
+ <li>
82
+ <r:label for='card[type]'>Type Card</r:label>
83
+ <r:select name='card[type]'>
84
+ <r:option value='visa'>Visa</r:option>
85
+ <r:option value='mastercard'>Master Card</r:option>
86
+ <r:option value='diners'>Diners Club</r:option>
87
+ <r:option vlaue='amex'>AMEX</r:option>
88
+ </r:select>
89
+ </li>
90
+ <li>
91
+ <r:label for='card[name]'>Name on Card</r:label>
92
+ <r:text name='card[name]' />
93
+ </li>
94
+ <li>
95
+ <r:label for='card[number]'>Card Number</r:label>
96
+ <r:text name='card[number]' />
97
+ </li>
98
+ <li>
99
+ <r:label for='card[verification]'>Verification Code</r:label>
100
+ <r:text name='card[verification]' length='4' />
101
+ </li>
102
+ <li>
103
+ <r:label for='card[month]'>Date on Card</r:label>
104
+ # Todo turns these into tags
105
+ <r:select name='card[month]'>
106
+ <r:option value='01'>01 - January</r:option>
107
+ <r:option value='02'>02 - February</r:option>
108
+ <r:option value='03'>03 - March</r:option>
109
+ <r:option value='04'>04 - April</r:option>
110
+ <r:option value='05'>05 - May</r:option>
111
+ <r:option value='06'>06 - June</r:option>
112
+ <r:option value='07'>07 - July</r:option>
113
+ <r:option value='08'>08 - August</r:option>
114
+ <r:option value='09'>09 - September</r:option>
115
+ <r:option value='10'>10 - October</r:option>
116
+ <r:option value='11'>11 - November</r:option>
117
+ <r:option value='12'>12 - December</r:option>
118
+ </r:select>
119
+ <r:select name='card[year]'>
120
+ <r:option value='2010'>2010</r:option>
121
+ <r:option value='2011'>2011</r:option>
122
+ <r:option value='2012'>2012</r:option>
123
+ <r:option value='2013'>2013</r:option>
124
+ <r:option value='2014'>2014</r:option>
125
+ </r:select>
126
+ </li>
127
+ </ol>
128
+ <r:form:submit />
129
+ </r:shop:cart>
130
+ BODY
131
+ end
132
+
133
+ def content
134
+ <<-CONTENT
135
+
136
+ CONTENT
137
+ end
138
+
139
+ def config
140
+ <<-CONFIG
141
+ checkout:
142
+ shipping:
143
+ enabled: true
144
+ gateway:
145
+ name: PayWay
146
+ username: 123456
147
+ password: abcdef
148
+ merchant: test
149
+ pem: /var/www/certificate.pem
150
+ CONFIG
151
+ end
152
+
153
+ end