react-native-klarna-inapp-sdk 2.4.10 → 2.5.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 (121) hide show
  1. package/README.md +2 -1
  2. package/android/build.gradle +3 -1
  3. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/KlarnaMobileSDKPackage.java +5 -1
  4. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/checkout/KlarnaCheckoutViewManager.java +4 -10
  5. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/common/WebViewResizeObserver.java +28 -0
  6. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/common/event/ComponentEventSender.java +5 -1
  7. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/common/ui/ResizeObserverWrapperView.java +2 -2
  8. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/common/ui/WrapperView.java +2 -2
  9. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/common/ui/YogaLayoutHelper.java +39 -0
  10. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/expresscheckout/KlarnaExpressCheckoutViewCallback.kt +30 -0
  11. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/expresscheckout/KlarnaExpressCheckoutViewEventSender.kt +80 -0
  12. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/expresscheckout/KlarnaExpressCheckoutViewManager.java +544 -0
  13. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/osm/KlarnaOSMViewEventHandler.java +30 -0
  14. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/osm/KlarnaOSMViewEventSender.java +64 -0
  15. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/osm/KlarnaOSMViewManager.java +356 -0
  16. package/android/src/newarch/java/com/klarna/mobile/sdk/reactnative/spec/RNKlarnaExpressCheckoutViewSpec.java +31 -0
  17. package/android/src/newarch/java/com/klarna/mobile/sdk/reactnative/spec/RNKlarnaOSMViewSpec.java +31 -0
  18. package/android/src/oldarch/java/com/klarna/mobile/sdk/reactnative/spec/RNKlarnaExpressCheckoutViewSpec.java +36 -0
  19. package/android/src/oldarch/java/com/klarna/mobile/sdk/reactnative/spec/RNKlarnaOSMViewSpec.java +32 -0
  20. package/android/src/test/java/com/klarna/mobile/sdk/reactnative/KlarnaMobileSDKPackageTest.java +5 -1
  21. package/android/src/test/java/com/klarna/mobile/sdk/reactnative/common/ui/YogaLayoutHelperTest.java +79 -0
  22. package/android/src/test/java/com/klarna/mobile/sdk/reactnative/expresscheckout/KlarnaExpressCheckoutViewManagerTest.java +259 -0
  23. package/android/src/test/java/com/klarna/mobile/sdk/reactnative/osm/KlarnaOSMViewEventHandlerTest.java +136 -0
  24. package/android/src/test/java/com/klarna/mobile/sdk/reactnative/osm/KlarnaOSMViewEventSenderTest.java +184 -0
  25. package/android/src/test/java/com/klarna/mobile/sdk/reactnative/osm/KlarnaOSMViewManagerTest.java +385 -0
  26. package/ios/RNKlarnaMobileSDK.xcodeproj/project.pbxproj +55 -1
  27. package/ios/Sources/KlarnaExpressCheckoutViewManager.h +5 -0
  28. package/ios/Sources/KlarnaExpressCheckoutViewManager.mm +39 -0
  29. package/ios/Sources/KlarnaOSMViewManager.h +5 -0
  30. package/ios/Sources/KlarnaOSMViewManager.mm +59 -0
  31. package/ios/Sources/view/KlarnaExpressCheckoutButtonDelegateProxy.swift +145 -0
  32. package/ios/Sources/view/KlarnaExpressCheckoutViewWrapper.h +41 -0
  33. package/ios/Sources/view/KlarnaOSMViewWrapper.h +48 -0
  34. package/ios/Sources/view/newarch/KlarnaExpressCheckoutViewWrapper.mm +228 -0
  35. package/ios/Sources/view/newarch/KlarnaOSMViewWrapper.mm +294 -0
  36. package/ios/Sources/view/newarch/KlarnaStandaloneWebViewWrapper.mm +20 -13
  37. package/ios/Sources/view/oldarch/KlarnaExpressCheckoutViewWrapper.mm +222 -0
  38. package/ios/Sources/view/oldarch/KlarnaOSMViewWrapper.mm +273 -0
  39. package/ios/Sources/view/oldarch/KlarnaStandaloneWebViewWrapper.mm +11 -13
  40. package/ios/Tests/KlarnaExpressCheckoutViewWrapperTests.m +391 -0
  41. package/ios/Tests/KlarnaOSMViewWrapperTests.m +450 -0
  42. package/ios/Tests/KlarnaStandaloneWebViewWrapperTests.m +105 -0
  43. package/lib/commonjs/KlarnaExpressCheckoutView.js +75 -0
  44. package/lib/commonjs/KlarnaExpressCheckoutView.js.map +1 -0
  45. package/lib/commonjs/KlarnaOSMView.js +94 -0
  46. package/lib/commonjs/KlarnaOSMView.js.map +1 -0
  47. package/lib/commonjs/index.js +99 -0
  48. package/lib/commonjs/index.js.map +1 -1
  49. package/lib/commonjs/specs/KlarnaExpressCheckoutViewNativeComponent.js +11 -0
  50. package/lib/commonjs/specs/KlarnaExpressCheckoutViewNativeComponent.js.map +1 -0
  51. package/lib/commonjs/specs/KlarnaOSMViewNativeComponent.js +16 -0
  52. package/lib/commonjs/specs/KlarnaOSMViewNativeComponent.js.map +1 -0
  53. package/lib/commonjs/types/button/KlarnaButtonShape.js +14 -0
  54. package/lib/commonjs/types/button/KlarnaButtonShape.js.map +1 -0
  55. package/lib/commonjs/types/button/KlarnaButtonStyle.js +13 -0
  56. package/lib/commonjs/types/button/KlarnaButtonStyle.js.map +1 -0
  57. package/lib/commonjs/types/button/KlarnaButtonTheme.js +14 -0
  58. package/lib/commonjs/types/button/KlarnaButtonTheme.js.map +1 -0
  59. package/lib/commonjs/types/common/KlarnaExpressCheckoutSessionOptions.js +9 -0
  60. package/lib/commonjs/types/common/KlarnaExpressCheckoutSessionOptions.js.map +1 -0
  61. package/lib/commonjs/types/common/KlarnaOSMPlacementKey.js +2 -0
  62. package/lib/commonjs/types/common/KlarnaOSMPlacementKey.js.map +1 -0
  63. package/lib/commonjs/types/common/KlarnaTheme.js +14 -0
  64. package/lib/commonjs/types/common/KlarnaTheme.js.map +1 -0
  65. package/lib/module/KlarnaExpressCheckoutView.js +64 -0
  66. package/lib/module/KlarnaExpressCheckoutView.js.map +1 -0
  67. package/lib/module/KlarnaOSMView.js +84 -0
  68. package/lib/module/KlarnaOSMView.js.map +1 -0
  69. package/lib/module/index.js +9 -0
  70. package/lib/module/index.js.map +1 -1
  71. package/lib/module/specs/KlarnaExpressCheckoutViewNativeComponent.js +3 -0
  72. package/lib/module/specs/KlarnaExpressCheckoutViewNativeComponent.js.map +1 -0
  73. package/lib/module/specs/KlarnaOSMViewNativeComponent.js +7 -0
  74. package/lib/module/specs/KlarnaOSMViewNativeComponent.js.map +1 -0
  75. package/lib/module/types/button/KlarnaButtonShape.js +7 -0
  76. package/lib/module/types/button/KlarnaButtonShape.js.map +1 -0
  77. package/lib/module/types/button/KlarnaButtonStyle.js +6 -0
  78. package/lib/module/types/button/KlarnaButtonStyle.js.map +1 -0
  79. package/lib/module/types/button/KlarnaButtonTheme.js +7 -0
  80. package/lib/module/types/button/KlarnaButtonTheme.js.map +1 -0
  81. package/lib/module/types/common/KlarnaExpressCheckoutSessionOptions.js +2 -0
  82. package/lib/module/types/common/KlarnaExpressCheckoutSessionOptions.js.map +1 -0
  83. package/lib/module/types/common/KlarnaOSMPlacementKey.js +2 -0
  84. package/lib/module/types/common/KlarnaOSMPlacementKey.js.map +1 -0
  85. package/lib/module/types/common/KlarnaTheme.js +7 -0
  86. package/lib/module/types/common/KlarnaTheme.js.map +1 -0
  87. package/lib/typescript/KlarnaExpressCheckoutView.d.ts +47 -0
  88. package/lib/typescript/KlarnaExpressCheckoutView.d.ts.map +1 -0
  89. package/lib/typescript/KlarnaOSMView.d.ts +36 -0
  90. package/lib/typescript/KlarnaOSMView.d.ts.map +1 -0
  91. package/lib/typescript/index.d.ts +9 -0
  92. package/lib/typescript/index.d.ts.map +1 -1
  93. package/lib/typescript/specs/KlarnaExpressCheckoutViewNativeComponent.d.ts +45 -0
  94. package/lib/typescript/specs/KlarnaExpressCheckoutViewNativeComponent.d.ts.map +1 -0
  95. package/lib/typescript/specs/KlarnaOSMViewNativeComponent.d.ts +35 -0
  96. package/lib/typescript/specs/KlarnaOSMViewNativeComponent.d.ts.map +1 -0
  97. package/lib/typescript/types/button/KlarnaButtonShape.d.ts +6 -0
  98. package/lib/typescript/types/button/KlarnaButtonShape.d.ts.map +1 -0
  99. package/lib/typescript/types/button/KlarnaButtonStyle.d.ts +5 -0
  100. package/lib/typescript/types/button/KlarnaButtonStyle.d.ts.map +1 -0
  101. package/lib/typescript/types/button/KlarnaButtonTheme.d.ts +6 -0
  102. package/lib/typescript/types/button/KlarnaButtonTheme.d.ts.map +1 -0
  103. package/lib/typescript/types/common/KlarnaExpressCheckoutSessionOptions.d.ts +10 -0
  104. package/lib/typescript/types/common/KlarnaExpressCheckoutSessionOptions.d.ts.map +1 -0
  105. package/lib/typescript/types/common/KlarnaOSMPlacementKey.d.ts +2 -0
  106. package/lib/typescript/types/common/KlarnaOSMPlacementKey.d.ts.map +1 -0
  107. package/lib/typescript/types/common/KlarnaTheme.d.ts +6 -0
  108. package/lib/typescript/types/common/KlarnaTheme.d.ts.map +1 -0
  109. package/package.json +5 -3
  110. package/react-native-klarna-inapp-sdk.podspec +2 -1
  111. package/src/KlarnaExpressCheckoutView.tsx +169 -0
  112. package/src/KlarnaOSMView.tsx +157 -0
  113. package/src/index.tsx +9 -0
  114. package/src/specs/KlarnaExpressCheckoutViewNativeComponent.ts +66 -0
  115. package/src/specs/KlarnaOSMViewNativeComponent.ts +50 -0
  116. package/src/types/button/KlarnaButtonShape.ts +5 -0
  117. package/src/types/button/KlarnaButtonStyle.ts +4 -0
  118. package/src/types/button/KlarnaButtonTheme.ts +5 -0
  119. package/src/types/common/KlarnaExpressCheckoutSessionOptions.ts +13 -0
  120. package/src/types/common/KlarnaOSMPlacementKey.ts +3 -0
  121. package/src/types/common/KlarnaTheme.ts +5 -0
@@ -0,0 +1,259 @@
1
+ package com.klarna.mobile.sdk.reactnative.expresscheckout;
2
+
3
+ import static org.junit.Assert.assertEquals;
4
+ import static org.junit.Assert.assertFalse;
5
+ import static org.junit.Assert.assertNotNull;
6
+ import static org.junit.Assert.assertNull;
7
+ import static org.junit.Assert.assertTrue;
8
+
9
+ import android.widget.FrameLayout;
10
+
11
+ import com.klarna.mobile.sdk.api.KlarnaEnvironment;
12
+ import com.klarna.mobile.sdk.api.KlarnaRegion;
13
+ import com.klarna.mobile.sdk.api.button.KlarnaButtonShape;
14
+ import com.klarna.mobile.sdk.api.button.KlarnaButtonStyle;
15
+ import com.klarna.mobile.sdk.api.button.KlarnaButtonTheme;
16
+ import com.klarna.mobile.sdk.api.expresscheckout.KlarnaExpressCheckoutButton;
17
+ import com.klarna.mobile.sdk.api.expresscheckout.KlarnaExpressCheckoutButtonAuthorizationResponse;
18
+ import com.klarna.mobile.sdk.api.expresscheckout.KlarnaExpressCheckoutError;
19
+
20
+ import org.junit.Assert;
21
+ import org.junit.Before;
22
+ import org.junit.Test;
23
+ import org.junit.runner.RunWith;
24
+ import org.mockito.Mockito;
25
+ import org.robolectric.RobolectricTestRunner;
26
+
27
+ @RunWith(RobolectricTestRunner.class)
28
+ public class KlarnaExpressCheckoutViewManagerTest {
29
+
30
+ private KlarnaExpressCheckoutViewManager manager;
31
+
32
+ @Before
33
+ public void setup() {
34
+ manager = new KlarnaExpressCheckoutViewManager();
35
+ }
36
+
37
+ // region React class name
38
+
39
+ @Test
40
+ public void testReactClassName() {
41
+ assertEquals("RNKlarnaExpressCheckoutView", manager.getName());
42
+ assertEquals("RNKlarnaExpressCheckoutView", KlarnaExpressCheckoutViewManager.REACT_CLASS);
43
+ }
44
+
45
+ // endregion
46
+
47
+ // region parseTheme
48
+
49
+ @Test
50
+ public void testParseTheme_light() {
51
+ assertEquals(KlarnaButtonTheme.LIGHT, KlarnaExpressCheckoutViewManager.parseTheme("light"));
52
+ }
53
+
54
+ @Test
55
+ public void testParseTheme_dark() {
56
+ assertEquals(KlarnaButtonTheme.DARK, KlarnaExpressCheckoutViewManager.parseTheme("dark"));
57
+ }
58
+
59
+ @Test
60
+ public void testParseTheme_auto() {
61
+ assertEquals(KlarnaButtonTheme.AUTO, KlarnaExpressCheckoutViewManager.parseTheme("auto"));
62
+ }
63
+
64
+ @Test
65
+ public void testParseTheme_null() {
66
+ assertNull(KlarnaExpressCheckoutViewManager.parseTheme(null));
67
+ }
68
+
69
+ @Test
70
+ public void testParseTheme_unknown() {
71
+ assertNull(KlarnaExpressCheckoutViewManager.parseTheme("neon"));
72
+ }
73
+
74
+ // endregion
75
+
76
+ // region parseShape
77
+
78
+ @Test
79
+ public void testParseShape_roundedRect() {
80
+ assertEquals(KlarnaButtonShape.ROUNDED_RECT, KlarnaExpressCheckoutViewManager.parseShape("roundedRect"));
81
+ }
82
+
83
+ @Test
84
+ public void testParseShape_pill() {
85
+ assertEquals(KlarnaButtonShape.PILL, KlarnaExpressCheckoutViewManager.parseShape("pill"));
86
+ }
87
+
88
+ @Test
89
+ public void testParseShape_rectangle() {
90
+ assertEquals(KlarnaButtonShape.RECTANGLE, KlarnaExpressCheckoutViewManager.parseShape("rectangle"));
91
+ }
92
+
93
+ @Test
94
+ public void testParseShape_null() {
95
+ assertNull(KlarnaExpressCheckoutViewManager.parseShape(null));
96
+ }
97
+
98
+ @Test
99
+ public void testParseShape_unknown() {
100
+ assertNull(KlarnaExpressCheckoutViewManager.parseShape("circle"));
101
+ }
102
+
103
+ // endregion
104
+
105
+ // region parseButtonStyle
106
+
107
+ @Test
108
+ public void testParseButtonStyle_filled() {
109
+ assertEquals(KlarnaButtonStyle.FILLED, KlarnaExpressCheckoutViewManager.parseButtonStyle("filled"));
110
+ }
111
+
112
+ @Test
113
+ public void testParseButtonStyle_outlined() {
114
+ assertEquals(KlarnaButtonStyle.OUTLINED, KlarnaExpressCheckoutViewManager.parseButtonStyle("outlined"));
115
+ }
116
+
117
+ @Test
118
+ public void testParseButtonStyle_null() {
119
+ assertNull(KlarnaExpressCheckoutViewManager.parseButtonStyle(null));
120
+ }
121
+
122
+ @Test
123
+ public void testParseButtonStyle_unknown() {
124
+ assertNull(KlarnaExpressCheckoutViewManager.parseButtonStyle("gradient"));
125
+ }
126
+
127
+ // endregion
128
+
129
+ // region parseEnvironment
130
+
131
+ @Test
132
+ public void testParseEnvironment_playground() {
133
+ assertEquals(KlarnaEnvironment.PLAYGROUND, KlarnaExpressCheckoutViewManager.parseEnvironment("playground"));
134
+ }
135
+
136
+ @Test
137
+ public void testParseEnvironment_production() {
138
+ assertEquals(KlarnaEnvironment.PRODUCTION, KlarnaExpressCheckoutViewManager.parseEnvironment("production"));
139
+ }
140
+
141
+ @Test
142
+ public void testParseEnvironment_null() {
143
+ assertNull(KlarnaExpressCheckoutViewManager.parseEnvironment(null));
144
+ }
145
+
146
+ @Test
147
+ public void testParseEnvironment_unknown() {
148
+ assertNull(KlarnaExpressCheckoutViewManager.parseEnvironment("staging"));
149
+ }
150
+
151
+ // endregion
152
+
153
+ // region parseRegion
154
+
155
+ @Test
156
+ public void testParseRegion_eu() {
157
+ assertEquals(KlarnaRegion.EU, KlarnaExpressCheckoutViewManager.parseRegion("eu"));
158
+ }
159
+
160
+ @Test
161
+ public void testParseRegion_na() {
162
+ assertEquals(KlarnaRegion.NA, KlarnaExpressCheckoutViewManager.parseRegion("na"));
163
+ }
164
+
165
+ @Test
166
+ public void testParseRegion_oc() {
167
+ assertEquals(KlarnaRegion.OC, KlarnaExpressCheckoutViewManager.parseRegion("oc"));
168
+ }
169
+
170
+ @Test
171
+ public void testParseRegion_null() {
172
+ assertNull(KlarnaExpressCheckoutViewManager.parseRegion(null));
173
+ }
174
+
175
+ @Test
176
+ public void testParseRegion_unknown() {
177
+ assertNull(KlarnaExpressCheckoutViewManager.parseRegion("ap"));
178
+ }
179
+
180
+ // endregion
181
+
182
+ // region ExpressCheckoutProps defaults
183
+
184
+ @Test
185
+ public void testPropsDefaults() {
186
+ KlarnaExpressCheckoutViewManager.ExpressCheckoutProps props =
187
+ new KlarnaExpressCheckoutViewManager.ExpressCheckoutProps();
188
+
189
+ assertNull(props.sessionType);
190
+ assertNull(props.clientId);
191
+ assertNull(props.clientToken);
192
+ assertNull(props.locale);
193
+ assertNull(props.environment);
194
+ assertNull(props.region);
195
+ assertNull(props.returnUrl);
196
+ assertNull(props.theme);
197
+ assertNull(props.shape);
198
+ assertNull(props.buttonStyle);
199
+ assertTrue(props.autoFinalize);
200
+ assertFalse(props.collectShippingAddress);
201
+ assertNull(props.sessionData);
202
+ assertEquals(-1, props.lastSentHeightDp);
203
+ }
204
+
205
+ // endregion
206
+
207
+ // region Callback forwarding
208
+
209
+ @Test
210
+ public void testCallbackForwardsOnAuthorized() {
211
+ FrameLayout container = Mockito.mock(FrameLayout.class);
212
+ KlarnaExpressCheckoutViewEventSender sender =
213
+ Mockito.mock(KlarnaExpressCheckoutViewEventSender.class);
214
+
215
+ KlarnaExpressCheckoutViewCallback callback =
216
+ new KlarnaExpressCheckoutViewCallback(container, sender);
217
+
218
+ KlarnaExpressCheckoutButton button = Mockito.mock(KlarnaExpressCheckoutButton.class);
219
+ KlarnaExpressCheckoutButtonAuthorizationResponse response =
220
+ Mockito.mock(KlarnaExpressCheckoutButtonAuthorizationResponse.class);
221
+
222
+ callback.onAuthorized(button, response);
223
+
224
+ Mockito.verify(sender, Mockito.times(1))
225
+ .sendOnAuthorizedEvent(container, response);
226
+ }
227
+
228
+ @Test
229
+ public void testCallbackForwardsOnError() {
230
+ FrameLayout container = Mockito.mock(FrameLayout.class);
231
+ KlarnaExpressCheckoutViewEventSender sender =
232
+ Mockito.mock(KlarnaExpressCheckoutViewEventSender.class);
233
+
234
+ KlarnaExpressCheckoutViewCallback callback =
235
+ new KlarnaExpressCheckoutViewCallback(container, sender);
236
+
237
+ KlarnaExpressCheckoutButton button = Mockito.mock(KlarnaExpressCheckoutButton.class);
238
+ KlarnaExpressCheckoutError error = Mockito.mock(KlarnaExpressCheckoutError.class);
239
+
240
+ callback.onError(button, error);
241
+
242
+ Mockito.verify(sender, Mockito.times(1))
243
+ .sendKlarnaExpressCheckoutError(container, error);
244
+ }
245
+
246
+ // endregion
247
+
248
+ // region Event sender configuration
249
+
250
+ @Test
251
+ public void testExportedEventConstants() {
252
+ assertNotNull(manager.getExportedCustomDirectEventTypeConstants());
253
+ assertTrue(manager.getExportedCustomDirectEventTypeConstants().containsKey("onAuthorized"));
254
+ assertTrue(manager.getExportedCustomDirectEventTypeConstants().containsKey("onError"));
255
+ assertTrue(manager.getExportedCustomDirectEventTypeConstants().containsKey("onResized"));
256
+ }
257
+
258
+ // endregion
259
+ }
@@ -0,0 +1,136 @@
1
+ package com.klarna.mobile.sdk.reactnative.osm;
2
+
3
+ import android.os.SystemClock;
4
+
5
+ import com.facebook.react.bridge.Arguments;
6
+ import com.facebook.react.bridge.JavaOnlyArray;
7
+ import com.facebook.react.bridge.JavaOnlyMap;
8
+ import com.facebook.react.bridge.ReactContext;
9
+ import com.facebook.react.uimanager.UIManagerHelper;
10
+ import com.facebook.react.uimanager.events.EventDispatcher;
11
+ import com.klarna.mobile.sdk.KlarnaMobileSDKError;
12
+ import com.klarna.mobile.sdk.api.KlarnaProductEvent;
13
+ import com.klarna.mobile.sdk.api.component.KlarnaComponent;
14
+ import com.klarna.mobile.sdk.api.osm.KlarnaOSMView;
15
+ import com.klarna.mobile.sdk.reactnative.common.event.ComponentEvent;
16
+ import com.klarna.mobile.sdk.reactnative.common.ui.WrapperView;
17
+
18
+ import org.junit.After;
19
+ import org.junit.Before;
20
+ import org.junit.Test;
21
+ import org.junit.runner.RunWith;
22
+ import org.mockito.MockedStatic;
23
+ import org.mockito.Mockito;
24
+ import org.mockito.junit.MockitoJUnitRunner;
25
+
26
+ import java.util.HashMap;
27
+ import java.util.Map;
28
+
29
+ @RunWith(MockitoJUnitRunner.class)
30
+ public class KlarnaOSMViewEventHandlerTest {
31
+
32
+ private MockedStatic<UIManagerHelper> mockedStaticUiManagerHelper;
33
+ private MockedStatic<SystemClock> mockedStaticSystemClock;
34
+ private MockedStatic<Arguments> mockedStaticArguments;
35
+ private KlarnaOSMViewEventSender eventSender;
36
+ private KlarnaOSMViewEventHandler eventHandler;
37
+ private WrapperView<KlarnaOSMView> wrapper;
38
+ private KlarnaOSMView osmView;
39
+ private EventDispatcher eventDispatcher;
40
+
41
+ @SuppressWarnings("unchecked")
42
+ @Before
43
+ public void setup() {
44
+ osmView = Mockito.mock(KlarnaOSMView.class);
45
+ wrapper = Mockito.mock(WrapperView.class);
46
+ Mockito.when(wrapper.getView()).thenReturn(osmView);
47
+
48
+ ReactContext reactContext = Mockito.mock(ReactContext.class);
49
+ Mockito.when(wrapper.getContext()).thenReturn(reactContext);
50
+
51
+ eventDispatcher = Mockito.mock(EventDispatcher.class);
52
+ Map<WrapperView<KlarnaOSMView>, EventDispatcher> viewToDispatcher = new HashMap<>();
53
+ viewToDispatcher.put(wrapper, eventDispatcher);
54
+
55
+ mockedStaticUiManagerHelper = Mockito.mockStatic(UIManagerHelper.class);
56
+ Mockito.when(UIManagerHelper.getEventDispatcherForReactTag(Mockito.any(), Mockito.anyInt()))
57
+ .thenAnswer(invocation -> eventDispatcher);
58
+ mockedStaticSystemClock = Mockito.mockStatic(SystemClock.class);
59
+ mockedStaticArguments = Mockito.mockStatic(Arguments.class);
60
+ Mockito.when(Arguments.createArray())
61
+ .thenAnswer(invocation -> new JavaOnlyArray());
62
+ Mockito.when(Arguments.createMap())
63
+ .thenAnswer(invocation -> new JavaOnlyMap());
64
+
65
+ eventSender = new KlarnaOSMViewEventSender(viewToDispatcher);
66
+ eventHandler = new KlarnaOSMViewEventHandler(eventSender);
67
+ }
68
+
69
+ @After
70
+ public void teardown() {
71
+ mockedStaticUiManagerHelper.close();
72
+ mockedStaticSystemClock.close();
73
+ mockedStaticArguments.close();
74
+ }
75
+
76
+ // --- onError with KlarnaOSMView ---
77
+
78
+ @Test
79
+ public void testOnErrorWithOSMView() {
80
+ KlarnaMobileSDKError error = Mockito.mock(KlarnaMobileSDKError.class);
81
+ Mockito.when(error.getName()).thenReturn("RenderError");
82
+ Mockito.when(error.getMessage()).thenReturn("Failed to render OSM");
83
+ Mockito.when(error.isFatal()).thenReturn(false);
84
+
85
+ eventHandler.onError(osmView, error);
86
+
87
+ Mockito.verify(eventDispatcher).dispatchEvent(Mockito.any(ComponentEvent.class));
88
+ }
89
+
90
+ @Test
91
+ public void testOnErrorWithOSMViewFatal() {
92
+ KlarnaMobileSDKError error = Mockito.mock(KlarnaMobileSDKError.class);
93
+ Mockito.when(error.getName()).thenReturn("FatalError");
94
+ Mockito.when(error.getMessage()).thenReturn("Fatal SDK error");
95
+ Mockito.when(error.isFatal()).thenReturn(true);
96
+
97
+ eventHandler.onError(osmView, error);
98
+
99
+ Mockito.verify(eventDispatcher).dispatchEvent(Mockito.any(ComponentEvent.class));
100
+ }
101
+
102
+ // --- onError with non-OSM component ---
103
+
104
+ @Test
105
+ public void testOnErrorWithNonOSMComponent() {
106
+ KlarnaComponent nonOSMComponent = Mockito.mock(KlarnaComponent.class);
107
+ KlarnaMobileSDKError error = Mockito.mock(KlarnaMobileSDKError.class);
108
+
109
+ eventHandler.onError(nonOSMComponent, error);
110
+
111
+ // Should not dispatch any event for non-OSM components
112
+ Mockito.verify(eventDispatcher, Mockito.never()).dispatchEvent(Mockito.any());
113
+ }
114
+
115
+ // --- onEvent (no-op) ---
116
+
117
+ @Test
118
+ public void testOnEventIsNoOp() {
119
+ KlarnaProductEvent productEvent = Mockito.mock(KlarnaProductEvent.class);
120
+
121
+ eventHandler.onEvent(osmView, productEvent);
122
+
123
+ // onEvent should be a no-op for OSM
124
+ Mockito.verify(eventDispatcher, Mockito.never()).dispatchEvent(Mockito.any());
125
+ }
126
+
127
+ @Test
128
+ public void testOnEventWithNonOSMComponent() {
129
+ KlarnaComponent nonOSMComponent = Mockito.mock(KlarnaComponent.class);
130
+ KlarnaProductEvent productEvent = Mockito.mock(KlarnaProductEvent.class);
131
+
132
+ eventHandler.onEvent(nonOSMComponent, productEvent);
133
+
134
+ Mockito.verify(eventDispatcher, Mockito.never()).dispatchEvent(Mockito.any());
135
+ }
136
+ }
@@ -0,0 +1,184 @@
1
+ package com.klarna.mobile.sdk.reactnative.osm;
2
+
3
+ import android.os.SystemClock;
4
+ import android.view.View;
5
+
6
+ import com.facebook.react.bridge.Arguments;
7
+ import com.facebook.react.bridge.JavaOnlyArray;
8
+ import com.facebook.react.bridge.JavaOnlyMap;
9
+ import com.facebook.react.bridge.ReactContext;
10
+ import com.facebook.react.bridge.WritableMap;
11
+ import com.facebook.react.uimanager.UIManagerHelper;
12
+ import com.facebook.react.uimanager.events.EventDispatcher;
13
+ import com.klarna.mobile.sdk.KlarnaMobileSDKError;
14
+ import com.klarna.mobile.sdk.api.osm.KlarnaOSMView;
15
+ import com.klarna.mobile.sdk.reactnative.common.event.ComponentEvent;
16
+ import com.klarna.mobile.sdk.reactnative.common.ui.WrapperView;
17
+
18
+ import org.junit.After;
19
+ import org.junit.Assert;
20
+ import org.junit.Before;
21
+ import org.junit.Test;
22
+ import org.junit.runner.RunWith;
23
+ import org.mockito.ArgumentCaptor;
24
+ import org.mockito.MockedStatic;
25
+ import org.mockito.Mockito;
26
+ import org.mockito.junit.MockitoJUnitRunner;
27
+
28
+ import java.util.Collection;
29
+ import java.util.HashMap;
30
+ import java.util.Map;
31
+
32
+ @RunWith(MockitoJUnitRunner.class)
33
+ public class KlarnaOSMViewEventSenderTest {
34
+
35
+ private MockedStatic<UIManagerHelper> mockedStaticUiManagerHelper;
36
+ private MockedStatic<SystemClock> mockedStaticSystemClock;
37
+ private MockedStatic<Arguments> mockedStaticArguments;
38
+ private KlarnaOSMViewEventSender eventSender;
39
+ private WrapperView<KlarnaOSMView> wrapper;
40
+ private KlarnaOSMView osmView;
41
+ private EventDispatcher eventDispatcher;
42
+ private Map<WrapperView<KlarnaOSMView>, EventDispatcher> viewToDispatcher;
43
+
44
+ @SuppressWarnings("unchecked")
45
+ @Before
46
+ public void setup() {
47
+ osmView = Mockito.mock(KlarnaOSMView.class);
48
+ wrapper = Mockito.mock(WrapperView.class);
49
+ Mockito.when(wrapper.getView()).thenReturn(osmView);
50
+
51
+ ReactContext reactContext = Mockito.mock(ReactContext.class);
52
+ Mockito.when(wrapper.getContext()).thenReturn(reactContext);
53
+
54
+ eventDispatcher = Mockito.mock(EventDispatcher.class);
55
+ viewToDispatcher = new HashMap<>();
56
+ viewToDispatcher.put(wrapper, eventDispatcher);
57
+
58
+ eventSender = new KlarnaOSMViewEventSender(viewToDispatcher);
59
+
60
+ mockedStaticUiManagerHelper = Mockito.mockStatic(UIManagerHelper.class);
61
+ Mockito.when(UIManagerHelper.getEventDispatcherForReactTag(Mockito.any(), Mockito.anyInt()))
62
+ .thenAnswer(invocation -> eventDispatcher);
63
+ mockedStaticSystemClock = Mockito.mockStatic(SystemClock.class);
64
+ mockedStaticArguments = Mockito.mockStatic(Arguments.class);
65
+ Mockito.when(Arguments.createArray())
66
+ .thenAnswer(invocation -> new JavaOnlyArray());
67
+ Mockito.when(Arguments.createMap())
68
+ .thenAnswer(invocation -> new JavaOnlyMap());
69
+ }
70
+
71
+ @After
72
+ public void teardown() {
73
+ mockedStaticUiManagerHelper.close();
74
+ mockedStaticSystemClock.close();
75
+ mockedStaticArguments.close();
76
+ }
77
+
78
+ // --- getCallbackEventNames ---
79
+
80
+ @Test
81
+ public void testCallbackEventNames() {
82
+ Collection<String> names = eventSender.getCallbackEventNames();
83
+ Assert.assertEquals(3, names.size());
84
+ Assert.assertTrue(names.contains("onError"));
85
+ Assert.assertTrue(names.contains("onResized"));
86
+ Assert.assertTrue(names.contains("onOSMViewReady"));
87
+ }
88
+
89
+ // --- getExportedCustomDirectEventTypeConstants ---
90
+
91
+ @Test
92
+ public void testExportedCustomDirectEventTypeConstants() {
93
+ Map<String, Object> constants = eventSender.getExportedCustomDirectEventTypeConstants();
94
+ Assert.assertEquals(3, constants.size());
95
+ Assert.assertTrue(constants.containsKey("onError"));
96
+ Assert.assertTrue(constants.containsKey("onResized"));
97
+ Assert.assertTrue(constants.containsKey("onOSMViewReady"));
98
+
99
+ for (String key : constants.keySet()) {
100
+ @SuppressWarnings("unchecked")
101
+ Map<String, String> value = (Map<String, String>) constants.get(key);
102
+ Assert.assertNotNull(value);
103
+ Assert.assertEquals(key, value.get("registrationName"));
104
+ }
105
+ }
106
+
107
+ // --- sendError ---
108
+
109
+ @Test
110
+ public void testSendError() {
111
+ eventSender.sendError(osmView, "TestError", "Test message", false);
112
+ Mockito.verify(eventDispatcher).dispatchEvent(Mockito.any(ComponentEvent.class));
113
+ }
114
+
115
+ @Test
116
+ public void testSendErrorFatal() {
117
+ eventSender.sendError(osmView, "FatalError", "Fatal message", true);
118
+ Mockito.verify(eventDispatcher).dispatchEvent(Mockito.any(ComponentEvent.class));
119
+ }
120
+
121
+ // --- sendKlarnaMobileSDKError ---
122
+
123
+ @Test
124
+ public void testSendKlarnaMobileSDKError() {
125
+ KlarnaMobileSDKError error = Mockito.mock(KlarnaMobileSDKError.class);
126
+ Mockito.when(error.getName()).thenReturn("SDKError");
127
+ Mockito.when(error.getMessage()).thenReturn("SDK error message");
128
+ Mockito.when(error.isFatal()).thenReturn(true);
129
+
130
+ eventSender.sendKlarnaMobileSDKError(osmView, error);
131
+ Mockito.verify(eventDispatcher).dispatchEvent(Mockito.any(ComponentEvent.class));
132
+ }
133
+
134
+ // --- sendOnResizedEvent ---
135
+
136
+ @Test
137
+ public void testSendOnResizedEvent() {
138
+ eventSender.sendOnResizedEvent(osmView, 150);
139
+ Mockito.verify(eventDispatcher).dispatchEvent(Mockito.any(ComponentEvent.class));
140
+ }
141
+
142
+ @Test
143
+ public void testSendOnResizedEventZeroHeight() {
144
+ eventSender.sendOnResizedEvent(osmView, 0);
145
+ Mockito.verify(eventDispatcher).dispatchEvent(Mockito.any(ComponentEvent.class));
146
+ }
147
+
148
+ // --- sendOnOSMViewReadyEvent ---
149
+
150
+ @Test
151
+ public void testSendOnOSMViewReadyEvent() {
152
+ eventSender.sendOnOSMViewReadyEvent(osmView);
153
+ Mockito.verify(eventDispatcher).dispatchEvent(Mockito.any(ComponentEvent.class));
154
+ }
155
+
156
+ // --- null view handling ---
157
+
158
+ @Test
159
+ public void testSendErrorNullView() {
160
+ eventSender.sendError(null, "TestError", "Test message", false);
161
+ Mockito.verify(eventDispatcher, Mockito.never()).dispatchEvent(Mockito.any());
162
+ }
163
+
164
+ @Test
165
+ public void testSendOnResizedEventNullView() {
166
+ eventSender.sendOnResizedEvent(null, 100);
167
+ Mockito.verify(eventDispatcher, Mockito.never()).dispatchEvent(Mockito.any());
168
+ }
169
+
170
+ @Test
171
+ public void testSendOnOSMViewReadyEventNullView() {
172
+ eventSender.sendOnOSMViewReadyEvent(null);
173
+ Mockito.verify(eventDispatcher, Mockito.never()).dispatchEvent(Mockito.any());
174
+ }
175
+
176
+ // --- view not in dispatcher map ---
177
+
178
+ @Test
179
+ public void testSendErrorUnknownView() {
180
+ KlarnaOSMView unknownView = Mockito.mock(KlarnaOSMView.class);
181
+ eventSender.sendError(unknownView, "TestError", "Test message", false);
182
+ Mockito.verify(eventDispatcher, Mockito.never()).dispatchEvent(Mockito.any());
183
+ }
184
+ }