Skip to content

Commit defd1d3

Browse files
feat: add react-native unit test coverage (#14567)
1 parent 54c92b0 commit defd1d3

File tree

5 files changed

+396
-1
lines changed

5 files changed

+396
-1
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import {
5+
computeModPow,
6+
computeS,
7+
getDeviceName,
8+
getOperatingSystem,
9+
} from '../src/apis';
10+
import { nativeModule } from '../src/nativeModule';
11+
12+
jest.mock('react-native', () => ({
13+
Platform: { OS: 'ios' },
14+
NativeModules: {},
15+
}));
16+
17+
jest.mock('../src/nativeModule', () => ({
18+
nativeModule: {
19+
computeModPow: jest.fn(),
20+
computeS: jest.fn(),
21+
getDeviceName: jest.fn(),
22+
},
23+
}));
24+
25+
describe('APIs', () => {
26+
beforeEach(() => {
27+
jest.clearAllMocks();
28+
});
29+
30+
describe('getOperatingSystem', () => {
31+
it('should return Platform.OS', () => {
32+
expect(getOperatingSystem()).toBe('ios');
33+
});
34+
});
35+
36+
describe('computeModPow', () => {
37+
it('should call nativeModule.computeModPow with payload', () => {
38+
const payload = { base: '2', exponent: '3', divisor: '5' };
39+
computeModPow(payload);
40+
expect(nativeModule.computeModPow).toHaveBeenCalledWith(payload);
41+
});
42+
});
43+
44+
describe('computeS', () => {
45+
it('should call nativeModule.computeS with payload', () => {
46+
const payload = { g: '1', x: '2', k: '3', a: '4', b: '5', u: '6' };
47+
computeS(payload);
48+
expect(nativeModule.computeS).toHaveBeenCalledWith(payload);
49+
});
50+
});
51+
52+
describe('getDeviceName', () => {
53+
it('should call nativeModule.getDeviceName', () => {
54+
getDeviceName();
55+
expect(nativeModule.getDeviceName).toHaveBeenCalled();
56+
});
57+
});
58+
});
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
jest.mock('react-native', () => ({
5+
Platform: { OS: 'ios', select: jest.fn(() => '') },
6+
NativeModules: {
7+
AmplifyRTNCore: {
8+
computeModPow: jest.fn(),
9+
computeS: jest.fn(),
10+
getDeviceName: jest.fn(),
11+
},
12+
},
13+
AppState: { currentState: 'active' },
14+
}));
15+
16+
jest.mock('buffer', () => ({ Buffer: {} }));
17+
jest.mock('base-64', () => ({ decode: jest.fn(), encode: jest.fn() }));
18+
19+
describe('@aws-amplify/react-native', () => {
20+
it('should export all APIs', () => {
21+
const ReactNativeModule = require('../src/index');
22+
expect(ReactNativeModule.computeModPow).toBeDefined();
23+
expect(ReactNativeModule.computeS).toBeDefined();
24+
expect(ReactNativeModule.getOperatingSystem).toBeDefined();
25+
expect(ReactNativeModule.getDeviceName).toBeDefined();
26+
});
27+
28+
it('should export all module loaders', () => {
29+
const ReactNativeModule = require('../src/index');
30+
expect(ReactNativeModule.loadAmplifyPushNotification).toBeDefined();
31+
expect(ReactNativeModule.loadAmplifyWebBrowser).toBeDefined();
32+
expect(ReactNativeModule.loadAsyncStorage).toBeDefined();
33+
expect(ReactNativeModule.loadNetInfo).toBeDefined();
34+
expect(ReactNativeModule.loadBuffer).toBeDefined();
35+
expect(ReactNativeModule.loadUrlPolyfill).toBeDefined();
36+
expect(ReactNativeModule.loadGetRandomValues).toBeDefined();
37+
expect(ReactNativeModule.loadBase64).toBeDefined();
38+
expect(ReactNativeModule.loadAppState).toBeDefined();
39+
});
40+
});
Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
describe('Module Loaders', () => {
5+
beforeEach(() => {
6+
jest.resetModules();
7+
jest.clearAllMocks();
8+
});
9+
10+
describe('loadBuffer', () => {
11+
it('should return Buffer', () => {
12+
const mockBuffer = { from: jest.fn() };
13+
jest.doMock('buffer', () => ({ Buffer: mockBuffer }));
14+
const { loadBuffer } = require('../src/moduleLoaders/loadBuffer');
15+
expect(loadBuffer()).toBe(mockBuffer);
16+
});
17+
});
18+
19+
describe('loadBase64', () => {
20+
it('should return decode and encode functions', () => {
21+
const mockDecode = jest.fn();
22+
const mockEncode = jest.fn();
23+
jest.doMock('base-64', () => ({
24+
decode: mockDecode,
25+
encode: mockEncode,
26+
}));
27+
const { loadBase64 } = require('../src/moduleLoaders/loadBase64');
28+
const result = loadBase64();
29+
expect(result.decode).toBe(mockDecode);
30+
expect(result.encode).toBe(mockEncode);
31+
});
32+
});
33+
34+
describe('loadAppState', () => {
35+
it('should return AppState', () => {
36+
const mockAppState = { currentState: 'active' };
37+
jest.doMock('react-native', () => ({ AppState: mockAppState }));
38+
const { loadAppState } = require('../src/moduleLoaders/loadAppState');
39+
expect(loadAppState()).toBe(mockAppState);
40+
});
41+
});
42+
43+
describe('loadAsyncStorage', () => {
44+
it('should return AsyncStorage module when available', () => {
45+
const mockAsyncStorage = { getItem: jest.fn() };
46+
jest.doMock('@react-native-async-storage/async-storage', () => ({
47+
default: mockAsyncStorage,
48+
}));
49+
50+
const {
51+
loadAsyncStorage,
52+
} = require('../src/moduleLoaders/loadAsyncStorage');
53+
expect(loadAsyncStorage()).toBe(mockAsyncStorage);
54+
});
55+
56+
it('should throw error when AsyncStorage is not available', () => {
57+
jest.doMock('@react-native-async-storage/async-storage', () => {
58+
throw new Error('Cannot resolve module undefined');
59+
});
60+
61+
const {
62+
loadAsyncStorage,
63+
} = require('../src/moduleLoaders/loadAsyncStorage');
64+
expect(() => loadAsyncStorage()).toThrow(
65+
'@react-native-async-storage/async-storage',
66+
);
67+
});
68+
69+
it('should throw error when AsyncStorage default is null', () => {
70+
jest.doMock('@react-native-async-storage/async-storage', () => ({
71+
default: null,
72+
}));
73+
74+
const {
75+
loadAsyncStorage,
76+
} = require('../src/moduleLoaders/loadAsyncStorage');
77+
expect(() => loadAsyncStorage()).toThrow(
78+
'Ensure `@react-native-async-storage/async-storage` is installed and linked.',
79+
);
80+
});
81+
});
82+
83+
describe('loadNetInfo', () => {
84+
it('should return NetInfo module when available', () => {
85+
const mockNetInfo = { fetch: jest.fn() };
86+
jest.doMock('@react-native-community/netinfo', () => ({
87+
default: mockNetInfo,
88+
}));
89+
90+
const { loadNetInfo } = require('../src/moduleLoaders/loadNetInfo');
91+
expect(loadNetInfo()).toBe(mockNetInfo);
92+
});
93+
94+
it('should throw error when NetInfo is not available', () => {
95+
jest.doMock('@react-native-community/netinfo', () => {
96+
throw new Error('Cannot resolve module undefined');
97+
});
98+
99+
const { loadNetInfo } = require('../src/moduleLoaders/loadNetInfo');
100+
expect(() => loadNetInfo()).toThrow('@react-native-community/netinfo');
101+
});
102+
103+
it('should throw error when NetInfo default is null', () => {
104+
jest.doMock('@react-native-community/netinfo', () => ({
105+
default: null,
106+
}));
107+
108+
const { loadNetInfo } = require('../src/moduleLoaders/loadNetInfo');
109+
expect(() => loadNetInfo()).toThrow(
110+
'Ensure `@react-native-community/netinfo` is installed and linked.',
111+
);
112+
});
113+
});
114+
115+
describe('loadAmplifyPushNotification', () => {
116+
it('should return push notification module when available', () => {
117+
const mockModule = { initialize: jest.fn() };
118+
jest.doMock('@aws-amplify/rtn-push-notification', () => ({
119+
module: mockModule,
120+
}));
121+
122+
const {
123+
loadAmplifyPushNotification,
124+
} = require('../src/moduleLoaders/loadAmplifyPushNotification');
125+
expect(loadAmplifyPushNotification()).toBe(mockModule);
126+
});
127+
128+
it('should throw error when push notification module is not available', () => {
129+
jest.doMock('@aws-amplify/rtn-push-notification', () => {
130+
throw new Error('Cannot resolve module undefined');
131+
});
132+
133+
const {
134+
loadAmplifyPushNotification,
135+
} = require('../src/moduleLoaders/loadAmplifyPushNotification');
136+
expect(() => loadAmplifyPushNotification()).toThrow(
137+
'@aws-amplify/rtn-push-notification',
138+
);
139+
});
140+
141+
it('should throw error when push notification module is null', () => {
142+
jest.doMock('@aws-amplify/rtn-push-notification', () => ({
143+
module: null,
144+
}));
145+
146+
const {
147+
loadAmplifyPushNotification,
148+
} = require('../src/moduleLoaders/loadAmplifyPushNotification');
149+
expect(() => loadAmplifyPushNotification()).toThrow(
150+
'Ensure `@aws-amplify/rtn-push-notification` is installed and linked.',
151+
);
152+
});
153+
});
154+
155+
describe('loadAmplifyWebBrowser', () => {
156+
it('should return web browser module when available', () => {
157+
const mockModule = { openAuthSessionAsync: jest.fn() };
158+
jest.doMock('@aws-amplify/rtn-web-browser', () => ({
159+
module: mockModule,
160+
}));
161+
162+
const {
163+
loadAmplifyWebBrowser,
164+
} = require('../src/moduleLoaders/loadAmplifyWebBrowser');
165+
expect(loadAmplifyWebBrowser()).toBe(mockModule);
166+
});
167+
168+
it('should throw error when web browser module is not available', () => {
169+
jest.doMock('@aws-amplify/rtn-web-browser', () => {
170+
throw new Error('Cannot resolve module undefined');
171+
});
172+
173+
const {
174+
loadAmplifyWebBrowser,
175+
} = require('../src/moduleLoaders/loadAmplifyWebBrowser');
176+
expect(() => loadAmplifyWebBrowser()).toThrow(
177+
'@aws-amplify/rtn-web-browser',
178+
);
179+
});
180+
181+
it('should throw error when web browser module is null', () => {
182+
jest.doMock('@aws-amplify/rtn-web-browser', () => ({
183+
module: null,
184+
}));
185+
186+
const {
187+
loadAmplifyWebBrowser,
188+
} = require('../src/moduleLoaders/loadAmplifyWebBrowser');
189+
expect(() => loadAmplifyWebBrowser()).toThrow(
190+
'Ensure `@aws-amplify/rtn-web-browser` is installed and linked.',
191+
);
192+
});
193+
});
194+
195+
describe('loadUrlPolyfill', () => {
196+
it('should require react-native-url-polyfill/auto successfully', () => {
197+
jest.doMock('react-native-url-polyfill/auto', () => ({}));
198+
199+
const {
200+
loadUrlPolyfill,
201+
} = require('../src/moduleLoaders/loadUrlPolyfill');
202+
expect(() => loadUrlPolyfill()).not.toThrow();
203+
});
204+
205+
it('should throw error when url polyfill is not available', () => {
206+
jest.doMock('react-native-url-polyfill/auto', () => {
207+
throw new Error('Cannot resolve module undefined');
208+
});
209+
210+
const {
211+
loadUrlPolyfill,
212+
} = require('../src/moduleLoaders/loadUrlPolyfill');
213+
expect(() => loadUrlPolyfill()).toThrow('react-native-url-polyfill');
214+
});
215+
});
216+
217+
describe('loadGetRandomValues', () => {
218+
it('should require react-native-get-random-values successfully', () => {
219+
jest.doMock('react-native-get-random-values', () => ({}));
220+
221+
const {
222+
loadGetRandomValues,
223+
} = require('../src/moduleLoaders/loadGetRandomValues');
224+
expect(() => loadGetRandomValues()).not.toThrow();
225+
});
226+
227+
it('should throw error when get random values is not available', () => {
228+
jest.doMock('react-native-get-random-values', () => {
229+
throw new Error('Cannot resolve module undefined');
230+
});
231+
232+
const {
233+
loadGetRandomValues,
234+
} = require('../src/moduleLoaders/loadGetRandomValues');
235+
expect(() => loadGetRandomValues()).toThrow(
236+
'react-native-get-random-values',
237+
);
238+
});
239+
});
240+
});
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
describe('nativeModule', () => {
5+
beforeEach(() => {
6+
jest.resetModules();
7+
jest.clearAllMocks();
8+
});
9+
10+
it('should return NativeModules.AmplifyRTNCore when available', () => {
11+
const mockModule = { computeModPow: jest.fn() };
12+
jest.doMock('react-native', () => ({
13+
NativeModules: { AmplifyRTNCore: mockModule },
14+
Platform: { select: jest.fn() },
15+
}));
16+
17+
const { nativeModule } = require('../src/nativeModule');
18+
expect(nativeModule).toBe(mockModule);
19+
});
20+
21+
it('should return NativeModules.AmplifyRTNCore when it exists as empty object', () => {
22+
const mockModule = {};
23+
jest.doMock('react-native', () => ({
24+
NativeModules: { AmplifyRTNCore: mockModule },
25+
Platform: { select: jest.fn() },
26+
}));
27+
28+
const { nativeModule } = require('../src/nativeModule');
29+
expect(nativeModule).toBe(mockModule);
30+
});
31+
32+
it('should return proxy that throws error when AmplifyRTNCore is not available', () => {
33+
jest.doMock('react-native', () => ({
34+
NativeModules: {},
35+
Platform: { select: () => "- You have run 'pod install'\n" },
36+
}));
37+
38+
const { nativeModule } = require('../src/nativeModule');
39+
40+
expect(() => nativeModule.computeModPow()).toThrow(
41+
"The package '@aws-amplify/react-native' doesn't seem to be linked.",
42+
);
43+
});
44+
45+
it('should handle Platform.select returning empty string', () => {
46+
jest.doMock('react-native', () => ({
47+
NativeModules: {},
48+
Platform: { select: () => '' },
49+
}));
50+
51+
const { nativeModule } = require('../src/nativeModule');
52+
53+
expect(() => nativeModule.anyMethod()).toThrow(
54+
"The package '@aws-amplify/react-native' doesn't seem to be linked.",
55+
);
56+
});
57+
});

0 commit comments

Comments
 (0)