Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unit tests #353

Merged
merged 9 commits into from
Jun 29, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions dev-app/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -471,8 +471,8 @@ SPEC CHECKSUMS:
FBLazyVector: 2c76493a346ef8cacf1f442926a39f805fffec1f
FBReactNativeSpec: 371350f24afa87b6aba606972ec959dcd4a95c9a
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
glog: 476ee3e89abb49e07f822b48323c51c57124b572
RCT-Folly: 4d8508a426467c48885f1151029bc15fa5d7b3b8
glog: 5337263514dd6f09803962437687240c5dc39aa4
RCT-Folly: a21c126816d8025b547704b777a2ba552f3d9fa9
RCTRequired: 00581111c53531e39e3c6346ef0d2c0cf52a5a37
RCTTypeSafety: 07e03ee7800e7dd65cba8e52ad0c2edb06c96604
React: e61f4bf3c573d0c61c56b53dc3eb1d9daf0768a0
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"@expo/config-plugins": "^4.0.18",
"@react-native-community/bob": "^0.16.2",
"@react-native-community/eslint-config": "^2.0.0",
"@testing-library/react-native": "https://github.com/callstack/react-native-testing-library#main",
"@types/base-64": "^1.0.0",
"@types/jest": "^27.0.2",
"@types/react": "^16.9.19",
Expand All @@ -73,6 +74,7 @@
"prettier": "^2.0.5",
"react": "17.0.2",
"react-native": "0.68.1",
"react-test-renderer": "17.0.2",
"stripe": "^7.14.0",
"typedoc": "^0.22.15",
"typescript": "^4.6.2"
Expand Down
42 changes: 42 additions & 0 deletions src/__tests__/__snapshots__/functions.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`functions.test.ts Functions snapshot ensure there are no unexpected changes to the functions exports 1`] = `
Object {
"cancelCollectPaymentMethod": [Function],
"cancelCollectRefundPaymentMethod": [Function],
"cancelCollectSetupIntent": [Function],
"cancelDiscovering": [Function],
"cancelInstallingUpdate": [Function],
"cancelPaymentIntent": [Function],
"cancelReadReusableCard": [Function],
"cancelSetupIntent": [Function],
"clearCachedCredentials": [Function],
"clearReaderDisplay": [Function],
"collectPaymentMethod": [Function],
"collectRefundPaymentMethod": [Function],
"collectSetupIntentPaymentMethod": [Function],
"confirmSetupIntent": [Function],
"connectBluetoothReader": [Function],
"connectEmbeddedReader": [Function],
"connectHandoffReader": [Function],
"connectInternetReader": [Function],
"connectLocalMobileReader": [Function],
"connectUsbReader": [Function],
"createPaymentIntent": [Function],
"createSetupIntent": [Function],
"disconnectReader": [Function],
"discoverReaders": [Function],
"getLocations": [Function],
"initialize": [Function],
"installAvailableUpdate": [Function],
"processPayment": [Function],
"processRefund": [Function],
"readReusableCard": [Function],
"retrievePaymentIntent": [Function],
"retrieveSetupIntent": [Function],
"setConnectionToken": [Function],
"setReaderDisplay": [Function],
"setSimulatedCard": [Function],
"simulateReaderUpdate": [Function],
}
`;
9 changes: 9 additions & 0 deletions src/__tests__/functions.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import * as functions from '../functions';

describe('functions.test.ts', () => {
describe('Functions snapshot', () => {
it('ensure there are no unexpected changes to the functions exports', () => {
expect(functions).toMatchSnapshot();
});
});
});
4 changes: 2 additions & 2 deletions src/index.test.tsx → src/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as StripeTerminal from './index';
import * as StripeTerminal from '../index';

jest.mock(
'../node_modules/react-native/Libraries/EventEmitter/NativeEventEmitter'
'../../node_modules/react-native/Libraries/EventEmitter/NativeEventEmitter'
);

describe('index.ts', () => {
Expand Down
1 change: 0 additions & 1 deletion src/components/StripeTerminalProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { StripeTerminalContext } from './StripeTerminalContext';
import { initialize, setConnectionToken } from '../functions';
import { useListener } from '../hooks/useListener';
import { NativeModules } from 'react-native';
// @ts-ignore
import EventEmitter from 'react-native/Libraries/vendor/emitter/EventEmitter';

const {
Expand Down
59 changes: 59 additions & 0 deletions src/components/__tests__/StripeTerminalProvider.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import * as React from 'react';
import { StripeTerminalProvider } from '../StripeTerminalProvider';
import { fireEvent, render } from '@testing-library/react-native';
import { Text, TouchableOpacity } from 'react-native';
import { useStripeTerminal } from '../../hooks/useStripeTerminal';

jest.mock(
'../../../node_modules/react-native/Libraries/EventEmitter/NativeEventEmitter'
);

describe('StripeTerminalProvider.tsx', () => {
it('renders children correctly', () => {
const tokenProvider = jest.fn();
const { toJSON, findByText } = render(
<StripeTerminalProvider tokenProvider={tokenProvider} logLevel="error">
<Text>test text</Text>
</StripeTerminalProvider>
);
const childText = findByText('test text');
expect(toJSON()).toMatchSnapshot();
expect(childText).toBeTruthy();
});

it('ensure if tokenProvider is not called on render', () => {
const tokenProvider = jest.fn();
render(
<StripeTerminalProvider
tokenProvider={tokenProvider}
logLevel="error"
children={<></>}
/>
);
expect(tokenProvider).not.toBeCalled();
});

it('trigger tokenProvider on init', () => {
const tokenProvider = jest.fn().mockReturnValue('_token');

const ChildImpl = () => {
const { initialize } = useStripeTerminal();

return (
<TouchableOpacity onPress={() => initialize()}>
<Text>init</Text>
</TouchableOpacity>
);
};

const { getByText } = render(
<StripeTerminalProvider tokenProvider={tokenProvider} logLevel="error">
<ChildImpl />
</StripeTerminalProvider>
);

fireEvent.press(getByText('init'));
expect(tokenProvider).toBeCalled();
expect(tokenProvider).toReturnWith('_token');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`StripeTerminalProvider.tsx renders children correctly 1`] = `
<Text>
test text
</Text>
`;
2 changes: 1 addition & 1 deletion src/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ export async function getLocations(
}
return {
locations: locations!,
hasMore: hasMore!,
hasMore: hasMore || false,
error: undefined,
};
} catch (error) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`useStripeTerminal.test.tsx Public API snapshot ensure there are no unexpected changes to the hook exports 1`] = `
Object {
"current": Object {
"cancelCollectPaymentMethod": [Function],
"cancelCollectRefundPaymentMethod": [Function],
"cancelCollectSetupIntent": [Function],
"cancelDiscovering": [Function],
"cancelInstallingUpdate": [Function],
"cancelPaymentIntent": [Function],
"cancelReadReusableCard": [Function],
"cancelSetupIntent": [Function],
"clearCachedCredentials": [Function],
"clearReaderDisplay": [Function],
"collectPaymentMethod": [Function],
"collectRefundPaymentMethod": [Function],
"collectSetupIntentPaymentMethod": [Function],
"confirmSetupIntent": [Function],
"connectBluetoothReader": [Function],
"connectEmbeddedReader": [Function],
"connectHandoffReader": [Function],
"connectInternetReader": [Function],
"connectLocalMobileReader": [Function],
"connectUsbReader": [Function],
"connectedReader": null,
"createPaymentIntent": [Function],
"createSetupIntent": [Function],
"disconnectReader": [Function],
"discoverReaders": [Function],
"discoveredReaders": Array [],
"emitter": undefined,
"getLocations": [Function],
"initialize": [Function],
"installAvailableUpdate": [Function],
"isInitialized": false,
"loading": false,
"processPayment": [Function],
"processRefund": [Function],
"readReusableCard": [Function],
"retrievePaymentIntent": [Function],
"retrieveSetupIntent": [Function],
"setReaderDisplay": [Function],
"setSimulatedCard": [Function],
"simulateReaderUpdate": [Function],
},
}
`;
148 changes: 148 additions & 0 deletions src/hooks/__tests__/useStripeTerminal.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import * as React from 'react';
import { useStripeTerminal } from '../useStripeTerminal';
import { act, renderHook } from '@testing-library/react-native';
import { StripeTerminalContext } from '../../components/StripeTerminalContext';
import * as functions from '../../functions';

jest.mock(
'../../../node_modules/react-native/Libraries/EventEmitter/NativeEventEmitter'
);

const createContextWrapper =
(providerProps: any): React.FC =>
({ children }) =>
(
<StripeTerminalContext.Provider
value={{
isInitialized: false,
loading: false,
discoveredReaders: [],
setConnectedReader: jest.fn(),
log: jest.fn(),
setDiscoveredReaders: jest.fn(),
setIsInitialized: jest.fn(),
setLoading: jest.fn(),
connectedReader: null,
emitter: undefined,
initialize: jest.fn(),
...providerProps,
}}
>
{children}
</StripeTerminalContext.Provider>
);

describe('useStripeTerminal.test.tsx', () => {
describe('Public API snapshot', () => {
it('ensure there are no unexpected changes to the hook exports', () => {
const { result } = renderHook(() => useStripeTerminal(), {
wrapper: createContextWrapper({}),
});

expect(result).toMatchSnapshot();
});
});

it('should use context values', () => {
const { result } = renderHook(() => useStripeTerminal(), {
wrapper: createContextWrapper({
isInitialized: true,
loading: false,
connectedReader: { id: 12 },
discoveredReaders: [{ id: 12 }, { id: 15 }],
}),
});

const { isInitialized, loading, connectedReader, discoveredReaders } =
result.current;

expect(isInitialized).toEqual(true);
expect(loading).toEqual(loading);
expect(connectedReader).toMatchObject({ id: 12 });
expect(discoveredReaders).toMatchObject([{ id: 12 }, { id: 15 }]);
});

describe('Public methods are called properly', () => {
it('initialized method is called', () => {
const initializeFn = jest.fn();
const ContextWrapper = createContextWrapper({ initialize: initializeFn });
const { result } = renderHook(() => useStripeTerminal(), {
wrapper: ContextWrapper,
});

act(() => {
result.current.initialize();
});

expect(initializeFn).toBeCalled();
});

it('public methods are called when it is initialized', () => {
const connectBluetoothReaderFn = jest.fn();
const discoverReadersFn = jest.fn();
const cancelDiscoveringFn = jest.fn();

jest
.spyOn(functions, 'connectBluetoothReader')
.mockImplementation(connectBluetoothReaderFn);
jest
.spyOn(functions, 'discoverReaders')
.mockImplementation(discoverReadersFn);
jest
.spyOn(functions, 'cancelDiscovering')
.mockImplementation(cancelDiscoveringFn);

const ContextWrapper = createContextWrapper({ isInitialized: true });
const { result } = renderHook(() => useStripeTerminal(), {
wrapper: ContextWrapper,
});

act(() => {
result.current.connectBluetoothReader({} as any);
result.current.discoverReaders({} as any);
result.current.cancelDiscovering();
});

expect(connectBluetoothReaderFn).toBeCalled();
expect(discoverReadersFn).toBeCalled();
expect(cancelDiscoveringFn).toBeCalled();
});

it('public methods are not called when it is not initialized', () => {
const connectBluetoothReaderFn = jest.fn();
const discoverReadersFn = jest.fn();
const cancelDiscoveringFn = jest.fn();

jest
.spyOn(functions, 'connectBluetoothReader')
.mockImplementation(connectBluetoothReaderFn);
jest
.spyOn(functions, 'discoverReaders')
.mockImplementation(discoverReadersFn);
jest
.spyOn(functions, 'cancelDiscovering')
.mockImplementation(cancelDiscoveringFn);

console.error = jest.fn();

const ContextWrapper = createContextWrapper({ isInitialized: false });
const { result } = renderHook(() => useStripeTerminal(), {
wrapper: ContextWrapper,
});

act(() => {
result.current.connectBluetoothReader({} as any);
result.current.discoverReaders({} as any);
result.current.cancelDiscovering();
});

expect(connectBluetoothReaderFn).not.toBeCalled();
expect(discoverReadersFn).not.toBeCalled();
expect(cancelDiscoveringFn).not.toBeCalled();
expect(console.error).toBeCalledWith(
'First initialize the Stripe Terminal SDK before performing any action'
);
expect(console.error).toBeCalledTimes(3);
});
});
});
Loading