solidus_easypost 2.0.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +6 -0
- data/.github/stale.yml +4 -4
- data/.github_changelog_generator +2 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +3 -0
- data/.rubocop_todo.yml +12 -47
- data/CHANGELOG.md +113 -0
- data/LICENSE +1 -1
- data/README.md +111 -21
- data/app/controllers/spree/admin/postage_labels_controller.rb +20 -0
- data/app/decorators/models/solidus_easypost/spree/carton_decorator.rb +38 -0
- data/app/decorators/models/solidus_easypost/spree/shipment_decorator.rb +18 -23
- data/app/models/solidus_easypost/parcel_dimension.rb +34 -0
- data/app/models/solidus_easypost/return_authorization.rb +2 -13
- data/app/overrides/spree/admin/orders/_shipment/add_postage_label.html.erb.deface +10 -0
- data/bin/rails +0 -1
- data/bin/rails-engine +0 -2
- data/bin/rails-sandbox +1 -2
- data/bin/sandbox +2 -0
- data/config/initializers/webhooks.rb +7 -0
- data/config/locales/en.yml +7 -4
- data/config/routes.rb +5 -1
- data/db/migrate/20201025110912_add_tracker_id_to_cartons.rb +6 -0
- data/lib/generators/solidus_easypost/install/install_generator.rb +7 -1
- data/lib/generators/solidus_easypost/install/templates/initializer.rb +26 -0
- data/lib/solidus_easypost/address_builder.rb +45 -0
- data/lib/solidus_easypost/calculator/base_dimension_calculator.rb +28 -0
- data/lib/solidus_easypost/calculator/weight_dimension_calculator.rb +22 -0
- data/lib/solidus_easypost/configuration.rb +25 -2
- data/lib/solidus_easypost/errors/unknown_partial_resource_error.rb +11 -0
- data/lib/solidus_easypost/estimator.rb +37 -0
- data/lib/solidus_easypost/parcel_builder.rb +27 -0
- data/lib/solidus_easypost/shipment_builder.rb +32 -0
- data/lib/solidus_easypost/shipping_method_selector.rb +17 -0
- data/lib/solidus_easypost/shipping_rate_calculator.rb +9 -0
- data/lib/solidus_easypost/testing_support/factories/address_factory.rb +10 -0
- data/lib/solidus_easypost/testing_support/factories/product_factory.rb +7 -0
- data/lib/solidus_easypost/testing_support/factories/shipment_factory.rb +30 -0
- data/lib/solidus_easypost/testing_support/factories/shipping_method_factory.rb +8 -0
- data/lib/solidus_easypost/testing_support/factories/stock_location_factory.rb +10 -0
- data/lib/solidus_easypost/testing_support/factories/variant_factory.rb +7 -0
- data/lib/solidus_easypost/testing_support/factories.rb +3 -0
- data/lib/solidus_easypost/tracker_webhook_handler.rb +14 -0
- data/lib/solidus_easypost/version.rb +1 -1
- data/lib/solidus_easypost.rb +11 -0
- data/solidus_easypost.gemspec +8 -5
- data/spec/cassettes/{Spree_Address/_easypost_address/is_an_EasyPost_Address_object.yml → address_builder/from_address.yml} +19 -23
- data/spec/cassettes/{Spree_StockLocation/_easypost_address/is_an_EasyPost_Address_object.yml → address_builder/from_stock_location.yml} +19 -23
- data/spec/cassettes/{Spree_Stock_Estimator/_shipping_rates/when_rates_are_found/when_shipping_methods_exist/when_shipping_methods_are_front_end_visible/has_the_correct_costs.yml → estimator.yml} +0 -0
- data/spec/cassettes/integration/checkout.yml +377 -0
- data/spec/cassettes/integration/order_shipping/with_purchase_labels.yml +373 -0
- data/spec/cassettes/integration/order_shipping/without_purchase_labels.yml +251 -0
- data/spec/cassettes/{Spree_Stock_Package/_easypost_parcel/is_an_EasyPost_Parcel_object.yml → parcel_builder/from_package.yml} +17 -22
- data/spec/cassettes/{Spree_Stock_Package/_easypost_parcel/has_the_correct_attributes.yml → parcel_builder/from_return_authorization.yml} +17 -22
- data/spec/cassettes/postage_labels/show.yml +72 -0
- data/spec/cassettes/return_authorization.yml +310 -0
- data/spec/cassettes/{Spree_Stock_Package/_easypost_shipment/is_an_EasyPost_Shipment_object.yml → shipment_builder/from_package.yml} +74 -92
- data/spec/cassettes/{Spree_Stock_Estimator/_shipping_rates/when_rates_are_found/when_shipping_methods_exist/create_no_new_shipping_methods.yml → shipment_builder/from_return_authorization.yml} +77 -95
- data/spec/cassettes/shipment_builder/from_shipment.yml +250 -0
- data/spec/controllers/spree/admin/postage_labels_controller_spec.rb +18 -0
- data/spec/features/admin/postage_labels_spec.rb +18 -0
- data/spec/integration/checkout_spec.rb +45 -0
- data/spec/integration/order_shipping_spec.rb +33 -0
- data/spec/models/solidus_easypost/parcel_dimension_spec.rb +80 -0
- data/spec/models/solidus_easypost/return_authorization_spec.rb +7 -40
- data/spec/models/spree/carton_spec.rb +57 -0
- data/spec/models/spree/shipment_spec.rb +48 -59
- data/spec/models/spree/shipping_rate_spec.rb +14 -7
- data/spec/solidus_easypost/address_builder_spec.rb +17 -0
- data/spec/solidus_easypost/calculator/weight_dimension_calculator_spec.rb +39 -0
- data/spec/solidus_easypost/estimator_spec.rb +52 -0
- data/spec/solidus_easypost/parcel_builder_spec.rb +113 -0
- data/spec/solidus_easypost/shipment_builder_spec.rb +28 -0
- data/spec/solidus_easypost/shipping_method_selector_spec.rb +33 -0
- data/spec/solidus_easypost/shipping_rate_calculator_spec.rb +12 -0
- data/spec/solidus_easypost/tracker_webhook_handler_spec.rb +58 -0
- data/spec/spec_helper.rb +11 -7
- data/spec/support/easypost.rb +3 -1
- data/spec/support/helpers/api_stubs.rb +40 -0
- data/spec/support/helpers/configuration.rb +28 -0
- data/spec/support/helpers/shipping_methods.rb +26 -0
- data/spec/support/solidus.rb +1 -0
- data/spec/support/vcr.rb +1 -0
- metadata +118 -85
- data/app/decorators/models/solidus_easypost/spree/address_decorator.rb +0 -30
- data/app/decorators/models/solidus_easypost/spree/stock/estimator_decorator.rb +0 -15
- data/app/decorators/models/solidus_easypost/spree/stock/package_decorator.rb +0 -27
- data/app/decorators/models/solidus_easypost/spree/stock_location_decorator.rb +0 -26
- data/app/models/solidus_easypost/estimator.rb +0 -51
- data/lib/solidus_easypost/factories.rb +0 -24
- data/spec/cassettes/SolidusEasypost_ReturnAuthorization/_easypost_shipment/is_an_EasyPost_Shipment_object.yml +0 -271
- data/spec/cassettes/SolidusEasypost_ReturnAuthorization/_return_label/has_the_correct_fields.yml +0 -336
- data/spec/cassettes/SolidusEasypost_ReturnAuthorization/_return_label/is_an_EasyPost_PackageLabel_object.yml +0 -336
- data/spec/cassettes/Spree_Address/_easypost_address/has_the_correct_attributes.yml +0 -69
- data/spec/cassettes/Spree_Order/_refresh_shipment_rates/can_get_rates_from_easy_post.yml +0 -271
- data/spec/cassettes/Spree_Order/_refresh_shipment_rates/create_shipping_methods_for_the_rates.yml +0 -269
- data/spec/cassettes/Spree_Shipment/_buys_a_shipping_rate_after_transitioning_to_ship.yml +0 -403
- data/spec/cassettes/Spree_Shipment/_easypost_shipment/when_it_is_a_new_shipment/behaves_like_an_easypost_shipment/is_an_EasyPost_Shipment_object.yml +0 -271
- data/spec/cassettes/Spree_Shipment/_easypost_shipment/when_it_is_a_new_shipment/calls_the_api.yml +0 -200
- data/spec/cassettes/Spree_Shipment/_easypost_shipment/when_it_is_an_existing_shipment/behaves_like_an_easypost_shipment/is_an_EasyPost_Shipment_object.yml +0 -334
- data/spec/cassettes/Spree_Shipment/_easypost_shipment/when_it_is_an_existing_shipment/loads_the_existing_shipment.yml +0 -271
- data/spec/cassettes/Spree_StockLocation/_easypost_address/has_the_correct_attributes.yml +0 -69
- data/spec/cassettes/Spree_Stock_Estimator/_shipping_rates/when_rates_are_found/when_shipping_methods_dont_exist/creates_new_shipping_methods.yml +0 -269
- data/spec/cassettes/Spree_Stock_Estimator/_shipping_rates/when_rates_are_found/when_shipping_methods_dont_exist/is_empty.yml +0 -269
- data/spec/cassettes/Spree_Stock_Estimator/_shipping_rates/when_rates_are_found/when_shipping_methods_exist/when_shipping_methods_are_front_end_visible/has_the_correct_names.yml +0 -269
- data/spec/cassettes/Spree_Stock_Estimator/_shipping_rates/when_rates_are_found/when_shipping_methods_exist/when_shipping_methods_are_not_front_end_visible/is_empty.yml +0 -269
- data/spec/cassettes/Spree_Stock_Package/_easypost_shipment/calls_the_api.yml +0 -200
- data/spec/factories/spree_modification.rb +0 -25
- data/spec/models/spree/address_spec.rb +0 -31
- data/spec/models/spree/order_spec.rb +0 -31
- data/spec/models/spree/stock/estimator_spec.rb +0 -80
- data/spec/models/spree/stock/package_spec.rb +0 -35
- data/spec/models/spree/stock_location_spec.rb +0 -31
- data/spec/support/shipping_method_helpers.rb +0 -43
@@ -0,0 +1,45 @@
|
|
1
|
+
RSpec.describe 'Checkout' do
|
2
|
+
it 'retrieves the rates from EasyPost', vcr: { cassette_name: 'integration/checkout' } do
|
3
|
+
stub_easypost_config(purchase_labels: true)
|
4
|
+
stub_spree_preferences(require_payment_to_ship: false, track_inventory_levels: false)
|
5
|
+
use_easypost_estimator
|
6
|
+
create_easypost_shipping_methods
|
7
|
+
|
8
|
+
order = Spree::TestingSupport::OrderWalkthrough.up_to(:complete)
|
9
|
+
shipment = order.shipments.first
|
10
|
+
shipment.ship!
|
11
|
+
|
12
|
+
expect(order.state).to eq('complete')
|
13
|
+
expect(shipment.shipping_rates).to match_array([
|
14
|
+
have_attributes(
|
15
|
+
selected: true,
|
16
|
+
cost: 0.393e1,
|
17
|
+
name: 'USPS First',
|
18
|
+
easy_post_shipment_id: /shp_/,
|
19
|
+
easy_post_rate_id: /rate_/,
|
20
|
+
),
|
21
|
+
have_attributes(
|
22
|
+
selected: false,
|
23
|
+
cost: 0.692e1,
|
24
|
+
name: 'USPS ParcelSelect',
|
25
|
+
easy_post_shipment_id: /shp_/,
|
26
|
+
easy_post_rate_id: /rate_/,
|
27
|
+
),
|
28
|
+
have_attributes(
|
29
|
+
selected: false,
|
30
|
+
cost: 0.702e1,
|
31
|
+
name: 'USPS Priority',
|
32
|
+
easy_post_shipment_id: /shp_/,
|
33
|
+
easy_post_rate_id: /rate_/,
|
34
|
+
),
|
35
|
+
have_attributes(
|
36
|
+
selected: false,
|
37
|
+
cost: 0.23e2,
|
38
|
+
name: 'USPS Express',
|
39
|
+
easy_post_shipment_id: /shp_/,
|
40
|
+
easy_post_rate_id: /rate_/,
|
41
|
+
),
|
42
|
+
])
|
43
|
+
expect(shipment.tracking).to be_present
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
RSpec.describe 'Order shipping' do
|
2
|
+
context 'with purchase_labels set to true', vcr: { cassette_name: 'integration/order_shipping/with_purchase_labels' } do
|
3
|
+
it 'buys the rate in EasyPost' do
|
4
|
+
stub_easypost_config(purchase_labels: true)
|
5
|
+
stub_spree_preferences(require_payment_to_ship: false, track_inventory_levels: false)
|
6
|
+
use_easypost_estimator
|
7
|
+
create_easypost_shipping_methods
|
8
|
+
|
9
|
+
order = Spree::TestingSupport::OrderWalkthrough.up_to(:complete)
|
10
|
+
shipment = order.shipments.first
|
11
|
+
shipment.ship!
|
12
|
+
|
13
|
+
expect(shipment).to be_shipped
|
14
|
+
expect(shipment.tracking).to be_present
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'with purchase_labels set to false', vcr: { cassette_name: 'integration/order_shipping/without_purchase_labels' } do
|
19
|
+
it 'does not buy the rate in EasyPost' do
|
20
|
+
stub_easypost_config(purchase_labels: false)
|
21
|
+
stub_spree_preferences(require_payment_to_ship: false, track_inventory_levels: false)
|
22
|
+
use_easypost_estimator
|
23
|
+
create_easypost_shipping_methods
|
24
|
+
|
25
|
+
order = Spree::TestingSupport::OrderWalkthrough.up_to(:complete)
|
26
|
+
shipment = order.shipments.first
|
27
|
+
shipment.ship!
|
28
|
+
|
29
|
+
expect(shipment).to be_shipped
|
30
|
+
expect(shipment.tracking).not_to be_present
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe SolidusEasypost::ParcelDimension do
|
6
|
+
describe '.new' do
|
7
|
+
subject(:instance) { described_class.new(params) }
|
8
|
+
|
9
|
+
let(:params) do
|
10
|
+
{ height: 3 }
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'when the weight is not passed' do
|
14
|
+
let(:params) do
|
15
|
+
{ height: 3 }
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'raises an argument error exception' do
|
19
|
+
expect {
|
20
|
+
instance
|
21
|
+
}.to raise_error(ArgumentError)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when the passed weight is zero' do
|
26
|
+
let(:params) do
|
27
|
+
{ height: 3, weight: 0 }
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'raises an argument error exception' do
|
31
|
+
expect {
|
32
|
+
instance
|
33
|
+
}.to raise_error(ArgumentError)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#to_h' do
|
39
|
+
subject(:instance_hash) { described_class.new(params).to_h }
|
40
|
+
|
41
|
+
context 'when the params contains zero values' do
|
42
|
+
let(:params) do
|
43
|
+
{ weight: 3, width: 0, height: 0, unknown: -1 }
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'returns the correct parcel dimension hash' do
|
47
|
+
expect(instance_hash).to eq({
|
48
|
+
weight: 3
|
49
|
+
})
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'when the params contains the wrong params' do
|
54
|
+
let(:params) do
|
55
|
+
{ weight: 3, unknown: -1, another: 11 }
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'returns the correct parcel dimension hash' do
|
59
|
+
expect(instance_hash).to eq({
|
60
|
+
weight: 3
|
61
|
+
})
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'when the params contains the correct params' do
|
66
|
+
let(:params) do
|
67
|
+
{ weight: 3, width: 1, depth: 6, height: 11 }
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'returns the correct parcel dimension hash' do
|
71
|
+
expect(instance_hash).to eq({
|
72
|
+
height: 11,
|
73
|
+
weight: 3,
|
74
|
+
width: 1,
|
75
|
+
length: 6,
|
76
|
+
})
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -2,49 +2,16 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
RSpec.describe SolidusEasypost::ReturnAuthorization, :
|
6
|
-
let(:auth) { described_class.new return_authorization }
|
7
|
-
let(:return_authorization) do
|
8
|
-
create :return_authorization do |ra|
|
9
|
-
ra.return_items << create(:return_item)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
before { create :shipping_method, admin_name: 'USPS Priority' }
|
13
|
-
|
14
|
-
before { create :store }
|
15
|
-
|
16
|
-
describe '#easypost_shipment' do
|
17
|
-
subject { auth.easypost_shipment }
|
18
|
-
|
19
|
-
it 'is an EasyPost::Shipment object' do
|
20
|
-
expect(subject).to be_a(EasyPost::Shipment)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
5
|
+
RSpec.describe SolidusEasypost::ReturnAuthorization, vcr: { cassette_name: 'return_authorization' } do
|
24
6
|
describe '#return_label' do
|
25
|
-
|
7
|
+
it 'returns a valid return label' do
|
8
|
+
return_authorization = create(:return_item).return_authorization
|
26
9
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
expect(subject).to be_a(EasyPost::PostageLabel)
|
31
|
-
end
|
10
|
+
easypost_return_authorization = described_class.new(return_authorization)
|
11
|
+
selected_easypost_rate = easypost_return_authorization.easypost_shipment.rates.first
|
12
|
+
return_label = easypost_return_authorization.return_label(selected_easypost_rate)
|
32
13
|
|
33
|
-
|
34
|
-
expect(subject).to have_attributes(
|
35
|
-
id: "pl_37f765f275dd46c2866d0515694a306c",
|
36
|
-
object: "PostageLabel",
|
37
|
-
created_at: "2019-11-12T08:36:50Z",
|
38
|
-
updated_at: "2019-11-12T08:36:51Z",
|
39
|
-
date_advance: 0,
|
40
|
-
integrated_form: "none",
|
41
|
-
label_date: "2019-11-12T08:36:50Z",
|
42
|
-
label_resolution: 300,
|
43
|
-
label_size: "4x6",
|
44
|
-
label_type: "default",
|
45
|
-
label_url: "https://easypost-files.s3-us-west-2.amazonaws.com/files/postage_label/20191112/ebe045d367a742dd8bf718e63a58c390.png",
|
46
|
-
label_file_type: "image/png"
|
47
|
-
)
|
14
|
+
expect(return_label).to have_attributes(object: 'PostageLabel')
|
48
15
|
end
|
49
16
|
end
|
50
17
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
RSpec.describe Spree::Carton do
|
2
|
+
describe '.create' do
|
3
|
+
context 'when track_all_cartons is true' do
|
4
|
+
it 'tracks the package automatically' do
|
5
|
+
stub_easypost_config(track_all_cartons: true)
|
6
|
+
tracker = instance_double(EasyPost::Tracker, id: 'trk_test')
|
7
|
+
allow(EasyPost::Tracker).to receive(:create).and_return(tracker)
|
8
|
+
|
9
|
+
carton = create(:carton)
|
10
|
+
|
11
|
+
expect(carton.easy_post_tracker_id).to eq('trk_test')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'when track_all_cartons is false' do
|
16
|
+
it 'does not track all packages automatically' do
|
17
|
+
stub_easypost_config(track_all_cartons: false)
|
18
|
+
|
19
|
+
carton = create(:carton)
|
20
|
+
|
21
|
+
expect(carton.easy_post_tracker_id).to eq(nil)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#easypost_tracker' do
|
27
|
+
context 'when a tracker was already created' do
|
28
|
+
it 'returns the existing tracker' do
|
29
|
+
carton = create(:carton, easy_post_tracker_id: 'trk_test')
|
30
|
+
tracker = instance_double(EasyPost::Tracker)
|
31
|
+
allow(EasyPost::Tracker).to receive(:retrieve).with('trk_test').and_return(tracker)
|
32
|
+
|
33
|
+
expect(carton.easypost_tracker).to eq(tracker)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'when a tracker was not created' do
|
38
|
+
it 'creates a new tracker' do
|
39
|
+
carton = create(:carton, tracking: 'TESTTRACKING', shipping_method: create(:shipping_method, carrier: 'FedEx'))
|
40
|
+
tracker = instance_double(EasyPost::Tracker, id: 'trk_test')
|
41
|
+
allow(EasyPost::Tracker).to receive(:create).with(tracking_code: 'TESTTRACKING', carrier: 'FedEx').and_return(tracker)
|
42
|
+
|
43
|
+
expect(carton.easypost_tracker).to eq(tracker)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "sets the tracker's ID on the carton" do
|
47
|
+
carton = create(:carton)
|
48
|
+
tracker = instance_double(EasyPost::Tracker, id: 'trk_test')
|
49
|
+
allow(EasyPost::Tracker).to receive(:create).and_return(tracker)
|
50
|
+
|
51
|
+
carton.easypost_tracker
|
52
|
+
|
53
|
+
expect(carton.easy_post_tracker_id).to eq('trk_test')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -2,78 +2,67 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
RSpec.describe Spree::Shipment
|
6
|
-
let!(:shipment) { order.shipments.first }
|
7
|
-
let!(:order) do
|
8
|
-
create(:order_with_line_items, line_items_count: 1, ship_address: to) do |order|
|
9
|
-
order.variants.each { |v| v.update! weight: 10 }
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
let(:to) do
|
14
|
-
Spree::Address.create(
|
15
|
-
firstname: 'Newt',
|
16
|
-
lastname: 'Scamander',
|
17
|
-
address1: '200 19th St',
|
18
|
-
city: 'Birmingham',
|
19
|
-
state: Spree::State.first || create(:state),
|
20
|
-
country: Spree::Country.first || create(:country),
|
21
|
-
zipcode: 35_203,
|
22
|
-
phone: '123456789'
|
23
|
-
)
|
24
|
-
end
|
25
|
-
|
26
|
-
before do
|
27
|
-
create_shipping_methods
|
28
|
-
shipment.stock_location.update(
|
29
|
-
address1: '2630 Cahaba Rd',
|
30
|
-
city: 'Birmingham',
|
31
|
-
state: Spree::State.first,
|
32
|
-
country: Spree::Country.first,
|
33
|
-
zipcode: 35_223,
|
34
|
-
)
|
35
|
-
end
|
36
|
-
|
37
|
-
it "'buys' a shipping rate after transitioning to ship" do
|
38
|
-
shipment.refresh_rates
|
39
|
-
shipment.state = 'ready'
|
40
|
-
|
41
|
-
shipment.ship!
|
42
|
-
expect(shipment.tracking).to be_present
|
43
|
-
end
|
44
|
-
|
5
|
+
RSpec.describe Spree::Shipment do
|
45
6
|
describe '#easypost_shipment' do
|
46
|
-
|
7
|
+
context 'when no shipping rate was selected' do
|
8
|
+
it 'returns nil' do
|
9
|
+
shipment = create(:shipment)
|
47
10
|
|
48
|
-
|
49
|
-
it 'is an EasyPost::Shipment object' do
|
50
|
-
expect(subject).to be_a(EasyPost::Shipment)
|
11
|
+
expect(shipment.easypost_shipment).to be_nil
|
51
12
|
end
|
52
13
|
end
|
53
14
|
|
54
|
-
context 'when
|
55
|
-
|
15
|
+
context 'when a shipping rate was selected' do
|
16
|
+
it 'returns the shipment associated with the shipping rate' do
|
17
|
+
easypost_shipment = stub_easypost_shipment
|
18
|
+
shipment = create(
|
19
|
+
:shipment,
|
20
|
+
:with_easypost,
|
21
|
+
easypost_shipment_id: easypost_shipment.id,
|
22
|
+
)
|
56
23
|
|
57
|
-
|
58
|
-
expect(EasyPost::Shipment).to receive(:create).with(anything)
|
59
|
-
subject
|
24
|
+
expect(shipment.easypost_shipment).to eq(easypost_shipment)
|
60
25
|
end
|
61
26
|
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#ship!' do
|
30
|
+
context 'when purchase_labels is true' do
|
31
|
+
it 'buys the selected rate' do
|
32
|
+
stub_easypost_config(purchase_labels: true)
|
33
|
+
easypost_shipment = stub_easypost_shipment
|
34
|
+
selected_easypost_rate = easypost_shipment.rates.first
|
62
35
|
|
63
|
-
|
64
|
-
|
36
|
+
shipment = create(
|
37
|
+
:shipment,
|
38
|
+
:with_easypost,
|
39
|
+
state: 'ready',
|
40
|
+
easypost_shipment_id: easypost_shipment.id,
|
41
|
+
easypost_rate_id: selected_easypost_rate.id,
|
42
|
+
)
|
43
|
+
shipment.ship!
|
65
44
|
|
66
|
-
|
67
|
-
ep_id = shipment.easypost_shipment.id
|
68
|
-
shipment.shipping_rates.first.update selected: true, easy_post_shipment_id: ep_id
|
69
|
-
shipment.instance_variable_set('@ep_shipment', nil)
|
45
|
+
expect(easypost_shipment).to have_received(:buy).with(selected_easypost_rate)
|
70
46
|
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'when purchase_labels is false' do
|
50
|
+
it 'does not buy rates automatically' do
|
51
|
+
stub_easypost_config(purchase_labels: false)
|
52
|
+
easypost_shipment = stub_easypost_shipment
|
53
|
+
selected_easypost_rate = easypost_shipment.rates.first
|
54
|
+
|
55
|
+
shipment = create(
|
56
|
+
:shipment,
|
57
|
+
:with_easypost,
|
58
|
+
state: 'ready',
|
59
|
+
easypost_shipment_id: easypost_shipment.id,
|
60
|
+
easypost_rate_id: selected_easypost_rate.id,
|
61
|
+
)
|
71
62
|
|
72
|
-
|
63
|
+
shipment.ship!
|
73
64
|
|
74
|
-
|
75
|
-
expect(EasyPost::Shipment).to receive(:retrieve).with(anything)
|
76
|
-
subject
|
65
|
+
expect(easypost_shipment).not_to have_received(:buy)
|
77
66
|
end
|
78
67
|
end
|
79
68
|
end
|
@@ -2,15 +2,22 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
RSpec.describe Spree::ShippingRate
|
6
|
-
let(:rate) { described_class.new name: name }
|
7
|
-
let(:name) { 'SuperAwesomeCool' }
|
8
|
-
|
5
|
+
RSpec.describe Spree::ShippingRate do
|
9
6
|
describe '#name' do
|
10
|
-
|
7
|
+
context 'when the shipping rate has its own name' do
|
8
|
+
it 'returns the name on the shipping rate' do
|
9
|
+
shipping_rate = build_stubbed(:shipping_rate, name: 'USPS Express')
|
10
|
+
|
11
|
+
expect(shipping_rate.name).to eq('USPS Express')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'when the shipping rate does not have its own name' do
|
16
|
+
it 'returns the name on the shipping method' do
|
17
|
+
shipping_rate = build_stubbed(:shipping_rate, name: nil)
|
11
18
|
|
12
|
-
|
13
|
-
|
19
|
+
expect(shipping_rate.name).to eq(shipping_rate.shipping_method.name)
|
20
|
+
end
|
14
21
|
end
|
15
22
|
end
|
16
23
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
RSpec.describe SolidusEasypost::AddressBuilder do
|
2
|
+
describe '.from_address', vcr: { cassette_name: 'address_builder/from_address' } do
|
3
|
+
it 'builds an address with the correct attributes' do
|
4
|
+
address = described_class.from_address(build_stubbed(:address))
|
5
|
+
|
6
|
+
expect(address).to have_attributes(object: 'Address')
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '.from_stock_location', vcr: { cassette_name: 'address_builder/from_stock_location' } do
|
11
|
+
it 'builds an address with the correct attributes' do
|
12
|
+
address = described_class.from_stock_location(create(:stock_location))
|
13
|
+
|
14
|
+
expect(address).to have_attributes(object: 'Address')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe SolidusEasypost::Calculator::WeightDimensionCalculator do
|
4
|
+
describe '#compute' do
|
5
|
+
subject(:compute) { described_class.new.compute(resource) }
|
6
|
+
|
7
|
+
context 'when a wrong resource is passed' do
|
8
|
+
let(:resource) { create(:shipment) }
|
9
|
+
|
10
|
+
it 'raises an unknown partial resource error' do
|
11
|
+
expect { compute }.to raise_error(SolidusEasypost::Errors::UnknownPartialResourceError)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'when a Spree::Stock::Package is passed' do
|
16
|
+
let(:resource) { create(:shipment).to_package }
|
17
|
+
|
18
|
+
before { allow(SolidusEasypost::ParcelDimension).to receive(:new) }
|
19
|
+
|
20
|
+
it 'build a parcel dimension' do
|
21
|
+
compute
|
22
|
+
|
23
|
+
expect(SolidusEasypost::ParcelDimension).to have_received(:new).with({ weight: 10.to_f })
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when a SolidusEasypost::ReturnAuthorization is passed' do
|
28
|
+
let(:resource) { SolidusEasypost::ReturnAuthorization.new(create(:return_authorization)) }
|
29
|
+
|
30
|
+
before { allow(SolidusEasypost::ParcelDimension).to receive(:new) }
|
31
|
+
|
32
|
+
it 'build a parcel dimension' do
|
33
|
+
compute
|
34
|
+
|
35
|
+
expect(SolidusEasypost::ParcelDimension).to have_received(:new).with({ weight: 0.to_f })
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe SolidusEasypost::Estimator, vcr: { cassette_name: 'estimator' } do
|
6
|
+
describe '#shipping_rates' do
|
7
|
+
context 'when the shipping methods are available to users' do
|
8
|
+
it 'returns the shipping rates' do
|
9
|
+
stub_shipping_method_selector(available_to_users: true)
|
10
|
+
|
11
|
+
rates = described_class.new.shipping_rates(create(:shipment).to_package)
|
12
|
+
|
13
|
+
hash = {
|
14
|
+
"USPS Express" => 22.74,
|
15
|
+
"USPS First" => 3.82,
|
16
|
+
"USPS ParcelSelect" => 6.85,
|
17
|
+
"USPS Priority" => 6.95,
|
18
|
+
}
|
19
|
+
|
20
|
+
expect(rates.sort_by(&:name).map { |r| [r.name, r.cost] }.to_h).to eq(hash)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when the shipping methods are not available to users' do
|
25
|
+
it 'returns no rates' do
|
26
|
+
stub_shipping_method_selector(available_to_users: false)
|
27
|
+
|
28
|
+
rates = described_class.new.shipping_rates(create(:shipment).to_package)
|
29
|
+
|
30
|
+
expect(rates).to be_empty
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def stub_shipping_method_selector(available_to_users:)
|
38
|
+
shipping_method_selector = Class.new.tap do |klass|
|
39
|
+
klass.define_method(:shipping_method_for) do |rate|
|
40
|
+
Spree::ShippingMethod.new(
|
41
|
+
name: "#{rate.carrier} #{rate.service}",
|
42
|
+
available_to_users: available_to_users,
|
43
|
+
)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
stub_const('FakeShippingMethodSelector', shipping_method_selector)
|
48
|
+
|
49
|
+
allow(SolidusEasypost.configuration).to receive(:shipping_method_selector_class)
|
50
|
+
.and_return(FakeShippingMethodSelector)
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe SolidusEasypost::ParcelBuilder do
|
4
|
+
describe '.from_package', vcr: { cassette_name: 'parcel_builder/from_package' } do
|
5
|
+
let(:shipment) { create(:shipment) }
|
6
|
+
let(:package) { shipment.to_package }
|
7
|
+
let(:parcel_dimension_calculator) { instance_spy('SolidusEasypost.configuration.parcel_dimension_calculator_class') }
|
8
|
+
let(:parcel_dimension) { instance_spy('SolidusEasypost::ParcelDimension') }
|
9
|
+
|
10
|
+
before do
|
11
|
+
allow(SolidusEasypost.configuration.parcel_dimension_calculator_class)
|
12
|
+
.to receive(:new)
|
13
|
+
.and_return(parcel_dimension_calculator)
|
14
|
+
|
15
|
+
allow(parcel_dimension_calculator).to receive(:compute).and_return(parcel_dimension)
|
16
|
+
allow(parcel_dimension).to receive(:to_h).and_return(dimension_hash)
|
17
|
+
allow(EasyPost::Parcel).to receive(:create).and_call_original
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'when there is only the weight set' do
|
21
|
+
let(:dimension_hash) { { weight: 10.to_f } }
|
22
|
+
|
23
|
+
it 'builds a parcel with the correct attributes' do
|
24
|
+
parcel = described_class.from_package(package)
|
25
|
+
|
26
|
+
expect(parcel_dimension_calculator)
|
27
|
+
.to have_received(:compute)
|
28
|
+
.with(package)
|
29
|
+
|
30
|
+
expect(EasyPost::Parcel)
|
31
|
+
.to have_received(:create)
|
32
|
+
.with({ weight: 10.to_f })
|
33
|
+
|
34
|
+
expect(parcel).to have_attributes(object: 'Parcel')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'when all the properties are set' do
|
39
|
+
let(:dimension_hash) do
|
40
|
+
{ weight: 10.to_f, height: 2.to_f, width: 3.to_f, depth: 4.to_f }
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'builds a parcel with the correct attributes' do
|
44
|
+
parcel = described_class.from_package(package)
|
45
|
+
|
46
|
+
expect(parcel_dimension_calculator)
|
47
|
+
.to have_received(:compute)
|
48
|
+
.with(package)
|
49
|
+
|
50
|
+
expect(EasyPost::Parcel)
|
51
|
+
.to have_received(:create)
|
52
|
+
.with({ weight: 10.to_f, height: 2.to_f, width: 3.to_f, depth: 4.to_f })
|
53
|
+
|
54
|
+
expect(parcel).to have_attributes(object: 'Parcel')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '.from_return_authorization', vcr: { cassette_name: 'parcel_builder/from_return_authorization' } do
|
60
|
+
let(:return_item) { create(:return_item) }
|
61
|
+
let(:return_authorization) { return_item.return_authorization }
|
62
|
+
let(:parcel_dimension_calculator) { instance_spy('SolidusEasypost.configuration.parcel_dimension_calculator_class') }
|
63
|
+
let(:parcel_dimension) { instance_spy('SolidusEasypost::ParcelDimension') }
|
64
|
+
|
65
|
+
before do
|
66
|
+
allow(SolidusEasypost.configuration.parcel_dimension_calculator_class)
|
67
|
+
.to receive(:new)
|
68
|
+
.and_return(parcel_dimension_calculator)
|
69
|
+
|
70
|
+
allow(parcel_dimension_calculator).to receive(:compute).and_return(parcel_dimension)
|
71
|
+
allow(parcel_dimension).to receive(:to_h).and_return(dimension_hash)
|
72
|
+
allow(EasyPost::Parcel).to receive(:create).and_call_original
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'when there is only the weight set' do
|
76
|
+
let(:dimension_hash) { { weight: 10.to_f } }
|
77
|
+
|
78
|
+
it 'builds a parcel with the correct attributes' do
|
79
|
+
parcel = described_class.from_return_authorization(return_authorization)
|
80
|
+
|
81
|
+
expect(parcel_dimension_calculator)
|
82
|
+
.to have_received(:compute)
|
83
|
+
.with(return_authorization)
|
84
|
+
|
85
|
+
expect(EasyPost::Parcel)
|
86
|
+
.to have_received(:create)
|
87
|
+
.with({ weight: 10.to_f })
|
88
|
+
|
89
|
+
expect(parcel).to have_attributes(object: 'Parcel')
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'when all the properties are set' do
|
94
|
+
let(:dimension_hash) do
|
95
|
+
{ weight: 10.to_f, height: 2.to_f, width: 3.to_f, depth: 4.to_f }
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'builds a parcel with the correct attributes' do
|
99
|
+
parcel = described_class.from_return_authorization(return_authorization)
|
100
|
+
|
101
|
+
expect(parcel_dimension_calculator)
|
102
|
+
.to have_received(:compute)
|
103
|
+
.with(return_authorization)
|
104
|
+
|
105
|
+
expect(EasyPost::Parcel)
|
106
|
+
.to have_received(:create)
|
107
|
+
.with({ weight: 10.to_f, height: 2.to_f, width: 3.to_f, depth: 4.to_f })
|
108
|
+
|
109
|
+
expect(parcel).to have_attributes(object: 'Parcel')
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe SolidusEasypost::ShipmentBuilder do
|
4
|
+
describe '.from_package', vcr: { cassette_name: 'shipment_builder/from_package' } do
|
5
|
+
it 'builds a shipment with the correct attributes' do
|
6
|
+
shipment = described_class.from_package(create(:shipment).to_package)
|
7
|
+
|
8
|
+
expect(shipment).to have_attributes(object: 'Shipment')
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '.from_shipment', vcr: { cassette_name: 'shipment_builder/from_shipment' } do
|
13
|
+
it 'builds a shipment with the correct attributes' do
|
14
|
+
shipment = described_class.from_shipment(create(:shipment))
|
15
|
+
|
16
|
+
expect(shipment).to have_attributes(object: 'Shipment')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '.from_return_authorization', vcr: { cassette_name: 'shipment_builder/from_return_authorization' } do
|
21
|
+
it 'builds a shipment with the correct attributes' do
|
22
|
+
solidus_return_authorization = create(:return_item).return_authorization
|
23
|
+
shipment = described_class.from_return_authorization(SolidusEasypost::ReturnAuthorization.new(solidus_return_authorization))
|
24
|
+
|
25
|
+
expect(shipment).to have_attributes(object: 'Shipment')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|