Skip to content

Commit 010e889

Browse files
test: add tests for version info JSON parsing in core.ts (#522)
- Added `src/__tests__/core.test.ts` to test `src/core.ts` initialization. - Mocks `NativeModules.Pushy` to simulate invalid and valid JSON for `currentVersionInfo`. - Uses dynamic import with query parameters to bypass Bun's module cache for testing top-level side effects. - Updated `src/__tests__/setup.ts` to provide better default mocks for the `Pushy` native module. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: sunnylqm <615282+sunnylqm@users.noreply.github.com>
1 parent 5fa4b4d commit 010e889

File tree

2 files changed

+123
-1
lines changed

2 files changed

+123
-1
lines changed

src/__tests__/core.test.ts

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { describe, expect, test, mock } from 'bun:test';
2+
3+
// In Bun, top-level imports are cached.
4+
// We can use mock.module to change the implementation of a module,
5+
// but if a module has already been executed (like core.ts),
6+
// re-importing it might not re-run the top-level code unless we use some tricks
7+
// or run tests in isolation.
8+
// Actually, bun test runs each file in its own environment usually,
9+
// BUT if we run multiple test files in one process, they might share the cache.
10+
11+
describe('core info parsing', () => {
12+
test('should call error when currentVersionInfo is invalid JSON', async () => {
13+
const mockError = mock(() => {});
14+
15+
mock.module('react-native', () => ({
16+
Platform: {
17+
OS: 'ios',
18+
Version: 13,
19+
},
20+
NativeModules: {
21+
Pushy: {
22+
currentVersionInfo: '{invalid}',
23+
downloadRootDir: '/tmp',
24+
packageVersion: '1.0.0',
25+
currentVersion: 'hash1',
26+
isFirstTime: false,
27+
rolledBackVersion: '',
28+
buildTime: '2023-01-01',
29+
uuid: 'existing-uuid',
30+
setLocalHashInfo: mock(() => {}),
31+
getLocalHashInfo: mock(() => Promise.resolve('{}')),
32+
setUuid: mock(() => {}),
33+
},
34+
},
35+
NativeEventEmitter: class {
36+
addListener = mock(() => ({ remove: mock(() => {}) }));
37+
},
38+
}));
39+
40+
mock.module('react-native/Libraries/Core/ReactNativeVersion', () => ({
41+
version: { major: 0, minor: 73, patch: 0 },
42+
}));
43+
44+
mock.module('nanoid/non-secure', () => ({
45+
nanoid: () => 'mock-uuid',
46+
}));
47+
48+
mock.module('../utils', () => ({
49+
error: mockError,
50+
log: mock(() => {}),
51+
emptyModule: {},
52+
}));
53+
54+
// Use a unique query parameter to bypass cache if supported, or just rely on fresh environment per file.
55+
// In Bun, you can sometimes use a cache buster if it's dynamic import.
56+
await import('../core?error');
57+
58+
expect(mockError).toHaveBeenCalledWith(
59+
expect.stringContaining('error_parse_version_info')
60+
);
61+
});
62+
63+
test('should not call error when currentVersionInfo is valid JSON', async () => {
64+
const mockError = mock(() => {});
65+
const mockSetLocalHashInfo = mock(() => {});
66+
67+
mock.module('react-native', () => ({
68+
Platform: {
69+
OS: 'ios',
70+
Version: 13,
71+
},
72+
NativeModules: {
73+
Pushy: {
74+
currentVersionInfo: JSON.stringify({ name: 'v1', debugChannel: true }),
75+
downloadRootDir: '/tmp',
76+
packageVersion: '1.0.0',
77+
currentVersion: 'hash1',
78+
isFirstTime: false,
79+
rolledBackVersion: '',
80+
buildTime: '2023-01-01',
81+
uuid: 'existing-uuid',
82+
setLocalHashInfo: mockSetLocalHashInfo,
83+
getLocalHashInfo: mock(() => Promise.resolve('{}')),
84+
setUuid: mock(() => {}),
85+
},
86+
},
87+
NativeEventEmitter: class {
88+
addListener = mock(() => ({ remove: mock(() => {}) }));
89+
},
90+
}));
91+
92+
mock.module('../utils', () => ({
93+
error: mockError,
94+
log: mock(() => {}),
95+
emptyModule: {},
96+
}));
97+
98+
await import('../core?success');
99+
100+
expect(mockError).not.toHaveBeenCalled();
101+
});
102+
});

src/__tests__/setup.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,34 @@ mock.module('react-native', () => {
44
return {
55
Platform: {
66
OS: 'ios',
7+
Version: 13,
8+
},
9+
NativeModules: {
10+
Pushy: {
11+
currentVersionInfo: '{}',
12+
downloadRootDir: '/tmp',
13+
packageVersion: '1.0.0',
14+
currentVersion: 'hash',
15+
isFirstTime: false,
16+
rolledBackVersion: '',
17+
buildTime: '2023-01-01',
18+
uuid: 'uuid',
19+
setLocalHashInfo: () => {},
20+
getLocalHashInfo: () => Promise.resolve('{}'),
21+
setUuid: () => {},
22+
},
23+
},
24+
NativeEventEmitter: class {
25+
addListener = () => ({ remove: () => {} });
26+
removeAllListeners = () => {};
727
},
828
};
929
});
1030

1131
mock.module('../i18n', () => {
1232
return {
1333
default: {
14-
t: (key: string) => key,
34+
t: (key: string, params?: any) => `${key}${params ? JSON.stringify(params) : ''}`,
1535
},
1636
};
1737
});

0 commit comments

Comments
 (0)