solidus_backtracs 2.2.0
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.
- checksums.yaml +7 -0
- data/.bundle/config +2 -0
- data/.circleci/config.yml +41 -0
- data/.gem_release.yml +5 -0
- data/.github/stale.yml +17 -0
- data/.github_changelog_generator +2 -0
- data/.gitignore +20 -0
- data/.rspec +2 -0
- data/.rubocop.yml +14 -0
- data/.rubocop_todo.yml +40 -0
- data/CHANGELOG.md +2 -0
- data/Gemfile +33 -0
- data/LICENSE +26 -0
- data/README.md +208 -0
- data/Rakefile +6 -0
- data/app/assets/javascripts/spree/backend/solidus_backtracs.js +2 -0
- data/app/assets/javascripts/spree/frontend/solidus_backtracs.js +2 -0
- data/app/assets/stylesheets/spree/backend/solidus_backtracs.css +4 -0
- data/app/assets/stylesheets/spree/frontend/solidus_backtracs.css +4 -0
- data/app/controllers/spree/backtracs_controller.rb +46 -0
- data/app/decorators/models/solidus_backtracs/spree/shipment_decorator.rb +33 -0
- data/app/helpers/solidus_backtracs/export_helper.rb +52 -0
- data/app/jobs/solidus_backtracs/api/schedule_shipment_syncs_job.rb +28 -0
- data/app/jobs/solidus_backtracs/api/sync_shipment_job.rb +17 -0
- data/app/jobs/solidus_backtracs/api/sync_shipments_job.rb +41 -0
- data/app/queries/solidus_backtracs/shipment/between_query.rb +14 -0
- data/app/queries/solidus_backtracs/shipment/exportable_query.rb +24 -0
- data/app/queries/solidus_backtracs/shipment/pending_api_sync_query.rb +51 -0
- data/app/views/spree/backtracs/export.xml.builder +58 -0
- data/bin/console +17 -0
- data/bin/rails +7 -0
- data/bin/rails-engine +13 -0
- data/bin/rails-sandbox +16 -0
- data/bin/rake +7 -0
- data/bin/sandbox +86 -0
- data/bin/setup +8 -0
- data/config/locales/en.yml +5 -0
- data/config/routes.rb +6 -0
- data/db/migrate/20210220093010_add_backtracs_api_sync_fields.rb +8 -0
- data/lib/generators/solidus_backtracs/install/install_generator.rb +27 -0
- data/lib/generators/solidus_backtracs/install/templates/initializer.rb +91 -0
- data/lib/solidus_backtracs/api/batch_syncer.rb +45 -0
- data/lib/solidus_backtracs/api/client.rb +36 -0
- data/lib/solidus_backtracs/api/rate_limited_error.rb +23 -0
- data/lib/solidus_backtracs/api/request_error.rb +33 -0
- data/lib/solidus_backtracs/api/request_runner.rb +87 -0
- data/lib/solidus_backtracs/api/shipment_serializer.rb +103 -0
- data/lib/solidus_backtracs/api/threshold_verifier.rb +28 -0
- data/lib/solidus_backtracs/configuration.rb +62 -0
- data/lib/solidus_backtracs/engine.rb +19 -0
- data/lib/solidus_backtracs/errors.rb +23 -0
- data/lib/solidus_backtracs/shipment_notice.rb +58 -0
- data/lib/solidus_backtracs/testing_support/factories.rb +4 -0
- data/lib/solidus_backtracs/version.rb +5 -0
- data/lib/solidus_backtracs.rb +16 -0
- data/solidus_shipstation.gemspec +39 -0
- data/spec/controllers/spree/backtracs_controller_spec.rb +103 -0
- data/spec/fixtures/backtracs_xml_schema.xsd +171 -0
- data/spec/jobs/solidus_backtracs/api/schedule_shipment_syncs_job_spec.rb +32 -0
- data/spec/jobs/solidus_backtracs/api/sync_shipments_job_spec.rb +102 -0
- data/spec/lib/solidus_backtracs/api/batch_syncer_spec.rb +228 -0
- data/spec/lib/solidus_backtracs/api/client_spec.rb +120 -0
- data/spec/lib/solidus_backtracs/api/rate_limited_error_spec.rb +21 -0
- data/spec/lib/solidus_backtracs/api/request_error_spec.rb +20 -0
- data/spec/lib/solidus_backtracs/api/request_runner_spec.rb +65 -0
- data/spec/lib/solidus_backtracs/api/shipment_serializer_spec.rb +25 -0
- data/spec/lib/solidus_backtracs/api/threshold_verifier_spec.rb +61 -0
- data/spec/lib/solidus_backtracs/shipment_notice_spec.rb +111 -0
- data/spec/lib/solidus_backtracs_spec.rb +9 -0
- data/spec/models/spree/shipment_spec.rb +49 -0
- data/spec/queries/solidus_backtracs/shipment/between_query_spec.rb +53 -0
- data/spec/queries/solidus_backtracs/shipment/exportable_query_spec.rb +53 -0
- data/spec/queries/solidus_backtracs/shipment/pending_api_sync_query_spec.rb +37 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/support/configuration_helper.rb +13 -0
- data/spec/support/controllers.rb +1 -0
- data/spec/support/webmock.rb +3 -0
- data/spec/support/xsd.rb +5 -0
- metadata +248 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
RSpec.describe SolidusBacktracs::Api::RequestError do
|
2
|
+
describe '.from_response' do
|
3
|
+
it 'extracts the status code, body and headers from the response' do
|
4
|
+
response = instance_double(
|
5
|
+
'HTTParty::Response',
|
6
|
+
code: 500,
|
7
|
+
headers: { 'Key' => 'Value' },
|
8
|
+
body: '{ "message": "Internal Server Error" }',
|
9
|
+
)
|
10
|
+
|
11
|
+
error = described_class.from_response(response)
|
12
|
+
|
13
|
+
expect(error).to have_attributes(
|
14
|
+
response_code: 500,
|
15
|
+
response_headers: { 'Key' => 'Value' },
|
16
|
+
response_body: '{ "message": "Internal Server Error" }',
|
17
|
+
)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
RSpec.describe SolidusBacktracs::Api::RequestRunner do
|
2
|
+
#TODO
|
3
|
+
describe '.from_config' do
|
4
|
+
it 'builds a runner using credentials from the configuration' do
|
5
|
+
stub_configuration(api_key: 'user', api_secret: 'pass')
|
6
|
+
|
7
|
+
request_runner = described_class.from_config
|
8
|
+
|
9
|
+
expect(request_runner).to have_attributes(
|
10
|
+
username: 'user',
|
11
|
+
password: 'pass',
|
12
|
+
)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#call' do
|
17
|
+
context 'when the response code is 2xx' do
|
18
|
+
it 'returns the parsed response' do
|
19
|
+
stub_request(:post, %r{bactracstest.andlor.com}).with(
|
20
|
+
basic_auth: %w[user pass],
|
21
|
+
headers: { 'Content-Type' => 'application/json', 'Accept' => 'application/json' },
|
22
|
+
body: '{"request_key":"request_value"}',
|
23
|
+
).to_return(
|
24
|
+
headers: { 'Content-Type' => 'application/json' },
|
25
|
+
body: '{"response_key":"response_value"}',
|
26
|
+
)
|
27
|
+
request_runner = described_class.new(username: 'user', password: 'pass')
|
28
|
+
|
29
|
+
response = request_runner.call(:post, '/test', request_key: 'request_value')
|
30
|
+
|
31
|
+
expect(response).to eq('response_key' => 'response_value')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'when the response code is 429' do
|
36
|
+
it 'raises a RateLimitedError' do
|
37
|
+
stub_request(:post, %r{bactracstest.andlor.com}).to_return(
|
38
|
+
status: 429,
|
39
|
+
headers: { 'Content-Type' => 'application/json', 'X-Rate-Limit-Reset' => 20 },
|
40
|
+
body: '{"message":"Too Many Requests"}',
|
41
|
+
)
|
42
|
+
request_runner = described_class.new(username: 'user', password: 'pass')
|
43
|
+
|
44
|
+
expect {
|
45
|
+
request_runner.call(:post, '/test')
|
46
|
+
}.to raise_error(SolidusBacktracs::Api::RateLimitedError)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'when the response code is not 200 or 429' do
|
51
|
+
it 'raises a RequestError' do
|
52
|
+
stub_request(:post, %r{bactracstest.andlor.com}).to_return(
|
53
|
+
status: 500,
|
54
|
+
headers: { 'Content-Type' => 'application/json' },
|
55
|
+
body: '{"message":"Internal Server Error"}',
|
56
|
+
)
|
57
|
+
request_runner = described_class.new(username: 'user', password: 'pass')
|
58
|
+
|
59
|
+
expect {
|
60
|
+
request_runner.call(:post, '/test')
|
61
|
+
}.to raise_error(SolidusBacktracs::Api::RequestError)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
RSpec.describe SolidusBacktracs::Api::ShipmentSerializer do
|
2
|
+
describe '#call' do
|
3
|
+
it 'serializes the shipment' do
|
4
|
+
shipment = create(:order_ready_to_ship).shipments.first
|
5
|
+
|
6
|
+
serializer = described_class.new(store_id: '12345678')
|
7
|
+
result = serializer.call(shipment)
|
8
|
+
|
9
|
+
expect(result).to be_instance_of(Hash)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'sets residential = false in address if company is given' do
|
13
|
+
order = create(:order_ready_to_ship,
|
14
|
+
bill_address: build(:address, company: 'ACME Co.'),
|
15
|
+
ship_address: build(:address, company: nil))
|
16
|
+
shipment = order.shipments.first
|
17
|
+
|
18
|
+
serializer = described_class.new(store_id: '12345678')
|
19
|
+
result = serializer.call(shipment)
|
20
|
+
|
21
|
+
expect(result[:billTo][:residential]).to be false
|
22
|
+
expect(result[:shipTo][:residential]).to be true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
RSpec.describe SolidusBacktracs::Api::ThresholdVerifier do
|
2
|
+
context "when the shipment's order was completed" do
|
3
|
+
context 'when the shipment was never synced with Backtracs yet' do
|
4
|
+
it 'returns true when the shipment was never synced with backtracs yet' do
|
5
|
+
stub_configuration(api_sync_threshold: 10.minutes)
|
6
|
+
shipment = create(:order_ready_to_ship).shipments.first
|
7
|
+
|
8
|
+
expect(described_class.call(shipment)).to eq(true)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "returns false when the shipment's order was created too far in the past" do
|
12
|
+
stub_configuration(api_sync_threshold: 10.minutes)
|
13
|
+
shipment = create(:order_ready_to_ship).shipments.first.tap do |s|
|
14
|
+
s.order.update_columns(updated_at: 11.minutes.ago)
|
15
|
+
end
|
16
|
+
|
17
|
+
expect(described_class.call(shipment)).to eq(false)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when the shipment was already synced with Backtracs' do
|
22
|
+
it 'returns true when the shipment is pending a Backtracs re-sync' do
|
23
|
+
stub_configuration(api_sync_threshold: 10.minutes)
|
24
|
+
shipment = create(:order_ready_to_ship).shipments.first.tap do |s|
|
25
|
+
s.order.update_columns(updated_at: 4.minutes.ago)
|
26
|
+
s.update_columns(backtracs_synced_at: 5.minutes.ago)
|
27
|
+
end
|
28
|
+
|
29
|
+
expect(described_class.call(shipment)).to eq(true)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'returns false when the shipment is up-to-date in Backtracs' do
|
33
|
+
stub_configuration(api_sync_threshold: 10.minutes)
|
34
|
+
shipment = create(:order_ready_to_ship).shipments.first.tap do |s|
|
35
|
+
s.order.update_columns(updated_at: 6.minutes.ago)
|
36
|
+
s.update_columns(backtracs_synced_at: 5.minutes.ago)
|
37
|
+
end
|
38
|
+
|
39
|
+
expect(described_class.call(shipment)).to eq(false)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'returns false when the order was updated too far in the past' do
|
43
|
+
stub_configuration(api_sync_threshold: 10.minutes)
|
44
|
+
shipment = create(:order_ready_to_ship).shipments.first.tap do |s|
|
45
|
+
s.order.update_columns(updated_at: 11.minutes.ago)
|
46
|
+
s.update_columns(backtracs_synced_at: 12.minutes.ago)
|
47
|
+
end
|
48
|
+
|
49
|
+
expect(described_class.call(shipment)).to eq(false)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when the shipment's order was not completed" do
|
55
|
+
it 'returns false' do
|
56
|
+
shipment = create(:shipment)
|
57
|
+
|
58
|
+
expect(described_class.call(shipment)).to eq(false)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe SolidusBacktracs::ShipmentNotice do
|
4
|
+
shared_examples 'ships or updates the shipment' do
|
5
|
+
context 'when the order was not shipped yet' do
|
6
|
+
# rubocop:disable RSpec/MultipleExpectations
|
7
|
+
it 'ships the order successfully' do
|
8
|
+
shipment_notice = build_shipment_notice(order.shipments.first, shipment_tracking: '1Z1231234')
|
9
|
+
shipment_notice.apply
|
10
|
+
|
11
|
+
order.reload
|
12
|
+
expect(order.shipments.first).to be_shipped
|
13
|
+
expect(order.shipments.first.shipped_at).not_to be_nil
|
14
|
+
expect(order.shipments.first.tracking).to eq('1Z1231234')
|
15
|
+
expect(order.cartons.first.tracking).to eq('1Z1231234')
|
16
|
+
end
|
17
|
+
# rubocop:enable RSpec/MultipleExpectations
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'when the order was already shipped' do
|
21
|
+
it 'updates the tracking number on the shipment' do
|
22
|
+
order.shipments.first.ship!
|
23
|
+
|
24
|
+
shipment_notice = build_shipment_notice(order.shipments.first, shipment_tracking: '1Z1231234')
|
25
|
+
shipment_notice.apply
|
26
|
+
|
27
|
+
expect(order.reload.shipments.first.tracking).to eq('1Z1231234')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'when capture_at_notification is true' do
|
33
|
+
before { stub_configuration(capture_at_notification: true) }
|
34
|
+
|
35
|
+
context 'when the order is paid' do
|
36
|
+
let(:order) { create_order_ready_to_ship(paid: true) }
|
37
|
+
|
38
|
+
include_examples 'ships or updates the shipment'
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'when the order is not paid' do
|
42
|
+
let(:order) { create_order_ready_to_ship(paid: false) }
|
43
|
+
|
44
|
+
context 'when the payment can be captured successfully' do
|
45
|
+
include_examples 'ships or updates the shipment'
|
46
|
+
|
47
|
+
it 'pays the order successfully' do
|
48
|
+
shipment_notice = build_shipment_notice(order.shipments.first, shipment_tracking: '1Z1231234')
|
49
|
+
shipment_notice.apply
|
50
|
+
|
51
|
+
order.reload
|
52
|
+
expect(order.payments).to all(be_completed)
|
53
|
+
expect(order.reload).to be_paid
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'when the payment cannot be captured' do
|
58
|
+
it 'raises a PaymentError' do
|
59
|
+
allow_any_instance_of(Spree::Payment).to receive(:capture!).and_raise(Spree::Core::GatewayError)
|
60
|
+
|
61
|
+
shipment_notice = build_shipment_notice(order.shipments.first)
|
62
|
+
|
63
|
+
expect { shipment_notice.apply }.to raise_error(SolidusBacktracs::PaymentError) do |e|
|
64
|
+
expect(e.cause).to be_instance_of(Spree::Core::GatewayError)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'when capture_at_notification is false' do
|
72
|
+
before { stub_configuration(capture_at_notification: false) }
|
73
|
+
|
74
|
+
context 'when the order is paid' do
|
75
|
+
let(:order) { create_order_ready_to_ship(paid: true) }
|
76
|
+
|
77
|
+
include_examples 'ships or updates the shipment'
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'when the order is not paid' do
|
81
|
+
it 'raises an OrderNotPaidError' do
|
82
|
+
stub_configuration(capture_at_notification: false)
|
83
|
+
order = create_order_ready_to_ship(paid: false)
|
84
|
+
|
85
|
+
shipment_notice = build_shipment_notice(order.shipments.first)
|
86
|
+
|
87
|
+
expect { shipment_notice.apply }.to raise_error(SolidusBacktracs::OrderNotPaidError)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def create_order_ready_to_ship(paid: true)
|
95
|
+
order = create(:order_ready_to_ship)
|
96
|
+
|
97
|
+
unless paid
|
98
|
+
order.payments.update_all(state: 'pending')
|
99
|
+
order.recalculate
|
100
|
+
end
|
101
|
+
|
102
|
+
order
|
103
|
+
end
|
104
|
+
|
105
|
+
def build_shipment_notice(shipment, shipment_tracking: '1Z1231234')
|
106
|
+
SolidusBacktracs::ShipmentNotice.new(
|
107
|
+
shipment_number: shipment.number,
|
108
|
+
shipment_tracking: shipment_tracking,
|
109
|
+
)
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Spree::Shipment do
|
4
|
+
describe '.between' do
|
5
|
+
it 'delegates to BetweenQuery' do
|
6
|
+
shipment = build_stubbed(:shipment)
|
7
|
+
allow(SolidusBacktracs::Shipment::BetweenQuery).to receive(:apply).with(
|
8
|
+
any_args,
|
9
|
+
from: Time.zone.yesterday,
|
10
|
+
to: Time.zone.today,
|
11
|
+
).and_return([shipment])
|
12
|
+
|
13
|
+
result = Spree::Deprecation.silence do
|
14
|
+
described_class.between(Time.zone.yesterday, Time.zone.today)
|
15
|
+
end
|
16
|
+
|
17
|
+
expect(result).to eq([shipment])
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'prints a deprecation warning' do
|
21
|
+
allow(Spree::Deprecation).to receive(:warn)
|
22
|
+
|
23
|
+
described_class.between(Time.zone.yesterday, Time.zone.today)
|
24
|
+
|
25
|
+
expect(Spree::Deprecation).to have_received(:warn).with(/Spree::Shipment\.between/)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '.exportable' do
|
30
|
+
it 'delegates to ExportableQuery' do
|
31
|
+
shipment = build_stubbed(:shipment)
|
32
|
+
allow(SolidusBacktracs::Shipment::ExportableQuery).to receive(:apply).and_return([shipment])
|
33
|
+
|
34
|
+
result = Spree::Deprecation.silence do
|
35
|
+
described_class.exportable
|
36
|
+
end
|
37
|
+
|
38
|
+
expect(result).to eq([shipment])
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'prints a deprecation warning' do
|
42
|
+
allow(Spree::Deprecation).to receive(:warn)
|
43
|
+
|
44
|
+
described_class.exportable
|
45
|
+
|
46
|
+
expect(Spree::Deprecation).to have_received(:warn).with(/Spree::Shipment\.exportable/)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
RSpec.describe SolidusBacktracs::Shipment::BetweenQuery do
|
2
|
+
describe '.apply' do
|
3
|
+
it 'returns shipments whose updated_at falls within the given time range' do
|
4
|
+
shipment = create(:shipment) { |s| s.update_column(:updated_at, Time.zone.now) }
|
5
|
+
|
6
|
+
result = described_class.apply(
|
7
|
+
Spree::Shipment.all,
|
8
|
+
from: Time.zone.yesterday,
|
9
|
+
to: Time.zone.tomorrow,
|
10
|
+
)
|
11
|
+
|
12
|
+
expect(result).to eq([shipment])
|
13
|
+
end
|
14
|
+
|
15
|
+
it "returns shipments whose order's updated_at falls within the given time range" do
|
16
|
+
order = create(:order) { |o| o.update_column(:updated_at, Time.zone.now) }
|
17
|
+
shipment = create(:shipment, order: order)
|
18
|
+
|
19
|
+
result = described_class.apply(
|
20
|
+
Spree::Shipment.all,
|
21
|
+
from: Time.zone.yesterday,
|
22
|
+
to: Time.zone.tomorrow,
|
23
|
+
)
|
24
|
+
|
25
|
+
expect(result).to eq([shipment])
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'does not return shipments whose updated_at does not fall within the given time range' do
|
29
|
+
create(:shipment) { |s| s.update_column(:updated_at, Time.zone.now) }
|
30
|
+
|
31
|
+
result = described_class.apply(
|
32
|
+
Spree::Shipment.all,
|
33
|
+
from: Time.zone.tomorrow,
|
34
|
+
to: Time.zone.tomorrow + 1.day,
|
35
|
+
)
|
36
|
+
|
37
|
+
expect(result).to eq([])
|
38
|
+
end
|
39
|
+
|
40
|
+
it "does not return shipments whose order's updated_at falls within the given time range" do
|
41
|
+
order = create(:order) { |o| o.update_column(:updated_at, Time.zone.now) }
|
42
|
+
create(:shipment, order: order)
|
43
|
+
|
44
|
+
result = described_class.apply(
|
45
|
+
Spree::Shipment.all,
|
46
|
+
from: Time.zone.tomorrow,
|
47
|
+
to: Time.zone.tomorrow + 1.day,
|
48
|
+
)
|
49
|
+
|
50
|
+
expect(result).to eq([])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
RSpec.describe SolidusBacktracs::Shipment::ExportableQuery do
|
2
|
+
describe '.apply' do
|
3
|
+
context 'when capture_at_notification is false and export_canceled_shipments is false' do
|
4
|
+
it 'returns ready shipments from complete orders' do
|
5
|
+
stub_configuration(capture_at_notification: false, export_canceled_shipments: false)
|
6
|
+
|
7
|
+
ready_shipment = create(:order_ready_to_ship).shipments.first
|
8
|
+
create(:order_ready_to_ship) { |o| o.shipments.first.cancel! }
|
9
|
+
create(:shipped_order)
|
10
|
+
|
11
|
+
expect(described_class.apply(Spree::Shipment.all)).to eq([ready_shipment])
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'when capture_at_notification is true and export_canceled_shipments is false' do
|
16
|
+
it 'returns non-canceled shipments from complete orders' do
|
17
|
+
stub_configuration(capture_at_notification: true, export_canceled_shipments: false)
|
18
|
+
|
19
|
+
ready_shipment = create(:order_ready_to_ship).shipments.first
|
20
|
+
shipped_shipment = create(:shipped_order).shipments.first
|
21
|
+
create(:order_ready_to_ship) { |o| o.shipments.first.cancel! }
|
22
|
+
|
23
|
+
expect(described_class.apply(Spree::Shipment.all)).to eq([ready_shipment, shipped_shipment])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when capture_at_notification is false and export_canceled_shipments is true' do
|
28
|
+
it 'returns ready and canceled shipments from complete orders' do
|
29
|
+
stub_configuration(capture_at_notification: false, export_canceled_shipments: true)
|
30
|
+
|
31
|
+
ready_shipment = create(:order_ready_to_ship).shipments.first
|
32
|
+
canceled_shipment = create(:order_ready_to_ship).shipments.first
|
33
|
+
canceled_shipment.cancel!
|
34
|
+
create(:shipped_order)
|
35
|
+
|
36
|
+
expect(described_class.apply(Spree::Shipment.all)).to eq([ready_shipment, canceled_shipment])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'when capture_at_notification is true and export_canceled_shipments is true' do
|
41
|
+
it 'returns all shipments from complete orders' do
|
42
|
+
stub_configuration(capture_at_notification: true, export_canceled_shipments: true)
|
43
|
+
|
44
|
+
ready_shipment = create(:order_ready_to_ship).shipments.first
|
45
|
+
canceled_shipment = create(:order_ready_to_ship).shipments.first
|
46
|
+
canceled_shipment.cancel!
|
47
|
+
shipped_shipment = create(:shipped_order).shipments.first
|
48
|
+
|
49
|
+
expect(described_class.apply(Spree::Shipment.all)).to eq([ready_shipment, canceled_shipment, shipped_shipment])
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
RSpec.describe SolidusBacktracs::Shipment::PendingApiSyncQuery do
|
2
|
+
describe '.apply' do
|
3
|
+
context 'when dealing with shipments that were never synced' do
|
4
|
+
it 'returns the shipments that are within the threshold' do
|
5
|
+
stub_configuration(api_sync_threshold: 10.minutes)
|
6
|
+
shipment = create(:order_ready_to_ship).shipments.first.tap do |s|
|
7
|
+
s.order.update_columns(updated_at: 9.minutes.ago)
|
8
|
+
end
|
9
|
+
create(:order_ready_to_ship).shipments.first.tap do |s|
|
10
|
+
s.order.update_columns(updated_at: 11.minutes.ago)
|
11
|
+
end
|
12
|
+
|
13
|
+
expect(described_class.apply(Spree::Shipment.all)).to match_array([shipment])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'when dealing with shipments that were already synced' do
|
18
|
+
it 'returns the shipments that are within the threshold and pending a re-sync' do
|
19
|
+
stub_configuration(api_sync_threshold: 10.minutes)
|
20
|
+
shipment = create(:order_ready_to_ship).shipments.first.tap do |s|
|
21
|
+
s.order.update_columns(updated_at: 7.minutes.ago)
|
22
|
+
s.update_columns(shipstation_synced_at: 8.minutes.ago)
|
23
|
+
end
|
24
|
+
create(:order_ready_to_ship).shipments.first.tap do |s|
|
25
|
+
s.order.update_columns(updated_at: 9.minutes.ago)
|
26
|
+
s.update_columns(shipstation_synced_at: 8.minutes.ago)
|
27
|
+
end
|
28
|
+
create(:order_ready_to_ship).shipments.first.tap do |s|
|
29
|
+
s.order.update_columns(updated_at: 11.minutes.ago)
|
30
|
+
s.update_columns(shipstation_synced_at: 10.minutes.ago)
|
31
|
+
end
|
32
|
+
|
33
|
+
expect(described_class.apply(Spree::Shipment.all)).to match_array([shipment])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Configure Rails Environment
|
4
|
+
ENV['RAILS_ENV'] = 'test'
|
5
|
+
|
6
|
+
# Run Coverage report
|
7
|
+
require 'solidus_dev_support/rspec/coverage'
|
8
|
+
|
9
|
+
# Create the dummy app if it's still missing.
|
10
|
+
dummy_env = "#{__dir__}/dummy/config/environment.rb"
|
11
|
+
system 'bin/rake extension:test_app' unless File.exist? dummy_env
|
12
|
+
require dummy_env
|
13
|
+
|
14
|
+
# Requires factories and other useful helpers defined in spree_core.
|
15
|
+
require 'solidus_dev_support/rspec/feature_helper'
|
16
|
+
|
17
|
+
# Requires supporting ruby files with custom matchers and macros, etc,
|
18
|
+
# in spec/support/ and its subdirectories.
|
19
|
+
Dir["#{__dir__}/support/**/*.rb"].sort.each { |f| require f }
|
20
|
+
|
21
|
+
# Requires factories defined in lib/solidus_backtracs/testing_support/factories.rb
|
22
|
+
SolidusDevSupport::TestingSupport::Factories.load_for(SolidusBacktracs::Engine)
|
23
|
+
|
24
|
+
RSpec.configure do |config|
|
25
|
+
config.infer_spec_type_from_file_location!
|
26
|
+
config.use_transactional_fixtures = false
|
27
|
+
|
28
|
+
if Spree.solidus_gem_version < Gem::Version.new('2.11')
|
29
|
+
config.extend Spree::TestingSupport::AuthorizationHelpers::Request, type: :system
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module ConfigurationHelper
|
2
|
+
def stub_configuration(options)
|
3
|
+
allow(SolidusBacktracs.configuration).to receive_messages(options)
|
4
|
+
|
5
|
+
if options[:capture_at_notification]
|
6
|
+
stub_spree_preferences(require_payment_to_ship: false)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.include ConfigurationHelper
|
13
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'rails-controller-testing'
|