spree_multi_vendor 2.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 (124) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +44 -0
  5. data/Appraisals +11 -0
  6. data/Gemfile +7 -0
  7. data/LICENSE +26 -0
  8. data/README.md +166 -0
  9. data/Rakefile +21 -0
  10. data/app/controllers/spree/admin/vendor_settings_controller.rb +34 -0
  11. data/app/controllers/spree/admin/vendors_controller.rb +60 -0
  12. data/app/controllers/spree/api/v2/storefront/vendors_controller.rb +28 -0
  13. data/app/controllers/spree_multi_vendor/spree/admin/base_controller_decorator.rb +10 -0
  14. data/app/controllers/spree_multi_vendor/spree/admin/option_types_controller_decorator.rb +7 -0
  15. data/app/controllers/spree_multi_vendor/spree/admin/products_controller_decorator.rb +24 -0
  16. data/app/controllers/spree_multi_vendor/spree/admin/properties_controller_decorator.rb +7 -0
  17. data/app/controllers/spree_multi_vendor/spree/admin/resource_controller_decorator.rb +8 -0
  18. data/app/controllers/spree_multi_vendor/spree/admin/shipping_methods_controller_decorator.rb +7 -0
  19. data/app/controllers/spree_multi_vendor/spree/admin/stock_locations_controller_decorator.rb +7 -0
  20. data/app/controllers/spree_multi_vendor/spree/admin/users_controller_decorator.rb +13 -0
  21. data/app/controllers/spree_multi_vendor/spree/admin/variants_controller_decorator.rb +7 -0
  22. data/app/controllers/spree_multi_vendor/spree/api/v1/variants_controller_decorator.rb +22 -0
  23. data/app/finders/spree_multi_vendor/products_finder_decorator.rb +31 -0
  24. data/app/helpers/spree/admin/vendor_helper.rb +15 -0
  25. data/app/mailers/spree/vendor_mailer.rb +15 -0
  26. data/app/models/concerns/spree/vendor_concern.rb +11 -0
  27. data/app/models/spree/order_commission.rb +11 -0
  28. data/app/models/spree/vendor.rb +77 -0
  29. data/app/models/spree/vendor_ability.rb +140 -0
  30. data/app/models/spree/vendor_image.rb +18 -0
  31. data/app/models/spree/vendor_order_totals.rb +28 -0
  32. data/app/models/spree/vendor_user.rb +16 -0
  33. data/app/models/spree_multi_vendor/configuration.rb +10 -0
  34. data/app/models/spree_multi_vendor/spree/ability_decorator.rb +9 -0
  35. data/app/models/spree_multi_vendor/spree/base_decorator.rb +13 -0
  36. data/app/models/spree_multi_vendor/spree/line_item_decorator.rb +48 -0
  37. data/app/models/spree_multi_vendor/spree/order_decorator.rb +105 -0
  38. data/app/models/spree_multi_vendor/spree/shipment_decorator.rb +8 -0
  39. data/app/models/spree_multi_vendor/spree/stock/package_decorator.rb +14 -0
  40. data/app/models/spree_multi_vendor/spree/user_decorator.rb +8 -0
  41. data/app/models/spree_multi_vendor/spree/variant_decorator.rb +41 -0
  42. data/app/overrides/spree/admin/orders/_form.rb +13 -0
  43. data/app/overrides/spree/admin/orders/_line_items.rb +6 -0
  44. data/app/overrides/spree/admin/orders/_line_items_edit_form.rb +6 -0
  45. data/app/overrides/spree/admin/orders/index.rb +6 -0
  46. data/app/overrides/spree/admin/products/form.rb +29 -0
  47. data/app/overrides/spree/admin/products/new.rb +16 -0
  48. data/app/overrides/spree/admin/shared/_main_menu.rb +23 -0
  49. data/app/overrides/spree/admin/shared/_order_summary.rb +35 -0
  50. data/app/overrides/spree/admin/users/_form.rb +13 -0
  51. data/app/serializers/spree/v2/storefront/vendor_image_serializer.rb +11 -0
  52. data/app/serializers/spree/v2/storefront/vendor_order_totals_serializer.rb +18 -0
  53. data/app/serializers/spree/v2/storefront/vendor_serializer.rb +14 -0
  54. data/app/serializers/spree_multi_vendor/cart_serializer_decorator.rb +19 -0
  55. data/app/serializers/spree_multi_vendor/serializer_decorator.rb +23 -0
  56. data/app/services/spree/orders/generate_commissions.rb +34 -0
  57. data/app/views/spree/admin/translations/vendor.html.erb +21 -0
  58. data/app/views/spree/admin/vendor_settings/edit.html.erb +47 -0
  59. data/app/views/spree/admin/vendors/_form.html.erb +36 -0
  60. data/app/views/spree/admin/vendors/edit.html.erb +11 -0
  61. data/app/views/spree/admin/vendors/index.html.erb +83 -0
  62. data/app/views/spree/admin/vendors/new.html.erb +11 -0
  63. data/app/views/spree/vendor_mailer/vendor_notification_email.html.erb +81 -0
  64. data/app/views/spree/vendor_mailer/vendor_notification_email.text.erb +36 -0
  65. data/bin/rails +7 -0
  66. data/config/initializers/spree_permitted_attributes.rb +10 -0
  67. data/config/locales/en.yml +34 -0
  68. data/config/locales/es.yml +33 -0
  69. data/config/locales/fr.yml +33 -0
  70. data/config/routes.rb +19 -0
  71. data/db/default/vendors.rb +13 -0
  72. data/db/migrate/20170406102250_create_spree_vendors.rb +9 -0
  73. data/db/migrate/20170406102944_add_vendor_id_to_spree_models.rb +10 -0
  74. data/db/migrate/20170410111150_add_state_to_vendors.rb +6 -0
  75. data/db/migrate/20170412124925_add_deleted_at_to_spree_vendors.rb +6 -0
  76. data/db/migrate/20170413094447_create_spree_vendor_users.rb +11 -0
  77. data/db/migrate/20190212161426_add_slug_to_spree_vendors.rb +6 -0
  78. data/db/migrate/20190214120226_add_about_us_to_spree_vendors.rb +5 -0
  79. data/db/migrate/20190214142526_add_contact_us_to_spree_vendors.rb +5 -0
  80. data/db/migrate/20190305120337_add_commission_to_spree_vendors.rb +5 -0
  81. data/db/migrate/20190308091546_add_priority_to_vendor.rb +8 -0
  82. data/db/migrate/20190312130754_create_spree_order_commissions.rb +14 -0
  83. data/db/migrate/20190322133128_add_notification_email_to_vendors.rb +5 -0
  84. data/db/migrate/20200416030721_add_translations_to_vendor.rb +19 -0
  85. data/gemfiles/spree_4_2.gemfile +9 -0
  86. data/gemfiles/spree_master.gemfile +9 -0
  87. data/lib/generators/spree_multi_vendor/install/install_generator.rb +21 -0
  88. data/lib/generators/spree_multi_vendor/mailers_preview/mailers_preview_generator.rb +22 -0
  89. data/lib/generators/spree_multi_vendor/mailers_preview/templates/mailers/previews/vendor_notification_preview.rb +5 -0
  90. data/lib/spree_multi_vendor.rb +14 -0
  91. data/lib/spree_multi_vendor/engine.rb +24 -0
  92. data/lib/spree_multi_vendor/factories.rb +7 -0
  93. data/lib/spree_multi_vendor/version.rb +11 -0
  94. data/lib/tasks/vendors.rake +8 -0
  95. data/spec/factories/spree/vendor_factory.rb +22 -0
  96. data/spec/factories/spree/vendor_image_factory.rb +5 -0
  97. data/spec/factories/spree/vendor_user_factory.rb +6 -0
  98. data/spec/features/spree/admin/orders_spec.rb +36 -0
  99. data/spec/features/spree/admin/product_spec.rb +177 -0
  100. data/spec/features/spree/admin/shipping_method_spec.rb +72 -0
  101. data/spec/features/spree/admin/stock_location_spec.rb +90 -0
  102. data/spec/features/spree/admin/vendor_settings_spec.rb +76 -0
  103. data/spec/features/spree/admin/vendor_spec.rb +125 -0
  104. data/spec/fixtures/thinking-cat.jpg +0 -0
  105. data/spec/mailers/vendor_mailer_spec.rb +45 -0
  106. data/spec/models/spree/line_item_spec.rb +32 -0
  107. data/spec/models/spree/order_commission_spec.rb +8 -0
  108. data/spec/models/spree/order_spec.rb +179 -0
  109. data/spec/models/spree/product_spec.rb +19 -0
  110. data/spec/models/spree/variant_spec.rb +104 -0
  111. data/spec/models/spree/vendor_order_totals_spec.rb +33 -0
  112. data/spec/models/spree/vendor_spec.rb +57 -0
  113. data/spec/models/spree/vendor_user_spec.rb +12 -0
  114. data/spec/requests/spree/api/v2/storefront/cart_spec.rb +67 -0
  115. data/spec/requests/spree/api/v2/storefront/products_spec.rb +93 -0
  116. data/spec/requests/spree/api/v2/storefront/vendors_spec.rb +52 -0
  117. data/spec/serializers/spree/v2/storefront/stock_location_serializer_spec.rb +32 -0
  118. data/spec/serializers/spree/v2/storefront/vendor_image_serializer_spec.rb +18 -0
  119. data/spec/serializers/spree/v2/storefront/vendor_order_totals_serializer_spec.rb +54 -0
  120. data/spec/serializers/spree/v2/storefront/vendor_serializer_spec.rb +34 -0
  121. data/spec/spec_helper.rb +11 -0
  122. data/spec/support/shoulda_matchers.rb +6 -0
  123. data/spree_multi_vendor.gemspec +41 -0
  124. metadata +313 -0
@@ -0,0 +1,19 @@
1
+ require 'timecop'
2
+
3
+ describe Spree::Product do
4
+ let(:vendor) { create(:vendor) }
5
+ let(:product) { create(:product, vendor: vendor) }
6
+
7
+ context '.whitelisted_ransackable_associations' do
8
+ it { expect(described_class.whitelisted_ransackable_associations).to include('vendor') }
9
+ it { expect(described_class.whitelisted_ransackable_associations.count).to be > 1 }
10
+ end
11
+
12
+ it 'touches vendor after update' do
13
+ time = Time.current + 1.hour
14
+ product
15
+ Timecop.freeze(time) do
16
+ expect { product.touch }.to change { vendor.reload.updated_at }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,104 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::Variant do
4
+ let(:vendor) { create :vendor }
5
+ let(:other_vendor) { create :vendor, name: 'Other vendor' }
6
+ let(:product) { create(:product, vendor: vendor) }
7
+ subject { build(:variant, product: product) }
8
+
9
+ context 'after create' do
10
+ it "propagate to stock items only for Vendor's Stock Locations" do
11
+ expect { create(:variant, product: product) }.to change {
12
+ Spree::StockItem.where(stock_location: vendor.stock_locations.first).count
13
+ }
14
+ end
15
+
16
+ it "doesn't propagate to stock items for other vendors Stock Locations" do
17
+ expect { create(:variant, product: product) }.to_not change {
18
+ Spree::StockItem.where(stock_location: other_vendor.stock_locations.first).count
19
+ }
20
+ end
21
+ end
22
+
23
+ describe '#assign_vendor' do
24
+ context 'product vendorized, variant vendorized' do
25
+ it 'copies from product' do
26
+ expect(subject.attributes['vendor_id']).to be_nil
27
+ subject.save!
28
+ expect(subject.reload.attributes['vendor_id']).to eq(product.vendor_id)
29
+ end
30
+ end
31
+
32
+ context 'product not vendorized, variant vendorized' do
33
+ before do
34
+ SpreeMultiVendor::Config[:vendorized_models] = ['variant']
35
+ end
36
+
37
+ after do
38
+ SpreeMultiVendor::Config[:vendorized_models] = SpreeMultiVendor::Configuration::DEFAULT_VENDORIZED_MODELS
39
+ end
40
+
41
+ context 'no vendor' do
42
+ let(:product) { create(:product) }
43
+
44
+ it { expect { subject.save! }.not_to change { subject.vendor }.from(nil) }
45
+ end
46
+
47
+ context 'vendor assigned' do
48
+ subject { build(:variant, product: product, vendor: vendor) }
49
+
50
+ it { expect { subject.save! }.not_to change { subject.vendor }.from(vendor) }
51
+ end
52
+ end
53
+
54
+ context 'product vendorized, variant not vendorized' do
55
+ before do
56
+ SpreeMultiVendor::Config[:vendorized_models] = ['product']
57
+ end
58
+
59
+ after do
60
+ SpreeMultiVendor::Config[:vendorized_models] = SpreeMultiVendor::Configuration::DEFAULT_VENDORIZED_MODELS
61
+ end
62
+
63
+ it { expect { subject.save! }.not_to raise_error }
64
+ end
65
+ end
66
+
67
+ describe '#vendor' do
68
+ context 'product vendorized, variant vendorized' do
69
+ before { subject.save! }
70
+
71
+ it { expect(subject.vendor).to eq(product.vendor) }
72
+ end
73
+
74
+ context 'product not vendorized, variant vendorized' do
75
+ before do
76
+ SpreeMultiVendor::Config[:vendorized_models] = ['variant']
77
+ end
78
+
79
+ after do
80
+ SpreeMultiVendor::Config[:vendorized_models] = SpreeMultiVendor::Configuration::DEFAULT_VENDORIZED_MODELS
81
+ end
82
+
83
+ let(:product) { create(:product) }
84
+ subject { build(:variant, product: product, vendor: vendor) }
85
+
86
+ it { expect(subject.vendor).to eq(vendor) }
87
+ end
88
+
89
+ context 'product vendorized, variant not vendorized' do
90
+ before do
91
+ SpreeMultiVendor::Config[:vendorized_models] = ['product']
92
+ subject.save!
93
+ end
94
+
95
+ after do
96
+ SpreeMultiVendor::Config[:vendorized_models] = SpreeMultiVendor::Configuration::DEFAULT_VENDORIZED_MODELS
97
+ end
98
+
99
+ it { expect(subject.vendor).to eq(product.vendor) }
100
+ end
101
+ end
102
+
103
+ it { expect(described_class.whitelisted_ransackable_associations).to include('vendor') }
104
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::VendorOrderTotals do
4
+ let(:vendor) { create(:vendor) }
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, stock_location: vendor.stock_locations.first) }
7
+ let!(:promotion) { create(:promotion_with_item_adjustment, adjustment_rate: 10, code: '10off') }
8
+
9
+ subject { described_class.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.coupon_code = '10off'
16
+ Spree::PromotionHandler::Coupon.new(order).apply
17
+ order.reload
18
+ end
19
+
20
+ Spree::VendorOrderTotals::METHOD_NAMES.each do |method_name|
21
+ describe "##{method_name}" do
22
+ it { expect(subject.send(method_name)).to eq(order.send("vendor_#{method_name}", vendor)) }
23
+ end
24
+
25
+ describe "#display_#{method_name}" do
26
+ it { expect(subject.send("display_#{method_name}")).to eq(order.send("display_vendor_#{method_name}", vendor)) }
27
+ end
28
+ end
29
+
30
+ describe '#item_count' do
31
+ it { expect(subject.item_count).to eq(order.vendor_item_count(vendor)) }
32
+ end
33
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::Vendor do
4
+ describe 'associations' do
5
+ it { is_expected.to have_many(:commissions) }
6
+ it { is_expected.to have_many(:products) }
7
+ it { is_expected.to have_many(:shipping_methods) }
8
+ it { is_expected.to have_many(:stock_locations) }
9
+ it { is_expected.to have_many(:variants) }
10
+ it { is_expected.to have_many(:vendor_users) }
11
+ it { is_expected.to have_many(:users).through(:vendor_users) }
12
+ it { is_expected.to have_one(:image) }
13
+ end
14
+
15
+ describe 'validations' do
16
+ it { is_expected.to validate_presence_of(:name) }
17
+ it { is_expected.to allow_value('flower').for(:name) }
18
+ it { is_expected.to allow_value('flower455').for(:name) }
19
+ it { is_expected.to allow_value('flower 455').for(:name) }
20
+ it { is_expected.to allow_value('flower abc').for(:name) }
21
+ it { is_expected.to allow_value('flower455 abc').for(:name) }
22
+ it { is_expected.to allow_value('flower 455 abc').for(:name) }
23
+ it { is_expected.to allow_value('flower & bucket').for(:name) }
24
+ end
25
+
26
+ describe 'initial state' do
27
+ it 'initial state should be pending' do
28
+ should be_pending
29
+ end
30
+ end
31
+
32
+ describe 'after_create' do
33
+ let!(:vendor) { build(:vendor) }
34
+
35
+ it 'creates a stock location with default country' do
36
+ expect { vendor.save! }.to change(Spree::StockLocation, :count).by(1)
37
+ stock_location = Spree::StockLocation.last
38
+ expect(vendor.stock_locations.first).to eq stock_location
39
+ expect(stock_location.country).to eq Spree::Country.default
40
+ end
41
+
42
+ it 'should act as list' do
43
+ expect(vendor).to respond_to(:set_list_position)
44
+ end
45
+ end
46
+
47
+ describe 'after_update' do
48
+ let!(:vendor) { create(:vendor) }
49
+
50
+ it 'updates stock_location names when vendor name changed' do
51
+ old_name = vendor.name
52
+ new_name = 'new vendor name'
53
+ vendor.name = new_name
54
+ expect { vendor.save! }.to change { vendor.stock_locations.pluck(:name).uniq }.from([old_name]).to([new_name])
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::VendorUser do
4
+ describe 'associations' do
5
+ it { is_expected.to belong_to(:vendor) }
6
+ it { is_expected.to belong_to(:user) }
7
+ end
8
+
9
+ describe 'validations' do
10
+ it { is_expected.to validate_uniqueness_of(:vendor_id).scoped_to(:user_id) }
11
+ end
12
+ end
@@ -0,0 +1,67 @@
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 'includes vendor and totals data' 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 'includes line item vendor data' do
46
+ it_behaves_like 'showing the cart'
47
+
48
+ it 'via variants' do
49
+ get '/api/v2/storefront/cart', params: { include: 'variants.vendor' }, headers: headers_bearer
50
+ expect(json_response[:included][0]).to have_id(vendor.id.to_s)
51
+ expect(json_response[:included][0]).to have_type('vendor')
52
+ end
53
+
54
+ it 'via products' do
55
+ get '/api/v2/storefront/cart', params: { include: 'variants.product.vendor' }, headers: headers_bearer
56
+ expect(json_response[:included][0]).to have_id(vendor.id.to_s)
57
+ expect(json_response[:included][0]).to have_type('vendor')
58
+ end
59
+
60
+ it 'via line_items' do
61
+ get '/api/v2/storefront/cart', params: { include: 'line_items.vendor' }, headers: headers_bearer
62
+ expect(json_response[:included][0]).to have_id(vendor.id.to_s)
63
+ expect(json_response[:included][0]).to have_type('vendor')
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,93 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'API V2 Storefront Products Spec', type: :request do
4
+ let!(:products) { create_list(:product, 5) }
5
+ let!(:vendor) { create(:vendor) }
6
+ let!(:vendor_2) { create(:vendor) }
7
+
8
+ before do
9
+ vendors = Spree::Vendor.all.to_a
10
+ products.each do |product|
11
+ product.vendor = vendors.sample
12
+ product.save!
13
+ end
14
+ end
15
+
16
+ describe 'products#index' do
17
+ context 'with no params' do
18
+ before { get '/api/v2/storefront/products' }
19
+
20
+ it_behaves_like 'returns 200 HTTP status'
21
+
22
+ it 'returns all products' do
23
+ expect(json_response['data'].count).to eq Spree::Product.available.count
24
+ expect(json_response['data'].first).to have_type('product')
25
+ end
26
+ end
27
+
28
+ context 'with specified vendor ids' do
29
+ before { get "/api/v2/storefront/products?filter[vendor_ids]=#{vendor.id}&include=vendor" }
30
+
31
+ it_behaves_like 'returns 200 HTTP status'
32
+
33
+ it 'returns products with specified ids' do
34
+ expect(json_response['data'].count).to eq Spree::Product.available.where(vendor_id: vendor.id).count
35
+ expect(json_response['included'].first).to have_id(vendor.id.to_s)
36
+ expect(json_response['included'].first).to have_attribute(:name).with_value(vendor.name)
37
+ expect(json_response['included'].first).to have_attribute(:about_us).with_value(vendor.about_us)
38
+ end
39
+ end
40
+
41
+ context 'with specified multiple filters' do
42
+ before { get "/api/v2/storefront/products?filter[skus]=#{products.first.sku}&filter[vendor_ids]=#{products.first.vendor_id}&include=vendor" }
43
+
44
+ it_behaves_like 'returns 200 HTTP status'
45
+
46
+ it 'returns products with specified SKU and Vendor ID' do
47
+ expect(json_response['data'].count).to eq 1
48
+ expect(json_response['data'].first).to have_id(products.first.id.to_s)
49
+ expect(json_response['included'].first).to have_id(products.first.vendor_id.to_s)
50
+ expect(json_response['included'].first).to have_attribute(:name).with_value(products.first.vendor.name)
51
+ expect(json_response['included'].first).to have_attribute(:about_us).with_value(products.first.vendor.about_us)
52
+ end
53
+ end
54
+ end
55
+
56
+ describe 'products#show' do
57
+ let(:product) { products.first }
58
+
59
+ context 'with existing product' do
60
+ before { get "/api/v2/storefront/products/#{product.slug}?include=vendor" }
61
+
62
+ it_behaves_like 'returns 200 HTTP status'
63
+
64
+ it 'returns a valid JSON response' do
65
+ expect(json_response['data']).to have_id(product.id.to_s)
66
+
67
+ expect(json_response['data']).to have_type('product')
68
+
69
+ expect(json_response['data']).to have_attribute(:name).with_value(product.name)
70
+ expect(json_response['data']).to have_attribute(:description).with_value(product.description)
71
+ expect(json_response['data']).to have_attribute(:price).with_value(product.price.to_s)
72
+ expect(json_response['data']).to have_attribute(:currency).with_value(product.currency)
73
+ expect(json_response['data']).to have_attribute(:display_price).with_value(product.display_price.to_s)
74
+ expect(json_response['data']).to have_attribute(:available_on).with_value(product.available_on.as_json)
75
+ expect(json_response['data']).to have_attribute(:slug).with_value(product.slug)
76
+ expect(json_response['data']).to have_attribute(:meta_description).with_value(product.meta_description)
77
+ expect(json_response['data']).to have_attribute(:meta_keywords).with_value(product.meta_keywords)
78
+ expect(json_response['data']).to have_attribute(:updated_at).with_value(product.updated_at.as_json)
79
+ expect(json_response['data']).to have_attribute(:purchasable).with_value(product.purchasable?)
80
+ expect(json_response['data']).to have_attribute(:in_stock).with_value(product.in_stock?)
81
+ expect(json_response['data']).to have_attribute(:backorderable).with_value(product.backorderable?)
82
+
83
+ expect(json_response['data']).to have_relationships(
84
+ :variants, :option_types, :product_properties, :default_variant, :vendor
85
+ )
86
+
87
+ expect(json_response['included'].first).to have_id(product.vendor_id.to_s)
88
+ expect(json_response['included'].first).to have_attribute(:name).with_value(product.vendor.name)
89
+ expect(json_response['included'].first).to have_attribute(:about_us).with_value(product.vendor.about_us)
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,52 @@
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
+
9
+ describe 'vendors#show' do
10
+ context 'with invalid slug param' do
11
+ before { get '/api/v2/storefront/vendors/vendor1' }
12
+
13
+ it_behaves_like 'returns 404 HTTP status'
14
+ end
15
+
16
+ context 'with valid slug param' do
17
+ before { get "/api/v2/storefront/vendors/#{vendor.slug}" }
18
+
19
+ it_behaves_like 'returns 200 HTTP status'
20
+
21
+ it 'returns one vendor' do
22
+ json_response = JSON.parse(response.body)
23
+ expect(json_response.count).to eq 1
24
+ expect(json_response['data']['type']).to eq('vendor')
25
+ end
26
+
27
+ it 'does not return included' do
28
+ json_response = JSON.parse(response.body)
29
+ expect(json_response.keys).to contain_exactly('data')
30
+ end
31
+ end
32
+
33
+ context 'with products and images included' do
34
+ before { get "/api/v2/storefront/vendors/#{vendor.slug}?include=products,image" }
35
+
36
+ it_behaves_like 'returns 200 HTTP status'
37
+
38
+ it 'returns product information' do
39
+ json_response = JSON.parse(response.body)
40
+ expect(json_response.keys).to contain_exactly('data', 'included')
41
+ expect(json_response['included'].first['id']).to eq(product.id.to_s)
42
+ end
43
+
44
+ it 'returns image information' do
45
+ json_response = JSON.parse(response.body)
46
+ expect(json_response.keys).to contain_exactly('data', 'included')
47
+
48
+ expect(json_response['included'].second['id']).to eq(vendor_image.id.to_s)
49
+ end
50
+ end
51
+ end
52
+ end