about summary refs log tree commit diff
path: root/src/state/persisted/__tests__/migrate.test.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/state/persisted/__tests__/migrate.test.ts')
-rw-r--r--src/state/persisted/__tests__/migrate.test.ts93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/state/persisted/__tests__/migrate.test.ts b/src/state/persisted/__tests__/migrate.test.ts
new file mode 100644
index 000000000..d42580efd
--- /dev/null
+++ b/src/state/persisted/__tests__/migrate.test.ts
@@ -0,0 +1,93 @@
+import {jest, expect, test, afterEach} from '@jest/globals'
+import AsyncStorage from '@react-native-async-storage/async-storage'
+
+import {defaults, schema} from '#/state/persisted/schema'
+import {transform, migrate} from '#/state/persisted/legacy'
+import * as store from '#/state/persisted/store'
+import {logger} from '#/logger'
+import * as fixtures from '#/state/persisted/__tests__/fixtures'
+
+const write = jest.mocked(store.write)
+const read = jest.mocked(store.read)
+
+jest.mock('#/logger')
+jest.mock('#/state/persisted/store', () => ({
+  write: jest.fn(),
+  read: jest.fn(),
+}))
+
+afterEach(() => {
+  jest.clearAllMocks()
+  AsyncStorage.clear()
+})
+
+test('migrate: fresh install', async () => {
+  await migrate()
+
+  expect(AsyncStorage.getItem).toHaveBeenCalledWith('root')
+  expect(read).toHaveBeenCalledTimes(1)
+  expect(logger.log).toHaveBeenCalledWith(
+    'persisted state: no migration needed',
+  )
+})
+
+test('migrate: fresh install, existing new storage', async () => {
+  read.mockResolvedValueOnce(defaults)
+
+  await migrate()
+
+  expect(AsyncStorage.getItem).toHaveBeenCalledWith('root')
+  expect(read).toHaveBeenCalledTimes(1)
+  expect(logger.log).toHaveBeenCalledWith(
+    'persisted state: no migration needed',
+  )
+})
+
+test('migrate: fresh install, AsyncStorage error', async () => {
+  const prevGetItem = AsyncStorage.getItem
+
+  const error = new Error('test error')
+
+  AsyncStorage.getItem = jest.fn(() => {
+    throw error
+  })
+
+  await migrate()
+
+  expect(AsyncStorage.getItem).toHaveBeenCalledWith('root')
+  expect(logger.error).toHaveBeenCalledWith(error, {
+    message: 'persisted state: error migrating legacy storage',
+  })
+
+  AsyncStorage.getItem = prevGetItem
+})
+
+test('migrate: has legacy data', async () => {
+  await AsyncStorage.setItem('root', JSON.stringify(fixtures.LEGACY_DATA_DUMP))
+
+  await migrate()
+
+  expect(write).toHaveBeenCalledWith(transform(fixtures.LEGACY_DATA_DUMP))
+  expect(logger.log).toHaveBeenCalledWith(
+    'persisted state: migrated legacy storage',
+  )
+})
+
+test('migrate: has legacy data, fails validation', async () => {
+  const legacy = fixtures.LEGACY_DATA_DUMP
+  // @ts-ignore
+  legacy.shell.colorMode = 'invalid'
+  await AsyncStorage.setItem('root', JSON.stringify(legacy))
+
+  await migrate()
+
+  const transformed = transform(legacy)
+  const validate = schema.safeParse(transformed)
+
+  expect(write).not.toHaveBeenCalled()
+  expect(logger.error).toHaveBeenCalledWith(
+    'persisted state: legacy data failed validation',
+    // @ts-ignore
+    {error: validate.error},
+  )
+})