|
| 1 | +import { APP_ID } from '__test__/constants'; |
1 | 2 | import TestContext from '__test__/support/environment/TestContext'; |
2 | 3 | import { TestEnvironment } from '__test__/support/environment/TestEnvironment'; |
| 4 | +import { setupSubModelStore } from '__test__/support/environment/TestEnvironmentHelpers'; |
3 | 5 | import Context from 'src/page/models/Context'; |
4 | 6 | import { type AppConfig } from 'src/shared/config/types'; |
5 | 7 | import type { MockInstance } from 'vitest'; |
6 | 8 | import { db } from '../database/client'; |
| 9 | +import { getAppState } from '../database/config'; |
7 | 10 | import * as InitHelper from './init'; |
8 | 11 |
|
9 | 12 | let isSubscriptionExpiringSpy: MockInstance; |
@@ -97,3 +100,99 @@ test('correct degree of persistNotification setting should be stored', async () |
97 | 100 | persistNotification = (await db.get('Options', 'persistNotification'))?.value; |
98 | 101 | expect(persistNotification).toBe(true); |
99 | 102 | }); |
| 103 | + |
| 104 | +/** initSaveState – App ID migration */ |
| 105 | +describe('initSaveState: App ID migration', () => { |
| 106 | + const OLD_APP_ID = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'; |
| 107 | + const NEW_APP_ID = APP_ID; // the default test app id used in TestEnvironment |
| 108 | + |
| 109 | + async function seedStaleState() { |
| 110 | + await db.put('Ids', { type: 'appId', id: OLD_APP_ID }); |
| 111 | + await db.put('Options', { key: 'isPushEnabled', value: true }); |
| 112 | + await db.put('Options', { key: 'lastPushId', value: 'old-push-id' }); |
| 113 | + await db.put('Options', { |
| 114 | + key: 'lastPushToken', |
| 115 | + value: 'old-push-token', |
| 116 | + }); |
| 117 | + await db.put('Options', { key: 'lastOptedIn', value: true }); |
| 118 | + await db.put('Ids', { type: 'registrationId', id: 'old-reg-token' }); |
| 119 | + } |
| 120 | + |
| 121 | + test('clears stale lastKnown* values when App ID changes', async () => { |
| 122 | + await seedStaleState(); |
| 123 | + |
| 124 | + await InitHelper.initSaveState(); |
| 125 | + |
| 126 | + const appState = await getAppState(); |
| 127 | + expect(appState.lastKnownPushEnabled).toBeNull(); |
| 128 | + expect(appState.lastKnownPushId).toBeUndefined(); |
| 129 | + expect(appState.lastKnownPushToken).toBeUndefined(); |
| 130 | + expect(appState.lastKnownOptedIn).toBeNull(); |
| 131 | + }); |
| 132 | + |
| 133 | + test('clears subscription models when App ID changes', async () => { |
| 134 | + await setupSubModelStore({ id: 'old-sub-id', token: 'old-token' }); |
| 135 | + expect( |
| 136 | + OneSignal._coreDirector._subscriptionModelStore._list().length, |
| 137 | + ).toBeGreaterThan(0); |
| 138 | + |
| 139 | + await seedStaleState(); |
| 140 | + await InitHelper.initSaveState(); |
| 141 | + |
| 142 | + expect( |
| 143 | + OneSignal._coreDirector._subscriptionModelStore._list(), |
| 144 | + ).toHaveLength(0); |
| 145 | + }); |
| 146 | + |
| 147 | + test('clears stale registrationId and deviceId when App ID changes', async () => { |
| 148 | + await seedStaleState(); |
| 149 | + await db.put('Ids', { type: 'userId', id: 'old-device-id' }); |
| 150 | + |
| 151 | + await InitHelper.initSaveState(); |
| 152 | + |
| 153 | + const regId = await db.get('Ids', 'registrationId'); |
| 154 | + expect(regId?.id).toBeNull(); |
| 155 | + const userId = await db.get('Ids', 'userId'); |
| 156 | + expect(userId?.id).toBeNull(); |
| 157 | + }); |
| 158 | + |
| 159 | + test('saves the new App ID after migration', async () => { |
| 160 | + await seedStaleState(); |
| 161 | + |
| 162 | + await InitHelper.initSaveState(); |
| 163 | + |
| 164 | + const storedAppId = await db.get('Ids', 'appId'); |
| 165 | + expect(storedAppId?.id).toBe(NEW_APP_ID); |
| 166 | + }); |
| 167 | + |
| 168 | + test('does NOT clear state when App ID has not changed', async () => { |
| 169 | + await db.put('Ids', { type: 'appId', id: NEW_APP_ID }); |
| 170 | + await db.put('Options', { key: 'isPushEnabled', value: true }); |
| 171 | + await db.put('Options', { key: 'lastPushId', value: 'current-id' }); |
| 172 | + await db.put('Options', { |
| 173 | + key: 'lastPushToken', |
| 174 | + value: 'current-token', |
| 175 | + }); |
| 176 | + await db.put('Options', { key: 'lastOptedIn', value: true }); |
| 177 | + |
| 178 | + await InitHelper.initSaveState(); |
| 179 | + |
| 180 | + const appState = await getAppState(); |
| 181 | + expect(appState.lastKnownPushEnabled).toBe(true); |
| 182 | + expect(appState.lastKnownPushId).toBe('current-id'); |
| 183 | + expect(appState.lastKnownPushToken).toBe('current-token'); |
| 184 | + expect(appState.lastKnownOptedIn).toBe(true); |
| 185 | + }); |
| 186 | + |
| 187 | + test('does NOT clear state on first-ever initialization (no previous App ID)', async () => { |
| 188 | + await db.put('Options', { key: 'isPushEnabled', value: true }); |
| 189 | + |
| 190 | + await InitHelper.initSaveState(); |
| 191 | + |
| 192 | + const appState = await getAppState(); |
| 193 | + expect(appState.lastKnownPushEnabled).toBe(true); |
| 194 | + |
| 195 | + const storedAppId = await db.get('Ids', 'appId'); |
| 196 | + expect(storedAppId?.id).toBe(NEW_APP_ID); |
| 197 | + }); |
| 198 | +}); |
0 commit comments