atkhayar-dev-spree-multi-vendor 0.0.0

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 (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