@stripe/stripe-react-native 0.65.0 → 0.66.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 (239) hide show
  1. package/README.md +2 -2
  2. package/android/detekt/detekt-baseline.xml +1 -76
  3. package/android/gradle.properties +4 -4
  4. package/android/src/main/java/com/reactnativestripesdk/AuBECSDebitFormView.kt +3 -1
  5. package/android/src/main/java/com/reactnativestripesdk/AuBECSDebitFormViewManager.kt +2 -1
  6. package/android/src/main/java/com/reactnativestripesdk/CardFieldView.kt +56 -58
  7. package/android/src/main/java/com/reactnativestripesdk/CurrencySelectorElementEvent.kt +26 -0
  8. package/android/src/main/java/com/reactnativestripesdk/CurrencySelectorElementView.kt +139 -0
  9. package/android/src/main/java/com/reactnativestripesdk/CurrencySelectorElementViewManager.kt +59 -0
  10. package/android/src/main/java/com/reactnativestripesdk/EmbeddedPaymentElementView.kt +105 -49
  11. package/android/src/main/java/com/reactnativestripesdk/EmbeddedPaymentElementViewManager.kt +72 -12
  12. package/android/src/main/java/com/reactnativestripesdk/EventEmitterCompat.kt +4 -0
  13. package/android/src/main/java/com/reactnativestripesdk/FinancialConnectionsSheetManager.kt +8 -4
  14. package/android/src/main/java/com/reactnativestripesdk/GooglePayButtonManager.kt +2 -1
  15. package/android/src/main/java/com/reactnativestripesdk/GooglePayButtonView.kt +26 -11
  16. package/android/src/main/java/com/reactnativestripesdk/GooglePayLauncherManager.kt +2 -1
  17. package/android/src/main/java/com/reactnativestripesdk/NavigationBarView.kt +14 -5
  18. package/android/src/main/java/com/reactnativestripesdk/PaymentElementConfig.kt +6 -2
  19. package/android/src/main/java/com/reactnativestripesdk/PaymentLauncherManager.kt +2 -1
  20. package/android/src/main/java/com/reactnativestripesdk/PaymentMethodCreateParamsFactory.kt +2 -1
  21. package/android/src/main/java/com/reactnativestripesdk/PaymentMethodMessagingElementConfig.kt +6 -2
  22. package/android/src/main/java/com/reactnativestripesdk/PaymentMethodMessagingElementViewManager.kt +2 -1
  23. package/android/src/main/java/com/reactnativestripesdk/PaymentOptionDisplayDataMapper.kt +8 -4
  24. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetAppearance.kt +9 -3
  25. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetManager.kt +118 -48
  26. package/android/src/main/java/com/reactnativestripesdk/StripeAbstractComposeView.kt +1 -0
  27. package/android/src/main/java/com/reactnativestripesdk/StripeSdkModule.kt +281 -46
  28. package/android/src/main/java/com/reactnativestripesdk/StripeSdkPackage.kt +2 -0
  29. package/android/src/main/java/com/reactnativestripesdk/addresssheet/AddressLauncherManager.kt +2 -1
  30. package/android/src/main/java/com/reactnativestripesdk/addresssheet/AddressSheetView.kt +3 -1
  31. package/android/src/main/java/com/reactnativestripesdk/customersheet/CustomerSheetManager.kt +8 -18
  32. package/android/src/main/java/com/reactnativestripesdk/customersheet/ReactNativeCustomerAdapter.kt +3 -1
  33. package/android/src/main/java/com/reactnativestripesdk/customersheet/ReactNativeCustomerSessionProvider.kt +2 -1
  34. package/android/src/main/java/com/reactnativestripesdk/pushprovisioning/AddToWalletButtonManager.kt +2 -1
  35. package/android/src/main/java/com/reactnativestripesdk/utils/CheckoutAddressUpdate.kt +45 -0
  36. package/android/src/main/java/com/reactnativestripesdk/utils/CheckoutMappers.kt +127 -0
  37. package/android/src/main/java/com/reactnativestripesdk/utils/DefaultActivityLifecycleCallbacks.kt +41 -0
  38. package/android/src/main/java/com/reactnativestripesdk/utils/Errors.kt +4 -2
  39. package/android/src/main/java/com/reactnativestripesdk/utils/Extensions.kt +5 -1
  40. package/android/src/main/java/com/reactnativestripesdk/utils/Mappers.kt +29 -13
  41. package/android/src/main/java/com/reactnativestripesdk/utils/PostalCodeUtilities.kt +2 -1
  42. package/android/src/oldarch/java/com/facebook/react/viewmanagers/EmbeddedPaymentElementViewManagerDelegate.java +6 -0
  43. package/android/src/oldarch/java/com/facebook/react/viewmanagers/EmbeddedPaymentElementViewManagerInterface.java +2 -0
  44. package/android/src/oldarch/java/com/facebook/react/viewmanagers/StripeCurrencySelectorElementManagerDelegate.java +35 -0
  45. package/android/src/oldarch/java/com/facebook/react/viewmanagers/StripeCurrencySelectorElementManagerInterface.java +18 -0
  46. package/android/src/oldarch/java/com/reactnativestripesdk/NativeOnrampSdkModuleSpec.java +17 -3
  47. package/android/src/oldarch/java/com/reactnativestripesdk/NativeStripeSdkModuleSpec.java +13 -1
  48. package/android/src/onramp/java/com/reactnativestripesdk/OnrampMappers.kt +116 -0
  49. package/android/src/onramp/java/com/reactnativestripesdk/OnrampSdkModule.kt +109 -1
  50. package/android/src/test/java/com/reactnativestripesdk/DrawableLoadingTest.kt +6 -2
  51. package/android/src/test/java/com/reactnativestripesdk/mappers/MappersTest.kt +60 -0
  52. package/android/src/test/java/com/reactnativestripesdk/mappers/OnrampMappersTest.kt +145 -0
  53. package/android/src/test/java/com/reactnativestripesdk/mappers/PaymentOptionDisplayDataMapperTest.kt +9 -4
  54. package/android/src/test/java/com/reactnativestripesdk/utils/CheckoutMappersTest.kt +98 -0
  55. package/android/src/test/java/com/reactnativestripesdk/utils/CheckoutTestFixtures.java +57 -0
  56. package/ios/ConnectAccountOnboarding/ConnectAccountOnboardingViewController.swift +6 -8
  57. package/ios/CurrencySelectorElementManager.m +16 -0
  58. package/ios/CurrencySelectorElementView.swift +159 -0
  59. package/ios/EmbeddedPaymentElementView.swift +1 -1
  60. package/ios/Mappers+Checkout.swift +337 -0
  61. package/ios/Mappers.swift +90 -2
  62. package/ios/NewArch/EmbeddedPaymentElementViewComponentView.mm +16 -2
  63. package/ios/NewArch/StripeCurrencySelectorElementComponentView.h +10 -0
  64. package/ios/NewArch/StripeCurrencySelectorElementComponentView.mm +89 -0
  65. package/ios/OldArch/StripeSdkEventEmitterCompat.h +1 -0
  66. package/ios/OldArch/StripeSdkEventEmitterCompat.m +6 -0
  67. package/ios/PaymentOptionDisplayData+ReactNative.swift +1 -1
  68. package/ios/PaymentSheetAppearance.swift +1 -1
  69. package/ios/StripeOnrampSdk.mm +19 -0
  70. package/ios/StripeSdk.mm +136 -0
  71. package/ios/StripeSdkEmitter.swift +1 -0
  72. package/ios/StripeSdkImpl+Checkout.swift +360 -0
  73. package/ios/StripeSdkImpl+CustomerSheet.swift +1 -1
  74. package/ios/StripeSdkImpl+Embedded.swift +108 -27
  75. package/ios/StripeSdkImpl+PaymentSheet.swift +18 -2
  76. package/ios/StripeSdkImpl.swift +89 -7
  77. package/jest/mock.js +13 -1
  78. package/lib/commonjs/components/AddToWalletButton.js +1 -1
  79. package/lib/commonjs/components/AddToWalletButton.js.map +1 -1
  80. package/lib/commonjs/components/AddressSheet.js +1 -1
  81. package/lib/commonjs/components/AddressSheet.js.map +1 -1
  82. package/lib/commonjs/components/AuBECSDebitForm.js +1 -1
  83. package/lib/commonjs/components/AuBECSDebitForm.js.map +1 -1
  84. package/lib/commonjs/components/CardField.js +1 -1
  85. package/lib/commonjs/components/CardField.js.map +1 -1
  86. package/lib/commonjs/components/CardForm.js +1 -1
  87. package/lib/commonjs/components/CardForm.js.map +1 -1
  88. package/lib/commonjs/components/CurrencySelectorElement.js +2 -0
  89. package/lib/commonjs/components/CurrencySelectorElement.js.map +1 -0
  90. package/lib/commonjs/components/PaymentMethodMessagingElement.js +1 -1
  91. package/lib/commonjs/components/PaymentMethodMessagingElement.js.map +1 -1
  92. package/lib/commonjs/components/PlatformPayButton.js +1 -1
  93. package/lib/commonjs/components/PlatformPayButton.js.map +1 -1
  94. package/lib/commonjs/components/StripeContainer.js +1 -1
  95. package/lib/commonjs/components/StripeContainer.js.map +1 -1
  96. package/lib/commonjs/connect/Components.js +1 -1
  97. package/lib/commonjs/connect/Components.js.map +1 -1
  98. package/lib/commonjs/connect/ConnectComponentsProvider.js +1 -1
  99. package/lib/commonjs/connect/ConnectComponentsProvider.js.map +1 -1
  100. package/lib/commonjs/connect/EmbeddedComponent.js +1 -1
  101. package/lib/commonjs/connect/EmbeddedComponent.js.map +1 -1
  102. package/lib/commonjs/connect/ModalCloseButton.js +1 -1
  103. package/lib/commonjs/connect/ModalCloseButton.js.map +1 -1
  104. package/lib/commonjs/connect/NavigationBar.js +1 -1
  105. package/lib/commonjs/connect/NavigationBar.js.map +1 -1
  106. package/lib/commonjs/events.js.map +1 -1
  107. package/lib/commonjs/functions.js +1 -1
  108. package/lib/commonjs/functions.js.map +1 -1
  109. package/lib/commonjs/helpers.js +1 -1
  110. package/lib/commonjs/hooks/useCheckout.js +1 -1
  111. package/lib/commonjs/hooks/useCheckout.js.map +1 -1
  112. package/lib/commonjs/hooks/useOnramp.js +1 -1
  113. package/lib/commonjs/hooks/useOnramp.js.map +1 -1
  114. package/lib/commonjs/specs/NativeAddToWalletButton.js +1 -1
  115. package/lib/commonjs/specs/NativeAddressSheet.js +1 -1
  116. package/lib/commonjs/specs/NativeApplePayButton.js +1 -1
  117. package/lib/commonjs/specs/NativeAuBECSDebitForm.js +1 -1
  118. package/lib/commonjs/specs/NativeCardField.js +1 -1
  119. package/lib/commonjs/specs/NativeCardField.js.map +1 -1
  120. package/lib/commonjs/specs/NativeCardForm.js +1 -1
  121. package/lib/commonjs/specs/NativeCardForm.js.map +1 -1
  122. package/lib/commonjs/specs/NativeConnectAccountOnboardingView.js +1 -1
  123. package/lib/commonjs/specs/NativeCurrencySelectorElement.js +2 -0
  124. package/lib/commonjs/specs/NativeCurrencySelectorElement.js.map +1 -0
  125. package/lib/commonjs/specs/NativeEmbeddedPaymentElement.js +1 -1
  126. package/lib/commonjs/specs/NativeEmbeddedPaymentElement.js.map +1 -1
  127. package/lib/commonjs/specs/NativeGooglePayButton.js +1 -1
  128. package/lib/commonjs/specs/NativeNavigationBar.js +1 -1
  129. package/lib/commonjs/specs/NativeOnrampSdkModule.js.map +1 -1
  130. package/lib/commonjs/specs/NativePaymentMethodMessagingElement.js +1 -1
  131. package/lib/commonjs/specs/NativeStripeContainer.js +1 -1
  132. package/lib/commonjs/specs/NativeStripeSdkModule.js.map +1 -1
  133. package/lib/commonjs/types/EmbeddedPaymentElement.js +1 -1
  134. package/lib/commonjs/types/EmbeddedPaymentElement.js.map +1 -1
  135. package/lib/module/components/AddToWalletButton.js +1 -1
  136. package/lib/module/components/AddToWalletButton.js.map +1 -1
  137. package/lib/module/components/AddressSheet.js +1 -1
  138. package/lib/module/components/AddressSheet.js.map +1 -1
  139. package/lib/module/components/AuBECSDebitForm.js +1 -1
  140. package/lib/module/components/AuBECSDebitForm.js.map +1 -1
  141. package/lib/module/components/CardField.js +1 -1
  142. package/lib/module/components/CardField.js.map +1 -1
  143. package/lib/module/components/CardForm.js +1 -1
  144. package/lib/module/components/CardForm.js.map +1 -1
  145. package/lib/module/components/CurrencySelectorElement.js +2 -0
  146. package/lib/module/components/CurrencySelectorElement.js.map +1 -0
  147. package/lib/module/components/PaymentMethodMessagingElement.js +1 -1
  148. package/lib/module/components/PaymentMethodMessagingElement.js.map +1 -1
  149. package/lib/module/components/PlatformPayButton.js +1 -1
  150. package/lib/module/components/PlatformPayButton.js.map +1 -1
  151. package/lib/module/components/StripeContainer.js +1 -1
  152. package/lib/module/components/StripeContainer.js.map +1 -1
  153. package/lib/module/connect/Components.js +1 -1
  154. package/lib/module/connect/Components.js.map +1 -1
  155. package/lib/module/connect/ConnectComponentsProvider.js +1 -1
  156. package/lib/module/connect/ConnectComponentsProvider.js.map +1 -1
  157. package/lib/module/connect/EmbeddedComponent.js +1 -1
  158. package/lib/module/connect/EmbeddedComponent.js.map +1 -1
  159. package/lib/module/connect/ModalCloseButton.js +1 -1
  160. package/lib/module/connect/ModalCloseButton.js.map +1 -1
  161. package/lib/module/connect/NavigationBar.js +1 -1
  162. package/lib/module/connect/NavigationBar.js.map +1 -1
  163. package/lib/module/events.js.map +1 -1
  164. package/lib/module/functions.js +1 -1
  165. package/lib/module/functions.js.map +1 -1
  166. package/lib/module/helpers.js +1 -1
  167. package/lib/module/hooks/useCheckout.js +1 -1
  168. package/lib/module/hooks/useCheckout.js.map +1 -1
  169. package/lib/module/hooks/useOnramp.js +1 -1
  170. package/lib/module/hooks/useOnramp.js.map +1 -1
  171. package/lib/module/specs/NativeAddToWalletButton.js +1 -1
  172. package/lib/module/specs/NativeAddressSheet.js +1 -1
  173. package/lib/module/specs/NativeApplePayButton.js +1 -1
  174. package/lib/module/specs/NativeAuBECSDebitForm.js +1 -1
  175. package/lib/module/specs/NativeCardField.js +1 -1
  176. package/lib/module/specs/NativeCardField.js.map +1 -1
  177. package/lib/module/specs/NativeCardForm.js +1 -1
  178. package/lib/module/specs/NativeCardForm.js.map +1 -1
  179. package/lib/module/specs/NativeConnectAccountOnboardingView.js +1 -1
  180. package/lib/module/specs/NativeCurrencySelectorElement.js +2 -0
  181. package/lib/module/specs/NativeCurrencySelectorElement.js.map +1 -0
  182. package/lib/module/specs/NativeEmbeddedPaymentElement.js +1 -1
  183. package/lib/module/specs/NativeEmbeddedPaymentElement.js.map +1 -1
  184. package/lib/module/specs/NativeGooglePayButton.js +1 -1
  185. package/lib/module/specs/NativeNavigationBar.js +1 -1
  186. package/lib/module/specs/NativeOnrampSdkModule.js.map +1 -1
  187. package/lib/module/specs/NativePaymentMethodMessagingElement.js +1 -1
  188. package/lib/module/specs/NativeStripeContainer.js +1 -1
  189. package/lib/module/specs/NativeStripeSdkModule.js.map +1 -1
  190. package/lib/module/types/EmbeddedPaymentElement.js +1 -1
  191. package/lib/module/types/EmbeddedPaymentElement.js.map +1 -1
  192. package/lib/typescript/src/components/CurrencySelectorElement.d.ts +62 -0
  193. package/lib/typescript/src/components/CurrencySelectorElement.d.ts.map +1 -0
  194. package/lib/typescript/src/components/PaymentMethodMessagingElement.d.ts +1 -1
  195. package/lib/typescript/src/components/PaymentMethodMessagingElement.d.ts.map +1 -1
  196. package/lib/typescript/src/events.d.ts +11 -0
  197. package/lib/typescript/src/events.d.ts.map +1 -1
  198. package/lib/typescript/src/functions.d.ts.map +1 -1
  199. package/lib/typescript/src/hooks/useCheckout.d.ts.map +1 -1
  200. package/lib/typescript/src/hooks/useOnramp.d.ts +22 -0
  201. package/lib/typescript/src/hooks/useOnramp.d.ts.map +1 -1
  202. package/lib/typescript/src/specs/NativeCurrencySelectorElement.d.ts +25 -0
  203. package/lib/typescript/src/specs/NativeCurrencySelectorElement.d.ts.map +1 -0
  204. package/lib/typescript/src/specs/NativeEmbeddedPaymentElement.d.ts +5 -1
  205. package/lib/typescript/src/specs/NativeEmbeddedPaymentElement.d.ts.map +1 -1
  206. package/lib/typescript/src/specs/NativeOnrampSdkModule.d.ts +3 -0
  207. package/lib/typescript/src/specs/NativeOnrampSdkModule.d.ts.map +1 -1
  208. package/lib/typescript/src/specs/NativeStripeSdkModule.d.ts +5 -2
  209. package/lib/typescript/src/specs/NativeStripeSdkModule.d.ts.map +1 -1
  210. package/lib/typescript/src/types/Checkout.d.ts +268 -86
  211. package/lib/typescript/src/types/Checkout.d.ts.map +1 -1
  212. package/lib/typescript/src/types/EmbeddedPaymentElement.d.ts +36 -1
  213. package/lib/typescript/src/types/EmbeddedPaymentElement.d.ts.map +1 -1
  214. package/lib/typescript/src/types/Onramp.d.ts +94 -0
  215. package/lib/typescript/src/types/Onramp.d.ts.map +1 -1
  216. package/package.json +16 -4
  217. package/src/components/CurrencySelectorElement.tsx +95 -0
  218. package/src/components/PaymentMethodMessagingElement.tsx +54 -52
  219. package/src/events.ts +11 -0
  220. package/src/functions.ts +30 -1
  221. package/src/hooks/useCheckout.tsx +129 -74
  222. package/src/hooks/useOnramp.tsx +44 -0
  223. package/src/specs/NativeCurrencySelectorElement.ts +35 -0
  224. package/src/specs/NativeEmbeddedPaymentElement.ts +12 -2
  225. package/src/specs/NativeOnrampSdkModule.ts +5 -0
  226. package/src/specs/NativeStripeSdkModule.ts +16 -2
  227. package/src/types/Checkout.ts +291 -86
  228. package/src/types/EmbeddedPaymentElement.tsx +117 -26
  229. package/src/types/Onramp.ts +109 -0
  230. package/stripe-react-native.podspec +1 -1
  231. package/android/.idea/AndroidProjectSystem.xml +0 -6
  232. package/android/.idea/caches/deviceStreaming.xml +0 -835
  233. package/android/.idea/compiler.xml +0 -6
  234. package/android/.idea/gradle.xml +0 -17
  235. package/android/.idea/migrations.xml +0 -10
  236. package/android/.idea/misc.xml +0 -10
  237. package/android/.idea/runConfigurations.xml +0 -17
  238. package/android/.idea/vcs.xml +0 -6
  239. package/android/local.properties +0 -8
@@ -7,10 +7,12 @@ import android.app.Application
7
7
  import androidx.activity.ComponentActivity
8
8
  import androidx.fragment.app.FragmentActivity
9
9
  import androidx.lifecycle.SavedStateHandle
10
+ import com.stripe.android.core.model.CountryCode
10
11
  import com.facebook.react.bridge.Arguments
11
12
  import com.facebook.react.bridge.Promise
12
13
  import com.facebook.react.bridge.ReactApplicationContext
13
14
  import com.facebook.react.bridge.ReactMethod
15
+ import com.facebook.react.bridge.ReadableArray
14
16
  import com.facebook.react.bridge.ReadableMap
15
17
  import com.facebook.react.bridge.WritableNativeMap
16
18
  import com.facebook.react.module.annotations.ReactModule
@@ -23,6 +25,7 @@ import com.reactnativestripesdk.utils.createMissingActivityError
23
25
  import com.reactnativestripesdk.utils.createMissingInitError
24
26
  import com.reactnativestripesdk.utils.createOnrampNotConfiguredError
25
27
  import com.reactnativestripesdk.utils.createResult
28
+ import com.reactnativestripesdk.utils.getStringList
26
29
  import com.reactnativestripesdk.utils.getValOr
27
30
  import com.reactnativestripesdk.utils.mapToPaymentSheetAddress
28
31
  import com.stripe.android.crypto.onramp.ExperimentalCryptoOnramp
@@ -37,10 +40,13 @@ import com.stripe.android.crypto.onramp.model.OnrampCheckoutResult
37
40
  import com.stripe.android.crypto.onramp.model.OnrampCollectPaymentMethodResult
38
41
  import com.stripe.android.crypto.onramp.model.OnrampConfigurationResult
39
42
  import com.stripe.android.crypto.onramp.model.OnrampCreateCryptoPaymentTokenResult
43
+ import com.stripe.android.crypto.onramp.model.OnrampCrsCarfDeclarationResult
40
44
  import com.stripe.android.crypto.onramp.model.OnrampHasLinkAccountResult
41
45
  import com.stripe.android.crypto.onramp.model.OnrampLogOutResult
42
46
  import com.stripe.android.crypto.onramp.model.OnrampRegisterLinkUserResult
43
47
  import com.stripe.android.crypto.onramp.model.OnrampRegisterWalletAddressResult
48
+ import com.stripe.android.crypto.onramp.model.OnrampRetrieveMissingIdentifiersResult
49
+ import com.stripe.android.crypto.onramp.model.OnrampSubmitIdentifiersResult
44
50
  import com.stripe.android.crypto.onramp.model.OnrampTokenAuthenticationResult
45
51
  import com.stripe.android.crypto.onramp.model.OnrampUpdatePhoneNumberResult
46
52
  import com.stripe.android.crypto.onramp.model.OnrampVerifyIdentityResult
@@ -78,6 +84,7 @@ class OnrampSdkModule(
78
84
  private var authorizePromise: Promise? = null
79
85
  private var checkoutPromise: Promise? = null
80
86
  private var verifyKycPromise: Promise? = null
87
+ private var crsCarfDeclarationPromise: Promise? = null
81
88
 
82
89
  private var checkoutClientSecretDeferred: CompletableDeferred<String>? = null
83
90
  private val rnScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
@@ -141,6 +148,10 @@ class OnrampSdkModule(
141
148
  handleOnrampCheckoutResult(result, checkoutPromise!!)
142
149
  }.verifyKycCallback { result ->
143
150
  handleOnrampKycVerificationResult(result, verifyKycPromise!!)
151
+ }.crsCarfDeclarationCallback { result ->
152
+ crsCarfDeclarationPromise?.let {
153
+ handleOnrampCrsCarfDeclarationResult(result, it)
154
+ }
144
155
  }.onrampSessionClientSecretProvider { sessionId ->
145
156
  checkoutClientSecretDeferred = CompletableDeferred()
146
157
 
@@ -311,10 +322,16 @@ class OnrampSdkModule(
311
322
  )
312
323
  } else {
313
324
  null
314
- }
325
+ }
315
326
 
316
327
  val addressMap = kycInfo.getMap("address")
317
328
  val addressObj = mapToPaymentSheetAddress(addressMap)
329
+ val birthCountry = kycInfo.getString("birthCountry")?.let(CountryCode::create)
330
+ val birthCity = kycInfo.getString("birthCity")
331
+ val nationalities =
332
+ kycInfo.getStringList("nationalities")
333
+ ?.map(CountryCode::create)
334
+ ?.takeIf { it.isNotEmpty() }
318
335
 
319
336
  val kycInfoObj =
320
337
  KycInfo(
@@ -323,6 +340,9 @@ class OnrampSdkModule(
323
340
  idNumber = idNumber,
324
341
  dateOfBirth = dob,
325
342
  address = addressObj,
343
+ birthCountry = birthCountry,
344
+ birthCity = birthCity,
345
+ nationalities = nationalities,
326
346
  )
327
347
 
328
348
  when (val result = coordinator.attachKycInfo(kycInfoObj)) {
@@ -336,6 +356,75 @@ class OnrampSdkModule(
336
356
  }
337
357
  }
338
358
 
359
+ @ReactMethod
360
+ override fun retrieveMissingIdentifiers(promise: Promise) {
361
+ val coordinator =
362
+ onrampCoordinator ?: run {
363
+ promise.resolve(createOnrampNotConfiguredError())
364
+ return
365
+ }
366
+
367
+ CoroutineScope(Dispatchers.IO).launch {
368
+ when (val result = coordinator.retrieveMissingIdentifiers()) {
369
+ is OnrampRetrieveMissingIdentifiersResult.Completed -> {
370
+ promise.resolve(mapFromComplianceIdentifierRequirements(result.requirements))
371
+ }
372
+ is OnrampRetrieveMissingIdentifiersResult.Failed -> {
373
+ promise.resolve(createFailedError(result.error))
374
+ }
375
+ }
376
+ }
377
+ }
378
+
379
+ @ReactMethod
380
+ override fun submitIdentifiers(
381
+ identifiers: ReadableArray,
382
+ promise: Promise,
383
+ ) {
384
+ val coordinator =
385
+ onrampCoordinator ?: run {
386
+ promise.resolve(createOnrampNotConfiguredError())
387
+ return
388
+ }
389
+
390
+ val complianceIdentifiers =
391
+ try {
392
+ mapToComplianceIdentifiers(identifiers)
393
+ } catch (error: IllegalArgumentException) {
394
+ val errorType =
395
+ if (error is ComplianceIdentifierFieldException) {
396
+ ErrorType.Unknown
397
+ } else {
398
+ ErrorType.Failed
399
+ }
400
+ promise.resolve(createError(errorType.toString(), error.message ?: "Invalid identifiers"))
401
+ return
402
+ }
403
+
404
+ CoroutineScope(Dispatchers.IO).launch {
405
+ when (val result = coordinator.submitIdentifiers(complianceIdentifiers)) {
406
+ is OnrampSubmitIdentifiersResult.Completed -> {
407
+ promise.resolve(mapFromSubmitIdentifiersResult(result.result))
408
+ }
409
+ is OnrampSubmitIdentifiersResult.Failed -> {
410
+ promise.resolve(createFailedError(result.error))
411
+ }
412
+ }
413
+ }
414
+ }
415
+
416
+ @ReactMethod
417
+ override fun presentCRSCARFDeclaration(promise: Promise) {
418
+ val presenter =
419
+ onrampPresenter ?: run {
420
+ promise.resolve(createOnrampNotConfiguredError())
421
+ return
422
+ }
423
+
424
+ crsCarfDeclarationPromise = promise
425
+ presenter.presentCrsCarfDeclaration()
426
+ }
427
+
339
428
  @ReactMethod
340
429
  override fun updatePhoneNumber(
341
430
  phone: String,
@@ -689,6 +778,25 @@ class OnrampSdkModule(
689
778
  }
690
779
  }
691
780
 
781
+ private fun handleOnrampCrsCarfDeclarationResult(
782
+ result: OnrampCrsCarfDeclarationResult,
783
+ promise: Promise,
784
+ ) {
785
+ when (result) {
786
+ is OnrampCrsCarfDeclarationResult.Confirmed -> {
787
+ promise.resolve(
788
+ WritableNativeMap().apply { putString("status", "Confirmed") },
789
+ )
790
+ }
791
+ is OnrampCrsCarfDeclarationResult.Cancelled -> {
792
+ promise.resolve(createCanceledError("CRS/CARF declaration was cancelled"))
793
+ }
794
+ is OnrampCrsCarfDeclarationResult.Failed -> {
795
+ promise.resolve(createFailedError(result.error))
796
+ }
797
+ }
798
+ }
799
+
692
800
  private fun handleOnrampCollectPaymentResult(
693
801
  result: OnrampCollectPaymentMethodResult,
694
802
  promise: Promise,
@@ -41,9 +41,13 @@ class DrawableLoadingTest {
41
41
  canvas.drawColor(Color.RED)
42
42
  }
43
43
 
44
- override fun setAlpha(alpha: Int) {}
44
+ override fun setAlpha(alpha: Int) {
45
+ // NO-OP
46
+ }
45
47
 
46
- override fun setColorFilter(colorFilter: ColorFilter?) {}
48
+ override fun setColorFilter(colorFilter: ColorFilter?) {
49
+ // NO-OP
50
+ }
47
51
 
48
52
  override fun getOpacity(): Int = PixelFormat.OPAQUE
49
53
  }
@@ -2,6 +2,7 @@ package com.reactnativestripesdk.mappers
2
2
 
3
3
  import android.annotation.SuppressLint
4
4
  import com.facebook.react.bridge.WritableMap
5
+ import com.reactnativestripesdk.utils.buildCheckoutAddressUpdate
5
6
  import com.reactnativestripesdk.utils.createCanAddCardResult
6
7
  import com.reactnativestripesdk.utils.mapNextAction
7
8
  import com.reactnativestripesdk.utils.mapPaymentMethodType
@@ -348,6 +349,65 @@ class MappersTest {
348
349
  assertEquals("cpmt_valid", result[0].id)
349
350
  }
350
351
 
352
+ // ============================================
353
+ // buildCheckoutAddressUpdate Tests
354
+ // ============================================
355
+
356
+ @Test
357
+ fun buildCheckoutAddressUpdate_TrimsFields() {
358
+ val update =
359
+ buildCheckoutAddressUpdate(
360
+ name = " Jane Doe ",
361
+ phone = " 5551234567 ",
362
+ address =
363
+ readableMapOf(
364
+ "country" to " US ",
365
+ "line1" to " 123 Main St ",
366
+ "line2" to " Apt 4 ",
367
+ "city" to " San Francisco ",
368
+ "state" to " CA ",
369
+ "postalCode" to " 94111 ",
370
+ ),
371
+ )
372
+
373
+ assertNotNull(update)
374
+ assertEquals("Jane Doe", update!!.name)
375
+ assertEquals("5551234567", update.phone)
376
+ assertEquals("US", update.country)
377
+ assertEquals("123 Main St", update.line1)
378
+ assertEquals("Apt 4", update.line2)
379
+ assertEquals("San Francisco", update.city)
380
+ assertEquals("CA", update.state)
381
+ assertEquals("94111", update.postalCode)
382
+ }
383
+
384
+ @Test
385
+ fun buildCheckoutAddressUpdate_RequiresCountry() {
386
+ val withoutCountry =
387
+ buildCheckoutAddressUpdate(
388
+ name = "Jane Doe",
389
+ phone = "5551234567",
390
+ address =
391
+ readableMapOf(
392
+ "line1" to "123 Main St",
393
+ "city" to "San Francisco",
394
+ ),
395
+ )
396
+
397
+ val blankCountry =
398
+ buildCheckoutAddressUpdate(
399
+ name = "Jane Doe",
400
+ phone = "5551234567",
401
+ address =
402
+ readableMapOf(
403
+ "country" to " ",
404
+ ),
405
+ )
406
+
407
+ assertNull(withoutCountry)
408
+ assertNull(blankCountry)
409
+ }
410
+
351
411
  // ============================================
352
412
  // mapToAddress Tests
353
413
  // ============================================
@@ -4,13 +4,20 @@ package com.reactnativestripesdk.mappers
4
4
 
5
5
  import android.annotation.SuppressLint
6
6
  import androidx.compose.ui.graphics.toArgb
7
+ import com.reactnativestripesdk.ComplianceIdentifierFieldException
8
+ import com.reactnativestripesdk.InvalidIdentifiersArrayException
7
9
  import com.reactnativestripesdk.mapAppearance
8
10
  import com.reactnativestripesdk.mapConfig
9
11
  import com.reactnativestripesdk.mapFromKycInfo
10
12
  import com.reactnativestripesdk.mapGooglePayConfig
13
+ import com.reactnativestripesdk.mapPaymentDetailsType
14
+ import com.reactnativestripesdk.mapToComplianceIdentifiers
15
+ import com.reactnativestripesdk.utils.readableArrayOf
11
16
  import com.reactnativestripesdk.utils.readableMapOf
17
+ import com.stripe.android.core.model.CountryCode
12
18
  import com.stripe.android.crypto.onramp.ExperimentalCryptoOnramp
13
19
  import com.stripe.android.crypto.onramp.model.KycInfo
20
+ import com.stripe.android.crypto.onramp.model.PaymentMethodDisplayData
14
21
  import com.stripe.android.googlepaylauncher.GooglePayEnvironment
15
22
  import com.stripe.android.googlepaylauncher.GooglePayPaymentMethodLauncher
16
23
  import com.stripe.android.link.LinkAppearance.Style
@@ -20,12 +27,14 @@ import org.junit.Assert.assertEquals
20
27
  import org.junit.Assert.assertFalse
21
28
  import org.junit.Assert.assertNotNull
22
29
  import org.junit.Assert.assertNull
30
+ import org.junit.Assert.assertThrows
23
31
  import org.junit.Assert.assertTrue
24
32
  import org.junit.Test
25
33
  import org.junit.runner.RunWith
26
34
  import org.robolectric.RobolectricTestRunner
27
35
 
28
36
  @SuppressLint("RestrictedApi")
37
+ @Suppress("LargeClass")
29
38
  @RunWith(RobolectricTestRunner::class)
30
39
  class OnrampMappersTest {
31
40
  @Test
@@ -363,6 +372,35 @@ class OnrampMappersTest {
363
372
  assertNull(state.primaryButton.heightDp)
364
373
  }
365
374
 
375
+ @Test
376
+ fun mapAppearance_WithPrimaryButton_HeightOnly() {
377
+ val primaryButton =
378
+ readableMapOf(
379
+ "height" to 48.0,
380
+ )
381
+ val appearanceMap =
382
+ readableMapOf(
383
+ "primaryButton" to primaryButton,
384
+ )
385
+ val state = mapAppearance(appearanceMap).build()
386
+
387
+ assertNull(state.primaryButton.cornerRadiusDp)
388
+ assertEquals(48f, state.primaryButton.heightDp)
389
+ }
390
+
391
+ @Test
392
+ fun mapAppearance_WithPrimaryButton_EmptyMap() {
393
+ val primaryButton = readableMapOf()
394
+ val appearanceMap =
395
+ readableMapOf(
396
+ "primaryButton" to primaryButton,
397
+ )
398
+ val state = mapAppearance(appearanceMap).build()
399
+
400
+ assertNull(state.primaryButton.cornerRadiusDp)
401
+ assertNull(state.primaryButton.heightDp)
402
+ }
403
+
366
404
  @Test
367
405
  fun mapAppearance_FullConfig() {
368
406
  val lightColors =
@@ -405,6 +443,13 @@ class OnrampMappersTest {
405
443
  assertEquals(48f, state.primaryButton.heightDp)
406
444
  }
407
445
 
446
+ @Test
447
+ fun mapPaymentDetailsType_MapsAllSupportedTypes() {
448
+ assertEquals("Card", mapPaymentDetailsType(PaymentMethodDisplayData.Type.Card))
449
+ assertEquals("BankAccount", mapPaymentDetailsType(PaymentMethodDisplayData.Type.BankAccount))
450
+ assertEquals("GooglePay", mapPaymentDetailsType(PaymentMethodDisplayData.Type.GooglePay))
451
+ }
452
+
408
453
  @Test
409
454
  fun mapFromKycInfo_AllFields() {
410
455
  val kycInfo =
@@ -422,6 +467,13 @@ class OnrampMappersTest {
422
467
  state = "CA",
423
468
  ),
424
469
  dateOfBirth = DateOfBirth(day = 15, month = 6, year = 1990),
470
+ birthCountry = CountryCode.create("FR"),
471
+ birthCity = "Paris",
472
+ nationalities =
473
+ listOf(
474
+ CountryCode.create("FR"),
475
+ CountryCode.create("DE"),
476
+ ),
425
477
  )
426
478
  val result = mapFromKycInfo(kycInfo)
427
479
 
@@ -443,6 +495,14 @@ class OnrampMappersTest {
443
495
  assertEquals(15, dob!!.getInt("day"))
444
496
  assertEquals(6, dob.getInt("month"))
445
497
  assertEquals(1990, dob.getInt("year"))
498
+
499
+ assertEquals("FR", result.getString("birthCountry"))
500
+ assertEquals("Paris", result.getString("birthCity"))
501
+
502
+ val nationalities = result.getArray("nationalities")
503
+ assertNotNull(nationalities)
504
+ assertEquals("FR", nationalities!!.getString(0))
505
+ assertEquals("DE", nationalities.getString(1))
446
506
  }
447
507
 
448
508
  @Test
@@ -454,6 +514,9 @@ class OnrampMappersTest {
454
514
  idNumber = null,
455
515
  address = null,
456
516
  dateOfBirth = null,
517
+ birthCountry = null,
518
+ birthCity = null,
519
+ nationalities = null,
457
520
  )
458
521
  val result = mapFromKycInfo(kycInfo)
459
522
 
@@ -462,6 +525,9 @@ class OnrampMappersTest {
462
525
  assertFalse(result.hasKey("idNumber"))
463
526
  assertFalse(result.hasKey("address"))
464
527
  assertFalse(result.hasKey("dateOfBirth"))
528
+ assertFalse(result.hasKey("birthCountry"))
529
+ assertFalse(result.hasKey("birthCity"))
530
+ assertFalse(result.hasKey("nationalities"))
465
531
  }
466
532
 
467
533
  @Test
@@ -473,6 +539,9 @@ class OnrampMappersTest {
473
539
  idNumber = null,
474
540
  address = null,
475
541
  dateOfBirth = DateOfBirth(day = 1, month = 1, year = 2000),
542
+ birthCountry = CountryCode.create("IT"),
543
+ birthCity = "Rome",
544
+ nationalities = listOf(CountryCode.create("IT")),
476
545
  )
477
546
  val result = mapFromKycInfo(kycInfo)
478
547
 
@@ -486,6 +555,9 @@ class OnrampMappersTest {
486
555
  assertEquals(1, dob!!.getInt("day"))
487
556
  assertEquals(1, dob.getInt("month"))
488
557
  assertEquals(2000, dob.getInt("year"))
558
+ assertEquals("IT", result.getString("birthCountry"))
559
+ assertEquals("Rome", result.getString("birthCity"))
560
+ assertEquals("IT", result.getArray("nationalities")!!.getString(0))
489
561
  }
490
562
 
491
563
  @Test
@@ -505,6 +577,9 @@ class OnrampMappersTest {
505
577
  state = null,
506
578
  ),
507
579
  dateOfBirth = null,
580
+ birthCountry = null,
581
+ birthCity = null,
582
+ nationalities = null,
508
583
  )
509
584
  val result = mapFromKycInfo(kycInfo)
510
585
 
@@ -517,4 +592,74 @@ class OnrampMappersTest {
517
592
  assertFalse(address.hasKey("postalCode"))
518
593
  assertFalse(address.hasKey("state"))
519
594
  }
595
+
596
+ @Test
597
+ fun mapToComplianceIdentifiers_ValidIdentifiers_ReturnsIdentifiers() {
598
+ val identifiers =
599
+ readableArrayOf(
600
+ readableMapOf(
601
+ "type" to " AT_STN ",
602
+ "value" to " 123456789 ",
603
+ ),
604
+ readableMapOf(
605
+ "type" to "DE_STN",
606
+ "value" to "987654321",
607
+ ),
608
+ )
609
+
610
+ val result = mapToComplianceIdentifiers(identifiers)
611
+
612
+ assertEquals(2, result.size)
613
+ }
614
+
615
+ @Test
616
+ fun mapToComplianceIdentifiers_BlankType_ThrowsFieldException() {
617
+ val identifiers =
618
+ readableArrayOf(
619
+ readableMapOf(
620
+ "type" to " ",
621
+ "value" to "123456789",
622
+ ),
623
+ )
624
+
625
+ val error =
626
+ assertThrows(ComplianceIdentifierFieldException::class.java) {
627
+ mapToComplianceIdentifiers(identifiers)
628
+ }
629
+
630
+ assertEquals("Invalid format for field: type", error.message)
631
+ }
632
+
633
+ @Test
634
+ fun mapToComplianceIdentifiers_BlankValue_ThrowsFieldException() {
635
+ val identifiers =
636
+ readableArrayOf(
637
+ readableMapOf(
638
+ "type" to "AT_STN",
639
+ "value" to " ",
640
+ ),
641
+ )
642
+
643
+ val error =
644
+ assertThrows(ComplianceIdentifierFieldException::class.java) {
645
+ mapToComplianceIdentifiers(identifiers)
646
+ }
647
+
648
+ assertEquals("Invalid format for field: value", error.message)
649
+ }
650
+
651
+ @Test
652
+ fun mapToComplianceIdentifiers_NonMapEntry_ThrowsInvalidArrayException() {
653
+ val identifiers = readableArrayOf("AT_STN")
654
+
655
+ val error =
656
+ assertThrows(InvalidIdentifiersArrayException::class.java) {
657
+ mapToComplianceIdentifiers(identifiers)
658
+ }
659
+
660
+ assertEquals(
661
+ "Unexpected format of identifiers array. Expected dictionaries with String keys.",
662
+ error.message,
663
+ )
664
+ }
520
665
  }
@@ -52,7 +52,8 @@ class PaymentOptionDisplayDataMapperTest {
52
52
  val result = annotatedString.toHtmlString()
53
53
 
54
54
  Assert.assertEquals(
55
- "By continuing, you agree to our <a href=\"https://stripe.com/privacy\">Privacy Policy</a> and <a href=\"https://stripe.com/terms\">Terms of Service</a>.",
55
+ "By continuing, you agree to our <a href=\"https://stripe.com/privacy\">Privacy Policy</a>" +
56
+ " and <a href=\"https://stripe.com/terms\">Terms of Service</a>.",
56
57
  result,
57
58
  )
58
59
  }
@@ -193,7 +194,8 @@ class PaymentOptionDisplayDataMapperTest {
193
194
  val result = annotatedString.toHtmlString()
194
195
 
195
196
  Assert.assertEquals(
196
- "Visit our <b><font color=\"#0000FF\"><a href=\"https://stripe.com/privacy\">Privacy Policy</a></font></b> for details",
197
+ "Visit our <b><font color=\"#0000FF\"><a href=\"https://stripe.com/privacy\">" +
198
+ "Privacy Policy</a></font></b> for details",
197
199
  result,
198
200
  )
199
201
  }
@@ -293,7 +295,8 @@ class PaymentOptionDisplayDataMapperTest {
293
295
  val result = annotatedString.toHtmlString()
294
296
 
295
297
  Assert.assertEquals(
296
- "Check <b><a href=\"https://stripe.com\">Stripe</a></b> and <i><font color=\"#00FF00\"><a href=\"https://github.com\">GitHub</a></font></i>",
298
+ "Check <b><a href=\"https://stripe.com\">Stripe</a></b> and <i><font color=\"#00FF00\">" +
299
+ "<a href=\"https://github.com\">GitHub</a></font></i>",
297
300
  result,
298
301
  )
299
302
  }
@@ -449,7 +452,9 @@ class PaymentOptionDisplayDataMapperTest {
449
452
  val result = annotatedString.toHtmlString()
450
453
 
451
454
  Assert.assertEquals(
452
- "By continuing, you agree to <b><font color=\"#0000FF\"><u><a href=\"https://stripe.com/terms\">Terms</a></u></font></b> and <i><font color=\"#FF0000\"><a href=\"https://stripe.com/privacy\">Privacy</a></font></i>. Important details are <span style=\"background-color: #FFFF00;\">highlighted</span>.",
455
+ "By continuing, you agree to <b><font color=\"#0000FF\"><u><a href=\"https://stripe.com/terms\">" +
456
+ "Terms</a></u></font></b> and <i><font color=\"#FF0000\"><a href=\"https://stripe.com/privacy\">" +
457
+ "Privacy</a></font></i>. Important details are <span style=\"background-color: #FFFF00;\">highlighted</span>.",
453
458
  result,
454
459
  )
455
460
  }
@@ -0,0 +1,98 @@
1
+ package com.reactnativestripesdk.utils
2
+
3
+ import com.stripe.android.paymentelement.CheckoutSessionPreview
4
+ import org.junit.Assert.assertEquals
5
+ import org.junit.Assert.assertFalse
6
+ import org.junit.Assert.assertNotNull
7
+ import org.junit.Assert.assertNull
8
+ import org.junit.Test
9
+ import org.junit.runner.RunWith
10
+ import org.robolectric.RobolectricTestRunner
11
+
12
+ @RunWith(RobolectricTestRunner::class)
13
+ @OptIn(CheckoutSessionPreview::class)
14
+ class CheckoutMappersTest {
15
+ @Test
16
+ fun mapFromCheckoutState_mapsLoadedSession() {
17
+ val mapped =
18
+ mapFromCheckoutState(
19
+ isLoading = false,
20
+ session = CheckoutTestFixtures.fullSession(),
21
+ )
22
+
23
+ assertEquals("loaded", mapped.getString("status"))
24
+
25
+ val session = mapped.getMap("session")
26
+ assertNotNull(session)
27
+ assertEquals("cs_test_123", session!!.getString("id"))
28
+ assertFalse(session.getBoolean("livemode"))
29
+ assertEquals("usd", session.getString("currency"))
30
+
31
+ val status = session.getMap("status")
32
+ assertNotNull(status)
33
+ assertEquals("open", status!!.getString("type"))
34
+
35
+ val tax = session.getMap("tax")
36
+ assertNotNull(tax)
37
+ assertEquals("ready", tax!!.getString("status"))
38
+
39
+ val total = session.getMap("total")
40
+ assertNotNull(total)
41
+ val subtotal = total!!.getMap("subtotal")
42
+ assertNotNull(subtotal)
43
+ assertEquals(5000.0, subtotal!!.getDouble("minorUnitsAmount"), 0.0)
44
+ assertEquals("", subtotal.getString("amount"))
45
+
46
+ val grandTotal = total.getMap("total")
47
+ assertNotNull(grandTotal)
48
+ assertEquals(4044.0, grandTotal!!.getDouble("minorUnitsAmount"), 0.0)
49
+
50
+ val lineItems = session.getArray("lineItems")
51
+ assertNotNull(lineItems)
52
+ assertEquals(2, lineItems!!.size())
53
+ assertEquals("li_item1", lineItems.getMap(0)?.getString("id"))
54
+ assertEquals("Llama Figure", lineItems.getMap(0)?.getString("name"))
55
+ assertEquals(2, lineItems.getMap(0)?.getInt("quantity"))
56
+ assertFalse(lineItems.getMap(0)!!.hasKey("unitAmount"))
57
+
58
+ val item2UnitAmount = lineItems.getMap(1)?.getMap("unitAmount")
59
+ assertNotNull(item2UnitAmount)
60
+ assertEquals(2499.0, item2UnitAmount!!.getDouble("minorUnitsAmount"), 0.0)
61
+
62
+ val shippingOptions = session.getArray("shippingOptions")
63
+ assertNotNull(shippingOptions)
64
+ assertEquals(2, shippingOptions!!.size())
65
+ assertEquals("shr_standard", shippingOptions.getMap(0)?.getString("id"))
66
+ val shippingAmount = shippingOptions.getMap(0)?.getMap("amount")
67
+ assertNotNull(shippingAmount)
68
+ assertEquals(500.0, shippingAmount!!.getDouble("minorUnitsAmount"), 0.0)
69
+
70
+ val discountAmounts = session.getArray("discountAmounts")
71
+ assertNotNull(discountAmounts)
72
+ assertEquals(0, discountAmounts!!.size())
73
+
74
+ val currencyOptions = session.getArray("currencyOptions")
75
+ assertNotNull(currencyOptions)
76
+ assertEquals(0, currencyOptions!!.size())
77
+ }
78
+
79
+ @Test
80
+ fun mapFromCheckoutState_mapsLoadingStateAndOmitsBlankCurrency() {
81
+ val mapped =
82
+ mapFromCheckoutState(
83
+ isLoading = true,
84
+ session = CheckoutTestFixtures.blankCurrencySession(),
85
+ )
86
+
87
+ assertEquals("loading", mapped.getString("status"))
88
+
89
+ val session = mapped.getMap("session")
90
+ assertNotNull(session)
91
+ assertEquals("cs_test_blank_currency", session!!.getString("id"))
92
+ assertFalse(session.hasKey("currency"))
93
+ assertNull(session.getMap("total"))
94
+ assertEquals(0, session.getArray("lineItems")!!.size())
95
+ assertEquals(0, session.getArray("shippingOptions")!!.size())
96
+ assertEquals(0, session.getArray("discountAmounts")!!.size())
97
+ }
98
+ }