solidus_api 2.10.0 → 2.11.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 (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 +18 -15
  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 +8 -2
  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 +11 -2
  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 +17 -117
  46. data/openapi/api.oas2.yml +0 -6105
  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 -456
  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 -931
  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,259 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- module Spree
6
- describe Spree::Api::PaymentsController, type: :request do
7
- let!(:order) { create(:order) }
8
- let!(:payment) { create(:payment, order: order) }
9
- let!(:attributes) {
10
- [:id, :source_type, :source_id, :amount, :display_amount,
11
- :payment_method_id, :state, :avs_response,
12
- :created_at, :updated_at]
13
- }
14
-
15
- before do
16
- stub_authentication!
17
- end
18
-
19
- context "as a user" do
20
- context "when the order belongs to the user" do
21
- before do
22
- allow_any_instance_of(Order).to receive_messages user: current_api_user
23
- end
24
-
25
- it "can view the payments for their order" do
26
- get spree.api_order_payments_path(order)
27
- expect(json_response["payments"].first).to have_attributes(attributes)
28
- end
29
-
30
- it "can learn how to create a new payment" do
31
- get spree.new_api_order_payment_path(order)
32
- expect(json_response["attributes"]).to eq(attributes.map(&:to_s))
33
- expect(json_response["payment_methods"]).not_to be_empty
34
- expect(json_response["payment_methods"].first).to have_attributes([:id, :name, :description])
35
- end
36
-
37
- context "payment source is not required" do
38
- before do
39
- allow_any_instance_of(Spree::PaymentMethod::BogusCreditCard).to receive(:source_required?).and_return(false)
40
- end
41
-
42
- it "can create a new payment" do
43
- post spree.api_order_payments_path(order), params: { payment: { payment_method_id: PaymentMethod.first.id, amount: 50 } }
44
- expect(response.status).to eq(201)
45
- expect(json_response).to have_attributes(attributes)
46
- end
47
-
48
- context "disallowed payment method" do
49
- it "does not create a new payment" do
50
- PaymentMethod.first.update!(available_to_users: false)
51
-
52
- expect {
53
- post spree.api_order_payments_path(order), params: { payment: { payment_method_id: PaymentMethod.first.id, amount: 50 } }
54
- }.not_to change { Spree::Payment.count }
55
- expect(response.status).to eq(404)
56
- end
57
- end
58
- end
59
-
60
- context "payment source is required" do
61
- context "no source is provided" do
62
- it "returns errors" do
63
- post spree.api_order_payments_path(order), params: { payment: { payment_method_id: PaymentMethod.first.id, amount: 50 } }
64
- expect(response.status).to eq(422)
65
- expect(json_response['error']).to eq("Invalid resource. Please fix errors and try again.")
66
- expect(json_response['errors']['source']).to eq(["can't be blank"])
67
- end
68
- end
69
-
70
- context "source is provided" do
71
- it "can create a new payment" do
72
- post spree.api_order_payments_path(order), params: { payment: { payment_method_id: PaymentMethod.first.id, amount: 50, source_attributes: { gateway_payment_profile_id: 1 } } }
73
- expect(response.status).to eq(201)
74
- expect(json_response).to have_attributes(attributes)
75
- end
76
- end
77
- end
78
-
79
- it "can view a pre-existing payment's details" do
80
- get spree.api_order_payment_path(order, payment)
81
- expect(json_response).to have_attributes(attributes)
82
- end
83
-
84
- it "cannot update a payment" do
85
- put spree.api_order_payment_path(order, payment), params: { payment: { amount: 2.01 } }
86
- assert_unauthorized!
87
- end
88
-
89
- it "cannot authorize a payment" do
90
- put spree.authorize_api_order_payment_path(order, payment)
91
- assert_unauthorized!
92
- end
93
- end
94
-
95
- context "when the order does not belong to the user" do
96
- before do
97
- allow_any_instance_of(Order).to receive_messages user: stub_model(LegacyUser)
98
- end
99
-
100
- it "cannot view payments for somebody else's order" do
101
- get spree.api_order_payments_path(order)
102
- assert_unauthorized!
103
- end
104
-
105
- it "can view the payments for an order given the order token" do
106
- get spree.api_order_payments_path(order), params: { order_token: order.guest_token }
107
- expect(json_response["payments"].first).to have_attributes(attributes)
108
- end
109
- end
110
- end
111
-
112
- context "as an admin" do
113
- sign_in_as_admin!
114
-
115
- it "can view the payments on any order" do
116
- get spree.api_order_payments_path(order)
117
- expect(response.status).to eq(200)
118
- expect(json_response["payments"].first).to have_attributes(attributes)
119
- end
120
-
121
- context "multiple payments" do
122
- before { @payment = create(:payment, order: order) }
123
-
124
- it "can view all payments on an order" do
125
- get spree.api_order_payments_path(order)
126
- expect(json_response["count"]).to eq(2)
127
- end
128
-
129
- it 'can control the page size through a parameter' do
130
- get spree.api_order_payments_path(order), params: { per_page: 1 }
131
- expect(json_response['count']).to eq(1)
132
- expect(json_response['current_page']).to eq(1)
133
- expect(json_response['pages']).to eq(2)
134
- end
135
- end
136
-
137
- context "for a given payment" do
138
- context "updating" do
139
- it "can update" do
140
- payment.update(state: 'pending')
141
- put spree.api_order_payment_path(order, payment), params: { payment: { amount: 2.01 } }
142
- expect(response.status).to eq(200)
143
- expect(payment.reload.amount).to eq(2.01)
144
- end
145
-
146
- context "update fails" do
147
- it "returns a 422 status when the amount is invalid" do
148
- payment.update(state: 'pending')
149
- put spree.api_order_payment_path(order, payment), params: { payment: { amount: 'invalid' } }
150
- expect(response.status).to eq(422)
151
- expect(json_response["error"]).to eq("Invalid resource. Please fix errors and try again.")
152
- end
153
-
154
- it "returns a 403 status when the payment is not pending" do
155
- payment.update(state: 'completed')
156
- put spree.api_order_payment_path(order, payment), params: { payment: { amount: 2.01 } }
157
- expect(response.status).to eq(403)
158
- expect(json_response["error"]).to eq("This payment cannot be updated because it is completed.")
159
- end
160
- end
161
- end
162
-
163
- context "authorizing" do
164
- it "can authorize" do
165
- put spree.authorize_api_order_payment_path(order, payment)
166
- expect(response.status).to eq(200)
167
- expect(payment.reload.state).to eq("pending")
168
- end
169
-
170
- context "authorization fails" do
171
- before do
172
- fake_response = double(success?: false, to_s: "Could not authorize card")
173
- expect_any_instance_of(Spree::PaymentMethod::BogusCreditCard).to receive(:authorize).and_return(fake_response)
174
- put spree.authorize_api_order_payment_path(order, payment)
175
- end
176
-
177
- it "returns a 422 status" do
178
- expect(response.status).to eq(422)
179
- expect(json_response["error"]).to eq "Invalid resource. Please fix errors and try again."
180
- expect(json_response["errors"]["base"][0]).to eq "Could not authorize card"
181
- end
182
-
183
- it "does not raise a stack level error" do
184
- skip "Investigate why a payment.reload after the request raises 'stack level too deep'"
185
- expect(payment.reload.state).to eq("failed")
186
- end
187
- end
188
- end
189
-
190
- context "capturing" do
191
- it "can capture" do
192
- put spree.capture_api_order_payment_path(order, payment)
193
- expect(response.status).to eq(200)
194
- expect(payment.reload.state).to eq("completed")
195
- end
196
-
197
- context "capturing fails" do
198
- before do
199
- fake_response = double(success?: false, to_s: "Insufficient funds")
200
- expect_any_instance_of(Spree::PaymentMethod::BogusCreditCard).to receive(:capture).and_return(fake_response)
201
- end
202
-
203
- it "returns a 422 status" do
204
- put spree.capture_api_order_payment_path(order, payment)
205
- expect(response.status).to eq(422)
206
- expect(json_response["error"]).to eq "Invalid resource. Please fix errors and try again."
207
- expect(json_response["errors"]["base"][0]).to eq "Insufficient funds"
208
- end
209
- end
210
- end
211
-
212
- context "purchasing" do
213
- it "can purchase" do
214
- put spree.purchase_api_order_payment_path(order, payment)
215
- expect(response.status).to eq(200)
216
- expect(payment.reload.state).to eq("completed")
217
- end
218
-
219
- context "purchasing fails" do
220
- before do
221
- fake_response = double(success?: false, to_s: "Insufficient funds")
222
- expect_any_instance_of(Spree::PaymentMethod::BogusCreditCard).to receive(:purchase).and_return(fake_response)
223
- end
224
-
225
- it "returns a 422 status" do
226
- put spree.purchase_api_order_payment_path(order, payment)
227
- expect(response.status).to eq(422)
228
- expect(json_response["error"]).to eq "Invalid resource. Please fix errors and try again."
229
- expect(json_response["errors"]["base"][0]).to eq "Insufficient funds"
230
- end
231
- end
232
- end
233
-
234
- context "voiding" do
235
- it "can void" do
236
- put spree.void_api_order_payment_path(order, payment)
237
- expect(response.status).to eq 200
238
- expect(payment.reload.state).to eq "void"
239
- end
240
-
241
- context "voiding fails" do
242
- before do
243
- fake_response = double(success?: false, to_s: "NO REFUNDS")
244
- expect_any_instance_of(Spree::PaymentMethod::BogusCreditCard).to receive(:void).and_return(fake_response)
245
- end
246
-
247
- it "returns a 422 status" do
248
- put spree.void_api_order_payment_path(order, payment)
249
- expect(response.status).to eq 422
250
- expect(json_response["error"]).to eq "Invalid resource. Please fix errors and try again."
251
- expect(json_response["errors"]["base"][0]).to eq "NO REFUNDS"
252
- expect(payment.reload.state).to eq "checkout"
253
- end
254
- end
255
- end
256
- end
257
- end
258
- end
259
- end
@@ -1,114 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
- require 'shared_examples/protect_product_actions'
5
-
6
- module Spree
7
- describe Spree::Api::ProductPropertiesController, type: :request do
8
- let!(:product) { create(:product) }
9
- let!(:property_1) { product.product_properties.create(property_name: "My Property 1", value: "my value 1", position: 0) }
10
- let!(:property_2) { product.product_properties.create(property_name: "My Property 2", value: "my value 2", position: 1) }
11
-
12
- let(:attributes) { [:id, :product_id, :property_id, :value, :property_name] }
13
- let(:resource_scoping) { { product_id: product.to_param } }
14
-
15
- before do
16
- stub_authentication!
17
- end
18
-
19
- context "if product is deleted" do
20
- before do
21
- product.update_column(:deleted_at, 1.day.ago)
22
- end
23
-
24
- it "can not see a list of product properties" do
25
- get spree.api_product_product_properties_path(product)
26
- expect(response.status).to eq(404)
27
- end
28
- end
29
-
30
- it "can see a list of all product properties" do
31
- get spree.api_product_product_properties_path(product)
32
- expect(json_response["product_properties"].count).to eq 2
33
- expect(json_response["product_properties"].first).to have_attributes(attributes)
34
- end
35
-
36
- it "can control the page size through a parameter" do
37
- get spree.api_product_product_properties_path(product), params: { per_page: 1 }
38
- expect(json_response['product_properties'].count).to eq(1)
39
- expect(json_response['current_page']).to eq(1)
40
- expect(json_response['pages']).to eq(2)
41
- end
42
-
43
- it 'can query the results through a parameter' do
44
- Spree::ProductProperty.last.update_attribute(:value, 'loose')
45
- property = Spree::ProductProperty.last
46
- get spree.api_product_product_properties_path(product), params: { q: { value_cont: 'loose' } }
47
- expect(json_response['count']).to eq(1)
48
- expect(json_response['product_properties'].first['value']).to eq property.value
49
- end
50
-
51
- it "can see a single product_property" do
52
- get spree.api_product_product_property_path(product, property_1.property_name)
53
- expect(json_response).to have_attributes(attributes)
54
- end
55
-
56
- it "can learn how to create a new product property" do
57
- get spree.new_api_product_product_property_path(product)
58
- expect(json_response["attributes"]).to eq(attributes.map(&:to_s))
59
- expect(json_response["required_attributes"]).to be_empty
60
- end
61
-
62
- it "cannot create a new product property if not an admin" do
63
- post spree.api_product_product_properties_path(product), params: { product_property: { property_name: "My Property 3" } }
64
- assert_unauthorized!
65
- end
66
-
67
- it "cannot update a product property" do
68
- put spree.api_product_product_property_path(product, property_1.property_name), params: { product_property: { value: "my value 456" } }
69
- assert_unauthorized!
70
- end
71
-
72
- it "cannot delete a product property" do
73
- delete spree.api_product_product_property_path(product, property_1.property_name)
74
- assert_unauthorized!
75
- expect { property_1.reload }.not_to raise_error
76
- end
77
-
78
- context "as an admin" do
79
- sign_in_as_admin!
80
-
81
- it "can create a new product property" do
82
- expect do
83
- post spree.api_product_product_properties_path(product), params: { product_property: { property_name: "My Property 3", value: "my value 3" } }
84
- end.to change(product.product_properties, :count).by(1)
85
- expect(json_response).to have_attributes(attributes)
86
- expect(response.status).to eq(201)
87
- end
88
-
89
- it "can update a product property" do
90
- put spree.api_product_product_property_path(product, property_1.property_name), params: { product_property: { value: "my value 456" } }
91
- expect(response.status).to eq(200)
92
- end
93
-
94
- it "can delete a product property" do
95
- delete spree.api_product_product_property_path(product, property_1.property_name)
96
- expect(response.status).to eq(204)
97
- expect { property_1.reload }.to raise_error(ActiveRecord::RecordNotFound)
98
- end
99
- end
100
-
101
- context "with product identified by id" do
102
- it "can see a list of all product properties" do
103
- get spree.api_product_product_properties_path(product)
104
- expect(json_response["product_properties"].count).to eq 2
105
- expect(json_response["product_properties"].first).to have_attributes(attributes)
106
- end
107
-
108
- it "can see a single product_property by id" do
109
- get spree.api_product_product_property_path(product, property_1.id)
110
- expect(json_response).to have_attributes(attributes)
111
- end
112
- end
113
- end
114
- end
@@ -1,422 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
- require 'shared_examples/protect_product_actions'
5
-
6
- module Spree
7
- describe Spree::Api::ProductsController, type: :request do
8
- let!(:product) { create(:product) }
9
- let!(:inactive_product) { create(:product, available_on: Time.current.tomorrow, name: "inactive") }
10
- let(:base_attributes) { Api::ApiHelpers.product_attributes }
11
- let(:show_attributes) { base_attributes.dup.push(:has_variants) }
12
- let(:new_attributes) { base_attributes }
13
-
14
- let(:product_data) do
15
- { name: "The Other Product",
16
- price: 19.99,
17
- shipping_category_id: create(:shipping_category).id }
18
- end
19
- let(:attributes_for_variant) do
20
- attributes = attributes_for(:variant).except(:option_values, :product)
21
- attributes.merge({
22
- options: [
23
- { name: "size", value: "small" },
24
- { name: "color", value: "black" }
25
- ]
26
- })
27
- end
28
-
29
- before do
30
- stub_authentication!
31
- end
32
-
33
- context "as a normal user" do
34
- context "with caching enabled" do
35
- let!(:product_2) { create(:product) }
36
-
37
- before do
38
- ActionController::Base.perform_caching = true
39
- end
40
-
41
- it "returns unique products" do
42
- get spree.api_products_path
43
- product_ids = json_response["products"].map { |product| product["id"] }
44
- expect(product_ids.uniq.count).to eq(product_ids.count)
45
- end
46
-
47
- after do
48
- ActionController::Base.perform_caching = false
49
- end
50
- end
51
-
52
- it "retrieves a list of products" do
53
- get spree.api_products_path
54
- expect(json_response["products"].first).to have_attributes(show_attributes)
55
- expect(json_response["total_count"]).to eq(1)
56
- expect(json_response["current_page"]).to eq(1)
57
- expect(json_response["pages"]).to eq(1)
58
- expect(json_response["per_page"]).to eq(Kaminari.config.default_per_page)
59
- end
60
-
61
- it "retrieves a list of products by id" do
62
- get spree.api_products_path, params: { ids: [product.id] }
63
- expect(json_response["products"].first).to have_attributes(show_attributes)
64
- expect(json_response["total_count"]).to eq(1)
65
- expect(json_response["current_page"]).to eq(1)
66
- expect(json_response["pages"]).to eq(1)
67
- expect(json_response["per_page"]).to eq(Kaminari.config.default_per_page)
68
- end
69
-
70
- context "product has more than one price" do
71
- before { product.master.prices.create currency: "EUR", amount: 22 }
72
-
73
- it "returns distinct products only" do
74
- get spree.api_products_path
75
- expect(assigns(:products).map(&:id).uniq).to eq assigns(:products).map(&:id)
76
- end
77
- end
78
-
79
- it "retrieves a list of products by ids string" do
80
- second_product = create(:product)
81
- get spree.api_products_path, params: { ids: [product.id, second_product.id].join(",") }
82
- expect(json_response["products"].first).to have_attributes(show_attributes)
83
- expect(json_response["products"][1]).to have_attributes(show_attributes)
84
- expect(json_response["total_count"]).to eq(2)
85
- expect(json_response["current_page"]).to eq(1)
86
- expect(json_response["pages"]).to eq(1)
87
- expect(json_response["per_page"]).to eq(Kaminari.config.default_per_page)
88
- end
89
-
90
- it "does not return inactive products when queried by ids" do
91
- get spree.api_products_path, params: { ids: [inactive_product.id] }
92
- expect(json_response["count"]).to eq(0)
93
- end
94
-
95
- it "does not list unavailable products" do
96
- get spree.api_products_path
97
- expect(json_response["products"].first["name"]).not_to eq("inactive")
98
- end
99
-
100
- context "pagination" do
101
- it "can select the next page of products" do
102
- create(:product)
103
- get spree.api_products_path, params: { page: 2, per_page: 1 }
104
- expect(json_response["products"].first).to have_attributes(show_attributes)
105
- expect(json_response["total_count"]).to eq(2)
106
- expect(json_response["current_page"]).to eq(2)
107
- expect(json_response["pages"]).to eq(2)
108
- end
109
-
110
- it 'can control the page size through a parameter' do
111
- create(:product)
112
- get spree.api_products_path, params: { per_page: 1 }
113
- expect(json_response['count']).to eq(1)
114
- expect(json_response['total_count']).to eq(2)
115
- expect(json_response['current_page']).to eq(1)
116
- expect(json_response['pages']).to eq(2)
117
- end
118
- end
119
-
120
- it "can search for products" do
121
- create(:product, name: "The best product in the world")
122
- get spree.api_products_path, params: { q: { name_cont: "best" } }
123
- expect(json_response["products"].first).to have_attributes(show_attributes)
124
- expect(json_response["count"]).to eq(1)
125
- end
126
-
127
- it "gets a single product" do
128
- product.master.images.create!(attachment: image("thinking-cat.jpg"))
129
- product.variants.create!
130
- product.variants.first.images.create!(attachment: image("thinking-cat.jpg"))
131
- product.set_property("spree", "rocks")
132
- product.taxons << create(:taxon)
133
-
134
- get spree.api_product_path(product)
135
-
136
- expect(json_response).to have_attributes(show_attributes)
137
- expect(json_response['variants'].first).to have_attributes([:name,
138
- :is_master,
139
- :price,
140
- :images,
141
- :in_stock])
142
-
143
- expect(json_response['variants'].first['images'].first).to have_attributes([:attachment_file_name,
144
- :attachment_width,
145
- :attachment_height,
146
- :attachment_content_type,
147
- :mini_url,
148
- :small_url,
149
- :product_url,
150
- :large_url])
151
-
152
- expect(json_response["product_properties"].first).to have_attributes([:value,
153
- :product_id,
154
- :property_name])
155
-
156
- expect(json_response["classifications"].first).to have_attributes([:taxon_id, :position, :taxon])
157
- expect(json_response["classifications"].first['taxon']).to have_attributes([:id, :name, :pretty_name, :permalink, :taxonomy_id, :parent_id])
158
- end
159
-
160
- context "tracking is disabled" do
161
- before { stub_spree_preferences(track_inventory_levels: false) }
162
-
163
- it "still displays valid json with total_on_hand Float::INFINITY" do
164
- get spree.api_product_path(product)
165
- expect(response).to be_ok
166
- expect(json_response[:total_on_hand]).to eq nil
167
- end
168
- end
169
-
170
- context "finds a product by slug first then by id" do
171
- let!(:other_product) { create(:product, slug: "these-are-not-the-droids-you-are-looking-for") }
172
-
173
- before do
174
- product.update_column(:slug, "#{other_product.id}-and-1-ways")
175
- end
176
-
177
- specify do
178
- get spree.api_product_path(product)
179
- expect(json_response["slug"]).to match(/and-1-ways/)
180
- product.discard
181
-
182
- get spree.api_product_path(other_product)
183
- expect(json_response["slug"]).to match(/droids/)
184
- end
185
- end
186
-
187
- it "cannot see inactive products" do
188
- get spree.api_product_path(inactive_product)
189
- assert_not_found!
190
- end
191
-
192
- it "returns a 404 error when it cannot find a product" do
193
- get spree.api_product_path("non-existant")
194
- assert_not_found!
195
- end
196
-
197
- it "can learn how to create a new product" do
198
- get spree.new_api_product_path
199
- expect(json_response["attributes"]).to eq(new_attributes.map(&:to_s))
200
- required_attributes = json_response["required_attributes"]
201
- expect(required_attributes).to include("name")
202
- expect(required_attributes).to include("price")
203
- expect(required_attributes).to include("shipping_category_id")
204
- end
205
-
206
- it_behaves_like "modifying product actions are restricted"
207
- end
208
-
209
- context "as an admin" do
210
- let(:taxon_1) { create(:taxon) }
211
- let(:taxon_2) { create(:taxon) }
212
-
213
- sign_in_as_admin!
214
-
215
- it "can see all products" do
216
- get spree.api_products_path
217
- expect(json_response["products"].count).to eq(2)
218
- expect(json_response["count"]).to eq(2)
219
- expect(json_response["current_page"]).to eq(1)
220
- expect(json_response["pages"]).to eq(1)
221
- end
222
-
223
- # Regression test for https://github.com/spree/spree/issues/1626
224
- context "deleted products" do
225
- before do
226
- create(:product, deleted_at: 1.day.ago)
227
- end
228
-
229
- it "does not include deleted products" do
230
- get spree.api_products_path
231
- expect(json_response["products"].count).to eq(2)
232
- end
233
-
234
- it "can include deleted products" do
235
- get spree.api_products_path, params: { show_deleted: 1 }
236
- expect(json_response["products"].count).to eq(3)
237
- end
238
- end
239
-
240
- describe "creating a product" do
241
- it "can create a new product" do
242
- post spree.api_products_path, params: {
243
- product: { name: "The Other Product",
244
- price: 19.99,
245
- shipping_category_id: create(:shipping_category).id }
246
- }
247
- expect(json_response).to have_attributes(base_attributes)
248
- expect(response.status).to eq(201)
249
- end
250
-
251
- it "creates with embedded variants" do
252
- product_data[:variants] = [attributes_for_variant, attributes_for_variant]
253
-
254
- post spree.api_products_path, params: { product: product_data }
255
- expect(response.status).to eq 201
256
-
257
- variants = json_response['variants']
258
- expect(variants.count).to eq(2)
259
- expect(variants.last['option_values'][0]['name']).to eq('small')
260
- expect(variants.last['option_values'][0]['option_type_name']).to eq('size')
261
-
262
- expect(json_response['option_types'].count).to eq(2) # size, color
263
- end
264
-
265
- it "can create a new product with embedded product_properties" do
266
- product_data[:product_properties_attributes] = [{
267
- property_name: "fabric",
268
- value: "cotton"
269
- }]
270
-
271
- post spree.api_products_path, params: { product: product_data }
272
-
273
- expect(json_response['product_properties'][0]['property_name']).to eq('fabric')
274
- expect(json_response['product_properties'][0]['value']).to eq('cotton')
275
- end
276
-
277
- it "can create a new product with option_types" do
278
- product_data[:option_types] = ['size', 'color']
279
-
280
- post spree.api_products_path, params: { product: product_data }
281
- expect(json_response['option_types'].count).to eq(2)
282
- end
283
-
284
- it "creates with shipping categories" do
285
- hash = { name: "The Other Product",
286
- price: 19.99,
287
- shipping_category: "Free Ships" }
288
-
289
- post spree.api_products_path, params: { product: hash }
290
- expect(response.status).to eq 201
291
-
292
- shipping_id = ShippingCategory.find_by(name: "Free Ships").id
293
- expect(json_response['shipping_category_id']).to eq shipping_id
294
- end
295
-
296
- context "when tracking is disabled" do
297
- before { stub_spree_preferences(track_inventory_levels: false) }
298
-
299
- it "still displays valid json with total_on_hand Float::INFINITY" do
300
- post spree.api_products_path, params: {
301
- product: {
302
- name: "The Other Product",
303
- price: 19.99,
304
- shipping_category_id: create(:shipping_category).id
305
- }
306
- }
307
-
308
- expect(response.status).to eq(201)
309
- expect(json_response['total_on_hand']).to eq nil
310
- end
311
- end
312
-
313
- it "puts the created product in the given taxon" do
314
- product_data[:taxon_ids] = taxon_1.id.to_s
315
- post spree.api_products_path, params: { product: product_data }
316
- expect(json_response["taxon_ids"]).to eq([taxon_1.id])
317
- end
318
-
319
- # Regression test for https://github.com/spree/spree/issues/4123
320
- it "puts the created product in the given taxons" do
321
- product_data[:taxon_ids] = [taxon_1.id, taxon_2.id].join(',')
322
- post spree.api_products_path, params: { product: product_data }
323
- expect(json_response["taxon_ids"]).to eq([taxon_1.id, taxon_2.id])
324
- end
325
-
326
- # Regression test for https://github.com/spree/spree/issues/2140
327
- context "with authentication_required set to false" do
328
- before do
329
- stub_spree_preferences(Spree::Api::Config, requires_authentication: false)
330
- end
331
-
332
- it "can still create a product" do
333
- post spree.api_products_path, params: { product: product_data, token: "fake" }
334
- expect(json_response).to have_attributes(show_attributes)
335
- expect(response.status).to eq(201)
336
- end
337
- end
338
-
339
- it "cannot create a new product with invalid attributes" do
340
- post spree.api_products_path, params: { product: { foo: :bar } }
341
- expect(response.status).to eq(422)
342
- expect(json_response["error"]).to eq("Invalid resource. Please fix errors and try again.")
343
- errors = json_response["errors"]
344
- expect(errors.keys).to include("name", "price", "shipping_category_id")
345
- end
346
- end
347
-
348
- context 'updating a product' do
349
- it "can update a product" do
350
- put spree.api_product_path(product), params: { product: { name: "New and Improved Product!" } }
351
- expect(response.status).to eq(200)
352
- end
353
-
354
- it "can create new option types on a product" do
355
- put spree.api_product_path(product), params: { product: { option_types: ['shape', 'color'] } }
356
- expect(json_response['option_types'].count).to eq(2)
357
- end
358
-
359
- it "can create new variants on a product" do
360
- put spree.api_product_path(product), params: { product: { variants: [attributes_for_variant, attributes_for_variant.merge(sku: "ABC-#{Kernel.rand(9999)}")] } }
361
- expect(response.status).to eq 200
362
- expect(json_response['variants'].count).to eq(2) # 2 variants
363
-
364
- variants = json_response['variants'].reject { |variant| variant['is_master'] }
365
- size_option_value = variants.last['option_values'].detect{ |value| value['option_type_name'] == 'size' }
366
- expect(size_option_value['name']).to eq('small')
367
-
368
- expect(json_response['option_types'].count).to eq(2) # size, color
369
- end
370
-
371
- it "can update an existing variant on a product" do
372
- variant_hash = {
373
- sku: '123', price: 19.99, options: [{ name: "size", value: "small" }]
374
- }
375
- variant_id = product.variants.create!({ product: product }.merge(variant_hash)).id
376
-
377
- put spree.api_product_path(product), params: { product: {
378
- variants: [
379
- variant_hash.merge(
380
- id: variant_id.to_s,
381
- sku: '456',
382
- options: [{ name: "size", value: "large" }]
383
- )
384
- ]
385
- } }
386
-
387
- expect(json_response['variants'].count).to eq(1)
388
- variants = json_response['variants'].reject { |variant| variant['is_master'] }
389
- expect(variants.last['option_values'][0]['name']).to eq('large')
390
- expect(variants.last['sku']).to eq('456')
391
- expect(variants.count).to eq(1)
392
- end
393
-
394
- it "cannot update a product with an invalid attribute" do
395
- put spree.api_product_path(product), params: { product: { name: "" } }
396
- expect(response.status).to eq(422)
397
- expect(json_response["error"]).to eq("Invalid resource. Please fix errors and try again.")
398
- expect(json_response["errors"]["name"]).to eq(["can't be blank"])
399
- end
400
-
401
- # Regression test for https://github.com/spree/spree/issues/4123
402
- it "puts the created product in the given taxon" do
403
- put spree.api_product_path(product), params: { product: { taxon_ids: taxon_1.id.to_s } }
404
- expect(json_response["taxon_ids"]).to eq([taxon_1.id])
405
- end
406
-
407
- # Regression test for https://github.com/spree/spree/issues/4123
408
- it "puts the created product in the given taxons" do
409
- put spree.api_product_path(product), params: { product: { taxon_ids: [taxon_1.id, taxon_2.id].join(',') } }
410
- expect(json_response["taxon_ids"]).to match_array([taxon_1.id, taxon_2.id])
411
- end
412
- end
413
-
414
- it "can delete a product" do
415
- expect(product.deleted_at).to be_nil
416
- delete spree.api_product_path(product)
417
- expect(response.status).to eq(204)
418
- expect(product.reload.deleted_at).not_to be_nil
419
- end
420
- end
421
- end
422
- end