diff --git a/src/hooks/useLocalStorage.test.tsx b/src/hooks/useLocalStorage.test.tsx new file mode 100644 index 0000000..35a7e67 --- /dev/null +++ b/src/hooks/useLocalStorage.test.tsx @@ -0,0 +1,70 @@ +import { useLocalStorage } from './useLocalStorage'; +import React, { useCallback } from 'react'; +import { render, screen } from '@testing-library/react'; +import { UserEvent } from '@testing-library/user-event/dist/types/setup/setup'; +import userEvent from '@testing-library/user-event'; + +const valueToSave : string = 'Hello!'; +const storageKey: string = "Greeting"; + +describe(useLocalStorage.name, () => { + let user : UserEvent; + + beforeEach(() => { + user = userEvent.setup(); + }); + + afterEach(() => { + window.localStorage.clear(); + }); + + it('saves to local storage', async () => { + render(); + const buttonElement = screen.getByRole('button', { name: 'Save' }); + await user.click(buttonElement); + + expect(window.localStorage.getItem(storageKey)).toBe(valueToSave); + expect(screen.getByText(valueToSave)).toBeVisible(); + }); + + it('deletes from local storage', async () => { + render(); + const buttonElement = screen.getByRole('button', { name: 'Remove' }); + await user.click(buttonElement); + + expect(window.localStorage.getItem(storageKey)).toBe(null); + }); + + it('sets empty string when value is not in local storage', () => { + render(); + + expect(screen.getByTestId("currentValue").textContent).toBe(""); + }); + + it('reads from local storage', async () => { + window.localStorage.setItem(storageKey, valueToSave); + render(); + + expect(screen.getByText(valueToSave)).toBeVisible(); + }); +}); + +function StubComponent () { + const { save, currentValue, remove } = useLocalStorage(storageKey); + + const saveToLocalStorage = useCallback(() => { + save(valueToSave); + }, [save]); + + const removeFromLocalStorage = useCallback(() => { + remove(); + }, [save]); + + return ( +
+ + + {currentValue === null ? "null" : currentValue} +
+ ); +}; diff --git a/src/hooks/useLocalStorage.tsx b/src/hooks/useLocalStorage.tsx new file mode 100644 index 0000000..c742afc --- /dev/null +++ b/src/hooks/useLocalStorage.tsx @@ -0,0 +1,18 @@ +import { useState, useCallback } from "react"; + +export const useLocalStorage = (storageKey : string) => { + const [key] = useState(storageKey); + + const [currentValue, setCurrentValue] = useState(window.localStorage.getItem(key) ?? ""); + + const save = useCallback((input: string) => { + window.localStorage.setItem(key, input); + setCurrentValue(input); + }, [key]); + + const remove = useCallback(() => { + window.localStorage.removeItem(storageKey); + }, [key]); + + return { save, currentValue, remove }; +}; \ No newline at end of file