JSDom 11.12.0 - как издеваться над localStorage?

С момента последнего выпуска JSDom я не могу издеваться localStorage больше.

Я пробовал следующие методы:

  1. Object.defineProperty(window, 'localStorage', {value: LocalStorageMock})
  2. window.localStorage = LocalStorageMock;
  3. jest.spyOn(window.localStorage, 'setItem')

Любой из этих методов не работал для меня, я все время получаю оригинал localStorage,

4 ответа

setItemSpy = jest.spyOn(Storage.prototype, 'setItem'); работает для меня.

Видел это исправление здесь: https://github.com/facebook/jest/issues/6858

Вы можете использовать пакет dom-storage, доступный через npm:

const Storage = require('dom-storage');
global.localStorage = new Storage(null, { strict: true });
global.sessionStorage = new Storage(null, { strict: true });

Мы используем последнюю версию jsdom для наших модульных тестов и вышеупомянутый метод работал отлично.

Я действительно столкнулся с этой же проблемой при обновлении Jest, но не уверен, что это случилось с вами, но я нашел это исправление здесь: https://github.com/facebook/jest/issues/6766

От OlivierB-OB:

В качестве временного решения вы можете установить jsdom "11.11.0" (точный) в качестве dev-зависимости в вашем пакете. Затем jest-environment-jsdom должен использовать эту версию вместо последней версии 11.12.0, вызывающей такое поведение. Ура!

После этого я проверял местное хранилище в настройках теста, и шпионаж возвращался к норме.

И реализация макета localstorage: https://github.com/facebook/jest/issues/2098 однако, не содержит removeItem, поэтому вам, возможно, придется добавить его.

Я создал функцию, которая издевается над localStorage. Он реализует только два метода getItemа также setItem. При необходимости вы можете легко добавить другие методы.

      export const localStorageImpl = {
    register: () => {
        let storage = (window as any).customLocalStorage;

        if(storage) {
            return {
                storage,
                methods: (window as any).customLocalStorageMethods
            }
        }

        storage = (window as any).customLocalStorage = {} as any;

        const setItem = jest.spyOn(Storage.prototype, 'setItem');
        setItem.mockImplementation((key, value) => {
            storage[key] = value;
        });

        const getItem = jest.spyOn(Storage.prototype, 'getItem');
        getItem.mockImplementation((key) => {
            return storage[key];
        });

        const methods = (window as any).customLocalStorageMethods = {
            setItem,
            getItem
        };

        return {
            storage,
            methods
        }
    },
    unregister: () => {
        const methods = (window as any).customLocalStorageMethods;
        if(methods){
            const { setItem, getItem } = methods as { setItem: jest.SpyInstance<void, [key: string, value: string]>, getItem: jest.SpyInstance<string, [key: string]> };
            setItem.mockReset();
            getItem.mockReset();
        }
        delete (window as any).customLocalStorageMethods;
        delete (window as any).customLocalStorage;
    }
}

Применение:

      it('should mock localStorage', () => {        
    const { methods } = localStorageImpl.register(); // mock localStorage
    
    const { getByTestId } = render(<Root />);
    fireEvent.click(getByTestId('column-size'));        
    expect(methods.setItem).toBeCalledTimes(1);

    localStorageImpl.unregister();
});
Другие вопросы по тегам