diff --git a/src/index.ts b/src/index.ts index 4163a69..1682e70 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,12 +5,17 @@ function shouldResumeField(field: HTMLInputElement | HTMLTextAreaElement): boole return !!field.id && field.value !== field.defaultValue && field.form !== submittedForm } -type PersistOptions = {selector?: string; keyPrefix?: string} +type PersistOptions = { + selector?: string + keyPrefix?: string + storage?: Pick +} // Write all ids and values of the selected fields on the page into sessionStorage. export function persistResumableFields(id: string, options?: PersistOptions): void { const selector = options?.selector ?? '.js-session-resumable' const keyPrefix = options?.keyPrefix ?? 'session-resume:' + const storage = options?.storage ?? sessionStorage const key = `${keyPrefix}${id}` const resumables = [] @@ -24,7 +29,7 @@ export function persistResumableFields(id: string, options?: PersistOptions): vo if (fields.length) { try { - const previouslyStoredFieldsJson = sessionStorage.getItem(key) + const previouslyStoredFieldsJson = storage.getItem(key) if (previouslyStoredFieldsJson !== null) { const previouslyStoredFields: string[][] = JSON.parse(previouslyStoredFieldsJson) @@ -34,22 +39,23 @@ export function persistResumableFields(id: string, options?: PersistOptions): vo fields = fields.concat(fieldsNotReplaced) } - sessionStorage.setItem(key, JSON.stringify(fields)) + storage.setItem(key, JSON.stringify(fields)) } catch { // Ignore browser private mode error. } } } -type RestoreOptions = {keyPrefix?: string} +type RestoreOptions = {keyPrefix?: string; storage?: Pick} export function restoreResumableFields(id: string, options?: RestoreOptions): void { const keyPrefix = options?.keyPrefix ?? 'session-resume:' + const storage = options?.storage ?? sessionStorage const key = `${keyPrefix}${id}` let fields try { - fields = sessionStorage.getItem(key) + fields = storage.getItem(key) } catch { // Ignore browser private mode error. } @@ -84,12 +90,12 @@ export function restoreResumableFields(id: string, options?: RestoreOptions): vo // they're needed. if (storedFieldsNotFound.length === 0) { try { - sessionStorage.removeItem(key) + storage.removeItem(key) } catch { // Ignore browser private mode error. } } else { - sessionStorage.setItem(key, JSON.stringify(storedFieldsNotFound)) + storage.setItem(key, JSON.stringify(storedFieldsNotFound)) } setTimeout(function () { diff --git a/test/test.js b/test/test.js index c093665..1cd6a1a 100644 --- a/test/test.js +++ b/test/test.js @@ -14,7 +14,7 @@ describe('session-resume', function () { }) describe('restoreResumableFields', function () { - it('restores fields values from session storage', function () { + it('restores fields values from session storage by default', function () { sessionStorage.setItem('session-resume:test-persist', JSON.stringify([['my-first-field', 'test2']])) restoreResumableFields('test-persist') @@ -22,6 +22,24 @@ describe('session-resume', function () { assert.equal(document.querySelector('#my-second-field').value, 'second-field-value') }) + it('uses a Storage object when provided as an option', function () { + const fakeStorageBackend = {} + const fakeStorage = { + setItem(key, value) { + fakeStorageBackend[key] = JSON.stringify(value) + }, + getItem(key) { + return JSON.parse(fakeStorageBackend[key] || null) + } + } + + fakeStorage.setItem('session-resume:test-persist', JSON.stringify([['my-first-field', 'test2']])) + restoreResumableFields('test-persist', {storage: fakeStorage}) + + assert.equal(document.querySelector('#my-first-field').value, 'test2') + assert.equal(document.querySelector('#my-second-field').value, 'second-field-value') + }) + it('leaves unrestored values in session storage', function () { sessionStorage.setItem( 'session-resume:test-persist', @@ -79,7 +97,7 @@ describe('session-resume', function () { }) describe('persistResumableFields', function () { - it('persist fields values to session storage', function () { + it('persist fields values to session storage by default', function () { document.querySelector('#my-first-field').value = 'test1' document.querySelector('#my-second-field').value = 'test2' persistResumableFields('test-persist') @@ -90,6 +108,28 @@ describe('session-resume', function () { ]) }) + it('uses a Storage object when provided as an option', function () { + document.querySelector('#my-first-field').value = 'test1' + document.querySelector('#my-second-field').value = 'test2' + + const fakeStorageBackend = {} + const fakeStorage = { + setItem(key, value) { + fakeStorageBackend[key] = JSON.stringify(value) + }, + getItem(key) { + return JSON.parse(fakeStorageBackend[key] || null) + } + } + + persistResumableFields('test-persist', {storage: fakeStorage}) + + assert.deepEqual(JSON.parse(fakeStorage.getItem('session-resume:test-persist')), [ + ['my-first-field', 'test1'], + ['my-second-field', 'test2'] + ]) + }) + it('holds onto existing values in the store', function () { sessionStorage.setItem('session-resume:test-persist', JSON.stringify([['non-existant-field', 'test3']])) document.querySelector('#my-first-field').value = 'test1'