solidus_api 2.10.3 → 2.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/app/controllers/spree/api/addresses_controller.rb +1 -1
  4. data/app/controllers/spree/api/base_controller.rb +11 -3
  5. data/app/controllers/spree/api/checkouts_controller.rb +1 -11
  6. data/app/controllers/spree/api/countries_controller.rb +2 -2
  7. data/app/controllers/spree/api/credit_cards_controller.rb +2 -2
  8. data/app/controllers/spree/api/customer_returns_controller.rb +67 -0
  9. data/app/controllers/spree/api/images_controller.rb +4 -4
  10. data/app/controllers/spree/api/inventory_units_controller.rb +1 -1
  11. data/app/controllers/spree/api/option_types_controller.rb +3 -3
  12. data/app/controllers/spree/api/option_values_controller.rb +2 -2
  13. data/app/controllers/spree/api/orders_controller.rb +1 -1
  14. data/app/controllers/spree/api/payments_controller.rb +1 -1
  15. data/app/controllers/spree/api/product_properties_controller.rb +9 -14
  16. data/app/controllers/spree/api/promotions_controller.rb +3 -12
  17. data/app/controllers/spree/api/properties_controller.rb +3 -3
  18. data/app/controllers/spree/api/resource_controller.rb +2 -2
  19. data/app/controllers/spree/api/return_authorizations_controller.rb +3 -3
  20. data/app/controllers/spree/api/shipments_controller.rb +1 -1
  21. data/app/controllers/spree/api/states_controller.rb +3 -3
  22. data/app/controllers/spree/api/stock_items_controller.rb +2 -2
  23. data/app/controllers/spree/api/stock_locations_controller.rb +3 -3
  24. data/app/controllers/spree/api/stock_movements_controller.rb +3 -3
  25. data/app/controllers/spree/api/stores_controller.rb +3 -3
  26. data/app/controllers/spree/api/taxonomies_controller.rb +2 -2
  27. data/app/controllers/spree/api/taxons_controller.rb +4 -4
  28. data/app/controllers/spree/api/users_controller.rb +13 -0
  29. data/app/controllers/spree/api/variants_controller.rb +3 -3
  30. data/app/controllers/spree/api/zones_controller.rb +2 -2
  31. data/app/helpers/spree/api/api_helpers.rb +18 -5
  32. data/app/views/spree/api/customer_returns/index.json.jbuilder +6 -0
  33. data/app/views/spree/api/customer_returns/new.json.jbuilder +4 -0
  34. data/app/views/spree/api/customer_returns/show.json.jbuilder +3 -0
  35. data/app/views/spree/api/errors/could_not_transition.json.jbuilder +4 -0
  36. data/app/views/spree/api/orders/could_not_transition.json.jbuilder +5 -0
  37. data/config/locales/en.yml +2 -0
  38. data/config/routes.rb +6 -3
  39. data/lib/spree/api/testing_support/helpers.rb +1 -1
  40. data/openapi/authentication.md +9 -1
  41. data/openapi/checkout-flow.md +17 -4
  42. data/openapi/main.hub.yml +1 -1
  43. data/openapi/solidus-api.oas.yml +6753 -0
  44. data/solidus_api.gemspec +19 -19
  45. metadata +14 -114
  46. data/openapi/api.oas2.yml +0 -6108
  47. data/script/rails +0 -10
  48. data/spec/controllers/spree/api/base_controller_spec.rb +0 -118
  49. data/spec/controllers/spree/api/resource_controller_spec.rb +0 -190
  50. data/spec/features/checkout_spec.rb +0 -192
  51. data/spec/fixtures/thinking-cat.jpg +0 -0
  52. data/spec/lib/spree_api_responders_spec.rb +0 -10
  53. data/spec/models/spree/legacy_user_spec.rb +0 -103
  54. data/spec/requests/api/address_books_spec.rb +0 -240
  55. data/spec/requests/jbuilder_cache_spec.rb +0 -34
  56. data/spec/requests/ransackable_attributes_spec.rb +0 -79
  57. data/spec/requests/spree/api/addresses_controller_spec.rb +0 -57
  58. data/spec/requests/spree/api/checkouts_controller_spec.rb +0 -484
  59. data/spec/requests/spree/api/classifications_controller_spec.rb +0 -50
  60. data/spec/requests/spree/api/config_controller_spec.rb +0 -26
  61. data/spec/requests/spree/api/countries_controller_spec.rb +0 -48
  62. data/spec/requests/spree/api/coupon_codes_controller_spec.rb +0 -105
  63. data/spec/requests/spree/api/credit_cards_controller_spec.rb +0 -105
  64. data/spec/requests/spree/api/images_controller_spec.rb +0 -99
  65. data/spec/requests/spree/api/inventory_units_controller_spec.rb +0 -55
  66. data/spec/requests/spree/api/line_items_controller_spec.rb +0 -213
  67. data/spec/requests/spree/api/option_types_controller_spec.rb +0 -116
  68. data/spec/requests/spree/api/option_values_controller_spec.rb +0 -138
  69. data/spec/requests/spree/api/orders_controller_spec.rb +0 -954
  70. data/spec/requests/spree/api/payments_controller_spec.rb +0 -259
  71. data/spec/requests/spree/api/product_properties_controller_spec.rb +0 -114
  72. data/spec/requests/spree/api/products_controller_spec.rb +0 -422
  73. data/spec/requests/spree/api/promotion_application_spec.rb +0 -50
  74. data/spec/requests/spree/api/promotions_controller_spec.rb +0 -67
  75. data/spec/requests/spree/api/properties_controller_spec.rb +0 -102
  76. data/spec/requests/spree/api/return_authorizations_controller_spec.rb +0 -180
  77. data/spec/requests/spree/api/shipments_controller_spec.rb +0 -532
  78. data/spec/requests/spree/api/states_controller_spec.rb +0 -69
  79. data/spec/requests/spree/api/stock_items_controller_spec.rb +0 -311
  80. data/spec/requests/spree/api/stock_locations_controller_spec.rb +0 -170
  81. data/spec/requests/spree/api/stock_movements_controller_spec.rb +0 -81
  82. data/spec/requests/spree/api/store_credit_events_controller_spec.rb +0 -59
  83. data/spec/requests/spree/api/stores_controller_spec.rb +0 -134
  84. data/spec/requests/spree/api/taxonomies_controller_spec.rb +0 -114
  85. data/spec/requests/spree/api/taxons_controller_spec.rb +0 -217
  86. data/spec/requests/spree/api/unauthenticated_products_controller_spec.rb +0 -27
  87. data/spec/requests/spree/api/users_controller_spec.rb +0 -151
  88. data/spec/requests/spree/api/variants_controller_spec.rb +0 -340
  89. data/spec/requests/spree/api/zones_controller_spec.rb +0 -89
  90. data/spec/shared_examples/protect_product_actions.rb +0 -18
  91. data/spec/spec_helper.rb +0 -73
  92. data/spec/support/be_paginated_matcher.rb +0 -9
  93. data/spec/support/controller_hacks.rb +0 -43
  94. data/spec/support/database_cleaner.rb +0 -16
  95. data/spec/support/have_attributes_matcher.rb +0 -11
  96. data/spec/test_views/spree/api/widgets/_widget.json.jbuilder +0 -3
  97. data/spec/test_views/spree/api/widgets/index.json.jbuilder +0 -9
  98. data/spec/test_views/spree/api/widgets/new.json.jbuilder +0 -3
  99. data/spec/test_views/spree/api/widgets/show.json.jbuilder +0 -3
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'shared_examples/protect_product_actions'
4
- require 'spec_helper'
5
-
6
- module Spree
7
- describe Spree::Api::ProductsController, type: :request do
8
- let!(:product) { create(:product) }
9
- let(:attributes) { [:id, :name, :description, :price, :available_on, :slug, :meta_description, :meta_keywords, :taxon_ids, :meta_title] }
10
-
11
- context "without authentication" do
12
- before do
13
- stub_spree_preferences(Spree::Api::Config, requires_authentication: false)
14
- end
15
-
16
- it "retrieves a list of products" do
17
- get spree.api_products_path
18
- expect(json_response["products"].first).to have_attributes(attributes)
19
- expect(json_response["count"]).to eq(1)
20
- expect(json_response["current_page"]).to eq(1)
21
- expect(json_response["pages"]).to eq(1)
22
- end
23
-
24
- it_behaves_like "modifying product actions are restricted"
25
- end
26
- end
27
- end
@@ -1,151 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- module Spree
6
- describe Api::UsersController, type: :request do
7
- let(:user) { create(:user, spree_api_key: SecureRandom.hex) }
8
- let(:stranger) { create(:user, email: 'stranger@example.com') }
9
- let(:attributes) { [:id, :email, :created_at, :updated_at] }
10
-
11
- context "as a normal user" do
12
- it "can get own details" do
13
- get spree.api_user_path(user.id), params: { token: user.spree_api_key }
14
-
15
- expect(json_response['email']).to eq user.email
16
- end
17
-
18
- it "cannot get other users details" do
19
- get spree.api_user_path(stranger.id), params: { token: user.spree_api_key }
20
-
21
- assert_not_found!
22
- end
23
-
24
- it "can learn how to create a new user" do
25
- get spree.new_api_user_path, params: { token: user.spree_api_key }
26
- expect(json_response["attributes"]).to eq(attributes.map(&:to_s))
27
- end
28
-
29
- it "can create a new user" do
30
- user_params = {
31
- email: 'new@example.com', password: 'spree123', password_confirmation: 'spree123'
32
- }
33
-
34
- post spree.api_users_path, params: { user: user_params, token: user.spree_api_key }
35
- expect(json_response['email']).to eq 'new@example.com'
36
- end
37
-
38
- # there's no validations on LegacyUser?
39
- xit "cannot create a new user with invalid attributes" do
40
- post spree.api_users_path, params: { user: {}, token: user.spree_api_key }
41
- expect(response.status).to eq(422)
42
- expect(json_response["error"]).to eq("Invalid resource. Please fix errors and try again.")
43
- end
44
-
45
- it "can update own details" do
46
- country = create(:country)
47
- put spree.api_user_path(user.id), params: { token: user.spree_api_key, user: {
48
- email: "mine@example.com",
49
- bill_address_attributes: {
50
- first_name: 'First',
51
- last_name: 'Last',
52
- address1: '1 Test Rd',
53
- city: 'City',
54
- country_id: country.id,
55
- state_id: 1,
56
- zipcode: '55555',
57
- phone: '5555555555'
58
- },
59
- ship_address_attributes: {
60
- first_name: 'First',
61
- last_name: 'Last',
62
- address1: '1 Test Rd',
63
- city: 'City',
64
- country_id: country.id,
65
- state_id: 1,
66
- zipcode: '55555',
67
- phone: '5555555555'
68
- }
69
- } }
70
- expect(json_response['email']).to eq 'mine@example.com'
71
- expect(json_response['bill_address']).to_not be_nil
72
- expect(json_response['ship_address']).to_not be_nil
73
- end
74
-
75
- it "cannot update other users details" do
76
- put spree.api_user_path(stranger.id), params: { token: user.spree_api_key, user: { email: "mine@example.com" } }
77
- assert_not_found!
78
- end
79
-
80
- it "cannot delete itself" do
81
- delete spree.api_user_path(user.id), params: { token: user.spree_api_key }
82
- expect(response.status).to eq(401)
83
- end
84
-
85
- it "cannot delete other user" do
86
- delete spree.api_user_path(stranger.id), params: { token: user.spree_api_key }
87
- assert_not_found!
88
- end
89
-
90
- it "should only get own details on index" do
91
- 2.times { create(:user) }
92
- get spree.api_users_path, params: { token: user.spree_api_key }
93
-
94
- expect(Spree.user_class.count).to eq 3
95
- expect(json_response['count']).to eq 1
96
- expect(json_response['users'].size).to eq 1
97
- end
98
- end
99
-
100
- context "as an admin" do
101
- before { stub_authentication! }
102
-
103
- sign_in_as_admin!
104
-
105
- it "gets all users" do
106
- allow(Spree::LegacyUser).to receive(:find_by).with(hash_including(:spree_api_key)) { current_api_user }
107
-
108
- 2.times { create(:user) }
109
-
110
- get spree.api_users_path
111
- expect(Spree.user_class.count).to eq 2
112
- expect(json_response['count']).to eq 2
113
- expect(json_response['users'].size).to eq 2
114
- end
115
-
116
- it 'can control the page size through a parameter' do
117
- 2.times { create(:user) }
118
- get spree.api_users_path, params: { per_page: 1 }
119
- expect(json_response['count']).to eq(1)
120
- expect(json_response['current_page']).to eq(1)
121
- expect(json_response['pages']).to eq(2)
122
- end
123
-
124
- it 'can query the results through a paramter' do
125
- expected_result = create(:user, email: 'brian@spreecommerce.com')
126
- get spree.api_users_path, params: { q: { email_cont: 'brian' } }
127
- expect(json_response['count']).to eq(1)
128
- expect(json_response['users'].first['email']).to eq expected_result.email
129
- end
130
-
131
- it "can create" do
132
- post spree.api_users_path, params: { user: { email: "new@example.com", password: 'spree123', password_confirmation: 'spree123' } }
133
- expect(json_response).to have_attributes(attributes)
134
- expect(response.status).to eq(201)
135
- end
136
-
137
- it "can destroy user without orders" do
138
- user.orders.destroy_all
139
- delete spree.api_user_path(user)
140
- expect(response.status).to eq(204)
141
- end
142
-
143
- it "cannot destroy user with orders" do
144
- create(:completed_order_with_totals, user: user)
145
- delete spree.api_user_path(user)
146
- expect(response.status).to eq(422)
147
- expect(json_response).to eq({ "error" => "Cannot delete record." })
148
- end
149
- end
150
- end
151
- end
@@ -1,340 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- module Spree
6
- describe Api::VariantsController, type: :request do
7
- let!(:product) { create(:product) }
8
- let!(:variant) do
9
- variant = product.master
10
- variant.option_values << create(:option_value)
11
- variant
12
- end
13
-
14
- let!(:base_attributes) { Api::ApiHelpers.variant_attributes }
15
- let!(:show_attributes) { base_attributes.dup.push(:in_stock, :display_price, :variant_properties) }
16
- let!(:new_attributes) { base_attributes }
17
-
18
- before do
19
- stub_authentication!
20
- end
21
-
22
- describe "#index" do
23
- it "can see a paginated list of variants" do
24
- get spree.api_variants_path
25
- first_variant = json_response["variants"].first
26
- expect(first_variant).to have_attributes(show_attributes)
27
- expect(first_variant["stock_items"]).to be_present
28
- expect(json_response["count"]).to eq(1)
29
- expect(json_response["current_page"]).to eq(1)
30
- expect(json_response["pages"]).to eq(1)
31
- end
32
-
33
- it 'can control the page size through a parameter' do
34
- create(:variant)
35
- get spree.api_variants_path, params: { per_page: 1 }
36
- expect(json_response['count']).to eq(1)
37
- expect(json_response['current_page']).to eq(1)
38
- expect(json_response['pages']).to eq(3)
39
- end
40
-
41
- it 'can query the results through a paramter' do
42
- expected_result = create(:variant, sku: 'FOOBAR')
43
- get spree.api_variants_path, params: { q: { sku_cont: 'FOO' } }
44
- expect(json_response['count']).to eq(1)
45
- expect(json_response['variants'].first['sku']).to eq expected_result.sku
46
- end
47
-
48
- it "variants returned contain option values data" do
49
- get spree.api_variants_path
50
- option_values = json_response["variants"].last["option_values"]
51
- expect(option_values.first).to have_attributes([:name,
52
- :presentation,
53
- :option_type_name,
54
- :option_type_id])
55
- end
56
-
57
- it "variants returned contain images data" do
58
- variant.images.create!(attachment: image("thinking-cat.jpg"))
59
-
60
- get spree.api_variants_path
61
-
62
- expect(json_response["variants"].last).to have_attributes([:images])
63
- expect(json_response['variants'].first['images'].first).to have_attributes([:attachment_file_name,
64
- :attachment_width,
65
- :attachment_height,
66
- :attachment_content_type,
67
- :mini_url,
68
- :small_url,
69
- :product_url,
70
- :large_url])
71
- end
72
-
73
- # Regression test for https://github.com/spree/spree/issues/2141
74
- context "a deleted variant" do
75
- before do
76
- variant.update_column(:deleted_at, Time.current)
77
- end
78
-
79
- it "is not returned in the results" do
80
- get spree.api_variants_path
81
- expect(json_response["variants"].count).to eq(0)
82
- end
83
-
84
- it "is not returned even when show_deleted is passed" do
85
- get spree.api_variants_path, params: { show_deleted: true }
86
- expect(json_response["variants"].count).to eq(0)
87
- end
88
- end
89
-
90
- context "stock filtering" do
91
- context "only variants in stock" do
92
- subject { get spree.api_variants_path, params: { in_stock_only: "true" } }
93
-
94
- context "variant is out of stock" do
95
- before do
96
- variant.stock_items.update_all(count_on_hand: 0)
97
- end
98
-
99
- it "is not returned in the results" do
100
- subject
101
- expect(json_response["variants"].count).to eq 0
102
- end
103
- end
104
-
105
- context "variant is in stock" do
106
- before do
107
- variant.stock_items.update_all(count_on_hand: 10)
108
- end
109
-
110
- it "is returned in the results" do
111
- subject
112
- expect(json_response["variants"].count).to eq 1
113
- end
114
- end
115
- end
116
-
117
- context "only suplliable variants" do
118
- subject { get spree.api_variants_path, params: { suppliable_only: "true" } }
119
-
120
- context "variant is backorderable" do
121
- before do
122
- variant.stock_items.update_all(count_on_hand: 0, backorderable: true)
123
- end
124
-
125
- it "is not returned in the results" do
126
- subject
127
- expect(json_response["variants"].count).to eq 1
128
- end
129
- end
130
-
131
- context "variant is unsuppliable" do
132
- before do
133
- variant.stock_items.update_all(count_on_hand: 0, backorderable: false)
134
- end
135
-
136
- it "is returned in the results" do
137
- subject
138
- expect(json_response["variants"].count).to eq 0
139
- end
140
- end
141
- end
142
-
143
- context "all variants" do
144
- subject { get spree.api_variants_path, params: { in_stock_only: "false" } }
145
-
146
- context "variant is out of stock" do
147
- before do
148
- variant.stock_items.update_all(count_on_hand: 0)
149
- end
150
-
151
- it "is returned in the results" do
152
- subject
153
- expect(json_response["variants"].count).to eq 1
154
- end
155
- end
156
-
157
- context "variant is in stock" do
158
- before do
159
- variant.stock_items.update_all(count_on_hand: 10)
160
- end
161
-
162
- it "is returned in the results" do
163
- subject
164
- expect(json_response["variants"].count).to eq 1
165
- end
166
- end
167
- end
168
- end
169
-
170
- context "pagination" do
171
- it "can select the next page of variants" do
172
- create(:variant)
173
- get spree.api_variants_path, params: { page: 2, per_page: 1 }
174
- expect(json_response["variants"].first).to have_attributes(show_attributes)
175
- expect(json_response["total_count"]).to eq(3)
176
- expect(json_response["current_page"]).to eq(2)
177
- expect(json_response["pages"]).to eq(3)
178
- end
179
- end
180
-
181
- context "stock item filter" do
182
- let(:stock_location) { variant.stock_locations.first }
183
- let!(:inactive_stock_location) { create(:stock_location, propagate_all_variants: true, name: "My special stock location", active: false) }
184
-
185
- it "only returns stock items for active stock locations" do
186
- get spree.api_variants_path
187
- variant = json_response['variants'].first
188
- stock_items = variant['stock_items'].map { |si| si['stock_location_name'] }
189
-
190
- expect(stock_items).to include stock_location.name
191
- expect(stock_items).not_to include inactive_stock_location.name
192
- end
193
- end
194
- end
195
-
196
- describe "#show" do
197
- subject do
198
- get spree.api_variant_path(variant)
199
- end
200
-
201
- it "can see a single variant" do
202
- subject
203
- expect(json_response).to have_attributes(show_attributes)
204
- expect(json_response["stock_items"]).to be_present
205
- option_values = json_response["option_values"]
206
- expect(option_values.first).to have_attributes([:name,
207
- :presentation,
208
- :option_type_name,
209
- :option_type_id])
210
- end
211
-
212
- it "can see a single variant with images" do
213
- variant.images.create!(attachment: image("thinking-cat.jpg"))
214
-
215
- subject
216
-
217
- expect(json_response).to have_attributes(show_attributes + [:images])
218
- option_values = json_response["option_values"]
219
- expect(option_values.first).to have_attributes([:name,
220
- :presentation,
221
- :option_type_name,
222
- :option_type_id])
223
- end
224
-
225
- context "variant doesn't have variant properties" do
226
- before { subject }
227
-
228
- it "contains the expected attributes" do
229
- expect(json_response).to have_attributes(show_attributes)
230
- end
231
-
232
- it "variant properties is an empty list" do
233
- expect(json_response["variant_properties"]).to eq []
234
- end
235
- end
236
-
237
- context "variant has variant properties" do
238
- let!(:rule) { create(:variant_property_rule, product: variant.product, option_value: variant.option_values.first) }
239
-
240
- before { subject }
241
-
242
- it "contains the expected attributes" do
243
- expect(json_response).to have_attributes(show_attributes)
244
- end
245
-
246
- it "variant properties is an array of variant property values" do
247
- expected_attrs = [:id, :property_id, :value, :property_name]
248
- expect(json_response["variant_properties"].first).to have_attributes(expected_attrs)
249
- end
250
- end
251
-
252
- context "when tracking is disabled" do
253
- before do
254
- stub_spree_preferences(track_inventory_levels: false)
255
- subject
256
- end
257
-
258
- it "still displays valid json with total_on_hand Float::INFINITY" do
259
- expect(response.status).to eq(200)
260
- expect(json_response['total_on_hand']).to eq nil
261
- end
262
- end
263
- end
264
-
265
- it "can learn how to create a new variant" do
266
- get spree.new_api_variant_path(variant)
267
- expect(json_response["attributes"]).to eq(new_attributes.map(&:to_s))
268
- expect(json_response["required_attributes"]).to be_empty
269
- end
270
-
271
- it "cannot create a new variant if not an admin" do
272
- post spree.api_variants_path, params: { variant: { sku: "12345" } }
273
- assert_unauthorized!
274
- end
275
-
276
- it "cannot update a variant" do
277
- put spree.api_variant_path(variant), params: { variant: { sku: "12345" } }
278
- assert_not_found!
279
- end
280
-
281
- it "cannot delete a variant" do
282
- delete spree.api_variant_path(variant)
283
- assert_not_found!
284
- expect { variant.reload }.not_to raise_error
285
- end
286
-
287
- context "as an admin" do
288
- sign_in_as_admin!
289
-
290
- # Test for https://github.com/spree/spree/issues/2141
291
- context "deleted variants" do
292
- before do
293
- variant.update_column(:deleted_at, Time.current)
294
- end
295
-
296
- it "are visible by admin" do
297
- get spree.api_variants_path, params: { show_deleted: 1 }
298
- expect(json_response["variants"].count).to eq(1)
299
- end
300
- end
301
-
302
- it "can create a new variant" do
303
- post spree.api_product_variants_path(product), params: { variant: { sku: "12345" } }
304
- expect(json_response).to have_attributes(new_attributes)
305
- expect(response.status).to eq(201)
306
- expect(json_response["sku"]).to eq("12345")
307
-
308
- expect(variant.product.variants.count).to eq(1)
309
- end
310
-
311
- it "creates new variants with nested option values" do
312
- option_values = create_list(:option_value, 2)
313
- expect do
314
- post spree.api_product_variants_path(product), params: {
315
- variant: {
316
- sku: "12345",
317
- option_value_ids: option_values.map(&:id)
318
- }
319
- }
320
- end.to change { Spree::OptionValuesVariant.count }.by(2)
321
- end
322
-
323
- it "can update a variant" do
324
- put spree.api_variant_path(variant), params: { variant: { sku: "12345" } }
325
- expect(response.status).to eq(200)
326
- end
327
-
328
- it "can delete a variant" do
329
- delete spree.api_variant_path(variant)
330
- expect(response.status).to eq(204)
331
- expect { Spree::Variant.find(variant.id) }.to raise_error(ActiveRecord::RecordNotFound)
332
- end
333
-
334
- it 'variants returned contain cost price data' do
335
- get spree.api_variants_path
336
- expect(json_response["variants"].first.key?(:cost_price)).to eq true
337
- end
338
- end
339
- end
340
- end