solidus_braintree 1.4.0 → 2.0.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.
Files changed (204) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +12 -0
  3. data/.gem_release.yml +5 -0
  4. data/.github_changelog_generator +2 -0
  5. data/.gitignore +20 -11
  6. data/.rspec +1 -1
  7. data/.rubocop.yml +79 -0
  8. data/CHANGELOG.md +178 -18
  9. data/Gemfile +31 -23
  10. data/LICENSE +26 -0
  11. data/README.md +387 -26
  12. data/Rakefile +4 -19
  13. data/app/assets/config/solidus_braintree_manifest.js +1 -0
  14. data/app/assets/images/solidus_braintree/venmo/venmo_active_blue_button_280x48.svg +19 -0
  15. data/app/assets/images/solidus_braintree/venmo/venmo_active_blue_button_320x48.svg +19 -0
  16. data/app/assets/images/solidus_braintree/venmo/venmo_active_blue_button_375x48.svg +19 -0
  17. data/app/assets/images/solidus_braintree/venmo/venmo_active_white_button_280x48.svg +19 -0
  18. data/app/assets/images/solidus_braintree/venmo/venmo_active_white_button_320x48.svg +19 -0
  19. data/app/assets/images/solidus_braintree/venmo/venmo_active_white_button_375x48.svg +19 -0
  20. data/app/assets/images/solidus_braintree/venmo/venmo_blue_acceptance_mark.svg +15 -0
  21. data/app/assets/images/solidus_braintree/venmo/venmo_blue_button_280x48.svg +19 -0
  22. data/app/assets/images/solidus_braintree/venmo/venmo_blue_button_320x48.svg +19 -0
  23. data/app/assets/images/solidus_braintree/venmo/venmo_blue_button_375x48.svg +19 -0
  24. data/app/assets/images/solidus_braintree/venmo/venmo_blue_logo.svg +18 -0
  25. data/app/assets/images/solidus_braintree/venmo/venmo_white_acceptance_mark.svg +20 -0
  26. data/app/assets/images/solidus_braintree/venmo/venmo_white_button_280x48.svg +19 -0
  27. data/app/assets/images/solidus_braintree/venmo/venmo_white_button_320x48.svg +19 -0
  28. data/app/assets/images/solidus_braintree/venmo/venmo_white_button_375x48.svg +19 -0
  29. data/app/assets/images/solidus_braintree/venmo/venmo_white_logo.svg +18 -0
  30. data/app/assets/javascripts/solidus_braintree/apple_pay_button.js +179 -0
  31. data/app/assets/javascripts/solidus_braintree/checkout.js +108 -0
  32. data/app/assets/javascripts/solidus_braintree/client.js +239 -0
  33. data/app/assets/javascripts/solidus_braintree/constants.js +89 -0
  34. data/app/assets/javascripts/solidus_braintree/frontend.js +14 -0
  35. data/app/assets/javascripts/solidus_braintree/hosted_form.js +46 -0
  36. data/app/assets/javascripts/solidus_braintree/paypal_button.js +178 -0
  37. data/app/assets/javascripts/solidus_braintree/paypal_messaging.js +22 -0
  38. data/app/assets/javascripts/solidus_braintree/promise.js +20 -0
  39. data/app/assets/javascripts/solidus_braintree/venmo_button.js +86 -0
  40. data/app/assets/javascripts/spree/backend/solidus_braintree.js +96 -0
  41. data/app/assets/javascripts/spree/frontend/paypal_button.js +34 -0
  42. data/app/assets/javascripts/spree/frontend/solidus_braintree.js +1 -0
  43. data/app/assets/stylesheets/spree/backend/solidus_braintree.scss +28 -0
  44. data/app/assets/stylesheets/spree/frontend/solidus_braintree.scss +51 -0
  45. data/app/decorators/controllers/solidus_braintree/admin_payments_controller_decorator.rb +11 -0
  46. data/app/decorators/controllers/solidus_braintree/checkout_controller_decorator.rb +11 -0
  47. data/app/decorators/controllers/solidus_braintree/client_tokens_controller.rb +41 -0
  48. data/app/decorators/controllers/solidus_braintree/orders_controller_decorator.rb +11 -0
  49. data/app/decorators/models/solidus_braintree/spree/store_decorator.rb +20 -0
  50. data/app/decorators/models/solidus_braintree/spree/user_decorator.rb +13 -0
  51. data/app/helpers/solidus_braintree/braintree_admin_helper.rb +23 -0
  52. data/app/helpers/solidus_braintree/braintree_checkout_helper.rb +60 -0
  53. data/app/models/application_record.rb +5 -0
  54. data/app/models/solidus_braintree/address.rb +64 -0
  55. data/app/models/solidus_braintree/avs_result.rb +69 -0
  56. data/app/models/solidus_braintree/configuration.rb +39 -0
  57. data/app/models/solidus_braintree/customer.rb +8 -0
  58. data/app/models/solidus_braintree/gateway.rb +433 -0
  59. data/app/models/solidus_braintree/response.rb +80 -0
  60. data/app/models/solidus_braintree/source.rb +135 -0
  61. data/app/models/solidus_braintree/transaction.rb +31 -0
  62. data/app/models/solidus_braintree/transaction_address.rb +88 -0
  63. data/app/models/solidus_braintree/transaction_import.rb +98 -0
  64. data/app/overrides/spree/payments/payment/add_paypal_funding_source_to_payment.rb +9 -0
  65. data/app/views/spree/api/payments/source_views/_braintree.json.jbuilder +1 -1
  66. data/app/views/spree/checkout/existing_payment/_braintree.html.erb +10 -0
  67. data/app/views/spree/shared/_apple_pay_button.html.erb +27 -0
  68. data/app/views/spree/shared/_braintree_errors.html.erb +16 -0
  69. data/app/views/spree/shared/_braintree_head_scripts.html.erb +26 -0
  70. data/app/views/spree/shared/_braintree_hosted_fields.html.erb +43 -0
  71. data/app/views/spree/shared/_paypal_cart_button.html.erb +38 -0
  72. data/app/views/spree/shared/_paypal_messaging.html.erb +13 -0
  73. data/app/views/spree/shared/_venmo_button.html.erb +33 -0
  74. data/bin/console +4 -1
  75. data/bin/rails +5 -5
  76. data/bin/rails-engine +13 -0
  77. data/bin/rails-sandbox +16 -0
  78. data/bin/rake +7 -0
  79. data/bin/sandbox +103 -0
  80. data/bin/setup +5 -4
  81. data/config/locales/en.yml +94 -2
  82. data/config/locales/it.yml +56 -0
  83. data/config/routes.rb +12 -3
  84. data/db/migrate/20160830061749_create_solidus_paypal_braintree_sources.rb +16 -0
  85. data/db/migrate/20160906201711_create_solidus_paypal_braintree_customers.rb +13 -0
  86. data/db/migrate/20161114231422_create_solidus_paypal_braintree_configurations.rb +11 -0
  87. data/db/migrate/20161125172005_add_braintree_configuration_to_stores.rb +7 -0
  88. data/db/migrate/20170203191030_add_credit_card_to_braintree_configuration.rb +6 -0
  89. data/db/migrate/20170505193712_add_null_constraint_to_sources.rb +38 -0
  90. data/db/migrate/20170508085402_add_not_null_constraint_to_sources_payment_type.rb +14 -0
  91. data/db/migrate/20190705115327_add_paypal_button_preferences_to_braintree_configurations.rb +5 -0
  92. data/db/migrate/20190911141712_add_3d_secure_to_braintree_configuration.rb +5 -0
  93. data/db/migrate/20211222170950_add_paypal_funding_source_to_solidus_paypal_braintree_sources.rb +5 -0
  94. data/db/migrate/20220104150301_add_venmo_to_braintree_configuration.rb +5 -0
  95. data/db/migrate/20230109080950_rename_solidus_paypal_braintree_source_type.rb +31 -0
  96. data/lib/controllers/backend/solidus_braintree/configurations_controller.rb +48 -0
  97. data/lib/controllers/frontend/solidus_braintree/checkouts_controller.rb +31 -0
  98. data/lib/controllers/frontend/solidus_braintree/transactions_controller.rb +67 -0
  99. data/lib/generators/solidus_braintree/install/install_generator.rb +54 -18
  100. data/lib/generators/solidus_braintree/install/templates/initializer.rb +6 -0
  101. data/lib/solidus_braintree/country_mapper.rb +37 -0
  102. data/lib/solidus_braintree/engine.rb +55 -10
  103. data/lib/solidus_braintree/extension_configuration.rb +23 -0
  104. data/lib/solidus_braintree/request_protection.rb +21 -0
  105. data/lib/solidus_braintree/testing_support/factories.rb +53 -0
  106. data/lib/solidus_braintree/version.rb +3 -1
  107. data/lib/solidus_braintree.rb +14 -2
  108. data/lib/solidus_paypal_braintree.rb +6 -0
  109. data/lib/views/backend/solidus_braintree/configurations/list.html.erb +63 -0
  110. data/lib/views/backend/spree/admin/payments/source_forms/_braintree.html.erb +16 -0
  111. data/lib/views/backend/spree/admin/payments/source_views/_braintree.html.erb +39 -0
  112. data/lib/views/backend/spree/admin/shared/preference_fields/_preference_select.html.erb +13 -0
  113. data/lib/views/backend_v1.2/spree/admin/payments/source_forms/_braintree.html.erb +16 -0
  114. data/lib/views/backend_v2.4/spree/admin/shared/preference_fields/_hash.html.erb +12 -0
  115. data/lib/views/frontend/solidus_braintree/payments/_payment.html.erb +12 -0
  116. data/lib/views/frontend/spree/checkout/payment/_braintree.html.erb +23 -0
  117. data/lib/views/frontend/spree/shared/_paypal_checkout_button.html.erb +32 -0
  118. data/solidus_braintree.gemspec +39 -38
  119. data/spec/controllers/solidus_braintree/checkouts_controller_spec.rb +99 -0
  120. data/spec/controllers/solidus_braintree/client_tokens_controller_spec.rb +55 -0
  121. data/spec/controllers/solidus_braintree/configurations_controller_spec.rb +73 -0
  122. data/spec/controllers/solidus_braintree/transactions_controller_spec.rb +183 -0
  123. data/spec/features/backend/configuration_spec.rb +23 -0
  124. data/spec/features/backend/new_payment_spec.rb +137 -0
  125. data/spec/features/frontend/braintree_credit_card_checkout_spec.rb +191 -0
  126. data/spec/features/frontend/paypal_checkout_spec.rb +166 -0
  127. data/spec/features/frontend/venmo_checkout_spec.rb +194 -0
  128. data/spec/fixtures/cassettes/admin/invalid_credit_card.yml +63 -0
  129. data/spec/fixtures/cassettes/admin/resubmit_credit_card.yml +352 -0
  130. data/spec/fixtures/cassettes/admin/valid_credit_card.yml +412 -0
  131. data/spec/fixtures/cassettes/braintree/create_profile.yml +71 -0
  132. data/spec/fixtures/cassettes/braintree/generate_token.yml +63 -0
  133. data/spec/fixtures/cassettes/braintree/token.yml +63 -0
  134. data/spec/fixtures/cassettes/checkout/invalid_credit_card.yml +63 -0
  135. data/spec/fixtures/cassettes/checkout/resubmit_credit_card.yml +216 -0
  136. data/spec/fixtures/cassettes/checkout/update.yml +71 -0
  137. data/spec/fixtures/cassettes/checkout/valid_credit_card.yml +171 -0
  138. data/spec/fixtures/cassettes/checkout/valid_venmo_transaction.yml +599 -0
  139. data/spec/fixtures/cassettes/gateway/authorize/credit_card/address.yml +86 -0
  140. data/spec/fixtures/cassettes/gateway/authorize/merchant_account/EUR.yml +154 -0
  141. data/spec/fixtures/cassettes/gateway/authorize/paypal/EUR.yml +90 -0
  142. data/spec/fixtures/cassettes/gateway/authorize/paypal/address.yml +90 -0
  143. data/spec/fixtures/cassettes/gateway/authorize.yml +86 -0
  144. data/spec/fixtures/cassettes/gateway/authorized_transaction.yml +73 -0
  145. data/spec/fixtures/cassettes/gateway/cancel/missing.yml +63 -0
  146. data/spec/fixtures/cassettes/gateway/cancel/refunds.yml +272 -0
  147. data/spec/fixtures/cassettes/gateway/cancel/void.yml +201 -0
  148. data/spec/fixtures/cassettes/gateway/capture.yml +141 -0
  149. data/spec/fixtures/cassettes/gateway/complete.yml +157 -0
  150. data/spec/fixtures/cassettes/gateway/credit.yml +208 -0
  151. data/spec/fixtures/cassettes/gateway/customer.yml +79 -0
  152. data/spec/fixtures/cassettes/gateway/purchase.yml +87 -0
  153. data/spec/fixtures/cassettes/gateway/settled_transaction.yml +140 -0
  154. data/spec/fixtures/cassettes/gateway/void.yml +137 -0
  155. data/spec/fixtures/cassettes/source/bin.yml +295 -0
  156. data/spec/fixtures/cassettes/source/card_type.yml +267 -0
  157. data/spec/fixtures/cassettes/source/last4.yml +267 -0
  158. data/spec/fixtures/cassettes/transaction/import/valid/capture.yml +224 -0
  159. data/spec/fixtures/cassettes/transaction/import/valid.yml +71 -0
  160. data/spec/fixtures/views/spree/orders/edit.html.erb +50 -0
  161. data/spec/helpers/solidus_braintree/braintree_admin_helper_spec.rb +17 -0
  162. data/spec/helpers/solidus_braintree/braintree_checkout_helper_spec.rb +70 -0
  163. data/spec/models/solidus_braintree/address_spec.rb +71 -0
  164. data/spec/models/solidus_braintree/avs_result_spec.rb +317 -0
  165. data/spec/models/solidus_braintree/gateway_spec.rb +742 -0
  166. data/spec/models/solidus_braintree/response_spec.rb +280 -0
  167. data/spec/models/solidus_braintree/source_spec.rb +539 -0
  168. data/spec/models/solidus_braintree/transaction_address_spec.rb +235 -0
  169. data/spec/models/solidus_braintree/transaction_import_spec.rb +302 -0
  170. data/spec/models/solidus_braintree/transaction_spec.rb +86 -0
  171. data/spec/models/spree/store_spec.rb +14 -0
  172. data/spec/requests/spree/api/orders_controller_spec.rb +36 -0
  173. data/spec/spec_helper.rb +32 -0
  174. data/spec/support/capybara.rb +7 -0
  175. data/spec/support/gateway_helpers.rb +29 -0
  176. data/spec/support/order_ready_for_payment.rb +37 -0
  177. data/spec/support/vcr.rb +42 -0
  178. data/spec/support/views.rb +1 -0
  179. metadata +276 -224
  180. data/LICENSE.txt +0 -21
  181. data/app/controllers/spree/api/braintree_client_token_controller.rb +0 -13
  182. data/app/decorators/lib/solidus_braintree/spree/permitted_attributes_decorator.rb +0 -9
  183. data/app/decorators/models/solidus_braintree/spree/credit_card_decorator.rb +0 -11
  184. data/app/decorators/models/solidus_braintree/spree/payment_decorator.rb +0 -10
  185. data/app/helpers/braintree_view_helpers.rb +0 -20
  186. data/app/models/concerns/solidus_braintree/add_name_validation_concern.rb +0 -8
  187. data/app/models/concerns/solidus_braintree/inject_device_data_concern.rb +0 -18
  188. data/app/models/concerns/solidus_braintree/payment_braintree_nonce_concern.rb +0 -8
  189. data/app/models/concerns/solidus_braintree/permitted_attributes_concern.rb +0 -11
  190. data/app/models/concerns/solidus_braintree/skip_require_card_numbers_concern.rb +0 -14
  191. data/app/models/concerns/solidus_braintree/use_data_field_concern.rb +0 -23
  192. data/app/models/solidus/gateway/braintree_gateway.rb +0 -306
  193. data/app/overrides/spree/checkout/_confirm/braintree_security.html.erb.deface +0 -9
  194. data/app/views/spree/admin/payments/source_forms/_braintree.html.erb +0 -38
  195. data/app/views/spree/admin/payments/source_views/_braintree.html.erb +0 -30
  196. data/app/views/spree/checkout/payment/_braintree.html.erb +0 -55
  197. data/app/views/spree/checkout/payment/_braintree_initialization.html.erb +0 -12
  198. data/config/initializers/braintree.rb +0 -3
  199. data/db/migrate/20150910170527_add_data_to_credit_card.rb +0 -5
  200. data/db/migrate/20160426221931_add_braintree_device_data_to_order.rb +0 -5
  201. data/lib/assets/javascripts/spree/backend/braintree/solidus_braintree.js +0 -59
  202. data/lib/assets/javascripts/spree/frontend/braintree/solidus_braintree.js +0 -144
  203. data/lib/assets/javascripts/vendor/braintree.js +0 -8
  204. data/lib/assets/stylesheets/spree/frontend/solidus_braintree.scss +0 -26
@@ -0,0 +1,317 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe SolidusBraintree::AVSResult do
4
+ describe 'AVS response message' do
5
+ subject { described_class.build(transaction).to_hash['message'] }
6
+
7
+ context 'with avs_error_response_code' do
8
+ let(:transaction) do
9
+ instance_double(Braintree::Transaction,
10
+ avs_error_response_code: error_code,
11
+ avs_street_address_response_code: nil,
12
+ avs_postal_code_response_code: nil)
13
+ end
14
+
15
+ context 'when error code is S' do
16
+ let(:error_code) { 'S' }
17
+
18
+ it { is_expected.to eq 'U.S.-issuing bank does not support AVS.' }
19
+ end
20
+
21
+ context 'when error code is E' do
22
+ let(:error_code) { 'E' }
23
+
24
+ it { is_expected.to eq 'AVS data is invalid or AVS is not allowed for this card type.' }
25
+ end
26
+ end
27
+
28
+ context 'without avs_error_response_code' do
29
+ let(:transaction) do
30
+ instance_double(Braintree::Transaction,
31
+ avs_error_response_code: nil,
32
+ avs_street_address_response_code: codes.first,
33
+ avs_postal_code_response_code: codes.last)
34
+ end
35
+
36
+ context 'when street address result is M and postal code result is N' do
37
+ let(:codes) { %w(M N) }
38
+
39
+ it { is_expected.to eq 'Street address matches, but postal code does not match.' }
40
+
41
+ it {
42
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'M', 'postal_match' => 'N')
43
+ }
44
+ end
45
+
46
+ context 'when street address result is M and postal code result is U' do
47
+ let(:codes) { %w(M U) }
48
+
49
+ it { is_expected.to eq 'Street address matches, but postal code not verified.' }
50
+
51
+ it {
52
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'M', 'postal_match' => 'U')
53
+ }
54
+ end
55
+
56
+ context 'when street address result is M and postal code result is I' do
57
+ let(:codes) { %w(M I) }
58
+
59
+ it { is_expected.to eq 'Street address matches, but postal code not verified.' }
60
+
61
+ it {
62
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'M', 'postal_match' => 'I')
63
+ }
64
+ end
65
+
66
+ context 'when street address result is M and postal code result is A' do
67
+ let(:codes) { %w(M A) }
68
+
69
+ it { is_expected.to eq 'Street address matches, but postal code not verified.' }
70
+
71
+ it {
72
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'M', 'postal_match' => 'A')
73
+ }
74
+ end
75
+
76
+ context 'when street address result is N and postal code result is N' do
77
+ let(:codes) { %w(N N) }
78
+
79
+ it { is_expected.to eq 'Street address and postal code do not match.' }
80
+
81
+ it {
82
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'N', 'postal_match' => 'N')
83
+ }
84
+ end
85
+
86
+ context 'when street address result is N and postal code result is U' do
87
+ let(:codes) { %w(N U) }
88
+
89
+ it { is_expected.to eq 'Street address and postal code do not match.' }
90
+
91
+ it {
92
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'N', 'postal_match' => 'U')
93
+ }
94
+ end
95
+
96
+ context 'when street address result is N and postal code result is I' do
97
+ let(:codes) { %w(N I) }
98
+
99
+ it { is_expected.to eq 'Street address and postal code do not match.' }
100
+
101
+ it {
102
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'N', 'postal_match' => 'I')
103
+ }
104
+ end
105
+
106
+ context 'when street address result is N and postal code result is A' do
107
+ let(:codes) { %w(N A) }
108
+
109
+ it { is_expected.to eq 'Street address and postal code do not match.' }
110
+
111
+ it {
112
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'N', 'postal_match' => 'A')
113
+ }
114
+ end
115
+
116
+ context 'when street address result is I and postal code result is N' do
117
+ let(:codes) { %w(I N) }
118
+
119
+ it { is_expected.to eq 'Street address and postal code do not match.' }
120
+
121
+ it {
122
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'I', 'postal_match' => 'N')
123
+ }
124
+ end
125
+
126
+ context 'when street address result is A and postal code result is N' do
127
+ let(:codes) { %w(A N) }
128
+
129
+ it { is_expected.to eq 'Street address and postal code do not match.' }
130
+
131
+ it {
132
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'A', 'postal_match' => 'N')
133
+ }
134
+ end
135
+
136
+ context 'when street address result is U and postal code result is U' do
137
+ let(:codes) { %w(U U) }
138
+
139
+ it { is_expected.to eq 'Address not verified.' }
140
+
141
+ it {
142
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'U', 'postal_match' => 'U')
143
+ }
144
+ end
145
+
146
+ context 'when street address result is U and postal code result is I' do
147
+ let(:codes) { %w(U I) }
148
+
149
+ it { is_expected.to eq 'Address not verified.' }
150
+
151
+ it {
152
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'U', 'postal_match' => 'I')
153
+ }
154
+ end
155
+
156
+ context 'when street address result is U and postal code result is A' do
157
+ let(:codes) { %w(U A) }
158
+
159
+ it { is_expected.to eq 'Address not verified.' }
160
+
161
+ it {
162
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'U', 'postal_match' => 'A')
163
+ }
164
+ end
165
+
166
+ context 'when street address result is I and postal code result is U' do
167
+ let(:codes) { %w(I U) }
168
+
169
+ it { is_expected.to eq 'Address not verified.' }
170
+
171
+ it {
172
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'I', 'postal_match' => 'U')
173
+ }
174
+ end
175
+
176
+ context 'when street address result is I and postal code result is I' do
177
+ let(:codes) { %w(I I) }
178
+
179
+ it { is_expected.to eq 'Address not verified.' }
180
+
181
+ it {
182
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'I', 'postal_match' => 'I')
183
+ }
184
+ end
185
+
186
+ context 'when street address result is I and postal code result is A' do
187
+ let(:codes) { %w(I A) }
188
+
189
+ it { is_expected.to eq 'Address not verified.' }
190
+
191
+ it {
192
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'I', 'postal_match' => 'A')
193
+ }
194
+ end
195
+
196
+ context 'when street address result is A and postal code result is U' do
197
+ let(:codes) { %w(A U) }
198
+
199
+ it { is_expected.to eq 'Address not verified.' }
200
+
201
+ it {
202
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'A', 'postal_match' => 'U')
203
+ }
204
+ end
205
+
206
+ context 'when street address result is A and postal code result is I' do
207
+ let(:codes) { %w(A I) }
208
+
209
+ it { is_expected.to eq 'Address not verified.' }
210
+
211
+ it {
212
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'A', 'postal_match' => 'I')
213
+ }
214
+ end
215
+
216
+ context 'when street address result is A and postal code result is A' do
217
+ let(:codes) { %w(A A) }
218
+
219
+ it { is_expected.to eq 'Address not verified.' }
220
+
221
+ it {
222
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'A', 'postal_match' => 'A')
223
+ }
224
+ end
225
+
226
+ context 'when street address result is M and postal code result is M' do
227
+ let(:codes) { %w(M M) }
228
+
229
+ it { is_expected.to eq 'Street address and postal code match.' }
230
+
231
+ it {
232
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'M', 'postal_match' => 'M')
233
+ }
234
+ end
235
+
236
+ context 'when street address result is U and postal code result is N' do
237
+ let(:codes) { %w(U N) }
238
+
239
+ it { is_expected.to eq "Street address and postal code do not match. For American Express: Card member's name, street address and postal code do not match." } # rubocop:disable Layout/LineLength
240
+
241
+ it {
242
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'U', 'postal_match' => 'N')
243
+ }
244
+ end
245
+
246
+ context 'when street address result is U and postal code result is M' do
247
+ let(:codes) { %w(U M) }
248
+
249
+ it { is_expected.to eq 'Postal code matches, but street address not verified.' }
250
+
251
+ it {
252
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'U', 'postal_match' => 'M')
253
+ }
254
+ end
255
+
256
+ context 'when street address result is I and postal code result is M' do
257
+ let(:codes) { %w(I M) }
258
+
259
+ it { is_expected.to eq 'Postal code matches, but street address not verified.' }
260
+
261
+ it {
262
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'I', 'postal_match' => 'M')
263
+ }
264
+ end
265
+
266
+ context 'when street address result is A and postal code result is M' do
267
+ let(:codes) { %w(A M) }
268
+
269
+ it { is_expected.to eq 'Postal code matches, but street address not verified.' }
270
+
271
+ it {
272
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'A', 'postal_match' => 'M')
273
+ }
274
+ end
275
+
276
+ context 'when street address result is N and postal code result is M' do
277
+ let(:codes) { %w(N M) }
278
+
279
+ it { is_expected.to eq 'Street address does not match, but 5-digit postal code matches.' }
280
+
281
+ it {
282
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'N', 'postal_match' => 'M')
283
+ }
284
+ end
285
+
286
+ context 'when street address response code is nil' do
287
+ let(:codes) { [nil, 'M'] }
288
+
289
+ it { is_expected.to be_nil }
290
+
291
+ it {
292
+ expect(described_class.build(transaction).to_hash).to include('street_match' => nil, 'postal_match' => 'M')
293
+ }
294
+ end
295
+
296
+ context 'when postal code response code is nil' do
297
+ let(:codes) { ['M', nil] }
298
+
299
+ it { is_expected.to be_nil }
300
+
301
+ it {
302
+ expect(described_class.build(transaction).to_hash).to include('street_match' => 'M', 'postal_match' => nil)
303
+ }
304
+ end
305
+
306
+ context 'when postal code and street address response code is nil' do
307
+ let(:codes) { [nil, nil] }
308
+
309
+ it { is_expected.to be_nil }
310
+
311
+ it {
312
+ expect(described_class.build(transaction).to_hash).to include('street_match' => nil, 'postal_match' => nil)
313
+ }
314
+ end
315
+ end
316
+ end
317
+ end