diff --git a/README.md b/README.md index faf7a61bf..e788efaea 100644 --- a/README.md +++ b/README.md @@ -224,6 +224,28 @@ Certain payment methods require a [webhook listener](https://stripe.com/docs/pay - Run `stripe listen --forward-to localhost:4242/webhook` - The CLI will print a webhook secret (such as, `whsec_***`) to the console. Set STRIPE_WEBHOOK_SECRET to this value in your `example/.env` file. +## Testing + +This library includes a built in mock file for Jest. +In order to use it, add the following code to the Jest setup file: + +```tsx +import mock from '@stripe/stripe-react-native/jest/mock.js'; + +jest.mock('@stripe/stripe-react-native', () => mock); +``` + +To have a more control over the mocks, you can extend and override particular methods e.g.: + +```tsx +const presentApplePayMock = jest.fn(); + +jest.mock('@stripe/stripe-react-native', () => ({ + ...mock, + presentApplePay: presentApplePayMock, +})); +``` + ## Troubleshooting ### `Undefined symbols for architecture x86_64` on iOS diff --git a/jest/mock.js b/jest/mock.js new file mode 100644 index 000000000..c8d932da9 --- /dev/null +++ b/jest/mock.js @@ -0,0 +1,128 @@ +/* eslint-disable no-undef */ + +const mockFunctions = { + createPaymentMethod: jest.fn(async () => ({ + paymentMethod: {}, + error: null, + })), + createToken: jest.fn(async () => ({ + token: {}, + error: null, + })), + retrievePaymentIntent: jest.fn(async () => ({ + paymentIntent: {}, + error: null, + })), + retrieveSetupIntent: jest.fn(async () => ({ + setupIntent: {}, + error: null, + })), + confirmPayment: jest.fn(async () => ({ + paymentMethod: {}, + error: null, + })), + isApplePaySupported: jest.fn(async () => true), + presentApplePay: jest.fn(async () => ({ + error: null, + })), + updateApplePaySummaryItems: jest.fn(async () => ({})), + confirmApplePayPayment: jest.fn(async () => ({})), + handleCardAction: jest.fn(async () => ({ + paymentIntent: {}, + error: null, + })), + confirmSetupIntent: jest.fn(async () => ({ + setupIntent: {}, + error: null, + })), + createTokenForCVCUpdate: jest.fn(async () => ({ + tokenId: '123', + error: null, + })), + handleURLCallback: jest.fn(async () => true), + presentPaymentSheet: jest.fn(async () => ({ + paymentOption: {}, + error: null, + })), + confirmPaymentSheetPayment: jest.fn(async () => ({ + error: null, + })), + initGooglePay: jest.fn(async () => ({ + error: null, + })), + presentGooglePay: jest.fn(async () => ({ + error: null, + })), + createGooglePayPayment: jest.fn(async () => ({ + paymentMethod: {}, + error: null, + })), + openApplePaySetup: jest.fn(async () => ({ + error: null, + })), + initPaymentSheet: jest.fn(async () => ({ + paymentOption: {}, + error: null, + })), +}; + +const mockHooks = { + useConfirmPayment: jest.fn(() => ({ + confirmPayment: jest.fn(() => ({ + ...mockFunctions.confirmPayment(), + })), + })), + useConfirmSetupIntent: jest.fn(() => ({ + confirmSetupIntent: jest.fn(() => ({ + ...mockFunctions.confirmSetupIntent(), + })), + })), + useGooglePay: jest.fn(() => ({ + loading: false, + initGooglePay: jest.fn(async () => ({ + ...mockFunctions.initGooglePay(), + })), + presentGooglePay: jest.fn(async () => ({ + ...mockFunctions.presentGooglePay(), + })), + createGooglePayPaymentMethod: jest.fn(async () => ({ + ...mockFunctions.createGooglePayPayment(), + })), + })), + useApplePay: jest.fn(() => ({ + loading: false, + isApplePaySupported: true, + presentApplePay: jest.fn(async () => ({ + ...mockFunctions.presentApplePay(), + })), + confirmApplePayPayment: jest.fn(async () => ({ + ...mockFunctions.confirmApplePayPayment(), + })), + openApplePaySetup: jest.fn(async () => ({ + ...mockFunctions.openApplePaySetup(), + })), + })), + usePaymentSheet: jest.fn(() => ({ + loading: false, + initPaymentSheet: jest.fn(async () => ({ + ...mockFunctions.initPaymentSheet(), + })), + presentPaymentSheet: jest.fn(async () => ({ + ...mockFunctions.presentPaymentSheet(), + })), + confirmPaymentSheetPayment: jest.fn(async () => ({ + ...mockFunctions.confirmPaymentSheetPayment(), + })), + })), +}; + +module.exports = { + ...mockFunctions, + ...mockHooks, + StripeProvider: () => 'StripeProvider', + CardField: () => 'CardField', + ApplePayButton: () => 'ApplePayButton', + AuBECSDebitForm: () => 'AuBECSDebitForm', + GooglePayButton: () => 'GooglePayButton', + useStripe: jest.fn(() => mockHooks), +}; diff --git a/package.json b/package.json index 5aad3f756..2705baa9e 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "ios", "cpp", "app.plugin.js", - "stripe-react-native.podspec" + "stripe-react-native.podspec", + "jest" ], "scripts": { "test": "jest", diff --git a/src/hooks/useConfirmSetupIntent.tsx b/src/hooks/useConfirmSetupIntent.tsx index 9aa88c07b..7ff86827f 100644 --- a/src/hooks/useConfirmSetupIntent.tsx +++ b/src/hooks/useConfirmSetupIntent.tsx @@ -7,9 +7,9 @@ import { useStripe } from './useStripe'; */ export function useConfirmSetupIntent() { const [loading, setLoading] = useState(false); - const { confirmSetupIntent: confirmSetupIntentNative } = useStripe(); + const { confirmSetupIntent: confirmSetupIntent } = useStripe(); - const confirmSetupIntent = useCallback( + const _confirmSetupIntent = useCallback( async ( paymentIntentClientSecret: string, data: ConfirmSetupIntent.Params, @@ -17,7 +17,7 @@ export function useConfirmSetupIntent() { ) => { setLoading(true); - const result = await confirmSetupIntentNative( + const result = await confirmSetupIntent( paymentIntentClientSecret, data, options @@ -27,11 +27,11 @@ export function useConfirmSetupIntent() { return result; }, - [confirmSetupIntentNative] + [confirmSetupIntent] ); return { - confirmSetupIntent, + confirmSetupIntent: _confirmSetupIntent, loading, }; }