spree_api 3.1.14 → 3.2.0.rc1

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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -1
  3. data/app/controllers/spree/api/base_controller.rb +2 -2
  4. data/app/controllers/spree/api/v1/addresses_controller.rb +1 -1
  5. data/app/controllers/spree/api/v1/classifications_controller.rb +1 -1
  6. data/app/controllers/spree/api/v1/images_controller.rb +3 -0
  7. data/app/controllers/spree/api/v1/inventory_units_controller.rb +3 -3
  8. data/app/controllers/spree/api/v1/line_items_controller.rb +3 -0
  9. data/app/controllers/spree/api/v1/option_types_controller.rb +16 -7
  10. data/app/controllers/spree/api/v1/option_values_controller.rb +6 -3
  11. data/app/controllers/spree/api/v1/orders_controller.rb +13 -24
  12. data/app/controllers/spree/api/v1/payments_controller.rb +0 -1
  13. data/app/controllers/spree/api/v1/products_controller.rb +8 -5
  14. data/app/controllers/spree/api/v1/stock_items_controller.rb +1 -1
  15. data/app/controllers/spree/api/v1/stock_locations_controller.rb +1 -1
  16. data/app/controllers/spree/api/v1/tags_controller.rb +28 -0
  17. data/app/controllers/spree/api/v1/taxonomies_controller.rb +7 -4
  18. data/app/controllers/spree/api/v1/taxons_controller.rb +4 -1
  19. data/app/controllers/spree/api/v1/users_controller.rb +5 -3
  20. data/app/controllers/spree/api/v1/zones_controller.rb +3 -3
  21. data/app/helpers/spree/api/api_helpers.rb +4 -1
  22. data/app/models/spree/api_configuration.rb +1 -1
  23. data/app/views/spree/api/errors/invalid_api_key.v1.rabl +1 -1
  24. data/app/views/spree/api/errors/invalid_resource.v1.rabl +1 -1
  25. data/app/views/spree/api/errors/must_specify_api_key.v1.rabl +1 -1
  26. data/app/views/spree/api/errors/not_found.v1.rabl +1 -1
  27. data/app/views/spree/api/errors/unauthorized.v1.rabl +1 -1
  28. data/app/views/spree/api/v1/countries/show.v1.rabl +1 -1
  29. data/app/views/spree/api/v1/line_items/show.v1.rabl +2 -2
  30. data/app/views/spree/api/v1/option_types/show.v1.rabl +1 -1
  31. data/app/views/spree/api/v1/orders/invalid_shipping_method.v1.rabl +1 -1
  32. data/app/views/spree/api/v1/orders/payment.v1.rabl +1 -1
  33. data/app/views/spree/api/v1/orders/show.v1.rabl +9 -9
  34. data/app/views/spree/api/v1/payments/credit_over_limit.v1.rabl +1 -1
  35. data/app/views/spree/api/v1/payments/update_forbidden.v1.rabl +1 -1
  36. data/app/views/spree/api/v1/products/show.v1.rabl +5 -5
  37. data/app/views/spree/api/v1/shipments/cannot_ready_shipment.v1.rabl +1 -1
  38. data/app/views/spree/api/v1/shipments/show.v1.rabl +7 -7
  39. data/app/views/spree/api/v1/shipments/small.v1.rabl +8 -8
  40. data/app/views/spree/api/v1/tags/index.v1.rabl +9 -0
  41. data/app/views/spree/api/v1/taxonomies/jstree.rabl +2 -2
  42. data/app/views/spree/api/v1/taxonomies/nested.v1.rabl +2 -2
  43. data/app/views/spree/api/v1/taxons/jstree.rabl +3 -3
  44. data/app/views/spree/api/v1/taxons/show.v1.rabl +1 -1
  45. data/app/views/spree/api/v1/taxons/taxons.v1.rabl +1 -1
  46. data/app/views/spree/api/v1/users/show.v1.rabl +3 -2
  47. data/app/views/spree/api/v1/variants/big.v1.rabl +3 -3
  48. data/app/views/spree/api/v1/variants/small.v1.rabl +3 -2
  49. data/app/views/spree/api/v1/zones/show.v1.rabl +1 -1
  50. data/config/routes.rb +4 -6
  51. data/db/migrate/20100107141738_add_api_key_to_spree_users.rb +2 -2
  52. data/db/migrate/20120411123334_resize_api_key_field.rb +2 -2
  53. data/db/migrate/20120530054546_rename_api_key_to_spree_api_key.rb +1 -1
  54. data/db/migrate/20131017162334_add_index_to_user_spree_api_key.rb +1 -1
  55. data/lib/spree/api/engine.rb +11 -3
  56. data/lib/spree/api/responders/rabl_template.rb +1 -1
  57. data/lib/spree/api/testing_support/caching.rb +2 -2
  58. data/spec/controllers/spree/api/base_controller_spec.rb +96 -0
  59. data/spec/controllers/spree/api/v1/addresses_controller_spec.rb +56 -0
  60. data/spec/controllers/spree/api/v1/checkouts_controller_spec.rb +363 -0
  61. data/spec/controllers/spree/api/v1/classifications_controller_spec.rb +48 -0
  62. data/spec/controllers/spree/api/v1/countries_controller_spec.rb +48 -0
  63. data/spec/controllers/spree/api/v1/credit_cards_controller_spec.rb +80 -0
  64. data/spec/controllers/spree/api/v1/images_controller_spec.rb +114 -0
  65. data/spec/controllers/spree/api/v1/inventory_units_controller_spec.rb +48 -0
  66. data/spec/controllers/spree/api/v1/line_items_controller_spec.rb +203 -0
  67. data/spec/controllers/spree/api/v1/option_types_controller_spec.rb +122 -0
  68. data/spec/controllers/spree/api/v1/option_values_controller_spec.rb +141 -0
  69. data/spec/controllers/spree/api/v1/orders_controller_spec.rb +735 -0
  70. data/spec/controllers/spree/api/v1/payments_controller_spec.rb +234 -0
  71. data/spec/controllers/spree/api/v1/product_properties_controller_spec.rb +147 -0
  72. data/spec/controllers/spree/api/v1/products_controller_spec.rb +409 -0
  73. data/spec/controllers/spree/api/v1/promotion_application_spec.rb +50 -0
  74. data/spec/controllers/spree/api/v1/promotions_controller_spec.rb +64 -0
  75. data/spec/controllers/spree/api/v1/properties_controller_spec.rb +102 -0
  76. data/spec/controllers/spree/api/v1/return_authorizations_controller_spec.rb +161 -0
  77. data/spec/controllers/spree/api/v1/shipments_controller_spec.rb +187 -0
  78. data/spec/controllers/spree/api/v1/states_controller_spec.rb +86 -0
  79. data/spec/controllers/spree/api/v1/stock_items_controller_spec.rb +143 -0
  80. data/spec/controllers/spree/api/v1/stock_locations_controller_spec.rb +113 -0
  81. data/spec/controllers/spree/api/v1/stock_movements_controller_spec.rb +84 -0
  82. data/spec/controllers/spree/api/v1/stores_controller_spec.rb +133 -0
  83. data/spec/controllers/spree/api/v1/tags_controller_spec.rb +102 -0
  84. data/spec/controllers/spree/api/v1/taxonomies_controller_spec.rb +114 -0
  85. data/spec/controllers/spree/api/v1/taxons_controller_spec.rb +177 -0
  86. data/spec/controllers/spree/api/v1/unauthenticated_products_controller_spec.rb +26 -0
  87. data/spec/controllers/spree/api/v1/users_controller_spec.rb +153 -0
  88. data/spec/controllers/spree/api/v1/variants_controller_spec.rb +205 -0
  89. data/spec/controllers/spree/api/v1/zones_controller_spec.rb +91 -0
  90. data/spec/models/spree/legacy_user_spec.rb +19 -0
  91. data/spec/requests/rabl_cache_spec.rb +32 -0
  92. data/spec/requests/ransackable_attributes_spec.rb +79 -0
  93. data/spec/requests/version_spec.rb +19 -0
  94. data/spec/shared_examples/protect_product_actions.rb +17 -0
  95. data/spec/spec_helper.rb +60 -0
  96. data/spec/support/controller_hacks.rb +40 -0
  97. data/spec/support/database_cleaner.rb +14 -0
  98. data/spec/support/have_attributes_matcher.rb +13 -0
  99. data/spree_api.gemspec +7 -4
  100. metadata +99 -14
@@ -0,0 +1,205 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe Api::V1::VariantsController, type: :controller do
5
+ render_views
6
+
7
+ let(:option_value) { create(:option_value) }
8
+ let!(:product) { create(:product) }
9
+ let!(:variant) do
10
+ variant = product.master
11
+ variant.option_values << option_value
12
+ variant
13
+ end
14
+
15
+ let!(:base_attributes) { Api::ApiHelpers.variant_attributes }
16
+ let!(:show_attributes) { base_attributes.dup.push(:in_stock, :display_price) }
17
+ let!(:new_attributes) { base_attributes }
18
+
19
+ before do
20
+ stub_authentication!
21
+ end
22
+
23
+ it "can see a paginated list of variants" do
24
+ api_get :index
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
+ api_get :index, 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 parameter' do
42
+ expected_result = create(:variant, sku: 'FOOBAR')
43
+ api_get :index, 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
+ api_get :index
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
+ api_get :index
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
+
72
+ end
73
+
74
+ it 'variants returned do not contain cost price data' do
75
+ api_get :index
76
+ expect(json_response["variants"].first.has_key?(:cost_price)).to eq false
77
+ end
78
+
79
+ # Regression test for #2141
80
+ context "a deleted variant" do
81
+ before do
82
+ variant.update_column(:deleted_at, Time.current)
83
+ end
84
+
85
+ it "is not returned in the results" do
86
+ api_get :index
87
+ expect(json_response["variants"].count).to eq(0)
88
+ end
89
+
90
+ it "is not returned even when show_deleted is passed" do
91
+ api_get :index, show_deleted: true
92
+ expect(json_response["variants"].count).to eq(0)
93
+ end
94
+ end
95
+
96
+ context "pagination" do
97
+ it "can select the next page of variants" do
98
+ second_variant = create(:variant)
99
+ api_get :index, page: 2, per_page: 1
100
+ expect(json_response["variants"].first).to have_attributes(show_attributes)
101
+ expect(json_response["total_count"]).to eq(3)
102
+ expect(json_response["current_page"]).to eq(2)
103
+ expect(json_response["pages"]).to eq(3)
104
+ end
105
+ end
106
+
107
+ it "can see a single variant" do
108
+ api_get :show, id: variant.to_param
109
+ expect(json_response).to have_attributes(show_attributes)
110
+ expect(json_response["stock_items"]).to be_present
111
+ option_values = json_response["option_values"]
112
+ expect(option_values.first).to have_attributes([:name,
113
+ :presentation,
114
+ :option_type_name,
115
+ :option_type_id])
116
+ end
117
+
118
+ it "can see a single variant with images" do
119
+ variant.images.create!(attachment: image("thinking-cat.jpg"))
120
+
121
+ api_get :show, id: variant.to_param
122
+
123
+ expect(json_response).to have_attributes(show_attributes + [:images])
124
+ option_values = json_response["option_values"]
125
+ expect(option_values.first).to have_attributes([:name,
126
+ :presentation,
127
+ :option_type_name,
128
+ :option_type_id])
129
+ end
130
+
131
+ it "can learn how to create a new variant" do
132
+ api_get :new
133
+ expect(json_response["attributes"]).to eq(new_attributes.map(&:to_s))
134
+ expect(json_response["required_attributes"]).to be_empty
135
+ end
136
+
137
+ it "cannot create a new variant if not an admin" do
138
+ api_post :create, variant: { sku: "12345" }
139
+ assert_unauthorized!
140
+ end
141
+
142
+ it "cannot update a variant" do
143
+ api_put :update, id: variant.to_param, variant: { sku: "12345" }
144
+ assert_not_found!
145
+ end
146
+
147
+ it "cannot delete a variant" do
148
+ api_delete :destroy, id: variant.to_param
149
+ assert_not_found!
150
+ expect { variant.reload }.not_to raise_error
151
+ end
152
+
153
+ context "as an admin" do
154
+ sign_in_as_admin!
155
+ let(:resource_scoping) { { product_id: variant.product.to_param } }
156
+
157
+ # Test for #2141
158
+ context "deleted variants" do
159
+ before do
160
+ variant.update_column(:deleted_at, Time.current)
161
+ end
162
+
163
+ it "are visible by admin" do
164
+ api_get :index, show_deleted: 1
165
+ expect(json_response["variants"].count).to eq(1)
166
+ end
167
+ end
168
+
169
+ it "can create a new variant" do
170
+ other_value = create(:option_value)
171
+ api_post :create, variant: {
172
+ sku: "12345",
173
+ price: "20",
174
+ option_value_ids: [option_value.id, other_value.id]
175
+ }
176
+
177
+ expect(json_response).to have_attributes(new_attributes)
178
+ expect(response.status).to eq(201)
179
+ expect(json_response["sku"]).to eq("12345")
180
+ expect(json_response["price"]).to match "20"
181
+
182
+ option_value_ids = json_response["option_values"].map { |o| o['id'] }
183
+ expect(option_value_ids).to match_array [option_value.id, other_value.id]
184
+
185
+ expect(variant.product.variants.count).to eq(1)
186
+ end
187
+
188
+ it "can update a variant" do
189
+ api_put :update, id: variant.to_param, variant: { sku: "12345" }
190
+ expect(response.status).to eq(200)
191
+ end
192
+
193
+ it "can delete a variant" do
194
+ api_delete :destroy, id: variant.to_param
195
+ expect(response.status).to eq(204)
196
+ expect { Spree::Variant.find(variant.id) }.to raise_error(ActiveRecord::RecordNotFound)
197
+ end
198
+
199
+ it 'variants returned contain cost price data' do
200
+ api_get :index
201
+ expect(json_response["variants"].first.has_key?(:cost_price)).to eq true
202
+ end
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,91 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe Api::V1::ZonesController, type: :controller do
5
+ render_views
6
+
7
+ let!(:attributes) { [:id, :name, :zone_members] }
8
+
9
+ before do
10
+ stub_authentication!
11
+ @zone = create(:zone, name: 'Europe')
12
+ end
13
+
14
+ it "gets list of zones" do
15
+ api_get :index
16
+ expect(json_response['zones'].first).to have_attributes(attributes)
17
+ end
18
+
19
+ it 'can control the page size through a parameter' do
20
+ create(:zone)
21
+ api_get :index, per_page: 1
22
+ expect(json_response['count']).to eq(1)
23
+ expect(json_response['current_page']).to eq(1)
24
+ expect(json_response['pages']).to eq(2)
25
+ end
26
+
27
+ it 'can query the results through a paramter' do
28
+ expected_result = create(:zone, name: 'South America')
29
+ api_get :index, q: { name_cont: 'south' }
30
+ expect(json_response['count']).to eq(1)
31
+ expect(json_response['zones'].first['name']).to eq expected_result.name
32
+ end
33
+
34
+ it "gets a zone" do
35
+ api_get :show, id: @zone.id
36
+ expect(json_response).to have_attributes(attributes)
37
+ expect(json_response['name']).to eq @zone.name
38
+ expect(json_response['zone_members'].size).to eq @zone.zone_members.count
39
+ end
40
+
41
+ context "as an admin" do
42
+ sign_in_as_admin!
43
+
44
+ let!(:country) { create(:country) }
45
+
46
+ it "can create a new zone" do
47
+ params = {
48
+ zone: {
49
+ name: "North Pole",
50
+ zone_members: [
51
+ {
52
+ zoneable_type: "Spree::Country",
53
+ zoneable_id: country.id
54
+ }
55
+ ]
56
+ }
57
+ }
58
+
59
+ api_post :create, params
60
+ expect(response.status).to eq(201)
61
+ expect(json_response).to have_attributes(attributes)
62
+ expect(json_response["zone_members"]).not_to be_empty
63
+ end
64
+
65
+ it "updates a zone" do
66
+ params = { id: @zone.id,
67
+ zone: {
68
+ name: "North Pole",
69
+ zone_members: [
70
+ {
71
+ zoneable_type: "Spree::Country",
72
+ zoneable_id: country.id
73
+ }
74
+ ]
75
+ }
76
+ }
77
+
78
+ api_put :update, params
79
+ expect(response.status).to eq(200)
80
+ expect(json_response['name']).to eq 'North Pole'
81
+ expect(json_response['zone_members']).not_to be_blank
82
+ end
83
+
84
+ it "can delete a zone" do
85
+ api_delete :destroy, id: @zone.id
86
+ expect(response.status).to eq(204)
87
+ expect { @zone.reload }.to raise_error(ActiveRecord::RecordNotFound)
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe LegacyUser, type: :model do
5
+ let(:user) { LegacyUser.new }
6
+
7
+ it "can generate an API key" do
8
+ expect(user).to receive(:save!)
9
+ user.generate_spree_api_key!
10
+ expect(user.spree_api_key).not_to be_blank
11
+ end
12
+
13
+ it "can clear an API key" do
14
+ expect(user).to receive(:save!)
15
+ user.clear_spree_api_key!
16
+ expect(user.spree_api_key).to be_blank
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Rabl Cache", type: :request, caching: true do
4
+ let!(:user) { create(:admin_user) }
5
+
6
+ before do
7
+ create(:variant)
8
+ user.generate_spree_api_key!
9
+ expect(Spree::Product.count).to eq(1)
10
+ end
11
+
12
+ it "doesn't create a cache key collision for models with different rabl templates" do
13
+ get "/api/v1/variants", params: { token: user.spree_api_key }
14
+ expect(response.status).to eq(200)
15
+
16
+ # Make sure we get a non master variant
17
+ variant_a = JSON.parse(response.body)['variants'].select do |v|
18
+ !v['is_master']
19
+ end.first
20
+
21
+ expect(variant_a['is_master']).to be false
22
+ expect(variant_a['stock_items']).not_to be_nil
23
+
24
+ get "/api/v1/products/#{Spree::Product.first.id}", params: { token: user.spree_api_key }
25
+ expect(response.status).to eq(200)
26
+ variant_b = JSON.parse(response.body)['variants'].last
27
+ expect(variant_b['is_master']).to be false
28
+
29
+ expect(variant_a['id']).to eq(variant_b['id'])
30
+ expect(variant_b['stock_items']).to be_nil
31
+ end
32
+ end
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Ransackable Attributes" do
4
+ let(:user) { create(:user).tap(&:generate_spree_api_key!) }
5
+ let(:order) { create(:order_with_line_items, user: user) }
6
+ context "filtering by attributes one association away" do
7
+ it "does not allow the filtering of variants by order attributes" do
8
+ 2.times { create(:variant) }
9
+
10
+ get "/api/v1/variants?q[orders_email_start]=#{order.email}", params: { token: user.spree_api_key }
11
+
12
+ variants_response = JSON.parse(response.body)
13
+ expect(variants_response['total_count']).to eq(Spree::Variant.count)
14
+ end
15
+ end
16
+
17
+ context "filtering by attributes two associations away" do
18
+ it "does not allow the filtering of variants by user attributes" do
19
+ 2.times { create(:variant) }
20
+
21
+ get "/api/v1/variants?q[orders_user_email_start]=#{order.user.email}", params: { token: user.spree_api_key }
22
+
23
+ variants_response = JSON.parse(response.body)
24
+ expect(variants_response['total_count']).to eq(Spree::Variant.count)
25
+ end
26
+ end
27
+
28
+ context "it maintains desired association behavior" do
29
+ it "allows filtering of variants product name" do
30
+ product = create(:product, name: "Fritos")
31
+ variant = create(:variant, product: product)
32
+ other_variant = create(:variant)
33
+
34
+ get "/api/v1/variants?q[product_name_or_sku_cont]=fritos", params: { token: user.spree_api_key }
35
+
36
+ skus = JSON.parse(response.body)['variants'].map { |variant| variant['sku'] }
37
+ expect(skus).to include variant.sku
38
+ expect(skus).not_to include other_variant.sku
39
+ end
40
+ end
41
+
42
+ context "filtering by attributes" do
43
+ it "most attributes are not filterable by default" do
44
+ product = create(:product, meta_title: "special product")
45
+ other_product = create(:product)
46
+
47
+ get "/api/v1/products?q[meta_title_cont]=special", params: { token: user.spree_api_key }
48
+
49
+ products_response = JSON.parse(response.body)
50
+ expect(products_response['total_count']).to eq(Spree::Product.count)
51
+ end
52
+
53
+ it "id is filterable by default" do
54
+ product = create(:product)
55
+ other_product = create(:product)
56
+
57
+ get "/api/v1/products?q[id_eq]=#{product.id}", params: { token: user.spree_api_key }
58
+
59
+ product_names = JSON.parse(response.body)['products'].map { |product| product['name'] }
60
+ expect(product_names).to include product.name
61
+ expect(product_names).not_to include other_product.name
62
+ end
63
+ end
64
+
65
+ context "filtering by whitelisted attributes" do
66
+ it "filtering is supported for whitelisted attributes" do
67
+ product = create(:product, name: "Fritos")
68
+ other_product = create(:product)
69
+
70
+ get "/api/v1/products?q[name_cont]=fritos", params: { token: user.spree_api_key }
71
+
72
+ product_names = JSON.parse(response.body)['products'].map { |product| product['name'] }
73
+ expect(product_names).to include product.name
74
+ expect(product_names).not_to include other_product.name
75
+ end
76
+ end
77
+
78
+
79
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Version", type: :request do
4
+ let!(:countries) { 2.times.map { create :country } }
5
+
6
+ describe "/api" do
7
+ it "be a redirect" do
8
+ get "/api/countries"
9
+ expect(response).to have_http_status 301
10
+ end
11
+ end
12
+
13
+ describe "/api/v1" do
14
+ it "be successful" do
15
+ get "/api/v1/countries"
16
+ expect(response).to have_http_status 200
17
+ end
18
+ end
19
+ end