jest-localstorage-mock
Advanced tools
Comparing version 2.0.1 to 2.1.0
'use strict'; | ||
var asyncGenerator = function () { | ||
function AwaitValue(value) { | ||
this.value = value; | ||
class LocalStorage { | ||
constructor() { | ||
this.store = {}; | ||
} | ||
function AsyncGenerator(gen) { | ||
var front, back; | ||
clear() { | ||
this.store = {}; | ||
} | ||
function send(key, arg) { | ||
return new Promise(function (resolve, reject) { | ||
var request = { | ||
key: key, | ||
arg: arg, | ||
resolve: resolve, | ||
reject: reject, | ||
next: null | ||
}; | ||
getItem(key) { | ||
return this.store[key] || null; | ||
} | ||
if (back) { | ||
back = back.next = request; | ||
} else { | ||
front = back = request; | ||
resume(key, arg); | ||
} | ||
}); | ||
} | ||
function resume(key, arg) { | ||
try { | ||
var result = gen[key](arg); | ||
var value = result.value; | ||
if (value instanceof AwaitValue) { | ||
Promise.resolve(value.value).then(function (arg) { | ||
resume("next", arg); | ||
}, function (arg) { | ||
resume("throw", arg); | ||
}); | ||
} else { | ||
settle(result.done ? "return" : "normal", result.value); | ||
} | ||
} catch (err) { | ||
settle("throw", err); | ||
} | ||
} | ||
function settle(type, value) { | ||
switch (type) { | ||
case "return": | ||
front.resolve({ | ||
value: value, | ||
done: true | ||
}); | ||
break; | ||
case "throw": | ||
front.reject(value); | ||
break; | ||
default: | ||
front.resolve({ | ||
value: value, | ||
done: false | ||
}); | ||
break; | ||
} | ||
front = front.next; | ||
if (front) { | ||
resume(front.key, front.arg); | ||
} else { | ||
back = null; | ||
} | ||
} | ||
this._invoke = send; | ||
if (typeof gen.return !== "function") { | ||
this.return = undefined; | ||
} | ||
setItem(key, value = '') { | ||
// not mentioned in the spec, but we must always coerce to a string | ||
this.store[key] = value + ''; | ||
} | ||
if (typeof Symbol === "function" && Symbol.asyncIterator) { | ||
AsyncGenerator.prototype[Symbol.asyncIterator] = function () { | ||
return this; | ||
}; | ||
removeItem(key) { | ||
delete this.store[key]; | ||
} | ||
AsyncGenerator.prototype.next = function (arg) { | ||
return this._invoke("next", arg); | ||
}; | ||
AsyncGenerator.prototype.throw = function (arg) { | ||
return this._invoke("throw", arg); | ||
}; | ||
AsyncGenerator.prototype.return = function (arg) { | ||
return this._invoke("return", arg); | ||
}; | ||
return { | ||
wrap: function (fn) { | ||
return function () { | ||
return new AsyncGenerator(fn.apply(this, arguments)); | ||
}; | ||
}, | ||
await: function (value) { | ||
return new AwaitValue(value); | ||
} | ||
}; | ||
}(); | ||
var classCallCheck = function (instance, Constructor) { | ||
if (!(instance instanceof Constructor)) { | ||
throw new TypeError("Cannot call a class as a function"); | ||
key(index) { | ||
const keys = Object.keys(this.store); | ||
return keys[index] || null; | ||
} | ||
}; | ||
var createClass = function () { | ||
function defineProperties(target, props) { | ||
for (var i = 0; i < props.length; i++) { | ||
var descriptor = props[i]; | ||
descriptor.enumerable = descriptor.enumerable || false; | ||
descriptor.configurable = true; | ||
if ("value" in descriptor) descriptor.writable = true; | ||
Object.defineProperty(target, descriptor.key, descriptor); | ||
} | ||
get length() { | ||
return Object.keys(this.store).length; | ||
} | ||
return function (Constructor, protoProps, staticProps) { | ||
if (protoProps) defineProperties(Constructor.prototype, protoProps); | ||
if (staticProps) defineProperties(Constructor, staticProps); | ||
return Constructor; | ||
}; | ||
}(); | ||
var LocalStorage = function () { | ||
function LocalStorage() { | ||
classCallCheck(this, LocalStorage); | ||
this.store = {}; | ||
toString() { | ||
return '[object Storage]'; | ||
} | ||
} | ||
createClass(LocalStorage, [{ | ||
key: 'clear', | ||
value: function clear() { | ||
this.store = {}; | ||
} | ||
}, { | ||
key: 'getItem', | ||
value: function getItem(key) { | ||
return this.store[key] || null; | ||
} | ||
}, { | ||
key: 'setItem', | ||
value: function setItem(key) { | ||
var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; | ||
const local = new LocalStorage(); | ||
const session = new LocalStorage(); | ||
// not mentioned in the spec, but we must always coerce to a string | ||
this.store[key] = value + ''; | ||
} | ||
}, { | ||
key: 'removeItem', | ||
value: function removeItem(key) { | ||
delete this.store[key]; | ||
} | ||
}, { | ||
key: 'key', | ||
value: function key(index) { | ||
var keys = Object.keys(this.store); | ||
return keys[index] || null; | ||
} | ||
}, { | ||
key: 'toString', | ||
value: function toString() { | ||
return '[object Storage]'; | ||
} | ||
}, { | ||
key: 'length', | ||
get: function get$$1() { | ||
return Object.keys(this.store).length; | ||
} | ||
}]); | ||
return LocalStorage; | ||
}(); | ||
var local = new LocalStorage(); | ||
var session = new LocalStorage(); | ||
global.localStorage = { | ||
clear: jest.fn(function () { | ||
return local.clear(); | ||
}), | ||
getItem: jest.fn(function (key) { | ||
return local.getItem(key); | ||
}), | ||
setItem: jest.fn(function (key, value) { | ||
return local.setItem(key, value); | ||
}), | ||
removeItem: jest.fn(function (key) { | ||
return local.removeItem(key); | ||
}), | ||
key: jest.fn(function (index) { | ||
return local.key(index); | ||
}), | ||
toString: jest.fn(function () { | ||
return local.toString(); | ||
}), | ||
clear: jest.fn(() => local.clear()), | ||
getItem: jest.fn(key => local.getItem(key)), | ||
setItem: jest.fn((key, value) => local.setItem(key, value)), | ||
removeItem: jest.fn(key => local.removeItem(key)), | ||
key: jest.fn(index => local.key(index)), | ||
toString: jest.fn(() => local.toString()), | ||
get __STORE__() { | ||
@@ -228,20 +61,8 @@ return local.store; | ||
global.sessionStorage = { | ||
clear: jest.fn(function () { | ||
return session.clear(); | ||
}), | ||
getItem: jest.fn(function (key) { | ||
return session.getItem(key); | ||
}), | ||
setItem: jest.fn(function (key, value) { | ||
return session.setItem(key, value); | ||
}), | ||
removeItem: jest.fn(function (key) { | ||
return session.removeItem(key); | ||
}), | ||
key: jest.fn(function (index) { | ||
return session.key(index); | ||
}), | ||
toString: jest.fn(function () { | ||
return session.toString(); | ||
}), | ||
clear: jest.fn(() => session.clear()), | ||
getItem: jest.fn(key => session.getItem(key)), | ||
setItem: jest.fn((key, value) => session.setItem(key, value)), | ||
removeItem: jest.fn(key => session.removeItem(key)), | ||
key: jest.fn(index => session.key(index)), | ||
toString: jest.fn(() => session.toString()), | ||
get __STORE__() { | ||
@@ -248,0 +69,0 @@ return session.store; |
{ | ||
"name": "jest-localstorage-mock", | ||
"version": "2.0.1", | ||
"description": "Mock localstorage in your Jest tests", | ||
"version": "2.1.0", | ||
"description": "Auto mock all localstorage and sessionstorage APIs for your Jest tests", | ||
"main": "dist/setup.js", | ||
"module": "src/setup.js", | ||
"author": "Bryan Clark <clarkbw@gmail.com> (https://twitter.com/clarkbw)", | ||
"maintainers": [ | ||
{ | ||
"name": "Bryan Clark", | ||
"email": "clarkbw@gmail.com", | ||
"web": "https://twitter.com/clarkbw" | ||
} | ||
], | ||
"contributors": [], | ||
"repository": { | ||
@@ -12,23 +20,56 @@ "type": "git", | ||
}, | ||
"repositories": [ | ||
{ | ||
"type": "git", | ||
"url": "https://github.com/clarkbw/jest-localstorage-mock.git" | ||
} | ||
], | ||
"bugs": { | ||
"url": "https://github.com/clarkbw/jest-localstorage-mock/issues" | ||
}, | ||
"homepage": "https://github.com/clarkbw/jest-localstorage-mock", | ||
"license": "ISC", | ||
"licenses": [ | ||
{ | ||
"type": "ISC" | ||
} | ||
], | ||
"keywords": [ | ||
"jest", | ||
"test", | ||
"mock", | ||
"localstorage", | ||
"sessionstorage", | ||
"storage", | ||
"node", | ||
"browser" | ||
], | ||
"directories": { | ||
"lib": "./src", | ||
"test": "./__tests__" | ||
}, | ||
"scripts": { | ||
"test": "jest", | ||
"build": "rollup -c", | ||
"prettier": "prettier --single-quote --trailing-comma es5 --write \"{src,__{tests,setups}__}/**/*.js\" rollup.config.js", | ||
"eslint-check": "eslint --print-config .eslintrc.js | eslint-config-prettier-check", | ||
"prettier": "prettier --single-quote --trailing-comma es5 --write \"{src,__{tests,setups}__}/**/*.js\" README.md CONTRIBUTING.md *.json rollup.config.js", | ||
"version": "yarn run build" | ||
}, | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"babel-jest": "^21.0.0", | ||
"babel-core": "^6.26.0", | ||
"babel-jest": "^21.2.0", | ||
"babel-plugin-external-helpers": "^6.22.0", | ||
"babel-preset-env": "^1.4.0", | ||
"eslint": "^4.1.0", | ||
"eslint-config-prettier": "^2.0.0", | ||
"eslint-plugin-prettier": "^2.0.1", | ||
"jest": "^21.0.0", | ||
"prettier": "^1.3.1", | ||
"rollup": "^0.50.0", | ||
"babel-preset-env": "^1.6.1", | ||
"eslint": "^4.10.0", | ||
"eslint-config-prettier": "^2.7.0", | ||
"eslint-plugin-prettier": "^2.3.1", | ||
"jest": "^21.2.1", | ||
"prettier": "^1.8.2", | ||
"rollup": "^0.51.0", | ||
"rollup-plugin-babel": "^3.0.0", | ||
"rollup-plugin-node-resolve": "^3.0.0" | ||
}, | ||
"engines": { | ||
"node": ">=6.11.3" | ||
}, | ||
"jest": { | ||
@@ -35,0 +76,0 @@ "bail": true, |
128
README.md
@@ -0,11 +1,20 @@ | ||
Use this module with [Jest](https://facebook.github.io/jest/) to run web tests | ||
that rely on `localstorage` and / or `sessionStorage` where you want a working | ||
localStorage API with mocked functions. | ||
Use this module with [Jest](https://facebook.github.io/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. | ||
This module has no runtime dependencies so your project won't pull in additional module dependencies by using this. | ||
[![npm](https://img.shields.io/npm/v/jest-localstorage-mock.svg)](https://www.npmjs.com/package/jest-localstorage-mock) | ||
[![npm](https://img.shields.io/npm/l/jest-localstorage-mock.svg)](https://github.com/clarkbw/jest-localstorage-mock/blob/master/LICENSE) | ||
[![Codecov](https://img.shields.io/codecov/c/github/clarkbw/jest-localstorage-mock.svg)](https://codecov.io/gh/clarkbw/jest-localstorage-mock) | ||
[![Greenkeeper badge](https://badges.greenkeeper.io/clarkbw/jest-localstorage-mock.svg)](https://greenkeeper.io/) | ||
[![Twitter](https://img.shields.io/twitter/url/https/github.com/clarkbw/jest-localstorage-mock.svg?style=social)](https://twitter.com/intent/tweet?text=Wow:&url=%5Bobject%20Object%5D) | ||
[![npm](https://img.shields.io/npm/v/jest-localstorage-mock.svg)](https://www.npmjs.com/package/jest-localstorage-mock) [![npm](https://img.shields.io/npm/l/jest-localstorage-mock.svg)](https://github.com/clarkbw/jest-localstorage-mock/blob/master/LICENSE) [![Codecov](https://img.shields.io/codecov/c/github/clarkbw/jest-localstorage-mock.svg)](https://codecov.io/gh/clarkbw/jest-localstorage-mock) [![Greenkeeper badge](https://badges.greenkeeper.io/clarkbw/jest-localstorage-mock.svg)](https://greenkeeper.io/) [![Twitter](https://img.shields.io/twitter/url/https/github.com/clarkbw/jest-localstorage-mock.svg?style=social)](https://twitter.com/intent/tweet?text=Wow:&url=%5Bobject%20Object%5D) | ||
## Install | ||
This should only be required as a dev dependency when your tests are running. | ||
This should only be installed as a development dependency (`devDependencies`) as | ||
it is only designed for testing. The module is transpiled via | ||
[babel](https://github.com/babel/babel) to support the current active Node LTS | ||
version (6.11.3). | ||
@@ -26,22 +35,27 @@ yarn: | ||
The simplest setup is to use the [module](#module) system, you may also choose | ||
to create a [setup file](#setup-file) if needed. | ||
### Module | ||
In your `package.json` under the `jest` section add the module name to the `setupFiles` array. This is by far the simplest method for using this. | ||
In your `package.json` under the `jest` | ||
[configuration section](https://facebook.github.io/jest/docs/en/configuration.html#content) | ||
create a `setupFiles` array and add `jest-localstorage-mock` to the array. | ||
```json | ||
"jest": { | ||
"setupFiles": [ | ||
"jest-localstorage-mock" | ||
] | ||
{ | ||
"jest": { | ||
"setupFiles": ["jest-localstorage-mock"] | ||
} | ||
} | ||
``` | ||
You can also append this to the array if you have other setup files. | ||
If you already have a `setupFiles` attribute you can also append | ||
`jest-localstorage-mock` to the array. | ||
```json | ||
"jest": { | ||
"setupFiles": [ | ||
"./__setups__/other.js", | ||
"jest-localstorage-mock" | ||
] | ||
{ | ||
"jest": { | ||
"setupFiles": ["./__setups__/other.js", "jest-localstorage-mock"] | ||
} | ||
} | ||
@@ -52,6 +66,10 @@ ``` | ||
Alternatively you can create a new setup file which then requires this module or add the `require` statement to an existing 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` | ||
```js | ||
import 'jest-localstorage-mock'; | ||
// or | ||
require('jest-localstorage-mock'); | ||
@@ -72,6 +90,9 @@ ``` | ||
For a [create-react-app](https://github.com/facebookincubator/create-react-app) project you can replace the [suggested mock](https://github.com/facebookincubator/create-react-app/tree/master/packages/react-scripts/template#srcsetuptestsjs) with this at the beginning of the existing `src/setupTests.js` file: | ||
For a [create-react-app](https://github.com/facebookincubator/create-react-app) | ||
project you can replace the | ||
[suggested mock](https://github.com/facebookincubator/create-react-app/tree/master/packages/react-scripts/template#srcsetuptestsjs-1) | ||
with this at the beginning of the existing `src/setupTests.js` file: | ||
```js | ||
require("jest-localstorage-mock"); | ||
require('jest-localstorage-mock'); | ||
``` | ||
@@ -81,5 +102,10 @@ | ||
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. | ||
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. | ||
The `__STORE__` attribute of `localStorage.__STORE__` or | ||
`sessionStorage.__STORE__` is made available for you to directly access the | ||
storage object if needed. | ||
@@ -92,3 +118,4 @@ ### Test Examples | ||
test('should save to localStorage', () => { | ||
const KEY = 'foo', VALUE = 'bar'; | ||
const KEY = 'foo', | ||
VALUE = 'bar'; | ||
dispatch(action.update(KEY, VALUE)); | ||
@@ -101,3 +128,4 @@ expect(localStorage.setItem).toHaveBeenLastCalledWith(KEY, VALUE); | ||
Check that your `sessionStorage` is empty, examples work with either `localStorage` or `sessionStorage`. | ||
Check that your `sessionStorage` is empty, examples work with either | ||
`localStorage` or `sessionStorage`. | ||
@@ -117,3 +145,4 @@ ```js | ||
test('should not have saved to localStorage', () => { | ||
const KEY = 'foo', VALUE = 'bar'; | ||
const KEY = 'foo', | ||
VALUE = 'bar'; | ||
dispatch(action.notIdempotent(KEY, VALUE)); | ||
@@ -125,27 +154,36 @@ expect(localStorage.setItem).not.toHaveBeenLastCalledWith(KEY, VALUE); | ||
## Development | ||
Reset your `localStorage` data and mocks before each test to prevent leaking. | ||
``` | ||
yarn install | ||
yarn test | ||
``` | ||
```js | ||
beforeEach(() => { | ||
// values stored in tests will also be available in other tests unless you run | ||
localStorage.clear(); | ||
// or directly reset the storage | ||
localStorage.__STORE__ = {}; | ||
// you may also reset all mocks, which could impact your other mocks | ||
jest.resetAllMocks(); | ||
// or individually reset a mock used | ||
localStorage.setItem.mockReset(); | ||
}); | ||
## Pull Request | ||
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); | ||
}); | ||
Before every PR run the following: | ||
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); | ||
}); | ||
``` | ||
yarn run prettier | ||
``` | ||
## Publish | ||
When publishing a new build, run the following: | ||
``` | ||
yarn run prettier | ||
yarn run build | ||
npm version `${version}` | ||
npm publish | ||
git push --tags | ||
``` | ||
See the [contributing guide](./CONTRIBUTING.md) for details on how you can | ||
contribute. |
@@ -11,3 +11,13 @@ import resolve from 'rollup-plugin-node-resolve'; | ||
babelrc: false, | ||
presets: [['env', { modules: false }]], | ||
presets: [ | ||
[ | ||
'env', | ||
{ | ||
targets: { | ||
node: '6.11.3', | ||
}, | ||
modules: false, | ||
}, | ||
], | ||
], | ||
plugins: ['external-helpers'], | ||
@@ -14,0 +24,0 @@ }), |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
17
0
0
182
145067
12
283