Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Testing - TypeError: localStorage.getItem is not a function

I'm having trouble testing a react component that uses localstorage to save a JWT token and retrieves it for api calls and routing based on authentication.

The component itself works fine, but when i test, i'm getting this error in all the three tests

TypeError: localStorage.getItem is not a function

Here is the code i have written

home.test.js

import React from 'react';
import { shallow, mount } from 'enzyme';
import { expect } from 'chai';
import sinon from 'sinon';

import Home from '../containers/Home.jsx';


describe('<Home />', () => {
  beforeAll(() => {
    global.localStorage = {
      i2x_token: 'someToken',
    };
  });

  it('renders without exploding', () => {
    shallow(<Home />);
  });

  it('renders children when passed in', () => {
    const wrapper = shallow(
      <Home>
        <div className='unique' />
      </Home>,
   );
    expect(wrapper.contains(<div className='unique' />)).to.equal(true);
  });

  it('calls componentWillMount', () => {
    sinon.spy(Home.prototype, 'componentWillMount');
    const wrapper = mount(<Home />);

expect(Home.prototype.componentWillMount).to.have.property('callCount', 1);
    Home.prototype.componentWillMount.restore();
  });
});

home.jsx

import React, { Component } from 'react';
import { browserHistory } from 'react-router';

import Header from '../components/Header.jsx';
import Content from '../components/Content.jsx';

import { API_CONTENT } from '../utils/constants';
import request from '../utils/request';

class Home extends Component {
  constructor(props) {
    super(props);
    this.state = {
      content: null,
    };
    this.logout = this.logout.bind(this);
  }

  componentWillMount() {
    const token = localStorage.getItem('i2x_token');
    const requestURL = API_CONTENT;
    const requestObj = {
      method: 'GET',
      headers: new Headers({
        Authorization: `JWT ${token}`,
      }),
    };
    request(requestURL, requestObj).then((reply) => {
      if (reply.results.length > 0) {
        this.setState({ content: reply.results });
       } else {
        console.log('no reply from API');
      }
    });
  }

  logout() {
     localStorage.removeItem('i2x_token');
     browserHistory.push('/');
   }

  render() {
    const data = this.state.content;
    if (data !== null) {
      return (
        <div className='container'>
          <Header logout={ this.logout } />
          <Content data={ this.state.content } />
        </div>
      );
    }
    return (
      <div className='container'>
        <Header logout={ this.logout } />
      </div>
    );
  }
}

export default Home;
like image 746
rizvified Avatar asked Apr 25 '17 06:04

rizvified


People also ask

How do I deal with localStorage in jest tests?

defineProperty(window, "localStorage", { value: localStorageMock }); This can be used directly in the test file for a specific, or globally. You can mock localStorage globally for React in Jest by adding the above to the setupTests. js file and adding global.

What is localStorage getItem()?

getItem() The getItem() method of the Storage interface, when passed a key name, will return that key's value, or null if the key does not exist, in the given Storage object.

What is getItem?

The getItem() method returns value of the specified Storage Object item. The getItem() method belongs to the Storage Object, which can be either a localStorage object or a sessionStorage object.


2 Answers

localStorage is part of your Browser which is not available in a unit test, you need to mock it. You can mock the necessary methods in the localStorage object:

home.test.js

beforeAll(() => {
   global.localStorage = {
      i2x_token: 'someToken',
      getItem: function () {
         return 'someToken'
      }
   };
});
....
like image 191
Thomas Sojka Avatar answered Sep 25 '22 04:09

Thomas Sojka


I recently had the same issue and I resolved it by using the following: "mock-local-storage": "^1.0.4". The package can be found here.

This module mocks the localStorage and the sessionStorage for you, which was hustle free for me. The plug in allows you to add middleware to the store such as redux-thunk and redux-sagas.

N.B. I am using Mocha to run my tests.

For other frameworks you can use the following configuration

global.window = {}
import localStorage from 'mock-local-storage'
window.localStorage = global.localStorage
like image 33
Tawanike Avatar answered Sep 22 '22 04:09

Tawanike