Skip to content

Commit

Permalink
feat: implement useSession for managing web sessions
Browse files Browse the repository at this point in the history
  • Loading branch information
Ala committed Jun 11, 2024
1 parent 3110746 commit 9d556a9
Show file tree
Hide file tree
Showing 2 changed files with 231 additions and 0 deletions.
98 changes: 98 additions & 0 deletions src/hooks/__tests__/use-session.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { checkItem, getCurrentSession, useSession } from '../use-session'
import { renderHook, waitFor } from '@testing-library/react'
import { act } from 'react'

describe('useSessionStorage', () => {
beforeAll(() => {
localStorage.clear()
})

it('should clear the session storage', () => {
const { result } = renderHook(() => useSession())

act(() => result.current.clearsessionStorage())

expect(result.current.session.length).toBe(0)
})

it('should return session storage items after first call', () => {
const { result } = renderHook(() => useSession())

expect(result.current.session).toEqual(getCurrentSession())
})

it('should return an item or undefined', () => {
const { result } = renderHook(() => useSession())

const item = result.current.getValue('lib')

if (item) {
expect(item).toBe('rehook')
} else {
expect(item).toBeNull()
}
})

it('should rename the old key to the new key', () => {
const { result } = renderHook(() => useSession())

act(() => result.current.addItem('name', 'alaeddine'))

act(() => result.current.renameKey('name', 'firstname'))

expect(result.current.getValue('firstname')).not.toBeNull()
})

it('should delete the item', () => {
const { result } = renderHook(() => useSession())

act(() => result.current.addItem('age', 30))

act(() => result.current.deleteItem('age'))

expect(localStorage.getItem('age')).toBeNull()
})

it('should delete the item after 2 seconds', () => {
const { result } = renderHook(() => useSession())

act(() => result.current.addItem('age', '30'))

act(() => result.current.deleteItemAfterDelay('age', 2000))

waitFor(() => expect(localStorage.getItem('age')).toBeNull())
})

it('should return the the exact values or undefined', () => {
const { result } = renderHook(() => useSession())

act(() =>
result.current.addMultipleItems([
{ key: 'lib', value: 'rehook' },
{ key: 'creator', value: 'alaeddine' },
]),
)

const items = result.current.getMultipleValues(['lib', 'creator'])

expect(items.length).toBe(2)

expect(checkItem('lib')).toBe('rehook')

expect(checkItem('creator')).toBe('alaeddine')
})

it('should add a new item or throws an error if it is exist', () => {
const { result } = renderHook(() => useSession())

const item = result.current.getValue('lib')

if (item !== null) {
act(() => {
result.current.addItem('lib', 'rehook')
})

expect(item).toBe('rehook')
}
})
})
133 changes: 133 additions & 0 deletions src/hooks/use-session.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { useEffect, useState } from 'react'

export type Item = string | number | object | null

export const useSession = (fn?: () => void) => {
const items = getCurrentSession()

const [session, setSession] = useState<{ [x: string]: Item }[]>(items)

useEffect(() => {
if (fn && typeof fn == 'function') {
fn()
}
}, [session, fn])

const getValue = (itemKey: string) => {
const items = Object.values(session)

for (const item of items) {
if (itemKey in item) {
return item[itemKey]
}
}

return null
}

const renameKey = (oldKey: string, newKey: string) => {
const item = checkItem(oldKey)

if (!item) {
throw new Error('This item does not exist in the session storage')
}

const value = sessionStorage.getItem(oldKey)

sessionStorage.removeItem(oldKey)

if (value) {
sessionStorage.setItem(newKey, value)
setSession(getCurrentSession())
}
}

const getMultipleValues = (keys: string[]) => {
const multipleValues: string[] = []

keys.forEach(key => {
const value = getValue(key) as string
multipleValues.push(value)
})

return multipleValues
}

const addItem = (key: string, value: Item) => {
if (typeof value === 'object') {
sessionStorage.setItem(key, JSON.stringify(value))
}

if (typeof value === 'number') {
sessionStorage.setItem(key, value.toString())
}

if (typeof value === 'string') {
sessionStorage.setItem(key, value)
}

setSession([...session, { [key]: value }])
}

const addMultipleItems = (items: { key: string; value: string }[]) => {
for (const item of items) {
addItem(item.key, item.value)
}
}

const deleteItem = (key: string) => {
const item = checkItem(key)
if (!item) {
throw new Error('This item does not exist in the session storage')
}

if (item) {
sessionStorage.removeItem(key)
setSession(getCurrentSession())
}
}

const deleteItemAfterDelay = (key: string, time: number) => {
setTimeout(() => {
deleteItem(key)
}, time)
}

const deleteMultipleItems = (keys: string[]) => {
keys.forEach(key => {
deleteItem(key)
})
}

const clearsessionStorage = () => {
sessionStorage.clear()
setSession([])
}

return {
session,
getValue,
getMultipleValues,
addItem,
addMultipleItems,
renameKey,
deleteItem,
deleteItemAfterDelay,
deleteMultipleItems,
clearsessionStorage,
}
}

export const checkItem = (key: string) => sessionStorage.getItem(key)

export const getCurrentSession = () => {
const items: { [x: string]: string | null }[] = []

const keys = Object.keys(sessionStorage)

keys.forEach(key => {
items.push({ [key]: sessionStorage.getItem(key) })
})

return items
}

0 comments on commit 9d556a9

Please sign in to comment.