Git Product home page Git Product logo

jest-localstorage-mock's Introduction

Use this module with Jest to run web tests that rely on localstorage and / or sessionStorage where you want a working localStorage API with mocked functions.

This module has no runtime dependencies so your project won't pull in additional module dependencies by using this.

npm npm Codecov Greenkeeper badge Twitter

Jest 24+

Note that with jest@24 and above this project potentially duplicating functionality.

Install

This should only be installed as a development dependency (devDependencies) as it is only designed for testing. The module is transpiled via babel to support the current active Node LTS version (6.11.3).

yarn:

yarn add --dev jest-localstorage-mock

npm:

npm i --save-dev jest-localstorage-mock

Setup

The simplest setup is to use the module system, you may also choose to create a setup file if needed.

Module

In your package.json under the jest configuration section create a setupFiles array and add jest-localstorage-mock to the array. Also, ensure you have not enabled resetMocks.

{
  "jest": {
    "resetMocks": false,
    "setupFiles": ["jest-localstorage-mock"]
  }
}

If you already have a setupFiles attribute you can also append jest-localstorage-mock to the array.

{
  "jest": {
    "resetMocks": false,
    "setupFiles": ["./__setups__/other.js", "jest-localstorage-mock"]
  }
}

Setup file

Alternatively you can create a new setup file which then requires this module or add the require statement to an existing setup file.

__setups__/localstorage.js

import 'jest-localstorage-mock';
// or
require('jest-localstorage-mock');

Add that file to your setupFiles array:

"jest": {
  "setupFiles": [
    "./__setups__/localstorage.js"
  ]
}

In create-react-app

For a create-react-app project you can replace the suggested mock with this at the beginning of the existing src/setupTests.js file:

require('jest-localstorage-mock');

You must also override some of create-react-app's default jest configuration. You can do so in your package.json:

{
  "jest": {
    "resetMocks": false
  }
}

For more information, see #125.

In tests

By including this in your Jest setup you'll allow tests that expect a localStorage and sessionStorage object to continue to run. The module can also allow you to use the mocks provided to check that your localStorage is being used as expected.

The __STORE__ attribute of localStorage.__STORE__ or sessionStorage.__STORE__ is made available for you to directly access the storage object if needed.

Test Examples

Check that your localStorage calls were made when they were supposed to.

test('should save to localStorage', () => {
  const KEY = 'foo',
    VALUE = 'bar';
  dispatch(action.update(KEY, VALUE));
  expect(localStorage.setItem).toHaveBeenLastCalledWith(KEY, VALUE);
  expect(localStorage.__STORE__[KEY]).toBe(VALUE);
  expect(Object.keys(localStorage.__STORE__).length).toBe(1);
});

Check that your sessionStorage is empty, examples work with either localStorage or sessionStorage.

test('should have cleared the sessionStorage', () => {
  dispatch(action.reset());
  expect(sessionStorage.clear).toHaveBeenCalledTimes(1);
  expect(sessionStorage.__STORE__).toEqual({}); // check store values
  expect(sessionStorage.length).toBe(0); // or check length
});

Check that localStorage calls were not made when they shouldn't have been.

test('should not have saved to localStorage', () => {
  const KEY = 'foo',
    VALUE = 'bar';
  dispatch(action.notIdempotent(KEY, VALUE));
  expect(localStorage.setItem).not.toHaveBeenLastCalledWith(KEY, VALUE);
  expect(Object.keys(localStorage.__STORE__).length).toBe(0);
});

Reset your localStorage data and mocks before each test to prevent leaking.

beforeEach(() => {
  // to fully reset the state between tests, clear the storage
  localStorage.clear();
  // and reset all mocks
  jest.clearAllMocks();
  
  // clearAllMocks will impact your other mocks too, so you can optionally reset individual mocks instead:
  localStorage.setItem.mockClear();
});

test('should not impact the next test', () => {
  const KEY = 'foo',
    VALUE = 'bar';
  dispatch(action.update(KEY, VALUE));
  expect(localStorage.setItem).toHaveBeenLastCalledWith(KEY, VALUE);
  expect(localStorage.__STORE__[KEY]).toBe(VALUE);
  expect(Object.keys(localStorage.__STORE__).length).toBe(1);
});

test('should not be impacted by the previous test', () => {
  const KEY = 'baz',
    VALUE = 'zab';
  dispatch(action.update(KEY, VALUE));
  expect(localStorage.setItem).toHaveBeenLastCalledWith(KEY, VALUE);
  expect(localStorage.__STORE__[KEY]).toBe(VALUE);
  expect(Object.keys(localStorage.__STORE__).length).toBe(1);
});

See the contributing guide for details on how you can contribute.

jest-localstorage-mock's People

Contributors

amitzur avatar aoechamp avatar clarkbw avatar dependabot[bot] avatar flbraun avatar geoffdutton avatar greenkeeper[bot] avatar greenkeeperio-bot avatar mcshiz avatar mfogel avatar sbdchd avatar vst-h avatar zachmayry avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jest-localstorage-mock's Issues

How to extend localStorage.getItem?

The project I'm working on has extended the default localStorage.getItem method to return a fallback value (if set) if the item is undefined/null.

/**
 * Get an item from localStorage
 * @param {String} key - the key of the value
 * @param {*} fallbackValue - the fallback value in case the item cannot be retrieved
 */
export const getItem = (key, fallbackValue) => {
    let item;

    if (hasLocalStorage()) {
        item = localstorage.getItem(key);
    }

    if ((typeof item === 'undefined' || item === null) && typeof fallbackValue !== 'undefined') {
        return fallbackValue;
    }

    return item;
};

How would I extend the mock getItem method to match?

I'm currently using the function like this: const getItem = jest.fn(localStorage.getItem);

Cannot use it after update Jest

When I was using Jest 23.1.0, the library runs perfectly. After I update Jest to 23.4.2 and jest-environment-jsdom to 23.4.0, the test give me message:

SecurityError: localStorage is not available for opaque origins

I added

"testURL": "http://localhost" 
"verbose": true

to Jest configuration. But I still get the error message:

expect(jest.fn())[.not].toHaveBeenCalledTimes()
jest.fn() value must be a mock function or spy.

when I have test code like "expect(localStorage.removeItem).toHaveBeenCalledTimes(1);"

"jest.resetAllMocks();" does not work

capture d ecran 2018-08-22 a 16 28 23

in the README, you say that jest.resetAllMocks works, but it does not, if I use it, the __STORE__ is always empty even if I setItem() in my tests

localStorage.clear(); for instance works as expected

but when I use jest.resetAllMocks (to clear other mocks of my test) in combination to localStorage.clear();, it does not work anymore

I'm running jest v23.4.2

getItem() bug

I seem to have found the wrong work of getItem() method. Try this code in browser console and mock:

localStorage.setItem("param", 1);

typeof JSON.parse(localStorage.getItem("param")); // "number" in Chrome and "string" in this mock

It not bug in JSON.parse() method because I also tested typeof JSON.parse("1") in Node and it was "number".

SessionStorage?

I'm having issue with session storage working. When i use local storage it works, but when i replace the local storage with session storage it breaks. Does it need to be configured differently for session storage usage.

Thanks,
Derek

`setItem` does not set the value into storage

I cannot seem to get setItem working in the latest version of create-react-app. This is using jest 26.6.0.

Example code

// src/setupTests.js
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import "@testing-library/jest-dom";
import "jest-localstorage-mock";
// App.test.js
test("localStorage", () => {
  localStorage.setItem("test", "test");
  expect(localStorage.getItem("test")).toBe("test");
});

This will fail:

 FAIL  src/App.test.js
  ✕ localStorage (2 ms)

  ● localStorage

    expect(received).toBe(expected) // Object.is equality

    Expected: "test"
    Received: undefined

      1 | test("localStorage", () => {
      2 |   localStorage.setItem("test", "test");
    > 3 |   expect(localStorage.getItem("test")).toBe("test");
        |                                        ^
      4 | });
      5 |

      at Object.<anonymous> (src/App.test.js:3:40)

Am I missing something?

Reproduction repo

https://github.com/bitttttten/jest-localstorage-mock-issue-repro

docs: usage with create-react-app now requires explicitly setting resetMocks: false

Hi, thanks for this package, appreciate you sharing your work.

Since create react app 4.0, the default jest config has resetMocks: true set.

This is a bit controversial because it breaks stuff (including this packge).... see facebook/create-react-app#9935 Personally I think they would have been better off to stay conservative and just set clearMocks: true.

In any case, it might be worth mentioning in the README for this package that:

  • setting resetMocks: true will break this package
  • when using create react app, you need to explicitly set resetMocks: false

An in-range update of rollup is breaking the build 🚨

The devDependency rollup was updated from 1.27.6 to 1.27.7.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

rollup is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ci/circleci: Your tests failed on CircleCI (Details).

Release Notes for v1.27.7

2019-12-01

Bug Fixes

  • Fix a scenario where a reassignments to computed properties were not tracked (#3267)

Pull Requests

Commits

The new version differs by 4 commits.

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

An in-range update of rollup-plugin-babel is breaking the build 🚨

The devDependency rollup-plugin-babel was updated from 4.0.3 to 4.1.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

rollup-plugin-babel is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ci/circleci: Your tests failed on CircleCI (Details).

Commits

The new version differs by 12 commits.

  • de25402 4.1.0
  • 4f09a91 4.1.0-1
  • bb58960 Return null from the transform hook when it doesn't transform anything
  • 97953e1 Fix indentation in examples of configuration in readme (#266)
  • becd7ea Remove babel 6 test from AppVeyor (#263)
  • 5168424 Upgraded husky
  • 3a9ba87 Add options.extensions to README (#256)
  • b709cad 4.1.0-0
  • 8dbe1d2 Tweak eslint rules to stop conflicting with prettier output
  • 01d2095 Run prettier over the repo files
  • 6bb0e49 Setup prettier
  • 22f1b81 Fix preflightChecks for ignored files

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Test Retrieving from localStorage

If I am trying to initialize testing my component with some data like so

let obj = {
    date: "2017-12-23T17:33:33.265Z",
    obj: {"hello":"world"}
};

localStorage.setItem(obj.date, JSON.stringify(obj.obj));
expect(localStorage.setItem).toHaveBeenCalledTimes(1); // PASSES

But in my component I am setting the state with what is in localStorage like this:

let keys = Object.keys(localStorage);
keys.map((key) => {
        if(Date.parse(key) && moment(key).isValid()) {
            let item = JSON.parse(localStorage.getItem(key));
            item['date'] = moment(key);
            data.push(item)
        }
 });
this.setState({
        data: data
})

this.state.data will always be empty because all of the data is set to localStorage.__STORE__
How would you go about testing something like this?

Automatically run prettier

The README / development guide suggests always running yarn run prettier before every PR. I'd rather have this part automated.

How do I make API methods throw an exception

Here's a checklist you can use to make sure your issue can be more easily resolved:

  • Check against the latest
  • Include a link to the example application source code

I am trying to write a test, which assumes that sometimes getItem or setItem throw, this can happen f.e. if you are browser LS is running out of space.

What I've tried:

  • localStorage.setItem.mockImplementation(() => { throw new Error('error') })
  • jest.spyOn(localStorage, 'setItem').mockImplementation(() => { throw new Error('error') })

Both examples work, however I cannot restore mocks to original behaviour defined in the library, I've tried:

  • jest.resetAllMocks or localStorage.setItem.mockReset for 1st example
  • jest.restoreAllMocks or localStorage.setItem.mockRestore for 2nd example

Am I missing something obvious or is it methods defined through defineProperty prevents me from doing this?

The `undefined` value is inconsistent with the browser

localStorage.setItem("k", undefined)
let val1 = localStorage.getItem("k") 
console.log(val1) // val1 === null , browser:  val1 === "undefined"
console.log(localStorage) // LocalStorage { k: '' }

The above code val1 === null, by logging localStorage, the value of k is ''.
Check the code the problem should be here: code. (key, val = '') => , the val parameter should not have a default value.

An in-range update of prettier is breaking the build 🚨

The devDependency prettier was updated from 1.14.3 to 1.15.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

prettier is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ci/circleci: Your tests failed on CircleCI (Details).

Release Notes for Prettier 1.15: HTML, Vue, Angular and MDX Support

🔗 Release Notes

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

localStorage key "key" is reserved?

Hey,

I was using key and value dummy strings and it took me a while to figure out that key behaves differently in jest-localstorage-mock than other random strings:

console.log(localStorage.getItem("bla"));

  console.log src/utils/ReactApp/ReactAppUtils.js:13
    null

console.log(localStorage.getItem("key"));

  console.log src/utils/ReactApp/ReactAppUtils.js:12
    { [Function: mockConstructor]
      _isMockFunction: true,
      getMockImplementation: [Function],
      mock: [Getter/Setter],
      mockClear: [Function],
      mockReset: [Function],
      mockRestore: [Function],
      mockReturnValueOnce: [Function],
      mockResolvedValueOnce: [Function],
      mockRejectedValueOnce: [Function],
      mockReturnValue: [Function],
      mockResolvedValue: [Function],
      mockRejectedValue: [Function],
      mockImplementationOnce: [Function],
      mockImplementation: [Function],
      mockReturnThis: [Function],
      mockName: [Function],
      getMockName: [Function] }

While in my browser:

console.log(localStorage.getItem("key"));
// => null

I think this is pretty misleading. Perhaps it could be fixed or menioned in the readme?

getItem and setItem value implementation for localstorage

Hi,

Thanks for the nice work in creating this. I was working with it and I am wondering it both the setItem and getItem should force the value to become a string. Looking back into the specs. The interface shows that the values should be DOMString. I am not sure if I am reading the DOMString spec right but that appears to be a string as well. Mozilla indicates it to be a string as well.

I am wondering if there might be code required to handle JSON values as well. I tried accessing the store for github and I think the value is converted to be a string on Chrome and Firefox when the value is a json object

Object.defineProperty(this, 'getItem', {
enumerable: false,
value: jest.fn(key => this[key] || null),
});
Object.defineProperty(this, 'setItem', {
enumerable: false,
// not mentioned in the spec, but we must always coerce to a string
value: jest.fn((key, val = '') => {
this[key] = val + '';
}),
});

Image of localStorage.getItem in Chrome and Mozilla for json values
Screen Shot 2020-01-06 at 1 04 03 PM

Image of interface for localStorage
Screen Shot 2020-01-06 at 12 52 29 PM
Reference: https://html.spec.whatwg.org/multipage/webstorage.html

DOMString:
https://heycam.github.io/webidl/#idl-DOMString
https://developer.mozilla.org/en-US/docs/Web/API/DOMString

Add 2.0.0 changelog/migration notes

A quick look through the repo didn't make it clear what changed from version <2.0.0 to 2.0.0, and whether the assumed BC break would affect (my) use of the module.

Maybe the 2.0.0 release could be updated with a short blurb about the upgrade?

Error on latest version on Jest (23.5.0)

Here's a checklist you can use to make sure your issue can be more easily resolved:

  • Check against the latest
  • Include a link to the example application source code
  • Paste into this issue the exact error messages messages you're seeing

Whenever I run my tests with Jest version 21.2.1 everything works fine, but when I install Jest version 23.5.0 I receive the following error:

Error: expect(jest.fn())[.not].toHaveBeenCalledWith()
jest.fn() value must be a mock function or spy.
Received:  function: [Function getItem]

i.e. localStorage.getItem is not being mocked out

I'm on the latest version of jest-localstorage-mock (2.2.0) and my test setup file looks as follows:

import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import 'jest-localstorage-mock';

configure({ adapter: new Adapter() });

beforeEach(() => {
    localStorage.clear();
});

reset jest mock functions

I cannot run multiple tests without beeing sure that the evaluateing the jest.fn()´s are actually called only from the current test.

for example test like this will pass when run together but the second test will fail when run allone

test('should save to localStorage', () => {
  const KEY = 'foo', VALUE = 'bar';
  dispatch(action.update(KEY, VALUE));
  expect(localStorage.setItem).toHaveBeenCalledTimes(1);
});

test('should save to localStorage again', () => {
  const KEY = 'fooo', VALUE = 'barr';
  dispatch(action.update(KEY, VALUE));
  expect(localStorage.setItem).toHaveBeenCalledTimes(2);
});

there should be a way to reinitalize the mock functions in a beforeEach block so i can be sure that their calls are only from the current test and or related beforeEach blocks.

Version 2.30 breaks [email protected]

We currently use [email protected] in our project along with [email protected]. Version 2.3.0 does not appear to work with [email protected], we are receiving the following error:

Couldn't find preset "@babel/preset-env" relative to directory "C:\source\ohiohealth\node_modules\jest-localstorage-mock"

  at node_modules/babel-core/lib/transformation/file/options/option-manager.js:293:19
      at Array.map (<anonymous>)
  at OptionManager.resolvePresets (node_modules/babel-core/lib/transformation/file/options/option-manager.js:275:20)
  at OptionManager.mergePresets (node_modules/babel-core/lib/transformation/file/options/option-manager.js:264:10)
  at OptionManager.mergeOptions (node_modules/babel-core/lib/transformation/file/options/option-manager.js:249:14)
  at OptionManager.init (node_modules/babel-core/lib/transformation/file/options/option-manager.js:368:12)
  at File.initOptions (node_modules/babel-core/lib/transformation/file/index.js:212:65)
  at new File (node_modules/babel-core/lib/transformation/file/index.js:135:24)
  at Pipeline.transform (node_modules/babel-core/lib/transformation/pipeline.js:46:16)

When we revert back to version 2.2.0 everything works.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.