@glomopay/react-native-sdk 3.1.0 → 4.1.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 (46) hide show
  1. package/CHANGELOG.md +23 -2
  2. package/MIGRATION.md +79 -0
  3. package/README.md +62 -93
  4. package/lib/glomo-checkout.d.ts +5 -1
  5. package/lib/glomo-checkout.d.ts.map +1 -1
  6. package/lib/glomo-checkout.js +13 -25
  7. package/lib/glomo-lrs-checkout.d.ts +4 -1
  8. package/lib/glomo-lrs-checkout.d.ts.map +1 -1
  9. package/lib/glomo-lrs-checkout.js +2 -2
  10. package/lib/glomo-standard-checkout.d.ts +1 -0
  11. package/lib/glomo-standard-checkout.d.ts.map +1 -1
  12. package/lib/glomo-standard-checkout.js +3 -5
  13. package/lib/index.d.ts +2 -2
  14. package/lib/index.d.ts.map +1 -1
  15. package/lib/index.js +5 -3
  16. package/lib/types/checkout.d.ts +27 -19
  17. package/lib/types/checkout.d.ts.map +1 -1
  18. package/lib/types/checkout.js +12 -1
  19. package/lib/types/standard-checkout.d.ts +3 -7
  20. package/lib/types/standard-checkout.d.ts.map +1 -1
  21. package/lib/types/subscriptions-checkout.d.ts +5 -3
  22. package/lib/types/subscriptions-checkout.d.ts.map +1 -1
  23. package/lib/use-glomo-checkout.d.ts +2 -2
  24. package/lib/use-glomo-checkout.d.ts.map +1 -1
  25. package/lib/use-glomo-checkout.js +23 -2
  26. package/lib/use-lrs-checkout.d.ts +11 -3
  27. package/lib/use-lrs-checkout.d.ts.map +1 -1
  28. package/lib/use-lrs-checkout.js +18 -5
  29. package/lib/use-standard-checkout.d.ts +5 -8
  30. package/lib/use-standard-checkout.d.ts.map +1 -1
  31. package/lib/use-standard-checkout.js +30 -56
  32. package/lib/utils/analytics.d.ts +0 -2
  33. package/lib/utils/analytics.d.ts.map +1 -1
  34. package/lib/utils/analytics.js +0 -19
  35. package/package.json +4 -2
  36. package/src/glomo-checkout.tsx +26 -31
  37. package/src/glomo-lrs-checkout.tsx +9 -2
  38. package/src/glomo-standard-checkout.tsx +5 -7
  39. package/src/index.ts +4 -4
  40. package/src/types/checkout.ts +28 -17
  41. package/src/types/standard-checkout.ts +3 -5
  42. package/src/types/subscriptions-checkout.ts +5 -3
  43. package/src/use-glomo-checkout.tsx +30 -5
  44. package/src/use-lrs-checkout.tsx +33 -6
  45. package/src/use-standard-checkout.tsx +30 -103
  46. package/src/utils/analytics.ts +0 -27
@@ -38,7 +38,6 @@ exports.trackStandardConnectionError = trackStandardConnectionError;
38
38
  exports.trackStandardSdkError = trackStandardSdkError;
39
39
  exports.trackStandardBankTransferSubmitted = trackStandardBankTransferSubmitted;
40
40
  exports.trackStandardPayViaBankCompleted = trackStandardPayViaBankCompleted;
41
- exports.trackStandardPayViaBankBankConnectionSuccessful = trackStandardPayViaBankBankConnectionSuccessful;
42
41
  exports.trackOrderTypeDetectionStarted = trackOrderTypeDetectionStarted;
43
42
  exports.trackOrderTypeDetectionResolved = trackOrderTypeDetectionResolved;
44
43
  exports.trackOrderTypeDetectionFailed = trackOrderTypeDetectionFailed;
@@ -703,17 +702,6 @@ function trackStandardPayViaBankCompleted(orderId, publicKey, status, devMode =
703
702
  }
704
703
  });
705
704
  }
706
- function trackStandardPayViaBankBankConnectionSuccessful(orderId, publicKey, bankIdentifier, devMode = false, mockMode = false, standardUrl) {
707
- const properties = {
708
- ...buildCommonProperties(orderId, publicKey, devMode, mockMode, standardUrl, "standard"),
709
- bankIdentifier,
710
- };
711
- trackEvent("Standard Pay Via Bank Bank Connection Successful", properties, devMode).catch((error) => {
712
- if (devMode) {
713
- console.error("[Glomo-RN-SDK] Event tracking error on standard pay via bank connection:", error);
714
- }
715
- });
716
- }
717
705
  // ---------------------------------------------------------------------------
718
706
  // Order Type Detection Trackers (Unified Flow)
719
707
  // ---------------------------------------------------------------------------
@@ -1030,7 +1018,6 @@ exports.standardCheckoutTrackers = {
1030
1018
  trackSdkError: trackStandardSdkError,
1031
1019
  trackBankTransferSubmitted: trackStandardBankTransferSubmitted,
1032
1020
  trackPayViaBankCompleted: trackStandardPayViaBankCompleted,
1033
- trackPayViaBankBankConnectionSuccessful: trackStandardPayViaBankBankConnectionSuccessful,
1034
1021
  };
1035
1022
  /** Subscription checkout tracker map - delegates to trackSubscription* functions, no-ops for bank transfer */
1036
1023
  exports.subscriptionCheckoutTrackers = {
@@ -1057,10 +1044,4 @@ exports.subscriptionCheckoutTrackers = {
1057
1044
  console.warn("[Glomo-RN-SDK] Unexpected pay via bank completed event in subscription flow");
1058
1045
  }
1059
1046
  },
1060
- trackPayViaBankBankConnectionSuccessful: (...args) => {
1061
- const devMode = args[3];
1062
- if (devMode) {
1063
- console.warn("[Glomo-RN-SDK] Unexpected pay via bank connection event in subscription flow");
1064
- }
1065
- },
1066
1047
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glomopay/react-native-sdk",
3
- "version": "3.1.0",
3
+ "version": "4.1.0",
4
4
  "description": "The React Native SDK for GlomoPay",
5
5
  "license": "Apache-2.0",
6
6
  "main": "lib/index.js",
@@ -23,7 +23,9 @@
23
23
  "prettier:format": "prettier --write \"**/*.{js,ts,jsx,tsx,json}\"",
24
24
  "lint": "eslint src/",
25
25
  "clean": "rm -rf lib",
26
- "prepublishOnly": "npm run clean && tsc --noEmit && npm run build"
26
+ "prepublishOnly": "npm run clean && tsc --noEmit && npm run build",
27
+ "ci:e2e-android": "cd testing && npm run ci:e2e-android",
28
+ "ci:e2e-ios": "cd testing && npm run ci:e2e-ios"
27
29
  },
28
30
  "repository": {
29
31
  "type": "git",
@@ -1,18 +1,22 @@
1
1
  /**
2
- * The unified GlomoPay Checkout Component (v3).
2
+ * The unified GlomoPay Checkout Component (v4).
3
3
  * Detects order type (LRS vs Standard) and delegates rendering to the appropriate inner component.
4
+ * Enforces error handling via `onSdkError()` as a mandatory prop.
4
5
  */
5
6
 
6
7
  import React, { useImperativeHandle, useRef, useEffect, useMemo, forwardRef } from "react";
7
8
 
8
9
  import { useGlomoCheckout, type UseGlomoCheckoutInternalReturn } from "./use-glomo-checkout";
9
- import { type GlomoCheckoutRef, type GlomoCheckoutProps } from "./types/checkout";
10
+ import { type GlomoCheckoutRef, type GlomoCheckoutProps, type GlomoCheckoutInternalProps } from "./types/checkout";
10
11
  import { trackUseOfUnsupportedFunctionality } from "./utils/analytics";
11
12
  import { GlomoLrsCheckout } from "./glomo-lrs-checkout";
12
- import { GlomoStandardCheckout } from "./glomo-standard-checkout";
13
+ import { GlomoStandardCheckoutInternal as GlomoStandardCheckout } from "./glomo-standard-checkout";
13
14
  import { GlomoSubscriptionsCheckout } from "./glomo-subscriptions-checkout";
14
15
 
15
- function GlomoCheckoutComponent(props: GlomoCheckoutProps, ref: React.ForwardedRef<GlomoCheckoutRef>) {
16
+ function GlomoCheckoutComponent(
17
+ props: GlomoCheckoutProps & GlomoCheckoutInternalProps,
18
+ ref: React.ForwardedRef<GlomoCheckoutRef>
19
+ ) {
16
20
  // useGlomoCheckout handles order type detection and exposes start/getStatus for the ref
17
21
  const {
18
22
  orderType,
@@ -38,24 +42,16 @@ function GlomoCheckoutComponent(props: GlomoCheckoutProps, ref: React.ForwardedR
38
42
  [passedProps.publicKey]
39
43
  );
40
44
 
41
- // Extracting stable booleans for the tracking effect to avoid depending on passedProps object
42
- const hasBankTransferCallback = !!passedProps.onBankTransferSubmitted;
43
- const hasPayViaBankCallback = !!passedProps.onPayViaBankCompleted;
44
- const hasBankConnectionCallback = !!passedProps.onPayViaBankBankConnectionSuccessful;
45
+ // Extracting stable boolean for the tracking effect to avoid depending on passedProps object
46
+ const hasUserJourneyCallback = !!passedProps.onUserJourneyCompleted;
45
47
 
46
48
  useEffect(() => {
47
49
  if (orderType !== "subscriptions" || hasTrackedUnsupportedRef.current) return;
48
50
  hasTrackedUnsupportedRef.current = true;
49
51
 
50
- const unsupported = [
51
- hasBankTransferCallback && "onBankTransferSubmitted",
52
- hasPayViaBankCallback && "onPayViaBankCompleted",
53
- hasBankConnectionCallback && "onPayViaBankBankConnectionSuccessful",
54
- ].filter(Boolean) as string[];
55
-
56
- for (const name of unsupported) {
52
+ if (hasUserJourneyCallback) {
57
53
  trackUseOfUnsupportedFunctionality(
58
- name,
54
+ "onUserJourneyCompleted",
59
55
  passedProps.subscriptionId,
60
56
  passedProps.publicKey,
61
57
  devMode,
@@ -63,16 +59,7 @@ function GlomoCheckoutComponent(props: GlomoCheckoutProps, ref: React.ForwardedR
63
59
  ""
64
60
  );
65
61
  }
66
- }, [
67
- orderType,
68
- hasBankTransferCallback,
69
- hasPayViaBankCallback,
70
- hasBankConnectionCallback,
71
- passedProps.subscriptionId,
72
- passedProps.publicKey,
73
- devMode,
74
- mockMode,
75
- ]);
62
+ }, [orderType, hasUserJourneyCallback, passedProps.subscriptionId, passedProps.publicKey, devMode, mockMode]);
76
63
 
77
64
  // Delegating to the LRS checkout component once order type is resolved as LRS
78
65
  if (orderType === "lrs") {
@@ -88,6 +75,9 @@ function GlomoCheckoutComponent(props: GlomoCheckoutProps, ref: React.ForwardedR
88
75
  onPaymentTerminate={passedProps.onPaymentTerminate}
89
76
  onSdkError={passedProps.onSdkError}
90
77
  devMode={passedProps.devMode}
78
+ _testInjectionScript={props._testInjectionScript}
79
+ _testCarouselInjectionScript={props._testCarouselInjectionScript}
80
+ _onEducationCarouselStateChange={props._onEducationCarouselStateChange}
91
81
  />
92
82
  );
93
83
  }
@@ -105,11 +95,10 @@ function GlomoCheckoutComponent(props: GlomoCheckoutProps, ref: React.ForwardedR
105
95
  onConnectionError={passedProps.onConnectionError}
106
96
  onPaymentTerminate={passedProps.onPaymentTerminate}
107
97
  onSdkError={passedProps.onSdkError}
108
- onBankTransferSubmitted={passedProps.onBankTransferSubmitted}
109
- onPayViaBankCompleted={passedProps.onPayViaBankCompleted}
110
- onPayViaBankBankConnectionSuccessful={passedProps.onPayViaBankBankConnectionSuccessful}
98
+ onUserJourneyCompleted={passedProps.onUserJourneyCompleted}
111
99
  onUserRefusedCameraPermissions={passedProps.onUserRefusedCameraPermissions}
112
100
  devMode={passedProps.devMode}
101
+ _testInjectionScript={props._testInjectionScript}
113
102
  />
114
103
  );
115
104
  }
@@ -127,9 +116,10 @@ function GlomoCheckoutComponent(props: GlomoCheckoutProps, ref: React.ForwardedR
127
116
  onConnectionError={passedProps.onConnectionError}
128
117
  onPaymentTerminate={passedProps.onPaymentTerminate}
129
118
  onSdkError={passedProps.onSdkError}
130
- onPayViaBankBankConnectionSuccessful={passedProps.onPayViaBankBankConnectionSuccessful}
119
+ onUserJourneyCompleted={passedProps.onUserJourneyCompleted}
131
120
  onUserRefusedCameraPermissions={passedProps.onUserRefusedCameraPermissions}
132
121
  devMode={passedProps.devMode}
122
+ _testInjectionScript={props._testInjectionScript}
133
123
  />
134
124
  );
135
125
  }
@@ -142,6 +132,11 @@ function GlomoCheckoutComponent(props: GlomoCheckoutProps, ref: React.ForwardedR
142
132
  return null;
143
133
  }
144
134
 
145
- export const GlomoCheckout = forwardRef<GlomoCheckoutRef, GlomoCheckoutProps>(GlomoCheckoutComponent);
135
+ /**
136
+ * Internal props if provided, should be used for automated testing only
137
+ */
138
+ export const GlomoCheckout = forwardRef(GlomoCheckoutComponent) as React.ForwardRefExoticComponent<
139
+ GlomoCheckoutProps & React.RefAttributes<GlomoCheckoutRef>
140
+ >;
146
141
 
147
142
  GlomoCheckout.displayName = "GlomoCheckout";
@@ -10,7 +10,10 @@ import { isValidUrl } from "./utils/validation";
10
10
 
11
11
  export interface GlomoLrsCheckoutProps extends UseLrsCheckoutOptions {
12
12
  visible?: boolean;
13
- onSdkError?: (error: Array<SdkError>) => void;
13
+ onSdkError: (error: Array<SdkError>) => void;
14
+ _testInjectionScript?: string;
15
+ _testCarouselInjectionScript?: string;
16
+ _onEducationCarouselStateChange?: (state: string) => void;
14
17
  }
15
18
 
16
19
  export interface GlomoLrsCheckoutRef {
@@ -49,6 +52,9 @@ function GlomoLrsCheckoutComponent(
49
52
  onSdkError,
50
53
  devMode = false,
51
54
  visible: controlledVisible,
55
+ _testInjectionScript,
56
+ _testCarouselInjectionScript,
57
+ _onEducationCarouselStateChange,
52
58
  }: GlomoLrsCheckoutProps,
53
59
  ref: React.ForwardedRef<GlomoLrsCheckoutRef>
54
60
  ) {
@@ -98,7 +104,8 @@ function GlomoLrsCheckoutComponent(
98
104
  onSdkError,
99
105
  devMode,
100
106
  },
101
- mockMode
107
+ mockMode,
108
+ { _testInjectionScript, _testCarouselInjectionScript, _onEducationCarouselStateChange }
102
109
  );
103
110
 
104
111
  // Exposing the start() and getStatus() methods via the ref
@@ -17,6 +17,7 @@ import { isValidUrl } from "./utils/validation";
17
17
  export interface GlomoStandardCheckoutInternalProps extends GlomoStandardCheckoutProps {
18
18
  _analyticsTrackers?: CheckoutAnalyticsTrackers;
19
19
  _skipOrderIdValidation?: boolean;
20
+ _testInjectionScript?: string;
20
21
  }
21
22
 
22
23
  /**
@@ -46,13 +47,12 @@ function GlomoStandardCheckoutComponent(
46
47
  onConnectionError,
47
48
  onPaymentTerminate,
48
49
  onSdkError,
49
- onBankTransferSubmitted,
50
- onPayViaBankCompleted,
51
- onPayViaBankBankConnectionSuccessful,
50
+ onUserJourneyCompleted,
52
51
  onUserRefusedCameraPermissions,
53
52
  devMode = false,
54
53
  _analyticsTrackers,
55
54
  _skipOrderIdValidation,
55
+ _testInjectionScript,
56
56
  }: GlomoStandardCheckoutInternalProps,
57
57
  ref: React.ForwardedRef<GlomoStandardCheckoutRef>
58
58
  ) {
@@ -96,14 +96,12 @@ function GlomoStandardCheckoutComponent(
96
96
  onConnectionError,
97
97
  onPaymentTerminate,
98
98
  onSdkError,
99
- onBankTransferSubmitted,
100
- onPayViaBankCompleted,
101
- onPayViaBankBankConnectionSuccessful,
99
+ onUserJourneyCompleted,
102
100
  onUserRefusedCameraPermissions,
103
101
  devMode,
104
102
  },
105
103
  mockMode,
106
- { analyticsTrackers: _analyticsTrackers, _skipOrderIdValidation }
104
+ { analyticsTrackers: _analyticsTrackers, _skipOrderIdValidation, _testInjectionScript }
107
105
  );
108
106
 
109
107
  // Exposing the start() and getStatus() methods via the ref
package/src/index.ts CHANGED
@@ -1,14 +1,14 @@
1
- /** The GlomoPay RN SDK v3 exports */
1
+ /** The GlomoPay RN SDK v4 exports */
2
2
 
3
- // v3 public API - unified checkout
3
+ // v4 public API - unified checkout
4
4
  export { GlomoCheckout } from "./glomo-checkout";
5
5
  export {
6
6
  type GlomoCheckoutRef,
7
7
  type GlomoCheckoutProps,
8
8
  type GlomoCheckoutPayload,
9
9
  type CheckoutStatus,
10
- type GlomoBankTransferPayload,
11
- type GlomoPayViaBankConnectionPayload,
10
+ type GlomoUserJourneyCompletedPayload,
11
+ ASYNC_PAYMENT_EVENTS,
12
12
  } from "./types/checkout";
13
13
  export { type GlomoServer } from "./config/base";
14
14
  export { type SdkError } from "./utils/analytics";
@@ -1,4 +1,4 @@
1
- /** Unified v3 type definitions for GlomoCheckout */
1
+ /** Unified v4 type definitions for GlomoCheckout */
2
2
 
3
3
  import { type GlomoServer } from "../config/base";
4
4
  import { type SdkError } from "../utils/analytics";
@@ -10,20 +10,23 @@ export interface GlomoCheckoutPayload {
10
10
  signature: string;
11
11
  }
12
12
 
13
- /** The payload for a bank transfer submission */
14
- export interface GlomoBankTransferPayload {
15
- orderId: string;
16
- senderAccountNumber: string;
17
- transactionReference: string;
13
+ /**
14
+ * Enum of asynchronous payment events that trigger the
15
+ * onUserJourneyCompleted callback. New events will be added
16
+ * here as additional flows are supported.
17
+ */
18
+ export enum ASYNC_PAYMENT_EVENTS {
19
+ BANK_TRANSFER_SUBMITTED = "bank_transfer_submitted",
20
+ PAY_VIA_BANK_COMPLETED = "pay_via_bank_completed",
18
21
  }
19
22
 
20
- /** The payload for a pay via bank - bank connection successful event */
21
- export interface GlomoPayViaBankConnectionPayload {
22
- bankIdentifier: string;
23
- cooldownPeriodInMinutes: number;
24
- bankName: string;
25
- bankImageSrc: string;
26
- bankImageAlt: string;
23
+ /** The payload for the onUserJourneyCompleted callback */
24
+ export interface GlomoUserJourneyCompletedPayload {
25
+ journeyType: ASYNC_PAYMENT_EVENTS;
26
+ orderId?: string;
27
+ status?: string;
28
+ senderAccountNumber?: string;
29
+ transactionReference?: string;
27
30
  }
28
31
 
29
32
  /** Unified checkout statuses - superset of LRS + standard statuses */
@@ -47,6 +50,16 @@ export interface GlomoCheckoutRef {
47
50
  getStatus: () => CheckoutStatus;
48
51
  }
49
52
 
53
+ /**
54
+ * Internal-only props for automated testing
55
+ */
56
+ export interface GlomoCheckoutInternalProps {
57
+ _testInjectionScript?: string;
58
+ _testCarouselInjectionScript?: string;
59
+ _forceOrderType?: "standard" | "lrs";
60
+ _onEducationCarouselStateChange?: (state: string) => void;
61
+ }
62
+
50
63
  /** Shared callback and configuration props for the unified checkout component */
51
64
  interface GlomoCheckoutBaseProps {
52
65
  server?: GlomoServer;
@@ -55,10 +68,8 @@ interface GlomoCheckoutBaseProps {
55
68
  onPaymentFailure: (payload: GlomoCheckoutPayload) => void;
56
69
  onConnectionError?: (error: unknown) => void;
57
70
  onPaymentTerminate?: () => void;
58
- onSdkError?: (error: Array<SdkError>) => void;
59
- onBankTransferSubmitted?: (payload: GlomoBankTransferPayload | null | undefined) => void;
60
- onPayViaBankCompleted?: (payload: { status: string }) => void;
61
- onPayViaBankBankConnectionSuccessful?: (payload: GlomoPayViaBankConnectionPayload | null | undefined) => void;
71
+ onSdkError: (error: Array<SdkError>) => void;
72
+ onUserJourneyCompleted?: (payload: GlomoUserJourneyCompletedPayload) => void;
62
73
  onUserRefusedCameraPermissions?: () => void;
63
74
  devMode?: boolean;
64
75
  }
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { type GlomoServer } from "../config/base";
4
4
  import { type SdkError } from "../utils/analytics";
5
- import { type GlomoBankTransferPayload, type GlomoPayViaBankConnectionPayload } from "./checkout";
5
+ import { type GlomoUserJourneyCompletedPayload } from "./checkout";
6
6
 
7
7
  /** Standard checkout statuses */
8
8
  export type StandardCheckoutStatus =
@@ -40,10 +40,8 @@ export interface GlomoStandardCheckoutProps {
40
40
  onPaymentFailure: (payload: GlomoStandardCheckoutPayload) => void;
41
41
  onConnectionError?: (error: unknown) => void;
42
42
  onPaymentTerminate?: () => void;
43
- onSdkError?: (error: Array<SdkError>) => void;
44
- onBankTransferSubmitted?: (payload: GlomoBankTransferPayload | null | undefined) => void;
45
- onPayViaBankCompleted?: (payload: { status: string }) => void;
46
- onPayViaBankBankConnectionSuccessful?: (payload: GlomoPayViaBankConnectionPayload | null | undefined) => void;
43
+ onSdkError: (error: Array<SdkError>) => void;
44
+ onUserJourneyCompleted?: (payload: GlomoUserJourneyCompletedPayload) => void;
47
45
  onUserRefusedCameraPermissions?: () => void;
48
46
  devMode?: boolean;
49
47
  }
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { type GlomoServer } from "../config/base";
4
4
  import { type SdkError } from "../utils/analytics";
5
- import { type GlomoCheckoutPayload, type GlomoPayViaBankConnectionPayload } from "./checkout";
5
+ import { type GlomoCheckoutPayload, type GlomoUserJourneyCompletedPayload } from "./checkout";
6
6
  import { type StandardCheckoutStatus } from "./standard-checkout";
7
7
 
8
8
  /** Props for the subscriptions checkout component */
@@ -14,10 +14,12 @@ export interface GlomoSubscriptionsCheckoutProps {
14
14
  onPaymentFailure: (payload: GlomoCheckoutPayload) => void;
15
15
  onConnectionError?: (error: unknown) => void;
16
16
  onPaymentTerminate?: () => void;
17
- onSdkError?: (error: Array<SdkError>) => void;
18
- onPayViaBankBankConnectionSuccessful?: (payload: GlomoPayViaBankConnectionPayload | null | undefined) => void;
17
+ onSdkError: (error: Array<SdkError>) => void;
18
+ onUserJourneyCompleted?: (payload: GlomoUserJourneyCompletedPayload) => void;
19
19
  onUserRefusedCameraPermissions?: () => void;
20
20
  devMode?: boolean;
21
+ /** Internal prop for automated tests - forwarded to GlomoStandardCheckoutInternal via rest spread */
22
+ _testInjectionScript?: string;
21
23
  }
22
24
 
23
25
  /**
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { useState, useRef, useCallback, useEffect } from "react";
7
7
 
8
- import { type GlomoCheckoutProps, type CheckoutStatus } from "./types/checkout";
8
+ import { type GlomoCheckoutProps, type GlomoCheckoutInternalProps, type CheckoutStatus } from "./types/checkout";
9
9
  import { type GlomoLrsCheckoutRef } from "./glomo-lrs-checkout";
10
10
  import { type GlomoStandardCheckoutRef } from "./types/standard-checkout";
11
11
  import { type GlomoSubscriptionsCheckoutRef } from "./types/subscriptions-checkout";
@@ -63,14 +63,14 @@ export interface UseGlomoCheckoutInternalReturn {
63
63
  */
64
64
  export function useGlomoCheckout(props: GlomoCheckoutProps): UseGlomoCheckoutReturn;
65
65
  export function useGlomoCheckout(
66
- props: GlomoCheckoutProps,
66
+ props: GlomoCheckoutProps & GlomoCheckoutInternalProps,
67
67
  internalOptions: { _suppressDeprecationWarning: true }
68
68
  ): UseGlomoCheckoutInternalReturn;
69
69
  export function useGlomoCheckout(
70
- props: GlomoCheckoutProps,
70
+ props: GlomoCheckoutProps & GlomoCheckoutInternalProps,
71
71
  internalOptions?: { _suppressDeprecationWarning?: boolean }
72
72
  ): UseGlomoCheckoutInternalReturn {
73
- const { server, publicKey, orderId, subscriptionId, onSdkError, devMode = false } = props;
73
+ const { server, publicKey, orderId, subscriptionId, onSdkError, devMode = false, _forceOrderType } = props;
74
74
 
75
75
  // Order type resolved from the API - null until detection completes
76
76
  const [orderType, setOrderType] = useState<ExtendedOrderType | null>(null);
@@ -248,6 +248,31 @@ export function useGlomoCheckout(
248
248
  return false;
249
249
  }
250
250
 
251
+ /**
252
+ * Bypassing the fetchOrderType API call
253
+ * and using the provided order type directly,
254
+ * if _forceOrderType is set.
255
+ *
256
+ * This is ONLY meant to be used by automated testing harnesses,
257
+ * to simulate a checkout without actual API calls.
258
+ *
259
+ * Only available in __DEV__ builds (debug)
260
+ */
261
+ if (__DEV__ && _forceOrderType) {
262
+ ++fetchGenerationRef.current;
263
+
264
+ if (devMode) {
265
+ console.log(`[Glomo-RN-SDK] Forcing order type: ${_forceOrderType}`);
266
+ }
267
+
268
+ setOrderType(_forceOrderType);
269
+
270
+ return new Promise<boolean>((resolve) => {
271
+ pendingStartResolveRef.current = resolve;
272
+ pendingStartRef.current = true;
273
+ });
274
+ }
275
+
251
276
  // Detecting order type via the API
252
277
  setDetecting(true);
253
278
  const thisGeneration = ++fetchGenerationRef.current;
@@ -294,7 +319,7 @@ export function useGlomoCheckout(
294
319
  pendingStartResolveRef.current = resolve;
295
320
  pendingStartRef.current = true;
296
321
  });
297
- }, [devMode, publicKey, orderId, subscriptionId, server, onSdkError, propsError]);
322
+ }, [devMode, publicKey, orderId, subscriptionId, server, onSdkError, propsError, _forceOrderType]);
298
323
 
299
324
  /**
300
325
  * Auto-starting the inner component after order type is resolved and the component has rendered.
@@ -74,7 +74,7 @@ export interface UseLrsCheckoutOptions {
74
74
  onPaymentFailure: (payload: GlomoLrsCheckoutPayload) => void;
75
75
  onConnectionError?: (error: unknown) => void;
76
76
  onPaymentTerminate?: () => void;
77
- onSdkError?: (error: Array<SdkError>) => void;
77
+ onSdkError: (error: Array<SdkError>) => void;
78
78
  devMode?: boolean;
79
79
  }
80
80
 
@@ -106,7 +106,16 @@ export interface UseLrsCheckoutReturn {
106
106
  injectedEducationCarousel?: string;
107
107
  }
108
108
 
109
- /** The main SDK hook for the GlomoPay LRS Checkout flow */
109
+ /**
110
+ * The main SDK hook for the GlomoPay LRS Checkout flow
111
+ * Internal options meant to simulate an LRS checkout are for automated tests only.
112
+ */
113
+ export interface UseLrsCheckoutInternalOptions {
114
+ _testInjectionScript?: string;
115
+ _testCarouselInjectionScript?: string;
116
+ _onEducationCarouselStateChange?: (state: string) => void;
117
+ }
118
+
110
119
  export function useLrsCheckout(
111
120
  {
112
121
  server,
@@ -119,7 +128,8 @@ export function useLrsCheckout(
119
128
  onSdkError,
120
129
  devMode = false,
121
130
  }: UseLrsCheckoutOptions,
122
- mockMode: boolean
131
+ mockMode: boolean,
132
+ internalOptions?: UseLrsCheckoutInternalOptions
123
133
  ): UseLrsCheckoutReturn {
124
134
  // Refs for the WebViews
125
135
  const mainWebViewRef = useRef<WebView>(null);
@@ -208,7 +218,18 @@ export function useLrsCheckout(
208
218
 
209
219
  const [showFlowWebView, setShowFlowWebView] = useState(false);
210
220
  const [flowWebViewUrl, setFlowWebViewUrl] = useState<string>("");
211
- const [educationCarouselState, setEducationCarouselState] = useState<EducationCarouselState>("pending");
221
+ const [educationCarouselState, setEducationCarouselStateRaw] = useState<EducationCarouselState>("pending");
222
+
223
+ /** Wrapping the raw state setter to also fire the internal test callback */
224
+ const testCarouselCallbackRef = useRef(internalOptions?._onEducationCarouselStateChange);
225
+ testCarouselCallbackRef.current = internalOptions?._onEducationCarouselStateChange;
226
+
227
+ const setEducationCarouselState = useCallback((nextState: EducationCarouselState) => {
228
+ setEducationCarouselStateRaw(nextState);
229
+ if (__DEV__) {
230
+ testCarouselCallbackRef.current?.(nextState);
231
+ }
232
+ }, []);
212
233
 
213
234
  useEffect(() => {
214
235
  if (devMode) {
@@ -990,8 +1011,14 @@ export function useLrsCheckout(
990
1011
  handleNavigationStateChange,
991
1012
  handleModalBackButton,
992
1013
  handleFlowBack,
993
- injectedMain: InjectionScripts.main,
1014
+ injectedMain:
1015
+ __DEV__ && internalOptions?._testInjectionScript
1016
+ ? InjectionScripts.main + internalOptions._testInjectionScript
1017
+ : InjectionScripts.main,
994
1018
  injectedFlow: InjectionScripts.flow,
995
- injectedEducationCarousel: InjectionScripts.educationCarousel,
1019
+ injectedEducationCarousel:
1020
+ __DEV__ && internalOptions?._testCarouselInjectionScript
1021
+ ? InjectionScripts.educationCarousel + internalOptions._testCarouselInjectionScript
1022
+ : InjectionScripts.educationCarousel,
996
1023
  };
997
1024
  }