0

I've an issue on unit testing a simple component (even more simplified here) :

import React, { Component } from 'react';
import Logout from '../auth/Logout';
import { logoutUser } from '../../actions/auth';

export default class Navbar extends Component {

  render() {
    const { dispatch, isAuthenticated } = this.props;

    if (isAuthenticated) {
      logStatus = <Logout onLogoutClick={() => dispatch(logoutUser())} />;
    } else {
      logStatus = (
        <Link to="/login/">
          <Button>Login</Button>
        </Link>
      );
    }

    return (
      <AppBar>        
        {logStatus}
      </AppBar>
    );
  }
}

in import { logoutUser } from '../../actions/auth';
I have a function removeItem on localStorage. I won't be using it for my test but that's where I have an error.

My test is :

test('Navbar test series', () => {
  //Enzyme testing
  it('show the login button', () => {
    const wrapper = shallow(<Navbar isAuthenticated={true} />);
    expect(wrapper.find(Login)).to.have.length(1);
  });
});

I got :

ReferenceError: localStorage is not defined      
      at Object.<anonymous> (src/axios/axios.js:8:15) [I don't know why this is here...]
      at Object.<anonymous> (src/actions/auth.js:89:38) [my logoutUser using localStorage is here ]
      at Object.<anonymous> (src/components/UI/Navbar.js:3:13)
      at Object.<anonymous> (src/components/UI/Navbar.test.js:2:15)

Doing something like suggested here How do I deal with localStorage in jest tests? :

var localStorageMock = (function () { [...]})();
Object.defineProperty(window, 'localStorage', { value: localStorageMock });

is not helping.

What I don't get is that I'm not even calling dispatch(logoutUser()) so why trying to access localStorage ?? Is the issue due to redux through dispatch ?

Thanks a lot for your help !

EDIT1 : Logout component :

import React from 'react';
import Button from '@material-ui/core/Button';

const Logout = props => (
  <Button onClick={() => props.onLogoutClick()}     color="secondary">LOGOUT</Button>
);

export default Logout;

And code from actions/auth.js and logoutUser() :

export function logoutUser() {
  return dispatch => {
    dispatch(requestLogout());
    localStorage.removeItem('token');
    dispatch(receiveLogout());
  };
}
skyboyer
  • 22,209
  • 7
  • 57
  • 64
pierreaurelemartin
  • 1,592
  • 1
  • 14
  • 22

3 Answers3

1

You can add in your test files

global.localStorage = {
    getItem: () => undefined,
};

test('Navbar test series', () => {
  //Enzyme testing
  it('show the login button', () => {
    const wrapper = shallow(<Navbar isAuthenticated={true} />);
    expect(wrapper.find(Login)).to.have.length(1);
  });
});
Safi Nettah
  • 1,160
  • 9
  • 15
0

Have you tried mocking ../../actions/auth entirely for that test?

jest.setMock('../../actions/auth', () => ({ logoutUser: jest.fn() }))

bamse
  • 4,243
  • 18
  • 25
  • I just tried, I'm still blocked on that localStorage error :) It was a good idea though ! – pierreaurelemartin Jul 20 '18 at 11:40
  • A little off topic, but you should try [react-testing-library](https://github.com/kentcdodds/react-testing-library). Shallow rendering is a real pain. In my tests I mock `localStorage` with ```global.localStorage = { setItem: jest.fn() }; ``` and it does the trick. Hope you find the solution! – bamse Jul 20 '18 at 11:52
0

So the solution was in :

      at Object.<anonymous> (src/axios/axios.js:8:15) [I don't know why this is here...]

Where I've found a const using localstorage on runtime. Just put it in a condition and it solved the issue.

Thanks all for the effort, it was my mistake :-(

pierreaurelemartin
  • 1,592
  • 1
  • 14
  • 22
  • but why didn't the mock implementation get invoked? were you referring it by window.localstorage or something else? – dubes Jul 20 '18 at 12:30
  • because the `const token = localStorage.get[...]` was invoke at the root of my axios/axios.js and therefore call in the `import` chain. And so before the mock implementation of localStorage. – pierreaurelemartin Jul 20 '18 at 12:47
  • Even if I though I had tested once with the mock on first line but I guess I did it poorly... – pierreaurelemartin Jul 20 '18 at 12:47