From 6e61697a7e66b34783b9db897f11847dd6686a7e Mon Sep 17 00:00:00 2001 From: Shepherd Date: Thu, 12 Sep 2024 11:10:48 -0400 Subject: [PATCH] Fix subscriptions record migration --- __test__/unit/services/indexedDb.test.ts | 92 ++++++++++++++++++------ src/shared/services/IndexedDb.ts | 40 ++++++++--- 2 files changed, 98 insertions(+), 34 deletions(-) diff --git a/__test__/unit/services/indexedDb.test.ts b/__test__/unit/services/indexedDb.test.ts index 38c3b08d3..c654e2fb0 100644 --- a/__test__/unit/services/indexedDb.test.ts +++ b/__test__/unit/services/indexedDb.test.ts @@ -1,9 +1,11 @@ +import { DUMMY_EXTERNAL_ID, DUMMY_ONESIGNAL_ID } from '../../support/constants'; import { LegacyModelName, ModelName, } from '../../../src/core/models/SupportedModels'; import IndexedDb from '../../../src/shared/services/IndexedDb'; import Random from '../../support/utils/Random'; +import { SubscriptionType } from '../../../src/core/models/SubscriptionModels'; require('fake-indexeddb/auto'); @@ -128,12 +130,26 @@ describe('migrations', () => { expect(result).toEqual({ modelId: '1' }); }); - test('migrates emailSubscriptions records into subscriptions', async () => { + test('migrates v5 email, push, sms subscriptions records to v6 subscriptions record', async () => { const dbName = 'testDbV5upgradeToV6' + Random.getRandomString(10); const db = newOSIndexedDb(dbName, 5); await db.put(LegacyModelName.EmailSubscriptions, { modelId: '1', modelName: LegacyModelName.EmailSubscriptions, + onesignalId: DUMMY_ONESIGNAL_ID, + type: SubscriptionType.Email, + }); + await db.put(LegacyModelName.PushSubscriptions, { + modelId: '2', + modelName: LegacyModelName.PushSubscriptions, + onesignalId: DUMMY_ONESIGNAL_ID, + type: SubscriptionType.ChromePush, + }); + await db.put(LegacyModelName.SmsSubscriptions, { + modelId: '3', + modelName: LegacyModelName.SmsSubscriptions, + onesignalId: DUMMY_ONESIGNAL_ID, + type: SubscriptionType.SMS, }); db.close(); @@ -144,38 +160,53 @@ describe('migrations', () => { modelId: '1', modelName: ModelName.Subscriptions, externalId: undefined, - onesignalId: undefined, + onesignalId: DUMMY_ONESIGNAL_ID, + type: SubscriptionType.Email, }, - ]); - }); - - test('migrates pushSubscriptions records into subscriptions', async () => { - const dbName = 'testDbV5upgradeToV6' + Random.getRandomString(10); - const db = newOSIndexedDb(dbName, 5); - await db.put(LegacyModelName.PushSubscriptions, { - modelId: '1', - modelName: LegacyModelName.PushSubscriptions, - }); - db.close(); - - const db2 = newOSIndexedDb(dbName, 6); - const result = await db2.getAll(ModelName.Subscriptions); - expect(result).toEqual([ { - modelId: '1', + modelId: '2', modelName: ModelName.Subscriptions, externalId: undefined, - onesignalId: undefined, + onesignalId: DUMMY_ONESIGNAL_ID, + type: SubscriptionType.ChromePush, + }, + { + modelId: '3', + modelName: ModelName.Subscriptions, + externalId: undefined, + onesignalId: DUMMY_ONESIGNAL_ID, + type: SubscriptionType.SMS, }, ]); }); - test('migrates smsSubscriptions records into subscriptions', async () => { + test('migrates v5 email, push, sms subscriptions records of logged in user to v6 subscriptions record with external id', async () => { const dbName = 'testDbV5upgradeToV6' + Random.getRandomString(10); const db = newOSIndexedDb(dbName, 5); - await db.put(LegacyModelName.SmsSubscriptions, { + await db.put(LegacyModelName.EmailSubscriptions, { modelId: '1', + modelName: LegacyModelName.EmailSubscriptions, + onesignalId: DUMMY_ONESIGNAL_ID, + type: SubscriptionType.Email, + }); + await db.put(LegacyModelName.PushSubscriptions, { + modelId: '2', + modelName: LegacyModelName.PushSubscriptions, + onesignalId: DUMMY_ONESIGNAL_ID, + type: SubscriptionType.ChromePush, + }); + await db.put(LegacyModelName.SmsSubscriptions, { + modelId: '3', modelName: LegacyModelName.SmsSubscriptions, + onesignalId: DUMMY_ONESIGNAL_ID, + type: SubscriptionType.SMS, + }); + // user is logged in + await db.put(ModelName.Identity, { + modelId: '4', + modelName: ModelName.Identity, + onesignalId: DUMMY_ONESIGNAL_ID, + externalId: DUMMY_EXTERNAL_ID, }); db.close(); @@ -185,8 +216,23 @@ describe('migrations', () => { { modelId: '1', modelName: ModelName.Subscriptions, - externalId: undefined, - onesignalId: undefined, + externalId: DUMMY_EXTERNAL_ID, + onesignalId: DUMMY_ONESIGNAL_ID, + type: SubscriptionType.Email, + }, + { + modelId: '2', + modelName: ModelName.Subscriptions, + externalId: DUMMY_EXTERNAL_ID, + onesignalId: DUMMY_ONESIGNAL_ID, + type: SubscriptionType.ChromePush, + }, + { + modelId: '3', + modelName: ModelName.Subscriptions, + externalId: DUMMY_EXTERNAL_ID, + onesignalId: DUMMY_ONESIGNAL_ID, + type: SubscriptionType.SMS, }, ]); }); diff --git a/src/shared/services/IndexedDb.ts b/src/shared/services/IndexedDb.ts index b75bceae6..f5509adcd 100644 --- a/src/shared/services/IndexedDb.ts +++ b/src/shared/services/IndexedDb.ts @@ -265,31 +265,49 @@ export default class IndexedDb { const newTableName = ModelName.Subscriptions; db.createObjectStore(newTableName, { keyPath: 'modelId' }); + let currentExternalId: string; + const identityCursor = transaction + .objectStore(ModelName.Identity) + .openCursor(); + identityCursor.onsuccess = () => { + if (identityCursor.result) { + currentExternalId = identityCursor.result.value.externalId; + } + }; + identityCursor.onerror = () => { + // If there is an error getting old records nothing we can do but + // move on. Old table will stay around so an attempt could be made + // later. + console.error( + 'Could not find ' + ModelName.Identity + ' records', + identityCursor.error, + ); + }; + Object.values(LegacyModelName).forEach((oldTableName) => { - const cursor = transaction.objectStore(oldTableName).openCursor(); - cursor.onsuccess = () => { - if (!cursor.result) { + const legacyCursor = transaction.objectStore(oldTableName).openCursor(); + legacyCursor.onsuccess = () => { + if (!legacyCursor.result) { // Delete old table once we have gone through all records db.deleteObjectStore(oldTableName); return; } - const oldValue = cursor.result.value; + const oldValue = legacyCursor.result.value; + transaction.objectStore(newTableName).put({ - modelId: oldValue.modelId, + ...oldValue, modelName: ModelName.Subscriptions, - onesignalId: oldValue.onesignalId, - externalId: oldValue.externalId, - data: oldValue.data, + externalId: currentExternalId, }); - cursor.result.continue(); + legacyCursor.result.continue(); }; - cursor.onerror = () => { + legacyCursor.onerror = () => { // If there is an error getting old records nothing we can do but // move on. Old table will stay around so an attempt could be made // later. console.error( 'Could not migrate ' + oldTableName + ' records', - cursor.error, + legacyCursor.error, ); }; });