atkhayar-dev-spree-multi-vendor 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +10 -0
  3. data/LICENSE +26 -0
  4. data/README.md +181 -0
  5. data/Rakefile +21 -0
  6. data/app/controllers/spree/admin/vendor_settings_controller.rb +34 -0
  7. data/app/controllers/spree/admin/vendors_controller.rb +68 -0
  8. data/app/controllers/spree/api/v1/vendors_controller.rb +62 -0
  9. data/app/controllers/spree/api/v2/platform/vendors_controller.rb +32 -0
  10. data/app/controllers/spree/api/v2/storefront/vendors_controller.rb +33 -0
  11. data/app/controllers/spree_multi_vendor/spree/admin/base_controller_decorator.rb +10 -0
  12. data/app/controllers/spree_multi_vendor/spree/admin/products_controller_decorator.rb +79 -0
  13. data/app/controllers/spree_multi_vendor/spree/admin/resource_controller_decorator.rb +8 -0
  14. data/app/controllers/spree_multi_vendor/spree/admin/shipping_methods_controller_decorator.rb +7 -0
  15. data/app/controllers/spree_multi_vendor/spree/admin/stock_locations_controller_decorator.rb +7 -0
  16. data/app/controllers/spree_multi_vendor/spree/admin/users_controller_decorator.rb +13 -0
  17. data/app/controllers/spree_multi_vendor/spree/admin/variants_controller_decorator.rb +7 -0
  18. data/app/controllers/spree_multi_vendor/spree/api/base_controller_decorator.rb +17 -0
  19. data/app/controllers/spree_multi_vendor/spree/api/v1/products_controller_decorator.rb +9 -0
  20. data/app/controllers/spree_multi_vendor/spree/api/v1/users_controller_decorator.rb +13 -0
  21. data/app/controllers/spree_multi_vendor/spree/api/v2/platform/products_controller_decorator.rb +65 -0
  22. data/app/finders/spree_multi_vendor/products_finder_decorator.rb +31 -0
  23. data/app/helpers/spree/admin/vendor_helper.rb +15 -0
  24. data/app/helpers/spree/api/vendor_helper.rb +13 -0
  25. data/app/helpers/spree_multi_vendor/spree/api/api_helpers_decorator.rb +19 -0
  26. data/app/mailers/spree/vendor_mailer.rb +15 -0
  27. data/app/models/concerns/spree/vendor_concern.rb +11 -0
  28. data/app/models/spree/order_commission.rb +11 -0
  29. data/app/models/spree/vendor.rb +77 -0
  30. data/app/models/spree/vendor_ability.rb +155 -0
  31. data/app/models/spree/vendor_image.rb +18 -0
  32. data/app/models/spree/vendor_order_totals.rb +28 -0
  33. data/app/models/spree/vendor_user.rb +16 -0
  34. data/app/models/spree_multi_vendor/configuration.rb +10 -0
  35. data/app/models/spree_multi_vendor/spree/ability_decorator.rb +9 -0
  36. data/app/models/spree_multi_vendor/spree/base_decorator.rb +13 -0
  37. data/app/models/spree_multi_vendor/spree/line_item_decorator.rb +48 -0
  38. data/app/models/spree_multi_vendor/spree/order_decorator.rb +107 -0
  39. data/app/models/spree_multi_vendor/spree/shipment_decorator.rb +8 -0
  40. data/app/models/spree_multi_vendor/spree/stock/package_decorator.rb +14 -0
  41. data/app/models/spree_multi_vendor/spree/user_decorator.rb +8 -0
  42. data/app/models/spree_multi_vendor/spree/variant_decorator.rb +40 -0
  43. data/app/overrides/spree/admin/orders/_form.rb +13 -0
  44. data/app/overrides/spree/admin/orders/_line_items.rb +6 -0
  45. data/app/overrides/spree/admin/orders/_line_items_edit_form.rb +6 -0
  46. data/app/overrides/spree/admin/orders/index.rb +6 -0
  47. data/app/overrides/spree/admin/products/form.rb +29 -0
  48. data/app/overrides/spree/admin/products/new.rb +16 -0
  49. data/app/overrides/spree/admin/shared/_main_menu.rb +23 -0
  50. data/app/overrides/spree/admin/shared/_order_summary.rb +35 -0
  51. data/app/overrides/spree/admin/users/_form.rb +13 -0
  52. data/app/serializers/spree/api/v2/platform/vendor_serializer.rb +12 -0
  53. data/app/serializers/spree/v2/storefront/vendor_image_serializer.rb +11 -0
  54. data/app/serializers/spree/v2/storefront/vendor_order_totals_serializer.rb +20 -0
  55. data/app/serializers/spree/v2/storefront/vendor_serializer.rb +15 -0
  56. data/app/serializers/spree_multi_vendor/cart_serializer_decorator.rb +19 -0
  57. data/app/serializers/spree_multi_vendor/serializer_decorator.rb +23 -0
  58. data/app/services/spree/orders/generate_commissions.rb +34 -0
  59. data/app/views/spree/admin/translations/vendor.html.erb +21 -0
  60. data/app/views/spree/admin/vendor_settings/edit.html.erb +47 -0
  61. data/app/views/spree/admin/vendors/_form.html.erb +36 -0
  62. data/app/views/spree/admin/vendors/edit.html.erb +11 -0
  63. data/app/views/spree/admin/vendors/index.html.erb +83 -0
  64. data/app/views/spree/admin/vendors/new.html.erb +11 -0
  65. data/app/views/spree/api/v1/vendors/index.rabl +3 -0
  66. data/app/views/spree/api/v1/vendors/show.rabl +2 -0
  67. data/app/views/spree/vendor_mailer/vendor_notification_email.html.erb +81 -0
  68. data/app/views/spree/vendor_mailer/vendor_notification_email.text.erb +36 -0
  69. data/bin/rails +7 -0
  70. data/config/initializers/spree.rb +31 -0
  71. data/config/initializers/spree_permitted_attributes.rb +12 -0
  72. data/config/locales/en.yml +34 -0
  73. data/config/locales/es.yml +36 -0
  74. data/config/locales/fr.yml +33 -0
  75. data/config/routes.rb +29 -0
  76. data/db/default/vendors.rb +13 -0
  77. data/db/migrate/20170406102250_create_spree_vendors.rb +9 -0
  78. data/db/migrate/20170406102944_add_vendor_id_to_spree_models.rb +10 -0
  79. data/db/migrate/20170410111150_add_state_to_vendors.rb +6 -0
  80. data/db/migrate/20170412124925_add_deleted_at_to_spree_vendors.rb +6 -0
  81. data/db/migrate/20170413094447_create_spree_vendor_users.rb +11 -0
  82. data/db/migrate/20190212161426_add_slug_to_spree_vendors.rb +6 -0
  83. data/db/migrate/20190214120226_add_about_us_to_spree_vendors.rb +5 -0
  84. data/db/migrate/20190214142526_add_contact_us_to_spree_vendors.rb +5 -0
  85. data/db/migrate/20190305120337_add_commission_to_spree_vendors.rb +5 -0
  86. data/db/migrate/20190308091546_add_priority_to_vendor.rb +8 -0
  87. data/db/migrate/20190312130754_create_spree_order_commissions.rb +14 -0
  88. data/db/migrate/20190322133128_add_notification_email_to_vendors.rb +5 -0
  89. data/db/migrate/20200416030721_add_translations_to_vendor.rb +19 -0
  90. data/db/migrate/20210728120649_change_vendorized_models_vendor_id_type.rb +10 -0
  91. data/db/migrate/20210728120910_change_vendor_id_and_user_id_type_for_spree_vendor_users.rb +14 -0
  92. data/db/migrate/20210728121024_change_vendor_id_and_order_id_type_for_spree_order_commissions.rb +14 -0
  93. data/db/migrate/20221123095256_add_code_to_vendors.rb +6 -0
  94. data/lib/generators/spree_multi_vendor/install/install_generator.rb +21 -0
  95. data/lib/generators/spree_multi_vendor/mailers_preview/mailers_preview_generator.rb +22 -0
  96. data/lib/generators/spree_multi_vendor/mailers_preview/templates/mailers/previews/vendor_notification_preview.rb +5 -0
  97. data/lib/spree_multi_vendor/engine.rb +24 -0
  98. data/lib/spree_multi_vendor/factories.rb +7 -0
  99. data/lib/spree_multi_vendor/version.rb +11 -0
  100. data/lib/spree_multi_vendor.rb +16 -0
  101. data/lib/tasks/vendors.rake +8 -0
  102. data/spec/factories/spree/vendor_factory.rb +28 -0
  103. data/spec/factories/spree/vendor_image_factory.rb +5 -0
  104. data/spec/factories/spree/vendor_user_factory.rb +6 -0
  105. data/spec/features/spree/admin/orders_spec.rb +86 -0
  106. data/spec/features/spree/admin/product_spec.rb +177 -0
  107. data/spec/features/spree/admin/shipping_method_spec.rb +72 -0
  108. data/spec/features/spree/admin/stock_location_spec.rb +90 -0
  109. data/spec/features/spree/admin/vendor_settings_spec.rb +74 -0
  110. data/spec/features/spree/admin/vendor_spec.rb +125 -0
  111. data/spec/fixtures/thinking-cat.jpg +0 -0
  112. data/spec/mailers/vendor_mailer_spec.rb +45 -0
  113. data/spec/models/spree/line_item_spec.rb +32 -0
  114. data/spec/models/spree/order_commission_spec.rb +8 -0
  115. data/spec/models/spree/order_spec.rb +193 -0
  116. data/spec/models/spree/product_spec.rb +19 -0
  117. data/spec/models/spree/variant_spec.rb +104 -0
  118. data/spec/models/spree/vendor_order_totals_spec.rb +33 -0
  119. data/spec/models/spree/vendor_spec.rb +57 -0
  120. data/spec/models/spree/vendor_user_spec.rb +12 -0
  121. data/spec/requests/spree/api/v1/products_spec.rb +221 -0
  122. data/spec/requests/spree/api/v1/users_spec.rb +31 -0
  123. data/spec/requests/spree/api/v1/vendors_spec.rb +210 -0
  124. data/spec/requests/spree/api/v2/storefront/cart_spec.rb +85 -0
  125. data/spec/requests/spree/api/v2/storefront/products_spec.rb +96 -0
  126. data/spec/requests/spree/api/v2/storefront/vendors_spec.rb +118 -0
  127. data/spec/serializers/spree/v2/storefront/stock_location_serializer_spec.rb +32 -0
  128. data/spec/serializers/spree/v2/storefront/vendor_image_serializer_spec.rb +18 -0
  129. data/spec/serializers/spree/v2/storefront/vendor_order_totals_serializer_spec.rb +54 -0
  130. data/spec/serializers/spree/v2/storefront/vendor_serializer_spec.rb +34 -0
  131. data/spec/spec_helper.rb +13 -0
  132. data/spec/support/shoulda_matchers.rb +6 -0
  133. data/spree_multi_vendor.gemspec +42 -0
  134. metadata +308 -0
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe 'API V1 Users Spec', type: :request do
5
+ let(:user) { create(:user) }
6
+ let(:vendor) { create(:vendor, state: :active) }
7
+
8
+ before { stub_authentication! }
9
+
10
+ describe 'users#update' do
11
+ let(:params) do
12
+ {
13
+ user: {
14
+ vendor_ids: [vendor.id]
15
+ }
16
+ }
17
+ end
18
+
19
+ before { put "/api/v1/users/#{user.id}", params: params }
20
+
21
+ context 'as an admin' do
22
+ sign_in_as_admin!
23
+
24
+ it 'can update user' do
25
+ expect(response.status).to eq(200)
26
+ expect(json_response['vendor_ids']).to eq([vendor.id])
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,210 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe 'API V1 Vendors Spec', type: :request do
5
+ let(:params) { {} }
6
+ let(:selected_vendor) { vendor }
7
+
8
+ let!(:vendor) { create(:vendor, state: :active) }
9
+ let!(:another_vendor) { create(:vendor, state: :active) }
10
+
11
+ before { stub_authentication! }
12
+
13
+ describe 'vendors#index' do
14
+ before { get '/api/v1/vendors', params: params }
15
+
16
+ context 'as a regular user' do
17
+ it 'gets an empty list' do
18
+ expect(response.status).to eq(200)
19
+ expect(json_response.size).to eq(0)
20
+ end
21
+ end
22
+
23
+ context 'as an admin' do
24
+ sign_in_as_admin!
25
+
26
+ it 'gets a list of all vendors' do
27
+ expect(response.status).to eq(200)
28
+ expect(json_response.size).to eq(2)
29
+ end
30
+ end
31
+
32
+ context 'as a vendor' do
33
+ let!(:current_api_user) do
34
+ user = create(:user, vendors: [vendor])
35
+ user
36
+ end
37
+
38
+ it 'gets a list of assigned vendors' do
39
+ expect(response.status).to eq(200)
40
+ expect(json_response.size).to eq(1)
41
+ expect(json_response[0]['id']).to eq(vendor.id)
42
+ end
43
+ end
44
+ end
45
+
46
+ describe 'vendors#show' do
47
+ before { get "/api/v1/vendors/#{selected_vendor.id}" }
48
+
49
+ context 'as a regular user' do
50
+ it 'cannot view a vendor' do
51
+ expect(response.status).to eq(404)
52
+ end
53
+ end
54
+
55
+ context 'as an admin' do
56
+ sign_in_as_admin!
57
+ it 'can view a vendor' do
58
+ expect(response.status).to eq(200)
59
+ end
60
+ end
61
+
62
+ context 'as a vendor' do
63
+ let!(:current_api_user) do
64
+ user = create(:user, vendors: [vendor])
65
+ user
66
+ end
67
+
68
+ describe 'can view a assigned vendor' do
69
+ it do
70
+ expect(response.status).to eq(200)
71
+ end
72
+ end
73
+
74
+ describe 'cannot view an another vendor' do
75
+ let(:selected_vendor) { another_vendor }
76
+
77
+ it do
78
+ expect(response.status).to eq(404)
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ describe 'vendors#create' do
85
+ let(:params) do
86
+ {
87
+ vendor: {
88
+ name: 'name'
89
+ }
90
+ }
91
+ end
92
+
93
+ before { post '/api/v1/vendors', params: params }
94
+
95
+ context 'as regular user' do
96
+ it 'cannot create a new vendor' do
97
+ expect(response.status).to eq(401)
98
+ end
99
+ end
100
+
101
+ context 'as an admin' do
102
+ sign_in_as_admin!
103
+
104
+ it 'can create a new vendor' do
105
+ expect(response.status).to eq(201)
106
+ expect(json_response['name']).to eq(params[:vendor][:name])
107
+ end
108
+ end
109
+
110
+ context 'as a vendor' do
111
+ let!(:current_api_user) do
112
+ user = create(:user, vendors: [vendor], email: FFaker::Internet.email)
113
+ user
114
+ end
115
+
116
+ it 'cannot create a new vendor' do
117
+ expect(response.status).to eq(401)
118
+ end
119
+ end
120
+ end
121
+
122
+ describe 'vendors#update' do
123
+ let(:params) do
124
+ {
125
+ vendor: {
126
+ name: 'updated name'
127
+ }
128
+ }
129
+ end
130
+
131
+ before { put "/api/v1/vendors/#{selected_vendor.id}", params: params }
132
+
133
+ context 'as regular user' do
134
+ it 'cannot update vendor' do
135
+ expect(response.status).to eq(404)
136
+ end
137
+ end
138
+
139
+ context 'as an admin' do
140
+ sign_in_as_admin!
141
+
142
+ it 'can update vendor' do
143
+ expect(response.status).to eq(200)
144
+ expect(json_response['name']).to eq(params[:vendor][:name])
145
+ end
146
+ end
147
+
148
+ context 'as a vendor' do
149
+ let!(:current_api_user) do
150
+ user = create(:user, vendors: [vendor])
151
+ user
152
+ end
153
+
154
+ describe 'can update as assigned vendor' do
155
+ it do
156
+ expect(response.status).to eq(200)
157
+ end
158
+ end
159
+
160
+ describe 'cannot update an another vendor' do
161
+ let(:selected_vendor) { another_vendor }
162
+
163
+ it do
164
+ expect(response.status).to eq(404)
165
+ end
166
+ end
167
+ end
168
+ end
169
+
170
+ describe 'vendors#destroy' do
171
+ before { delete "/api/v1/vendors/#{selected_vendor.id}" }
172
+
173
+ context 'as regular user' do
174
+ it 'cannot delete vendor' do
175
+ expect(response.status).to eq(404)
176
+ end
177
+ end
178
+
179
+ context 'as an admin' do
180
+ sign_in_as_admin!
181
+
182
+ it 'can delete vendor' do
183
+ expect(response.status).to eq(204)
184
+ expect(vendor.reload.deleted_at).to_not eq(nil)
185
+ end
186
+ end
187
+
188
+ context 'as a vendor' do
189
+ let!(:current_api_user) do
190
+ user = create(:user, vendors: [vendor])
191
+ user
192
+ end
193
+
194
+ describe 'can delete an assigned vendor' do
195
+ it do
196
+ expect(response.status).to eq(204)
197
+ end
198
+ end
199
+
200
+ describe 'cannot delete an another vendor' do
201
+ let(:selected_vendor) { another_vendor }
202
+
203
+ it do
204
+ expect(response.status).to eq(404)
205
+ end
206
+ end
207
+ end
208
+ end
209
+ end
210
+ end
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'API V2 Storefront Cart Spec', type: :request do
4
+ let(:default_currency) { 'USD' }
5
+ let(:store) { Spree::Store.default }
6
+ let(:currency) { store.default_currency }
7
+ let(:user) { create(:user) }
8
+ let(:order) { create(:order, user: user, store: store, currency: currency) }
9
+ let!(:vendor) { create(:vendor) }
10
+ let!(:vendor_2) { create(:vendor) }
11
+ let(:product) { create(:product_in_stock, vendor: vendor) }
12
+ let(:product_2) { create(:product_in_stock, vendor: vendor_2) }
13
+
14
+ include_context 'API v2 tokens'
15
+
16
+ describe 'cart#show' do
17
+ let(:params) { {} }
18
+ let!(:line_item) { create(:line_item, order: order, product: product, variant: product.default_variant) }
19
+
20
+ shared_examples 'showing the cart' do
21
+ before do
22
+ get '/api/v2/storefront/cart', headers: headers_bearer, params: params
23
+ end
24
+
25
+ it_behaves_like 'returns 200 HTTP status'
26
+ it_behaves_like 'returns valid cart JSON'
27
+ end
28
+
29
+ context 'with one vendor' do
30
+ let(:params) { { include: 'vendors,vendor_totals' } }
31
+
32
+ it_behaves_like 'showing the cart'
33
+
34
+ it 'includes vendor and vendor totals' do
35
+ get '/api/v2/storefront/cart', headers: headers_bearer, params: params
36
+
37
+ expect(json_response['data']).to have_relationships(:vendors, :vendor_totals)
38
+ expect(json_response[:included][0]).to have_id(vendor.id.to_s)
39
+ expect(json_response[:included][0]).to have_type('vendor')
40
+ expect(json_response[:included][1]).to have_id(vendor.id.to_s)
41
+ expect(json_response[:included][1]).to have_type('vendor_totals')
42
+ end
43
+ end
44
+
45
+ context 'with many vendors' do
46
+ let!(:line_item_2) { create(:line_item, order: order, product: product_2, variant: product_2.default_variant) }
47
+ let(:params) { { include: 'vendors,vendor_totals' } }
48
+
49
+ it_behaves_like 'showing the cart'
50
+
51
+ it 'includes many vendors and vendor totals' do
52
+ get '/api/v2/storefront/cart', headers: headers_bearer, params: params
53
+
54
+ [vendor, vendor_2].each do |vendor|
55
+ expect(json_response['included']).to include(have_type('vendor').and have_id(vendor.id.to_s))
56
+ expect(json_response['included']).to include(have_type('vendor_totals').and have_id(vendor.id.to_s))
57
+ expect(json_response['included']).to include(have_type('vendor').and have_attribute(:name).with_value(vendor.name))
58
+ expect(json_response['included']).to include(have_type('vendor_totals').and have_attribute(:name).with_value(vendor.name))
59
+ end
60
+ end
61
+ end
62
+
63
+ context 'includes line item vendor data' do
64
+ it_behaves_like 'showing the cart'
65
+
66
+ it 'via variants' do
67
+ get '/api/v2/storefront/cart', params: { include: 'variants.vendor' }, headers: headers_bearer
68
+ expect(json_response[:included][0]).to have_id(vendor.id.to_s)
69
+ expect(json_response[:included][0]).to have_type('vendor')
70
+ end
71
+
72
+ it 'via products' do
73
+ get '/api/v2/storefront/cart', params: { include: 'variants.product.vendor' }, headers: headers_bearer
74
+ expect(json_response[:included][0]).to have_id(vendor.id.to_s)
75
+ expect(json_response[:included][0]).to have_type('vendor')
76
+ end
77
+
78
+ it 'via line_items' do
79
+ get '/api/v2/storefront/cart', params: { include: 'line_items.vendor' }, headers: headers_bearer
80
+ expect(json_response[:included][0]).to have_id(vendor.id.to_s)
81
+ expect(json_response[:included][0]).to have_type('vendor')
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'API V2 Storefront Products Spec', type: :request do
4
+ let(:store) { Spree::Store.default }
5
+ let!(:products) { create_list(:product, 5, stores: [store]) }
6
+ let!(:vendor) { create(:vendor) }
7
+ let!(:vendor_2) { create(:vendor) }
8
+
9
+ before do
10
+ vendors = Spree::Vendor.all.to_a
11
+ products.each do |product|
12
+ product.vendor = vendors.sample
13
+ product.save!
14
+ end
15
+ end
16
+
17
+ describe 'products#index' do
18
+ context 'with no params' do
19
+ before { get '/api/v2/storefront/products' }
20
+
21
+ it_behaves_like 'returns 200 HTTP status'
22
+
23
+ it 'returns all products' do
24
+ expect(json_response['data'].count).to eq Spree::Product.available.count
25
+ expect(json_response['data'].first).to have_type('product')
26
+ end
27
+ end
28
+
29
+ context 'with specified vendor ids' do
30
+ before { vendor.products << create(:product) }
31
+ before { vendor_2.products << create(:product) }
32
+ before { get "/api/v2/storefront/products?filter[vendor_ids]=#{vendor.id}&include=vendor" }
33
+
34
+ it_behaves_like 'returns 200 HTTP status'
35
+
36
+ it 'returns products with specified ids' do
37
+ expect(json_response['data'].count).to eq Spree::Product.available.where(vendor_id: vendor.id).count
38
+ expect(json_response['included'].first).to have_id(vendor.id.to_s)
39
+ expect(json_response['included'].first).to have_attribute(:name).with_value(vendor.name)
40
+ expect(json_response['included'].first).to have_attribute(:about_us).with_value(vendor.about_us)
41
+ end
42
+ end
43
+
44
+ context 'with specified multiple filters' do
45
+ before { get "/api/v2/storefront/products?filter[skus]=#{products.first.sku}&filter[vendor_ids]=#{products.first.vendor_id}&include=vendor" }
46
+
47
+ it_behaves_like 'returns 200 HTTP status'
48
+
49
+ it 'returns products with specified SKU and Vendor ID' do
50
+ expect(json_response['data'].count).to eq 1
51
+ expect(json_response['data'].first).to have_id(products.first.id.to_s)
52
+ expect(json_response['included'].first).to have_id(products.first.vendor_id.to_s)
53
+ expect(json_response['included'].first).to have_attribute(:name).with_value(products.first.vendor.name)
54
+ expect(json_response['included'].first).to have_attribute(:about_us).with_value(products.first.vendor.about_us)
55
+ end
56
+ end
57
+ end
58
+
59
+ describe 'products#show' do
60
+ let(:product) { products.first }
61
+
62
+ context 'with existing product' do
63
+ before { get "/api/v2/storefront/products/#{product.slug}?include=vendor" }
64
+
65
+ it_behaves_like 'returns 200 HTTP status'
66
+
67
+ it 'returns a valid JSON response' do
68
+ expect(json_response['data']).to have_id(product.id.to_s)
69
+
70
+ expect(json_response['data']).to have_type('product')
71
+
72
+ expect(json_response['data']).to have_attribute(:name).with_value(product.name)
73
+ expect(json_response['data']).to have_attribute(:description).with_value(product.description)
74
+ expect(json_response['data']).to have_attribute(:price).with_value(product.price.to_s)
75
+ expect(json_response['data']).to have_attribute(:currency).with_value(product.currency)
76
+ expect(json_response['data']).to have_attribute(:display_price).with_value(product.display_price.to_s)
77
+ expect(json_response['data']).to have_attribute(:available_on).with_value(product.available_on.as_json)
78
+ expect(json_response['data']).to have_attribute(:slug).with_value(product.slug)
79
+ expect(json_response['data']).to have_attribute(:meta_description).with_value(product.meta_description)
80
+ expect(json_response['data']).to have_attribute(:meta_keywords).with_value(product.meta_keywords)
81
+ expect(json_response['data']).to have_attribute(:updated_at).with_value(product.updated_at.as_json)
82
+ expect(json_response['data']).to have_attribute(:purchasable).with_value(product.purchasable?)
83
+ expect(json_response['data']).to have_attribute(:in_stock).with_value(product.in_stock?)
84
+ expect(json_response['data']).to have_attribute(:backorderable).with_value(product.backorderable?)
85
+
86
+ expect(json_response['data']).to have_relationships(
87
+ :variants, :option_types, :product_properties, :default_variant, :vendor
88
+ )
89
+
90
+ expect(json_response['included'].first).to have_id(product.vendor_id.to_s)
91
+ expect(json_response['included'].first).to have_attribute(:name).with_value(product.vendor.name)
92
+ expect(json_response['included'].first).to have_attribute(:about_us).with_value(product.vendor.about_us)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,118 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'API V2 Storefront Vendor Spec', type: :request do
4
+
5
+ let!(:vendor_image) { create(:vendor_image) }
6
+ let!(:vendor) { create(:active_vendor, name: 'vendor', image: vendor_image) }
7
+ let!(:product) { create(:product, vendor: vendor) }
8
+ let!(:vendors) {
9
+ create_list(:active_vendor_list, 30)}
10
+
11
+ describe 'vendors#show' do
12
+ context 'with invalid slug param' do
13
+ before { get '/api/v2/storefront/vendors/vendor1' }
14
+
15
+ it_behaves_like 'returns 404 HTTP status'
16
+ end
17
+
18
+ context 'with valid slug param' do
19
+ before { get "/api/v2/storefront/vendors/#{vendor.slug}" }
20
+
21
+ it_behaves_like 'returns 200 HTTP status'
22
+
23
+ it 'returns one vendor' do
24
+ json_response = JSON.parse(response.body)
25
+ expect(json_response.count).to eq 1
26
+ expect(json_response['data']['type']).to eq('vendor')
27
+ end
28
+
29
+ it 'does not return included' do
30
+ json_response = JSON.parse(response.body)
31
+ expect(json_response.keys).to contain_exactly('data')
32
+ end
33
+ end
34
+
35
+ context 'with products and images included' do
36
+ before { get "/api/v2/storefront/vendors/#{vendor.slug}?include=products,image" }
37
+
38
+ it_behaves_like 'returns 200 HTTP status'
39
+
40
+ it 'returns product information' do
41
+ json_response = JSON.parse(response.body)
42
+ expect(json_response.keys).to contain_exactly('data', 'included')
43
+ expect(json_response['included'].first['id']).to eq(product.id.to_s)
44
+ end
45
+
46
+ it 'returns image information' do
47
+ json_response = JSON.parse(response.body)
48
+ expect(json_response.keys).to contain_exactly('data', 'included')
49
+
50
+ expect(json_response['included'].second['id']).to eq(vendor_image.id.to_s)
51
+ end
52
+ end
53
+ end
54
+
55
+
56
+ describe 'vendors#index' do
57
+ context 'returns vendors list' do
58
+
59
+ it 'must return a list of vendor paged' do
60
+ get "/api/v2/storefront/vendors"
61
+ expect(response).to have_http_status(:ok)
62
+ json_response = JSON.parse(response.body)
63
+ expect(json_response)
64
+ expect(json_response['data'].count).to eq (25)
65
+ end
66
+
67
+ it 'can request different pages' do
68
+ get "/api/v2/storefront/vendors?page=2"
69
+ expect(response).to have_http_status(:ok)
70
+ json_response = JSON.parse(response.body)
71
+ expect(json_response)
72
+ expect(json_response['data'].count).to eq (6)
73
+
74
+ end
75
+
76
+ it 'can control paging size' do
77
+ get "/api/v2/storefront/vendors?page=2&per_page=10"
78
+ expect(response).to have_http_status(:ok)
79
+ json_response = JSON.parse(response.body)
80
+ expect(json_response)
81
+ expect(json_response['data'].count).to eq (10)
82
+ end
83
+
84
+
85
+ it 'returns data type vendor' do
86
+ get "/api/v2/storefront/vendors"
87
+ json_response = JSON.parse(response.body)
88
+ expect(json_response)
89
+ expect(json_response['data'][0]['type']).to eq('vendor')
90
+ end
91
+
92
+ it 'does not return included' do
93
+ get "/api/v2/storefront/vendors"
94
+ json_response = JSON.parse(response.body)
95
+ expect(json_response.keys).to contain_exactly('data', "links", "meta")
96
+ end
97
+ end
98
+
99
+ context 'with products and images included' do
100
+ before { get "/api/v2/storefront/vendors?include=products,image" }
101
+
102
+ it_behaves_like 'returns 200 HTTP status'
103
+
104
+ it 'returns product information' do
105
+ json_response = JSON.parse(response.body)
106
+ expect(json_response.keys).to contain_exactly('data', 'included', "links", "meta")
107
+ expect(json_response['included'].first['id']).to eq(product.id.to_s)
108
+ end
109
+
110
+ it 'returns image information' do
111
+ json_response = JSON.parse(response.body)
112
+ expect(json_response.keys).to contain_exactly('data', 'included',"links", "meta")
113
+
114
+ expect(json_response['included'].second['id']).to eq(vendor_image.id.to_s)
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::V2::Storefront::StockLocationSerializer do
4
+ let(:vendor) { create(:vendor, name: 'Test', about_us: 'Hello World') }
5
+ let(:stock_location) { create(:stock_location, vendor: vendor) }
6
+
7
+ subject { described_class.new(stock_location) }
8
+
9
+ it { expect(subject.serializable_hash).to be_kind_of(Hash) }
10
+ it do
11
+ expect(subject.serializable_hash).to eq(
12
+ {
13
+ data: {
14
+ id: stock_location.id.to_s,
15
+ type: :stock_location,
16
+ attributes: {
17
+ name: stock_location.name
18
+ },
19
+ relationships: {
20
+ vendor: {
21
+ data: {
22
+ id: vendor.id.to_s,
23
+ type: :vendor
24
+ }
25
+ }
26
+ }
27
+ }
28
+ }
29
+ )
30
+ end
31
+ end
32
+
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::V2::Storefront::VendorImageSerializer do
4
+ let!(:vendor_image) { create(:vendor_image) }
5
+ let!(:vendor) { create(:active_vendor, name: 'vendor', image: vendor_image) }
6
+
7
+ subject { described_class.new(vendor_image) }
8
+
9
+ it { expect(subject.serializable_hash).to be_kind_of(Hash) }
10
+
11
+ it 'returns right data attributes' do
12
+ expect(subject.serializable_hash[:data].keys).to contain_exactly(:id, :type, :attributes)
13
+ end
14
+
15
+ it 'returns right vendor_image attributes' do
16
+ expect(subject.serializable_hash[:data][:attributes].keys).to contain_exactly(:styles)
17
+ end
18
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::V2::Storefront::VendorOrderTotalsSerializer do
4
+ let(:vendor) { create(:vendor, name: 'Test', about_us: 'Hello World') }
5
+ let(:order) { create(:completed_order_with_totals, line_items_count: 6, line_items_price: 100, shipment_cost: 50) }
6
+ let!(:shipment) { create(:shipment, order: order, cost: 20, pre_tax_amount: 20, stock_location: vendor.stock_locations.first) }
7
+ let!(:promotion) { create(:promotion_with_item_adjustment, adjustment_rate: 10, code: '10off') }
8
+
9
+ let(:vendor_order_totals) { Spree::VendorOrderTotals.new(order: order, vendor: vendor) }
10
+
11
+ before do
12
+ order.products.update_all(vendor_id: vendor.id)
13
+ order.vendor_line_items(vendor).update_all(additional_tax_total: 10)
14
+ order.vendor_line_items(vendor).update_all(included_tax_total: 5)
15
+ order.vendor_shipments(vendor).update_all(adjustment_total: 5)
16
+ order.vendor_line_items(vendor).update_all(promo_total: 10)
17
+ end
18
+
19
+ subject { described_class.new(vendor_order_totals) }
20
+
21
+ let(:expected_hash) do
22
+ {
23
+ data: {
24
+ id: vendor.id.to_s,
25
+ type: :vendor_totals,
26
+ attributes: {
27
+ name: 'Test',
28
+ additional_tax_total: BigDecimal(60),
29
+ display_additional_tax_total: Spree::Money.new(60),
30
+ included_tax_total: BigDecimal(30),
31
+ display_included_tax_total: Spree::Money.new(30),
32
+ ship_total: BigDecimal(25),
33
+ display_ship_total: Spree::Money.new(25),
34
+ subtotal: BigDecimal(680),
35
+ display_subtotal: Spree::Money.new(680),
36
+ promo_total: BigDecimal(60),
37
+ display_promo_total: Spree::Money.new(60),
38
+ total: BigDecimal(625),
39
+ display_total: Spree::Money.new(625),
40
+ item_count: 6,
41
+ pre_tax_item_amount: BigDecimal(600),
42
+ display_pre_tax_item_amount: Spree::Money.new(600),
43
+ pre_tax_ship_amount: BigDecimal(20),
44
+ display_pre_tax_ship_amount: Spree::Money.new(20),
45
+ pre_tax_total: BigDecimal(620),
46
+ display_pre_tax_total: Spree::Money.new(620)
47
+ }
48
+ }
49
+ }
50
+ end
51
+
52
+ it { expect(subject.serializable_hash).to be_kind_of(Hash) }
53
+ it { expect(subject.serializable_hash).to eq(expected_hash) }
54
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::V2::Storefront::VendorSerializer do
4
+ let(:vendor) { create(:active_vendor, name: 'Test', about_us: 'Hello World', contact_us: 'Contact Info') }
5
+
6
+ subject { described_class.new(vendor) }
7
+
8
+ it { expect(subject.serializable_hash).to be_kind_of(Hash) }
9
+
10
+ it do
11
+ expect(subject.serializable_hash).to eq(
12
+ {
13
+ data: {
14
+ id: vendor.id.to_s,
15
+ type: :vendor,
16
+ relationships: {
17
+ image: {
18
+ data: nil
19
+ },
20
+ products: {
21
+ data: []
22
+ }
23
+ },
24
+ attributes: {
25
+ name: 'Test',
26
+ contact_us: 'Contact Info',
27
+ about_us: 'Hello World',
28
+ slug: 'test'
29
+ }
30
+ }
31
+ }
32
+ )
33
+ end
34
+ end