Skip to content

Commit 89cc17c

Browse files
test: restore branch coverage above 80% after merging main
Merging main's newer code nudged global branch coverage to 79.93%. Cover the gaps: - debugLogsStore: ring-buffer cap + clear (was 0%). - proLicenseService: resetProIdentityForTesting (anonymous/non-anonymous/error) and activateProByEmail error paths (logIn failure, miss + logOut failure). Branch coverage back to 80.06%. Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
1 parent 0a4aca2 commit 89cc17c

2 files changed

Lines changed: 69 additions & 0 deletions

File tree

__tests__/unit/services/proLicenseService.test.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
revalidatePro,
77
clearProForTesting,
88
configureRevenueCat,
9+
resetProIdentityForTesting,
910
} from '../../../src/services/proLicenseService';
1011

1112
jest.mock('react-native-purchases', () => ({
@@ -170,4 +171,45 @@ describe('proLicenseService', () => {
170171
expect(mockSetHasRegisteredPro).toHaveBeenCalledWith(false);
171172
});
172173
});
174+
175+
describe('resetProIdentityForTesting()', () => {
176+
it('logs out a non-anonymous user, clears the keychain, and resets the flag', async () => {
177+
Purchases.getCustomerInfo.mockResolvedValueOnce({ originalAppUserId: 'someone@example.com' });
178+
mockResetGenericPassword.mockResolvedValueOnce(true);
179+
await resetProIdentityForTesting();
180+
expect(Purchases.logOut).toHaveBeenCalledTimes(1);
181+
expect(mockResetGenericPassword).toHaveBeenCalledTimes(1);
182+
expect(mockSetHasRegisteredPro).toHaveBeenCalledWith(false);
183+
});
184+
185+
it('skips logOut for an anonymous user but still clears the keychain', async () => {
186+
Purchases.getCustomerInfo.mockResolvedValueOnce({ originalAppUserId: '$RCAnonymousID:abc123' });
187+
mockResetGenericPassword.mockResolvedValueOnce(true);
188+
await resetProIdentityForTesting();
189+
expect(Purchases.logOut).not.toHaveBeenCalled();
190+
expect(mockResetGenericPassword).toHaveBeenCalledTimes(1);
191+
expect(mockSetHasRegisteredPro).toHaveBeenCalledWith(false);
192+
});
193+
194+
it('still clears local state when getCustomerInfo throws', async () => {
195+
Purchases.getCustomerInfo.mockRejectedValueOnce(new Error('offline'));
196+
mockResetGenericPassword.mockResolvedValueOnce(true);
197+
await resetProIdentityForTesting();
198+
expect(mockResetGenericPassword).toHaveBeenCalledTimes(1);
199+
expect(mockSetHasRegisteredPro).toHaveBeenCalledWith(false);
200+
});
201+
});
202+
203+
describe('activateProByEmail() error paths', () => {
204+
it('rethrows when logIn fails', async () => {
205+
Purchases.logIn.mockRejectedValueOnce(new Error('network'));
206+
await expect(activateProByEmail('x@example.com')).rejects.toThrow('network');
207+
});
208+
209+
it('returns false on a miss and tolerates a logOut failure', async () => {
210+
Purchases.logIn.mockResolvedValueOnce({ customerInfo: customerWith(null) });
211+
Purchases.logOut.mockRejectedValueOnce(new Error('logout fail'));
212+
await expect(activateProByEmail('x@example.com')).resolves.toBe(false);
213+
});
214+
});
173215
});
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { useDebugLogsStore } from '../../../src/stores/debugLogsStore';
2+
3+
describe('debugLogsStore', () => {
4+
beforeEach(() => useDebugLogsStore.getState().clearLogs());
5+
6+
it('appends log entries in order', () => {
7+
useDebugLogsStore.getState().addLog({ timestamp: 1, level: 'log', message: 'a' });
8+
useDebugLogsStore.getState().addLog({ timestamp: 2, level: 'warn', message: 'b' });
9+
expect(useDebugLogsStore.getState().logs.map(l => l.message)).toEqual(['a', 'b']);
10+
});
11+
12+
it('caps the buffer at the in-memory limit, dropping the oldest', () => {
13+
for (let i = 0; i < 520; i++) {
14+
useDebugLogsStore.getState().addLog({ timestamp: i, level: 'log', message: `m${i}` });
15+
}
16+
const { logs } = useDebugLogsStore.getState();
17+
expect(logs.length).toBe(500);
18+
expect(logs[0].message).toBe('m20'); // oldest 20 dropped
19+
expect(logs[logs.length - 1].message).toBe('m519'); // newest kept
20+
});
21+
22+
it('clearLogs empties the buffer', () => {
23+
useDebugLogsStore.getState().addLog({ timestamp: 1, level: 'error', message: 'x' });
24+
useDebugLogsStore.getState().clearLogs();
25+
expect(useDebugLogsStore.getState().logs).toEqual([]);
26+
});
27+
});

0 commit comments

Comments
 (0)