spree_api 3.1.14 → 3.2.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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,48 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe Api::V1::ClassificationsController, type: :controller do
5
+ let(:taxon) do
6
+ taxon = create(:taxon)
7
+
8
+ 3.times do
9
+ product = create(:product)
10
+ product.taxons << taxon
11
+ end
12
+ taxon
13
+ end
14
+
15
+ before do
16
+ stub_authentication!
17
+ end
18
+
19
+ context "as a user" do
20
+ it "cannot change the order of a product" do
21
+ api_put :update, taxon_id: taxon, product_id: taxon.products.first, position: 1
22
+ expect(response.status).to eq(401)
23
+ end
24
+ end
25
+
26
+ context "as an admin" do
27
+ sign_in_as_admin!
28
+
29
+ let(:last_product) { taxon.products.last }
30
+
31
+ it "can change the order a product" do
32
+ classification = taxon.classifications.find_by(product_id: last_product.id)
33
+ expect(classification.position).to eq(3)
34
+ api_put :update, taxon_id: taxon.id, product_id: last_product.id, position: 0
35
+ expect(response.status).to eq(200)
36
+ expect(classification.reload.position).to eq(1)
37
+ end
38
+
39
+ it "should touch the taxon" do
40
+ taxon.update_attributes(updated_at: Time.current - 10.seconds)
41
+ taxon_last_updated_at = taxon.updated_at
42
+ api_put :update, taxon_id: taxon.id, product_id: last_product.id, position: 0
43
+ taxon.reload
44
+ expect(taxon_last_updated_at.to_i).to_not eq(taxon.updated_at.to_i)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe Api::V1::CountriesController, type: :controller do
5
+ render_views
6
+
7
+ before do
8
+ stub_authentication!
9
+ @state = create(:state)
10
+ @country = @state.country
11
+ end
12
+
13
+ it "gets all countries" do
14
+ api_get :index
15
+ expect(json_response['countries'].first['iso3']).to eq @country.iso3
16
+ end
17
+
18
+ context "with two countries" do
19
+ before { @zambia = create(:country, name: "Zambia") }
20
+
21
+ it "can view all countries" do
22
+ api_get :index
23
+ expect(json_response['count']).to eq(2)
24
+ expect(json_response['current_page']).to eq(1)
25
+ expect(json_response['pages']).to eq(1)
26
+ end
27
+
28
+ it 'can query the results through a paramter' do
29
+ api_get :index, q: { name_cont: 'zam' }
30
+ expect(json_response['count']).to eq(1)
31
+ expect(json_response['countries'].first['name']).to eq @zambia.name
32
+ end
33
+
34
+ it 'can control the page size through a parameter' do
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(2)
39
+ end
40
+ end
41
+
42
+ it "includes states" do
43
+ api_get :show, id: @country.id
44
+ states = json_response['states']
45
+ expect(states.first['name']).to eq @state.name
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe Api::V1::CreditCardsController, type: :controller do
5
+ render_views
6
+
7
+ let!(:admin_user) do
8
+ user = Spree.user_class.new(email: "spree@example.com", id: 1)
9
+ user.generate_spree_api_key!
10
+ allow(user).to receive(:has_spree_role?).with('admin').and_return(true)
11
+ user
12
+ end
13
+
14
+ let!(:normal_user) do
15
+ user = Spree.user_class.new(email: "spree2@example.com", id: 2)
16
+ user.generate_spree_api_key!
17
+ user
18
+ end
19
+
20
+ let!(:card) { create(:credit_card, user_id: admin_user.id, gateway_customer_profile_id: "random") }
21
+
22
+ before do
23
+ stub_authentication!
24
+ end
25
+
26
+ it "the user id doesn't exist" do
27
+ api_get :index, user_id: 1000
28
+ expect(response.status).to eq(404)
29
+ end
30
+
31
+ context "calling user is in admin role" do
32
+ let(:current_api_user) do
33
+ user = admin_user
34
+ user
35
+ end
36
+
37
+ it "no credit cards exist for user" do
38
+ api_get :index, user_id: normal_user.id
39
+
40
+ expect(response.status).to eq(200)
41
+ expect(json_response["pages"]).to eq(0)
42
+ end
43
+
44
+ it "can view all credit cards for user" do
45
+ api_get :index, user_id: current_api_user.id
46
+
47
+ expect(response.status).to eq(200)
48
+ expect(json_response["pages"]).to eq(1)
49
+ expect(json_response["current_page"]).to eq(1)
50
+ expect(json_response["credit_cards"].length).to eq(1)
51
+ expect(json_response["credit_cards"].first["id"]).to eq(card.id)
52
+ end
53
+ end
54
+
55
+ context "calling user is not in admin role" do
56
+ let(:current_api_user) do
57
+ user = normal_user
58
+ user
59
+ end
60
+
61
+ let!(:card) { create(:credit_card, user_id: normal_user.id, gateway_customer_profile_id: "random") }
62
+
63
+ it "can not view user" do
64
+ api_get :index, user_id: admin_user.id
65
+
66
+ expect(response.status).to eq(404)
67
+ end
68
+
69
+ it "can view own credit cards" do
70
+ api_get :index, user_id: normal_user.id
71
+
72
+ expect(response.status).to eq(200)
73
+ expect(json_response["pages"]).to eq(1)
74
+ expect(json_response["current_page"]).to eq(1)
75
+ expect(json_response["credit_cards"].length).to eq(1)
76
+ expect(json_response["credit_cards"].first["id"]).to eq(card.id)
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,114 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe Api::V1::ImagesController, type: :controller do
5
+ render_views
6
+
7
+ let!(:product) { create(:product) }
8
+ let!(:attributes) { [:id, :position, :attachment_content_type,
9
+ :attachment_file_name, :type, :attachment_updated_at, :attachment_width,
10
+ :attachment_height, :alt] }
11
+
12
+ before do
13
+ stub_authentication!
14
+ end
15
+
16
+ context "as an admin" do
17
+ sign_in_as_admin!
18
+
19
+ it "can learn how to create a new image" do
20
+ api_get :new, product_id: product.id
21
+ expect(json_response["attributes"]).to eq(attributes.map(&:to_s))
22
+ expect(json_response["required_attributes"]).to be_empty
23
+ end
24
+
25
+ it "can upload a new image for a variant" do
26
+ expect do
27
+ api_post :create,
28
+ image: { attachment: upload_image('thinking-cat.jpg'),
29
+ viewable_type: 'Spree::Variant',
30
+ viewable_id: product.master.to_param },
31
+ product_id: product.id
32
+ expect(response.status).to eq(201)
33
+ expect(json_response).to have_attributes(attributes)
34
+ end.to change(Image, :count).by(1)
35
+ end
36
+
37
+ it "can't upload a new image for a variant without attachment" do
38
+ api_post :create,
39
+ image: { viewable_type: 'Spree::Variant',
40
+ viewable_id: product.master.to_param
41
+ },
42
+ product_id: product.id
43
+ expect(response.status).to eq(422)
44
+ end
45
+
46
+ context "working with an existing image" do
47
+ let!(:product_image) { product.master.images.create!(attachment: image('thinking-cat.jpg')) }
48
+
49
+ it "can get a single product image" do
50
+ api_get :show, id: product_image.id, product_id: product.id
51
+ expect(response.status).to eq(200)
52
+ expect(json_response).to have_attributes(attributes)
53
+ end
54
+
55
+ it "can get a single variant image" do
56
+ api_get :show, id: product_image.id, variant_id: product.master.id
57
+ expect(response.status).to eq(200)
58
+ expect(json_response).to have_attributes(attributes)
59
+ end
60
+
61
+ it "can get a list of product images" do
62
+ api_get :index, product_id: product.id
63
+ expect(response.status).to eq(200)
64
+ expect(json_response).to have_key("images")
65
+ expect(json_response["images"].first).to have_attributes(attributes)
66
+ end
67
+
68
+ it "can get a list of variant images" do
69
+ api_get :index, variant_id: product.master.id
70
+ expect(response.status).to eq(200)
71
+ expect(json_response).to have_key("images")
72
+ expect(json_response["images"].first).to have_attributes(attributes)
73
+ end
74
+
75
+ it "can update image data" do
76
+ expect(product_image.position).to eq(1)
77
+ api_post :update, image: { position: 2 }, id: product_image.id, product_id: product.id
78
+ expect(response.status).to eq(200)
79
+ expect(json_response).to have_attributes(attributes)
80
+ expect(product_image.reload.position).to eq(2)
81
+ end
82
+
83
+ it "can't update an image without attachment" do
84
+ api_post :update,
85
+ id: product_image.id, product_id: product.id
86
+ expect(response.status).to eq(422)
87
+ end
88
+
89
+ it "can delete an image" do
90
+ api_delete :destroy, id: product_image.id, product_id: product.id
91
+ expect(response.status).to eq(204)
92
+ expect { product_image.reload }.to raise_error(ActiveRecord::RecordNotFound)
93
+ end
94
+ end
95
+ end
96
+
97
+ context "as a non-admin" do
98
+ it "cannot create an image" do
99
+ api_post :create, product_id: product.id
100
+ assert_unauthorized!
101
+ end
102
+
103
+ it "cannot update an image" do
104
+ api_put :update, id: 1, product_id: product.id
105
+ assert_not_found!
106
+ end
107
+
108
+ it "cannot delete an image" do
109
+ api_delete :destroy, id: 1, product_id: product.id
110
+ assert_not_found!
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe Api::V1::InventoryUnitsController, type: :controller do
5
+ render_views
6
+
7
+ before do
8
+ stub_authentication!
9
+ @inventory_unit = create(:inventory_unit)
10
+ end
11
+
12
+ context "as an admin" do
13
+ sign_in_as_admin!
14
+
15
+ it "gets an inventory unit" do
16
+ api_get :show, id: @inventory_unit.id
17
+ expect(json_response['state']).to eq @inventory_unit.state
18
+ end
19
+
20
+ it "updates an inventory unit" do
21
+ api_put :update, id: @inventory_unit.id,
22
+ inventory_unit: { shipment_id: nil }
23
+ expect(json_response['shipment_id']).to be_nil
24
+ end
25
+
26
+ context 'fires state event' do
27
+ it 'if supplied with :fire param' do
28
+ api_put :update, id: @inventory_unit.id,
29
+ fire: 'ship',
30
+ inventory_unit: { shipment: { tracking: 'foobar' } }
31
+ expect(json_response['state']).to eq 'shipped'
32
+ end
33
+
34
+ it 'and returns exception if cannot fire' do
35
+ api_put :update, id: @inventory_unit.id,
36
+ fire: 'return'
37
+ expect(json_response['exception']).to match /cannot transition to return/
38
+ end
39
+
40
+ it 'and returns exception bad state' do
41
+ api_put :update, id: @inventory_unit.id,
42
+ fire: 'bad'
43
+ expect(json_response['exception']).to match /cannot transition to bad/
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,203 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ PermittedAttributes.module_eval do
5
+ mattr_writer :line_item_attributes
6
+ end
7
+
8
+ unless PermittedAttributes.line_item_attributes.include? :some_option
9
+ PermittedAttributes.line_item_attributes += [:some_option]
10
+ end
11
+
12
+ # This should go in an initializer
13
+ Spree::Api::V1::LineItemsController.line_item_options += [:some_option]
14
+
15
+ describe Api::V1::LineItemsController, type: :controller do
16
+ render_views
17
+
18
+ let!(:order) { create(:order_with_line_items, line_items_count: 1) }
19
+
20
+ let(:product) { create(:product) }
21
+ let(:attributes) { [:id, :quantity, :price, :variant, :total, :display_amount, :single_display_amount] }
22
+ let(:resource_scoping) { { order_id: order.to_param } }
23
+
24
+ before do
25
+ stub_authentication!
26
+ end
27
+
28
+ it "can learn how to create a new line item" do
29
+ api_get :new
30
+ expect(json_response["attributes"]).to eq(["quantity", "price", "variant_id"])
31
+ required_attributes = json_response["required_attributes"]
32
+ expect(required_attributes).to include("quantity", "variant_id")
33
+ end
34
+
35
+ context "authenticating with a token" do
36
+ it "can add a new line item to an existing order" do
37
+ api_post :create, line_item: { variant_id: product.master.to_param, quantity: 1 }, order_token: order.guest_token
38
+ expect(response.status).to eq(201)
39
+ expect(json_response).to have_attributes(attributes)
40
+ expect(json_response["variant"]["name"]).not_to be_blank
41
+ end
42
+
43
+ it "can add a new line item to an existing order with token in header" do
44
+ request.headers["X-Spree-Order-Token"] = order.guest_token
45
+ api_post :create, line_item: { variant_id: product.master.to_param, quantity: 1 }
46
+ expect(response.status).to eq(201)
47
+ expect(json_response).to have_attributes(attributes)
48
+ expect(json_response["variant"]["name"]).not_to be_blank
49
+ end
50
+ end
51
+
52
+ context "as the order owner" do
53
+ before do
54
+ allow_any_instance_of(Order).to receive_messages user: current_api_user
55
+ end
56
+
57
+ it "can add a new line item to an existing order" do
58
+ api_post :create, line_item: { variant_id: product.master.to_param, quantity: 1 }
59
+ expect(response.status).to eq(201)
60
+ expect(json_response).to have_attributes(attributes)
61
+ expect(json_response["variant"]["name"]).not_to be_blank
62
+ end
63
+
64
+ it "can add a new line item to an existing order with options" do
65
+ expect_any_instance_of(LineItem).to receive(:some_option=).with("foo")
66
+ api_post :create,
67
+ line_item: {
68
+ variant_id: product.master.to_param,
69
+ quantity: 1,
70
+ options: { some_option: "foo" }
71
+ }
72
+ expect(response.status).to eq(201)
73
+ end
74
+
75
+ it "default quantity to 1 if none is given" do
76
+ api_post :create, line_item: { variant_id: product.master.to_param }
77
+ expect(response.status).to eq(201)
78
+ expect(json_response).to have_attributes(attributes)
79
+ expect(json_response[:quantity]).to eq 1
80
+ end
81
+
82
+ it "increases a line item's quantity if it exists already" do
83
+ order.line_items.create(variant_id: product.master.id, quantity: 10)
84
+ api_post :create, line_item: { variant_id: product.master.to_param, quantity: 1 }
85
+ expect(response.status).to eq(201)
86
+ order.reload
87
+ expect(order.line_items.count).to eq(2) # 1 original due to factory, + 1 in this test
88
+ expect(json_response).to have_attributes(attributes)
89
+ expect(json_response["quantity"]).to eq(11)
90
+ end
91
+
92
+ it "can update a line item on the order" do
93
+ line_item = order.line_items.first
94
+ api_put :update, id: line_item.id, line_item: { quantity: 101 }
95
+ expect(response.status).to eq(200)
96
+ order.reload
97
+ expect(order.total).to eq(1010) # 10 original due to factory, + 1000 in this test
98
+ expect(json_response).to have_attributes(attributes)
99
+ expect(json_response["quantity"]).to eq(101)
100
+ end
101
+
102
+ it "can update a line item's options on the order" do
103
+ expect_any_instance_of(LineItem).to receive(:some_option=).with("foo")
104
+ line_item = order.line_items.first
105
+ api_put :update,
106
+ id: line_item.id,
107
+ line_item: { quantity: 1, options: { some_option: "foo" } }
108
+ expect(response.status).to eq(200)
109
+ end
110
+
111
+ it "can delete a line item on the order" do
112
+ line_item = order.line_items.first
113
+ api_delete :destroy, id: line_item.id
114
+ expect(response.status).to eq(204)
115
+ order.reload
116
+ expect(order.line_items.count).to eq(0) # 1 original due to factory, - 1 in this test
117
+ expect { line_item.reload }.to raise_error(ActiveRecord::RecordNotFound)
118
+ end
119
+
120
+ context "order contents changed after shipments were created" do
121
+ let!(:order) { Order.create }
122
+ let!(:line_item) { order.contents.add(product.master) }
123
+
124
+ before { order.create_proposed_shipments }
125
+
126
+ it "clear out shipments on create" do
127
+ expect(order.reload.shipments).not_to be_empty
128
+ api_post :create, line_item: { variant_id: product.master.to_param, quantity: 1 }
129
+ expect(order.reload.shipments).to be_empty
130
+ end
131
+
132
+ it "clear out shipments on update" do
133
+ expect(order.reload.shipments).not_to be_empty
134
+ api_put :update, id: line_item.id, line_item: { quantity: 1000 }
135
+ expect(order.reload.shipments).to be_empty
136
+ end
137
+
138
+ it "clear out shipments on delete" do
139
+ expect(order.reload.shipments).not_to be_empty
140
+ api_delete :destroy, id: line_item.id
141
+ expect(order.reload.shipments).to be_empty
142
+ end
143
+
144
+ context "order is completed" do
145
+ before do
146
+ allow(order).to receive_messages completed?: true
147
+ allow(Order).to receive_message_chain :includes, find_by!: order
148
+ end
149
+
150
+ it "doesn't destroy shipments or restart checkout flow" do
151
+ expect(order.reload.shipments).not_to be_empty
152
+ api_post :create, line_item: { variant_id: product.master.to_param, quantity: 1 }
153
+ expect(order.reload.shipments).not_to be_empty
154
+ end
155
+
156
+ context 'deleting line items' do
157
+ it 'restocks product after line item removal' do
158
+ line_item = order.line_items.first
159
+ variant = line_item.variant
160
+ expect do
161
+ api_delete :destroy, id: line_item.id
162
+ end.to change { variant.total_on_hand }.by(line_item.quantity)
163
+
164
+ expect(response.status).to eq(204)
165
+ order.reload
166
+ expect(order.line_items.count).to eq(0)
167
+ end
168
+
169
+ it 'calls `restock` on proper stock location' do
170
+ expect(order.shipments.first.stock_location).to receive(:restock)
171
+ api_delete :destroy, id: line_item.id
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
177
+
178
+ context "as just another user" do
179
+ before do
180
+ user = create(:user)
181
+ end
182
+
183
+ it "cannot add a new line item to the order" do
184
+ api_post :create, line_item: { variant_id: product.master.to_param, quantity: 1 }
185
+ assert_unauthorized!
186
+ end
187
+
188
+ it "cannot update a line item on the order" do
189
+ line_item = order.line_items.first
190
+ api_put :update, id: line_item.id, line_item: { quantity: 1000 }
191
+ assert_unauthorized!
192
+ expect(line_item.reload.quantity).not_to eq(1000)
193
+ end
194
+
195
+ it "cannot delete a line item on the order" do
196
+ line_item = order.line_items.first
197
+ api_delete :destroy, id: line_item.id
198
+ assert_unauthorized!
199
+ expect { line_item.reload }.not_to raise_error
200
+ end
201
+ end
202
+ end
203
+ end