|
6 | 6 | revalidatePro, |
7 | 7 | clearProForTesting, |
8 | 8 | configureRevenueCat, |
| 9 | + resetProIdentityForTesting, |
9 | 10 | } from '../../../src/services/proLicenseService'; |
10 | 11 |
|
11 | 12 | jest.mock('react-native-purchases', () => ({ |
@@ -170,4 +171,45 @@ describe('proLicenseService', () => { |
170 | 171 | expect(mockSetHasRegisteredPro).toHaveBeenCalledWith(false); |
171 | 172 | }); |
172 | 173 | }); |
| 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 | + }); |
173 | 215 | }); |
0 commit comments