Auto mock all localStorage and sessionStorage APIs for your Jest tests
npx @tessl/cli install tessl/npm-jest-localstorage-mock@2.4.0Jest LocalStorage Mock provides working localStorage and sessionStorage APIs for Jest tests. It auto-mocks both storage APIs with Jest spy functions, enabling comprehensive testing of web applications that rely on browser storage without requiring a browser environment.
npm install --save-dev jest-localstorage-mock or yarn add --dev jest-localstorage-mockSetup typically happens via Jest configuration (no explicit imports needed):
{
"jest": {
"resetMocks": false,
"setupFiles": ["jest-localstorage-mock"]
}
}Manual setup:
import "jest-localstorage-mock";
// or
require("jest-localstorage-mock");For create-react-app projects, add to src/setupTests.js:
require('jest-localstorage-mock');And override Jest config in package.json:
{
"jest": {
"resetMocks": false
}
}For direct LocalStorage class usage:
import { LocalStorage } from "jest-localstorage-mock/src/localstorage";// After setup, localStorage and sessionStorage are available globally
test('should save to localStorage', () => {
const KEY = 'foo', VALUE = 'bar';
// Use localStorage/sessionStorage normally
localStorage.setItem(KEY, VALUE);
// Test with Jest spies
expect(localStorage.setItem).toHaveBeenLastCalledWith(KEY, VALUE);
expect(localStorage.__STORE__[KEY]).toBe(VALUE);
expect(Object.keys(localStorage.__STORE__).length).toBe(1);
});
// Clear storage between tests
beforeEach(() => {
localStorage.clear();
jest.clearAllMocks();
});Core mock implementation that provides all localStorage/sessionStorage methods as Jest spy functions.
/**
* LocalStorage mock class with Jest spy functions
* @param {Object} jest - Jest instance for creating mock functions
*/
class LocalStorage {
constructor(jest);
/** Get item from storage (Jest spy) */
getItem(key: string): string | null;
/** Store item in storage (Jest spy) - values coerced to string */
setItem(key: string, val: any): void;
/** Remove item from storage (Jest spy) */
removeItem(key: string): void;
/** Clear all items from storage (Jest spy) */
clear(): void;
/** Get key at specified index (Jest spy) */
key(idx: number): string | null;
/** Return string representation '[object Storage]' (Jest spy) */
toString(): string;
/** Number of items in storage */
get length(): number;
/** Direct access to storage object for test assertions */
get __STORE__(): LocalStorage;
}All standard Web Storage API methods are provided as Jest spy functions.
/**
* Get item from storage
* @param {string} key - Storage key
* @returns {string|null} Stored value or null if not found
*/
getItem(key: string): string | null;
/**
* Store item in storage
* @param {string} key - Storage key
* @param {any} val - Value to store (coerced to string)
*/
setItem(key: string, val: any): void;
/**
* Remove item from storage
* @param {string} key - Storage key to remove
*/
removeItem(key: string): void;
/**
* Clear all items from storage
*/
clear(): void;
/**
* Get key name at specified index
* @param {number} idx - Index of key to retrieve
* @returns {string|null} Key name or null if index out of bounds
*/
key(idx: number): string | null;/**
* Number of items currently stored
*/
length: number;
/**
* Direct access to storage object for test assertions
* Backwards compatibility property
*/
__STORE__: LocalStorage;The setup file automatically creates mock instances on the global scope.
/**
* Global localStorage mock (automatically created)
*/
global.localStorage: LocalStorage;
/**
* Global sessionStorage mock (automatically created)
*/
global.sessionStorage: LocalStorage;
/**
* Alternative localStorage mock (non-writable, if _localStorage exists)
*/
global._localStorage?: LocalStorage;
/**
* Alternative sessionStorage mock (non-writable, if _sessionStorage exists)
*/
global._sessionStorage?: LocalStorage;test('localStorage operations', () => {
// Store data
localStorage.setItem('user', 'alice');
localStorage.setItem('theme', 'dark');
// Retrieve data
expect(localStorage.getItem('user')).toBe('alice');
expect(localStorage.getItem('missing')).toBeNull();
// Check storage state
expect(localStorage.length).toBe(2);
expect(localStorage.key(0)).toBe('user');
// Remove data
localStorage.removeItem('theme');
expect(localStorage.length).toBe(1);
// Clear all
localStorage.clear();
expect(localStorage.length).toBe(0);
});test('storage method calls', () => {
localStorage.setItem('key', 'value');
// Verify method was called
expect(localStorage.setItem).toHaveBeenCalledTimes(1);
expect(localStorage.setItem).toHaveBeenLastCalledWith('key', 'value');
// Verify method was not called
expect(localStorage.removeItem).not.toHaveBeenCalled();
});test('direct storage inspection', () => {
localStorage.setItem('item1', 'value1');
localStorage.setItem('item2', 'value2');
// Access storage object directly
expect(localStorage.__STORE__.item1).toBe('value1');
expect(localStorage.__STORE__.item2).toBe('value2');
// Check all stored keys
const keys = Object.keys(localStorage.__STORE__);
expect(keys).toEqual(['item1', 'item2']);
});test('value coercion to string', () => {
// All values are coerced to strings
localStorage.setItem('number', 42);
localStorage.setItem('boolean', true);
localStorage.setItem('object', { key: 'value' });
expect(localStorage.getItem('number')).toBe('42');
expect(localStorage.getItem('boolean')).toBe('true');
expect(localStorage.getItem('object')).toBe('[object Object]');
});test('storage object behavior', () => {
// toString returns proper representation
expect(localStorage.toString()).toBe('[object Storage]');
expect(localStorage.toString).toHaveBeenCalled();
// Verify key method behavior
localStorage.setItem('first', 'value1');
localStorage.setItem('second', 'value2');
expect(localStorage.key(0)).toMatch(/^(first|second)$/);
expect(localStorage.key(999)).toBeNull();
});describe('localStorage tests', () => {
beforeEach(() => {
// Clear storage data
localStorage.clear();
// Reset Jest mocks
jest.clearAllMocks();
// Or reset individual mocks:
// localStorage.setItem.mockClear();
});
test('clean state for each test', () => {
expect(localStorage.length).toBe(0);
expect(localStorage.setItem).toHaveBeenCalledTimes(0);
});
});