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