super_good-solidus_taxjar 0.18.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +48 -6
  3. data/CHANGELOG.md +103 -1
  4. data/Gemfile +26 -10
  5. data/PULL_REQUEST_TEMPLATE.md +0 -1
  6. data/README.md +299 -39
  7. data/Rakefile +3 -0
  8. data/app/controllers/spree/admin/taxjar_settings_controller.rb +86 -1
  9. data/app/controllers/spree/admin/taxjar_transactions_controller.rb +37 -0
  10. data/app/controllers/spree/admin/transaction_sync_batches_controller.rb +18 -0
  11. data/app/jobs/super_good/solidus_taxjar/backfill_transaction_sync_batch_job.rb +23 -0
  12. data/app/jobs/super_good/solidus_taxjar/replace_transaction_job.rb +26 -0
  13. data/app/jobs/super_good/solidus_taxjar/report_transaction_job.rb +22 -0
  14. data/app/models/super_good/solidus_taxjar/configuration.rb +27 -0
  15. data/app/models/super_good/solidus_taxjar/order_transaction.rb +16 -0
  16. data/app/models/super_good/solidus_taxjar/refund_transaction.rb +13 -0
  17. data/app/models/super_good/solidus_taxjar/transaction_sync_batch.rb +11 -0
  18. data/app/models/super_good/solidus_taxjar/transaction_sync_log.rb +8 -0
  19. data/app/overrides/spree/admin/orders_controller_override.rb +12 -0
  20. data/app/overrides/spree/admin/shared/_order_submenu/add_taxjar_sync_history_tab.html.erb.deface +6 -0
  21. data/app/overrides/spree/admin/shared/_order_summary/add_taxjar_reported_at.html.erb.deface +30 -0
  22. data/app/overrides/spree/admin/shared/_taxes_tabs/add_configuration_menu_items.html.erb.deface +5 -0
  23. data/app/overrides/super_good/solidus_taxjar/spree/order_override.rb +21 -0
  24. data/app/views/spree/admin/orders/taxjar_transactions.html.erb +4 -0
  25. data/app/views/spree/admin/shared/_transaction_sync_log_table.html.erb +35 -0
  26. data/app/views/spree/admin/taxjar_settings/_nexus_regions.html.erb +23 -0
  27. data/app/views/spree/admin/taxjar_settings/_tax_categories.html.erb +41 -0
  28. data/app/views/spree/admin/taxjar_settings/edit.html.erb +17 -0
  29. data/app/views/spree/admin/taxjar_settings/edit_no_api_key.html.erb +21 -0
  30. data/app/views/spree/admin/transaction_sync_batches/index.html.erb +50 -0
  31. data/app/views/spree/admin/transaction_sync_batches/show.html.erb +7 -0
  32. data/bin/console +2 -0
  33. data/bin/rails-engine +1 -1
  34. data/bin/sandbox +43 -36
  35. data/bin/setup +3 -3
  36. data/config/routes.rb +13 -1
  37. data/db/migrate/20210908205201_create_taxjar_order_transactions.rb +16 -0
  38. data/db/migrate/20211008175113_create_taxjar_refund_transaction.rb +15 -0
  39. data/db/migrate/20211008183858_add_transaction_date_to_order_transaction.rb +5 -0
  40. data/db/migrate/20211119143354_create_configuration.rb +8 -0
  41. data/db/migrate/20220405213958_create_transaction_sync_batches.rb +7 -0
  42. data/db/migrate/20220405215225_create_transaction_sync_logs.rb +14 -0
  43. data/db/migrate/20220908181655_add_dates_to_transaction_sync_batch.rb +6 -0
  44. data/db/migrate/20220912182210_allow_null_transaction_sync_batches_on_logs.rb +5 -0
  45. data/db/migrate/20230320211309_add_refund_transaction_to_sync_logs.rb +5 -0
  46. data/lib/generators/super_good/solidus_taxjar/install/install_generator.rb +68 -0
  47. data/lib/super_good/solidus_taxjar/api.rb +41 -9
  48. data/lib/super_good/solidus_taxjar/api_params.rb +92 -25
  49. data/lib/super_good/solidus_taxjar/backfill_transactions.rb +11 -0
  50. data/lib/super_good/solidus_taxjar/cached_api.rb +23 -0
  51. data/lib/super_good/solidus_taxjar/calculator_helper.rb +33 -4
  52. data/lib/super_good/solidus_taxjar/discount_calculator.rb +1 -1
  53. data/lib/super_good/solidus_taxjar/overrides/request_override.rb +15 -0
  54. data/lib/super_good/solidus_taxjar/reportable.rb +91 -0
  55. data/lib/super_good/solidus_taxjar/reporting.rb +44 -0
  56. data/lib/super_good/solidus_taxjar/spree/legacy_reporting_subscriber.rb +41 -0
  57. data/lib/super_good/solidus_taxjar/spree/reporting_subscriber.rb +40 -0
  58. data/lib/super_good/solidus_taxjar/tax_calculator.rb +7 -1
  59. data/lib/super_good/solidus_taxjar/testing_support/factories/address_factory.rb +11 -0
  60. data/lib/super_good/solidus_taxjar/testing_support/factories/configuration_factory.rb +11 -0
  61. data/lib/super_good/solidus_taxjar/testing_support/factories/order_transaction_factory.rb +22 -0
  62. data/lib/super_good/solidus_taxjar/testing_support/factories/refund_transaction_factory.rb +7 -0
  63. data/lib/super_good/solidus_taxjar/testing_support/factories/transaction_sync_batch_factory.rb +9 -0
  64. data/lib/super_good/solidus_taxjar/testing_support/factories/transaction_sync_log_factory.rb +18 -0
  65. data/lib/super_good/solidus_taxjar/transaction_id_generator.rb +45 -0
  66. data/lib/super_good/solidus_taxjar/version.rb +1 -1
  67. data/lib/super_good/solidus_taxjar.rb +29 -2
  68. data/spec/features/spree/admin/backfill_transactions_spec.rb +138 -0
  69. data/spec/features/spree/admin/refund_spec.rb +167 -0
  70. data/spec/features/spree/admin/reporting_to_taxjar_spec.rb +156 -0
  71. data/spec/features/spree/admin/taxjar_settings_spec.rb +58 -16
  72. data/spec/features/spree/checkout_spec.rb +58 -0
  73. data/spec/fixtures/cassettes/Admin_TaxJar_Settings/GET_sync_nexus_regions/Taxjar_API_token_is_not_set/doesn_t_make_a_request_for_the_nexus_regions.yml +57 -0
  74. data/spec/fixtures/cassettes/Admin_TaxJar_Settings/GET_sync_tax_categories/Taxjar_API_token_is_not_set/doesn_t_make_a_request_for_the_tax_categories.yml +57 -0
  75. data/spec/fixtures/cassettes/Admin_TaxJar_Settings/Taxjar_settings_tab/Taxjar_API_token_is_set/shows_the_settings_page.yml +2437 -0
  76. data/spec/fixtures/cassettes/Admin_TaxJar_Settings/Taxjar_settings_tab/Taxjar_API_token_isn_t_set/doesn_t_show_any_other_TaxJar_features.yml +57 -0
  77. data/spec/fixtures/cassettes/Admin_TaxJar_Settings/Taxjar_settings_tab/Taxjar_API_token_isn_t_set/shows_a_descriptive_error_message.yml +57 -0
  78. data/spec/fixtures/cassettes/Admin_TaxJar_Settings/Taxjar_settings_tab/Taxjar_reporting_is_enabled/shows_that_reporting_is_enabled.yml +2382 -0
  79. data/spec/fixtures/cassettes/Admin_TaxJar_Settings/Taxjar_settings_tab/order_is_shipped/the_user_backfills_their_transactions.yml +2511 -0
  80. data/spec/fixtures/cassettes/Admin_TaxJar_Settings/Taxjar_settings_tab/the_user_navigates_to_the_TaxJar_Settings.yml +2382 -0
  81. data/spec/fixtures/cassettes/Admin_Transaction_Sync_Batches/user_has_a_shipped_order/starts_a_transaction_backfill.yml +370 -0
  82. data/spec/fixtures/cassettes/Reporting_orders_to_TaxJar/shipping_a_complete_and_paid_order.yml +310 -0
  83. data/spec/fixtures/cassettes/Reporting_orders_to_TaxJar/updating_an_order_which_was_not_reported_due_to_failure/it_reports_the_order_instead_of_trying_to_replace_it.yml +794 -0
  84. data/spec/fixtures/cassettes/Reporting_orders_to_TaxJar/with_an_order_with_invalid_zipcode/retry_of_a_previously_failed_transaction_sync.yml +418 -0
  85. data/spec/fixtures/cassettes/Spree_Admin_TransactionSyncBatchesController/_create/creates_a_batch.yml +250 -0
  86. data/spec/fixtures/cassettes/Spree_Admin_TransactionSyncBatchesController/_create/creates_a_log_in_the_batch_with_an_order.yml +250 -0
  87. data/spec/fixtures/cassettes/Spree_Admin_TransactionSyncBatchesController/_create/user_supplies_a_start_date/creates_a_batch.yml +250 -0
  88. data/spec/fixtures/cassettes/Spree_Admin_TransactionSyncBatchesController/_create/user_supplies_a_start_date/user_supplies_start_and_end_date/creates_a_batch.yml +250 -0
  89. data/spec/fixtures/cassettes/SuperGood_SolidusTaxjar_CalculatorHelper/_taxable_address_/when_taxable_address_check_returns_true/with_US_address/when_the_address_is_not_within_a_nexus_region/1_3_2_2_2_1.yml +58 -0
  90. data/spec/fixtures/cassettes/SuperGood_SolidusTaxjar_CalculatorHelper/_taxable_address_/when_taxable_address_check_returns_true/with_US_address/when_the_address_is_within_a_nexus_region/1_3_2_2_1_1.yml +58 -0
  91. data/spec/fixtures/cassettes/SuperGood_SolidusTaxjar_Reporting/_refund_and_create_transaction/when_Taxjar_cannot_create_a_refund_transaction/doesn_t_create_a_new_transaction.yml +393 -0
  92. data/spec/fixtures/cassettes/SuperGood_SolidusTaxjar_Reporting/_refund_and_create_transaction/when_Taxjar_cannot_create_a_refund_transaction/raises_an_error.yml +393 -0
  93. data/spec/fixtures/cassettes/Taxjar_API_Request/logging_is_disabled/doesn_t_call_the_logger.yml +158 -0
  94. data/spec/fixtures/cassettes/Taxjar_API_Request/logging_is_enabled/calls_the_logger.yml +158 -0
  95. data/spec/fixtures/cassettes/features/spree/admin/checkout.yml +238 -0
  96. data/spec/fixtures/cassettes/features/spree/admin/refund.yml +1162 -0
  97. data/spec/jobs/super_good/solidus_taxjar/backfill_transaction_sync_batch_job_spec.rb +117 -0
  98. data/spec/jobs/super_good/solidus_taxjar/replace_transaction_job_spec.rb +95 -0
  99. data/spec/jobs/super_good/solidus_taxjar/report_transaction_job_spec.rb +76 -0
  100. data/spec/models/super_good/solidus_taxjar/configuration_spec.rb +79 -0
  101. data/spec/models/super_good/solidus_taxjar/order_transaction_spec.rb +36 -0
  102. data/spec/models/super_good/solidus_taxjar/transaction_sync_batch_spec.rb +48 -0
  103. data/spec/requests/spree/admin/order_request_spec.rb +121 -0
  104. data/spec/requests/spree/admin/taxjar_settings_request_spec.rb +198 -0
  105. data/spec/requests/spree/admin/taxjar_transactions_request_spec.rb +62 -0
  106. data/spec/requests/spree/admin/transaction_sync_batches_request_spec.rb +82 -0
  107. data/spec/spec_helper.rb +46 -3
  108. data/spec/subscribers/super_good/solidus_taxjar/spree/reporting_subscriber_spec.rb +278 -0
  109. data/spec/super_good/solidus_taxjar/addresses_spec.rb +0 -14
  110. data/spec/super_good/solidus_taxjar/api_params_spec.rb +261 -89
  111. data/spec/super_good/solidus_taxjar/api_spec.rb +152 -29
  112. data/spec/super_good/solidus_taxjar/backfill_transactions_spec.rb +24 -0
  113. data/spec/super_good/solidus_taxjar/cached_api_spec.rb +58 -0
  114. data/spec/super_good/solidus_taxjar/calculator_helper_spec.rb +131 -0
  115. data/spec/super_good/solidus_taxjar/discount_calculator_spec.rb +19 -2
  116. data/spec/super_good/solidus_taxjar/reportable_spec.rb +194 -0
  117. data/spec/super_good/solidus_taxjar/reporting_spec.rb +243 -0
  118. data/spec/super_good/solidus_taxjar/tax_calculator_spec.rb +19 -19
  119. data/spec/super_good/solidus_taxjar/tax_rate_calculator_spec.rb +8 -3
  120. data/spec/super_good/solidus_taxjar/transaction_id_generator_spec.rb +77 -0
  121. data/spec/super_good/solidus_taxjar_spec.rb +84 -0
  122. data/spec/support/checkoutable_store_shared_context.rb +19 -0
  123. data/spec/support/solidus_events_helper.rb +26 -0
  124. data/spec/taxjar/api/request_spec.rb +52 -0
  125. data/super_good-solidus_taxjar.gemspec +3 -2
  126. metadata +169 -17
  127. data/app/decorators/super_good/solidus_taxjar/spree/order_updater/fire_recalculated_event.rb +0 -18
  128. data/app/overrides/spree/admin/shared/_configuration_menu.rb +0 -11
  129. data/app/views/spree/admin/taxjar_settings/show.html.erb +0 -13
  130. data/spec/models/spree/order_updater_spec.rb +0 -12
@@ -0,0 +1,198 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe 'Admin TaxJar Settings', :vcr, type: :request do
4
+ extend Spree::TestingSupport::AuthorizationHelpers::Request
5
+ stub_authorization!
6
+ let(:dummy_api) { instance_double(SuperGood::SolidusTaxjar::Api) }
7
+
8
+ around do |example|
9
+ original = ActionController::Base.allow_forgery_protection
10
+ ActionController::Base.allow_forgery_protection = false
11
+ example.run
12
+ ActionController::Base.allow_forgery_protection = original
13
+ end
14
+
15
+ describe "GET #sync_nexus_regions" do
16
+ subject { get spree.admin_taxjar_settings_sync_nexus_regions_path }
17
+
18
+ context "Taxjar API token is set" do
19
+ let(:api_token) { ENV.fetch("TAXJAR_API_KEY", "fake_token") }
20
+
21
+ before do
22
+ allow(ENV).to receive(:[]).and_call_original
23
+ allow(ENV).to receive(:[]).with("TAXJAR_API_KEY").and_return(api_token)
24
+ allow(SuperGood::SolidusTaxjar).to receive(:api).and_return(dummy_api)
25
+ allow(dummy_api).to receive(:nexus_regions).and_return([])
26
+ end
27
+
28
+ it "makes a request for the nexus regions" do
29
+ subject
30
+ expect(dummy_api).to have_received(:nexus_regions)
31
+ end
32
+
33
+ it "redirects back to TaxJar settings" do
34
+ subject
35
+ expect(response).to redirect_to "/admin/taxjar_settings"
36
+ end
37
+
38
+ context "Taxjar call is successful" do
39
+ it "flashes a success alert" do
40
+ subject
41
+
42
+ expect(flash[:success]).to eq("Updated with new Nexus Regions")
43
+ end
44
+ end
45
+
46
+ context "Taxjar responds with an error" do
47
+ before do
48
+ allow(dummy_api).to receive(:nexus_regions).and_raise(Taxjar::Error, "fake error message")
49
+ end
50
+
51
+ it "flashes an error alert" do
52
+ subject
53
+
54
+ expect(flash[:error]).to eq("Failed to complete request to TaxJar: fake error message")
55
+ end
56
+ end
57
+ end
58
+
59
+ context "Taxjar API token is not set" do
60
+ before do
61
+ allow(ENV).to receive(:[]).and_call_original
62
+ allow(ENV).to receive(:[]).with("TAXJAR_API_KEY").and_return(nil)
63
+ end
64
+
65
+ it "doesn't make a request for the nexus regions" do
66
+ subject
67
+ expect(flash[:error]).to eq "Failed to complete request to TaxJar: Not authorized for route 'GET /v2/nexus/regions'"
68
+ end
69
+ end
70
+ end
71
+
72
+ describe "GET #sync_tax_categories" do
73
+ subject { get spree.admin_taxjar_settings_sync_tax_categories_path }
74
+
75
+ context "Taxjar API token is set" do
76
+ let(:api_token) { ENV.fetch("TAXJAR_API_KEY", "fake_token") }
77
+
78
+ before do
79
+ allow(ENV).to receive(:[]).and_call_original
80
+ allow(ENV).to receive(:[]).with("TAXJAR_API_KEY").and_return(api_token)
81
+ allow(SuperGood::SolidusTaxjar).to receive(:api).and_return(dummy_api)
82
+ allow(dummy_api).to receive(:tax_categories).and_return([])
83
+ end
84
+
85
+ it "makes a request for the tax categories" do
86
+ subject
87
+ expect(dummy_api).to have_received(:tax_categories)
88
+ end
89
+
90
+ it "redirects back to TaxJar settings" do
91
+ subject
92
+ expect(response).to redirect_to "/admin/taxjar_settings"
93
+ end
94
+
95
+ context "Taxjar call is successful" do
96
+ it "flashes a success alert" do
97
+ subject
98
+
99
+ expect(flash[:success]).to eq("Updated with new tax categories")
100
+ end
101
+ end
102
+
103
+ context "Taxjar responds with an error" do
104
+ before do
105
+ allow(dummy_api).to receive(:tax_categories).and_raise(Taxjar::Error, "fake error message")
106
+ end
107
+
108
+ it "flashes an error alert" do
109
+ subject
110
+
111
+ expect(flash[:error]).to eq("Failed to complete request to TaxJar: fake error message")
112
+ end
113
+ end
114
+ end
115
+
116
+ context "Taxjar API token is not set" do
117
+ before do
118
+ allow(ENV).to receive(:[]).and_call_original
119
+ allow(ENV).to receive(:[]).with("TAXJAR_API_KEY").and_return(nil)
120
+ end
121
+
122
+ it "doesn't make a request for the tax categories" do
123
+ subject
124
+ expect(flash[:error]).to eq "Failed to complete request to TaxJar: Not authorized for route 'GET /v2/categories'"
125
+ end
126
+ end
127
+ end
128
+
129
+ describe "PUT #update" do
130
+ subject { put spree.admin_taxjar_settings_path params: params }
131
+
132
+ context "updating TaxJar settings" do
133
+ let(:taxjar_configuration) { create :taxjar_configuration, :reporting_disabled }
134
+ let(:params) { {super_good_solidus_taxjar_configuration: {"preferred_reporting_enabled" => "1"}} }
135
+
136
+ it "redirects back to TaxJar settings" do
137
+ subject
138
+ expect(response).to redirect_to "/admin/taxjar_settings"
139
+ end
140
+
141
+ it "shows a flash message" do
142
+ subject
143
+ expect(flash[:success]).to eq "TaxJar settings updated!"
144
+ end
145
+
146
+ it "enables reporting" do
147
+ expect { subject }
148
+ .to change { taxjar_configuration.reload.preferred_reporting_enabled }
149
+ .from(false)
150
+ .to(true)
151
+ .and change { taxjar_configuration.reload.preferred_reporting_enabled_at_integer }
152
+ .from(nil)
153
+ .to(kind_of(Integer))
154
+ end
155
+
156
+ context "reporting is enabled" do
157
+ let(:taxjar_configuration) { create :taxjar_configuration, :reporting_enabled }
158
+ let(:params) { {super_good_solidus_taxjar_configuration: {"preferred_reporting_enabled" => "0"}} }
159
+
160
+ it "disables reporting" do
161
+ expect { subject }
162
+ .to change { taxjar_configuration.reload.preferred_reporting_enabled }
163
+ .from(true)
164
+ .to(false)
165
+ .and change { taxjar_configuration.reload.preferred_reporting_enabled_at_integer }
166
+ .from(kind_of(Integer))
167
+ .to(nil)
168
+ end
169
+ end
170
+
171
+ context "update fails" do
172
+ before do
173
+ allow(SuperGood::SolidusTaxjar).to receive(:configuration).and_return(taxjar_configuration)
174
+ allow(taxjar_configuration).to receive(:update).and_return(false)
175
+ end
176
+
177
+ it "redirects back to TaxJar settings" do
178
+ subject
179
+ expect(response).to redirect_to "/admin/taxjar_settings"
180
+ end
181
+
182
+ it "shows a flash message" do
183
+ subject
184
+ expect(flash[:alert]).to eq "Failed to update settings!"
185
+ end
186
+ end
187
+ end
188
+
189
+ context "updating a tax category" do
190
+ let(:tax_category) { create(:tax_category, name: "Bibles", tax_code: "123") }
191
+ let(:params) { {tax_category: {name: "Bibles", tax_code: "123", id: tax_category.id}, tax_code_id: "81121"} }
192
+
193
+ it "updates the tax code" do
194
+ expect { subject }.to change { tax_category.reload.tax_code }.from("123").to("81121")
195
+ end
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,62 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Spree::Admin::TaxjarTransactionsController, type: :request do
4
+ extend Spree::TestingSupport::AuthorizationHelpers::Request
5
+
6
+ stub_authorization!
7
+
8
+ let(:dummy_taxjar_client) {
9
+ instance_double Taxjar::Client,
10
+ nexus_regions: "fake-value"
11
+ }
12
+ let(:order) { with_events_disabled { create :shipped_order } }
13
+
14
+ before do
15
+ create :taxjar_configuration,
16
+ preferred_reporting_enabled_at_integer: 1.hour.ago
17
+
18
+ allow(SuperGood::SolidusTaxjar::Api)
19
+ .to receive(:default_taxjar_client)
20
+ .and_return(dummy_taxjar_client)
21
+ end
22
+
23
+ describe "POST #retry" do
24
+ subject { post "/admin/orders/#{order.number}/taxjar_transaction/retry" }
25
+
26
+ context "when the order has TaxJar order transactions" do
27
+ before do
28
+ order.taxjar_order_transactions << create(
29
+ :taxjar_order_transaction,
30
+ order: order,
31
+ transaction_id: order.number
32
+ )
33
+ end
34
+
35
+ let(:dummy_taxjar_order) { instance_double ::Taxjar::Order }
36
+
37
+ it "replaces the latest order transaction" do
38
+ allow(::SuperGood::SolidusTaxjar.api)
39
+ .to receive(:show_latest_transaction_for)
40
+ .with(order)
41
+ .once
42
+
43
+ allow(dummy_taxjar_client)
44
+ .to receive(:show_order)
45
+ .with(order.taxjar_order_transactions.first.transaction_id)
46
+ .and_return(instance_double ::Taxjar::Order, amount: "fake-amount")
47
+
48
+ expect { subject }
49
+ .to have_enqueued_job(SuperGood::SolidusTaxjar::ReplaceTransactionJob)
50
+ .once
51
+ end
52
+ end
53
+
54
+ context "when the order does not have TaxJar order transactions" do
55
+ it "reports the initial order transaction" do
56
+ expect { subject }
57
+ .to have_enqueued_job(SuperGood::SolidusTaxjar::ReportTransactionJob)
58
+ .once
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Spree::Admin::TransactionSyncBatchesController, :vcr, :type => :request do
4
+ extend Spree::TestingSupport::AuthorizationHelpers::Request
5
+ stub_authorization!
6
+
7
+ around do |example|
8
+ original = ActionController::Base.allow_forgery_protection
9
+ ActionController::Base.allow_forgery_protection = false
10
+ example.run
11
+ ActionController::Base.allow_forgery_protection = original
12
+ end
13
+
14
+ describe "#create" do
15
+ subject { post spree.admin_transaction_sync_batches_path }
16
+
17
+ let!(:order) { create(:shipped_order) }
18
+
19
+ it "creates a batch" do
20
+ perform_enqueued_jobs do
21
+ expect { subject }
22
+ .to change { SuperGood::SolidusTaxjar::TransactionSyncBatch.count }
23
+ .from(0)
24
+ .to(1)
25
+ batch = SuperGood::SolidusTaxjar::TransactionSyncBatch.last
26
+ expect(batch).to have_attributes({start_date: nil, end_date: nil})
27
+ end
28
+ end
29
+
30
+ it "creates a log in the batch with an order" do
31
+ perform_enqueued_jobs do
32
+ subject
33
+
34
+ batch = SuperGood::SolidusTaxjar::TransactionSyncBatch.last
35
+ expect(batch.transaction_sync_logs.last.order).to eq order
36
+ end
37
+ end
38
+
39
+ context "user supplies a start date" do
40
+ subject { post spree.admin_transaction_sync_batches_path, params: {start_date: 1.day.ago.to_date.to_s} }
41
+
42
+ it "creates a batch" do
43
+ perform_enqueued_jobs do
44
+ expect { subject }
45
+ .to change { SuperGood::SolidusTaxjar::TransactionSyncBatch.count }
46
+ .from(0)
47
+ .to(1)
48
+ batch = SuperGood::SolidusTaxjar::TransactionSyncBatch.last
49
+ expect(batch).to have_attributes({start_date: 1.day.ago.to_date, end_date: nil})
50
+ end
51
+ end
52
+
53
+ context "user supplies start and end date" do
54
+ subject { post spree.admin_transaction_sync_batches_path, params: {start_date: 1.day.ago.to_date.to_s, end_date: Date.today.to_s} }
55
+
56
+ it "creates a batch" do
57
+ perform_enqueued_jobs do
58
+ expect { subject }
59
+ .to change { SuperGood::SolidusTaxjar::TransactionSyncBatch.count }
60
+ .from(0)
61
+ .to(1)
62
+ batch = SuperGood::SolidusTaxjar::TransactionSyncBatch.last
63
+ expect(batch).to have_attributes({start_date: 1.day.ago.to_date, end_date: Date.today})
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ describe "#show" do
71
+ subject { get spree.admin_transaction_sync_batch_path(transaction_sync_batch) }
72
+
73
+ let(:error_message) { "Uh Oh" }
74
+ let(:transaction_sync_batch) { create :transaction_sync_batch, transaction_sync_logs: [transaction_sync_log] }
75
+ let(:transaction_sync_log) { build :transaction_sync_log, error_message: error_message }
76
+
77
+ it "renders the transaction sync log error message" do
78
+ subject
79
+ expect(response.body).to include(error_message)
80
+ end
81
+ end
82
+ end
data/spec/spec_helper.rb CHANGED
@@ -10,11 +10,54 @@ require File.expand_path("dummy/config/environment.rb", __dir__).tap { |file|
10
10
 
11
11
  require "solidus_dev_support/rspec/feature_helper"
12
12
 
13
- # Requires supporting ruby files with custom matchers and macros, etc,
14
- # in spec/support/ and its subdirectories.
15
- Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each { |f| require f }
13
+ require "vcr"
14
+ require "selenium-webdriver"
15
+
16
+ chrome_options = Selenium::WebDriver::Chrome::Options.new.tap do |options|
17
+ options.add_argument("--window-size=#{CAPYBARA_WINDOW_SIZE.join(',')}")
18
+ options.add_argument("--headless") unless ENV["HEADED"]
19
+ options.add_argument("--disable-gpu")
20
+ end
21
+
22
+ version = Capybara::Selenium::Driver.load_selenium
23
+ options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
24
+
25
+ Capybara.register_driver :solidus_chrome_headless do |app|
26
+ Capybara::Selenium::Driver.new(app, browser: :chrome, options_key => chrome_options)
27
+ end
28
+
29
+ SolidusDevSupport::TestingSupport::Factories.load_for(SuperGoodSolidusTaxjar::Engine)
30
+
31
+ require "support/solidus_events_helper"
32
+ require "support/checkoutable_store_shared_context"
16
33
 
17
34
  RSpec.configure do |config|
35
+ config.include SolidusEventsHelper
18
36
  config.infer_spec_type_from_file_location!
19
37
  config.use_transactional_fixtures = false
38
+
39
+ config.before do
40
+ Rails.cache.clear
41
+ if RSpec.current_example.metadata[:js] && page.driver.browser.respond_to?(:url_blacklist)
42
+ page.driver.browser.url_blacklist = ['https://fonts.googleapis.com']
43
+ end
44
+ end
45
+ end
46
+
47
+ VCR.configure do |config|
48
+ config.cassette_library_dir = 'spec/fixtures/cassettes'
49
+ config.ignore_localhost = true
50
+ config.configure_rspec_metadata!
51
+ config.hook_into :webmock
52
+ config.ignore_hosts(
53
+ "chromedriver.storage.googleapis.com",
54
+ "googlechromelabs.github.io",
55
+ "edgedl.me.gvt1.com"
56
+ )
57
+ config.filter_sensitive_data('<BEARER_TOKEN>') { |interaction|
58
+ auths = interaction.request.headers['Authorization'].first
59
+ if (match = auths.match /^Bearer\s+([^,\s]+)/ )
60
+ match.captures.first
61
+ end
62
+ }
20
63
  end
@@ -0,0 +1,278 @@
1
+ require "spec_helper"
2
+
3
+ # These tests will excercise either the `ReportingSubscriber` or the
4
+ # `LegacyReportingSubscriber` depending on the version of Solidus they are
5
+ # run against. The loading of the correct subscriber is handled by the
6
+ # initializer added by this extension's install generator.
7
+ RSpec.describe "ReportingSubscriber" do
8
+ before do
9
+ create(:taxjar_configuration, preferred_reporting_enabled_at_integer: reporting_enabled_at.to_i)
10
+ end
11
+
12
+ let(:order_factory) { :shipped_order }
13
+ let(:order) { with_events_disabled { create order_factory } }
14
+
15
+ let(:reporting) { instance_spy ::SuperGood::SolidusTaxjar::Reporting }
16
+ let(:reporting_enabled_at) { 1.hour.ago }
17
+
18
+ describe "order_recalculated is fired" do
19
+ subject do
20
+ SolidusSupport::LegacyEventCompat::Bus.publish(
21
+ :order_recalculated,
22
+ order: order
23
+ )
24
+ end
25
+
26
+ context "when the order is completed" do
27
+ context "when the order has not been shipped" do
28
+ let(:order) {
29
+ with_events_disabled { create :completed_order_with_totals }
30
+ }
31
+
32
+ it "does nothing" do
33
+ subject
34
+
35
+ assert_no_enqueued_jobs
36
+ end
37
+ end
38
+
39
+ context "when the order's payment state is 'credit_owed'" do
40
+ before { order.update(payment_state: "credit_owed") }
41
+
42
+ it "does nothing" do
43
+ subject
44
+
45
+ assert_no_enqueued_jobs
46
+ end
47
+ end
48
+
49
+ context "when the order's payment state is 'paid'" do
50
+ context "when a TaxJar transaction already exists on the order" do
51
+ let!(:taxjar_transaction) { create(:taxjar_order_transaction, order: order) }
52
+
53
+ let(:dummy_client) { instance_double Taxjar::Client }
54
+ let(:dummy_response) {
55
+ instance_double(
56
+ ::Taxjar::Order,
57
+ amount: 110.00,
58
+ line_items: [
59
+ Taxjar::LineItem.new(
60
+ discount: 0,
61
+ sales_tax: 9999,
62
+ unit_price: 9999
63
+ )
64
+ ],
65
+ sales_tax: 9999999,
66
+ shipping: 99999,
67
+ transaction_id: order.number,
68
+ transaction_date: "2015-05-15T00:00:00Z"
69
+ )
70
+ }
71
+
72
+ let(:new_dummy_response) {
73
+ instance_double(
74
+ ::Taxjar::Order,
75
+ amount: 333.00,
76
+ transaction_id: "#{order.number}-1",
77
+ transaction_date: "2015-05-16T00:00:00Z"
78
+ )
79
+ }
80
+
81
+ before do
82
+ allow(SuperGood::SolidusTaxjar::Api)
83
+ .to receive(:default_taxjar_client)
84
+ .and_return(dummy_client)
85
+
86
+ allow(dummy_client)
87
+ .to receive(:show_order)
88
+ .with(taxjar_transaction.transaction_id)
89
+ .and_return(dummy_response)
90
+
91
+ allow(dummy_client)
92
+ .to receive(:create_refund)
93
+ .with(
94
+ SuperGood::SolidusTaxjar::ApiParams
95
+ .refund_transaction_params(order, dummy_response)
96
+ )
97
+ end
98
+
99
+ context "when the TaxJar transaction is up-to-date" do
100
+ it "does nothing" do
101
+ subject
102
+
103
+ assert_no_enqueued_jobs
104
+ end
105
+
106
+ context "when the order was completed before reporting was enabled" do
107
+ before do
108
+ order.update_column(:completed_at, 2.hours.ago)
109
+ end
110
+
111
+ it "does nothing" do
112
+ expect { subject }.not_to change(
113
+ ActiveJob::Base.queue_adapter.enqueued_jobs,
114
+ :count
115
+ )
116
+ end
117
+
118
+ it "creates a sync log" do
119
+ expect { subject }.to change { order.taxjar_transaction_sync_logs.count }
120
+ .from(0).to(1)
121
+ expect(order.taxjar_transaction_sync_logs.last.status).to eq "error"
122
+ expect(order.taxjar_transaction_sync_logs.last.error_message)
123
+ .to include "Order cannot be synced because it was completed before TaxJar reporting was enabled"
124
+ end
125
+ end
126
+ end
127
+
128
+ context "when the TaxJar transaction is not up-to-date" do
129
+ before do
130
+ allow(dummy_client).to receive(:nexus_regions)
131
+ allow(dummy_client).to receive(:tax_for_order)
132
+ with_events_disabled {
133
+ customer_return = create :customer_return_with_accepted_items, shipped_order: order
134
+ reimbursement = create :reimbursement, customer_return: customer_return, total: 10
135
+ create :refund, reimbursement: reimbursement, payment: order.payments.first, amount: 10
136
+ order.recalculate
137
+ }
138
+ end
139
+
140
+ it "enqueues a job to refund and create a new transaction" do
141
+ assert_enqueued_with(
142
+ job: SuperGood::SolidusTaxjar::ReplaceTransactionJob,
143
+ args: [order]
144
+ ) do
145
+ subject
146
+ end
147
+ end
148
+
149
+ context "when the order was completed before reporting was enabled" do
150
+ before do
151
+ order.update_column(:completed_at, 2.hours.ago)
152
+ end
153
+
154
+ it "does nothing" do
155
+ expect { subject }.not_to change(
156
+ ActiveJob::Base.queue_adapter.enqueued_jobs,
157
+ :count
158
+ )
159
+ end
160
+
161
+ it "creates a sync log" do
162
+ expect { subject }.to change { order.taxjar_transaction_sync_logs.count }.from(0).to(1)
163
+ expect(order.taxjar_transaction_sync_logs.last.status).to eq "error"
164
+ expect(order.taxjar_transaction_sync_logs.last.error_message).to include "Order cannot be synced because it was completed before TaxJar reporting was enabled"
165
+ end
166
+ end
167
+ end
168
+ end
169
+
170
+ context "when a TaxJar transaction does not exist on the order" do
171
+ it "enqueues a job to report the transaction" do
172
+ assert_enqueued_with(
173
+ job: SuperGood::SolidusTaxjar::ReportTransactionJob,
174
+ args: [order]
175
+ ) do
176
+ subject
177
+ end
178
+ end
179
+ end
180
+ end
181
+
182
+ context "when the order's payment state is 'balance_due'" do
183
+ let(:order_factory) { :completed_order_with_pending_payment }
184
+
185
+ it "does nothing" do
186
+ subject
187
+
188
+ assert_no_enqueued_jobs
189
+ end
190
+ end
191
+ end
192
+
193
+ context "when the order is not completed" do
194
+ let(:order_factory) { :order_with_totals }
195
+
196
+ it "does nothing" do
197
+ subject
198
+
199
+ assert_no_enqueued_jobs
200
+ end
201
+ end
202
+ end
203
+
204
+ describe "shipment is shipped" do
205
+ subject { shipment.ship! }
206
+
207
+ let(:shipment) { order.shipments.first }
208
+ let(:order) {
209
+ with_events_disabled { create :order_ready_to_ship }
210
+ }
211
+ let(:reporting) { instance_spy(::SuperGood::SolidusTaxjar::Reporting) }
212
+
213
+ context "reporting is enabled" do
214
+ it "enqueues job to report transaction" do
215
+ assert_enqueued_with(
216
+ job: SuperGood::SolidusTaxjar::ReportTransactionJob,
217
+ args: [shipment.order]
218
+ ) do
219
+ subject
220
+ end
221
+ end
222
+
223
+ it "does not enqueue the replace transaction job" do
224
+ expect { subject }
225
+ .to_not have_enqueued_job(SuperGood::SolidusTaxjar::ReplaceTransactionJob)
226
+ end
227
+ end
228
+
229
+ context "when the order was completed before reporting was enabled" do
230
+ let(:reporting_enabled_at) { 1.hour.ago }
231
+ let(:exception_handler) { double }
232
+
233
+ before do
234
+ allow(exception_handler).to receive(:call)
235
+ order.update_column(:completed_at, 2.hours.ago)
236
+ end
237
+
238
+ around do |example|
239
+ original_handler = SuperGood::SolidusTaxjar.exception_handler
240
+ SuperGood::SolidusTaxjar.exception_handler = exception_handler
241
+ SuperGood::SolidusTaxjar.test_mode = true
242
+ example.call
243
+ SuperGood::SolidusTaxjar.test_mode = false
244
+ SuperGood::SolidusTaxjar.exception_handler = original_handler
245
+ end
246
+
247
+ it "doesn't queue job to report the transaction" do
248
+ expect { subject }
249
+ .to_not have_enqueued_job(SuperGood::SolidusTaxjar::ReportTransactionJob)
250
+ end
251
+
252
+ it "doesn't queue job to replace the transaction" do
253
+ expect { subject }
254
+ .to_not have_enqueued_job(SuperGood::SolidusTaxjar::ReplaceTransactionJob)
255
+ end
256
+
257
+ it "creates a sync log" do
258
+ expect { subject }.to change { order.taxjar_transaction_sync_logs.count }.from(0).to(1)
259
+ expect(order.taxjar_transaction_sync_logs.last.status).to eq "error"
260
+ expect(order.taxjar_transaction_sync_logs.last.error_message)
261
+ .to include(
262
+ "Order cannot be synced because it was completed before " \
263
+ "TaxJar reporting was enabled"
264
+ )
265
+ end
266
+
267
+ it "calls the exception handler" do
268
+ subject
269
+ expect(exception_handler).to have_received(:call)
270
+ .with(
271
+ RuntimeError.new(
272
+ "Order cannot be synced because it was completed before TaxJar " \
273
+ "reporting was enabled")
274
+ )
275
+ end
276
+ end
277
+ end
278
+ end