Search code examples
javascriptmockingjestjsstoragenavigator

Jest: Mocking navigator.storage.persist


I am trying to mock the response for navigator.storage.persist:

 test('Navigator.storage.persist error should be caught', async () => {
        const persistMock = jest.fn(() => Promise.reject('Persist error'));

        Object.defineProperty(global.navigator,
            { 'storage': 'persist' }, {
            value: persistMock,
            configurable: true
        });

        try {
            await doStuff();
            expect(global.navigator.storage.persist.mock.calls).to.equal(1);
            expect(axios.mock.calls).to.equal(1);
        } catch (error) {
            expect(error).toBeUndefined();
        }
    })

The error I get: ReferenceError: persist is not defined

//Original Code

//Code in doStuff()
...
 try {
        const granted = await navigator.storage.persist();
        if (granted)
            console.log("Storage is now going to be persistent...", granted);
    } catch (error) {
        errorMessage = `Client did not allow storage to be persistent..${error}`;
    }
...

I know I'm mocking it wrong, but I cannot find any existing examples on web to imitate. At most I've seen something like How to mock window.navigator.language using jest , but in my case persist is nested in navigator.storage and I'm not sure how to get to that layer.

Thanks in advance!


Solution

  • You are almost there. Here is the unit test solution:

    index.ts:

    export async function doStuff() {
      try {
        const granted = await navigator.storage.persist();
        if (granted) {
          console.log('Storage is now going to be persistent...', granted);
        }
      } catch (error) {
        const errorMessage = `Client did not allow storage to be persistent..${error.message}`;
        throw new Error(errorMessage);
      }
    }
    

    index.test.ts:

    import { doStuff } from './';
    
    describe('61069460', () => {
      afterEach(() => {
        jest.restoreAllMocks();
      });
      it('should granted', async () => {
        const persistMock = jest.fn().mockResolvedValueOnce(true);
        Object.defineProperty(navigator, 'storage', {
          value: {
            persist: persistMock,
          },
          configurable: true,
        });
        const logSpy = jest.spyOn(console, 'log');
        await doStuff();
        expect(persistMock).toBeCalledTimes(1);
        expect(logSpy).toBeCalledWith('Storage is now going to be persistent...', true);
      });
    
      it('should throw custom error', async () => {
        const mError = new Error('IO');
        const persistMock = jest.fn().mockRejectedValueOnce(mError);
        Object.defineProperty(navigator, 'storage', {
          value: {
            persist: persistMock,
          },
          configurable: true,
        });
        const logSpy = jest.spyOn(console, 'log');
        await expect(doStuff()).rejects.toThrowError('Client did not allow storage to be persistent..IO');
        expect(persistMock).toBeCalledTimes(1);
        expect(logSpy).not.toBeCalled();
      });
    });
    

    unit test results with coverage report:

     PASS  stackoverflow/61069460/index.test.ts (9.134s)
      61069460
        ✓ should granted (15ms)
        ✓ should throw custom error (3ms)
    
      console.log node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866
        Storage is now going to be persistent... true
    
    ----------|---------|----------|---------|---------|-------------------
    File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    ----------|---------|----------|---------|---------|-------------------
    All files |     100 |       50 |     100 |     100 |                   
     index.ts |     100 |       50 |     100 |     100 | 4                 
    ----------|---------|----------|---------|---------|-------------------
    Test Suites: 1 passed, 1 total
    Tests:       2 passed, 2 total
    Snapshots:   0 total
    Time:        10.135s
    

    source code: https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/61069460