Skip to content

Commit

Permalink
Merge pull request #38 from Bestra/bestra/add-storage-option
Browse files Browse the repository at this point in the history
Allow callers to pass in a Storage implementation
  • Loading branch information
manuelpuyol authored Oct 12, 2022
2 parents 1011459 + 662a1a7 commit e2d3656
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 9 deletions.
20 changes: 13 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<Storage, 'getItem' | 'setItem'>
}

// 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 = []

Expand All @@ -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)
Expand All @@ -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<Storage, 'getItem' | 'setItem' | 'removeItem'>}

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.
}
Expand Down Expand Up @@ -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 () {
Expand Down
44 changes: 42 additions & 2 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,32 @@ 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')

assert.equal(document.querySelector('#my-first-field').value, 'test2')
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',
Expand Down Expand Up @@ -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')
Expand All @@ -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'
Expand Down

0 comments on commit e2d3656

Please sign in to comment.