admin管理员组

文章数量:1194164

I have event listener that will call a function that handle authentication. I want to test that if that function receives the wrong data, it will return a data and if not, will return another data.

But I not understanding how to mock that function and make expectations with that.

That's the listener:

window.addEventListener('message', authentication, false);

The function that I want to make expectations depending on the result:

export function* authentication({ data }) {
  // Data structure {
  //   action: 'authentication',
  //   id: '7293847829109932,
  //   displayName: 'User Name',
  //   avatar: '.png',
  //   access: 'access_token_string',
  //   refresh: 'refresh_token_string',
  // }

  if (data.action === 'authentication') {
    localStorage.setItem('dualbits:access', data.access);
    localStorage.setItem('dualbits:refresh', data.refresh);
  }

  // Will dispatch the success action if the data is correct
  yield put(signInSuccess(data));
}

What did until now was mock the window global variable and the method addEventListener. And I did that expectation:

expect(window.addEventListener).toHaveBeenCalledWith(
  'message',
  authentication,
  false
);

I have event listener that will call a function that handle authentication. I want to test that if that function receives the wrong data, it will return a data and if not, will return another data.

But I not understanding how to mock that function and make expectations with that.

That's the listener:

window.addEventListener('message', authentication, false);

The function that I want to make expectations depending on the result:

export function* authentication({ data }) {
  // Data structure {
  //   action: 'authentication',
  //   id: '7293847829109932,
  //   displayName: 'User Name',
  //   avatar: 'https://steamcommunity.com/images/user.png',
  //   access: 'access_token_string',
  //   refresh: 'refresh_token_string',
  // }

  if (data.action === 'authentication') {
    localStorage.setItem('dualbits:access', data.access);
    localStorage.setItem('dualbits:refresh', data.refresh);
  }

  // Will dispatch the success action if the data is correct
  yield put(signInSuccess(data));
}

What did until now was mock the window global variable and the method addEventListener. And I did that expectation:

expect(window.addEventListener).toHaveBeenCalledWith(
  'message',
  authentication,
  false
);
Share Improve this question edited Apr 13, 2020 at 5:51 Lin Du 102k134 gold badges332 silver badges560 bronze badges asked Apr 10, 2020 at 14:31 Laura BeatrisLaura Beatris 1,9229 gold badges31 silver badges56 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 23

You can use mockFn.mockImplementationOnce(fn) to mock window.addEventListener method and controll the execution of event handler(the authentication function for your case).

E.g.

index.js:

export function* authentication({ data }) {
  if (data.action === 'authentication') {
    localStorage.setItem('dualbits:access', data.access);
    localStorage.setItem('dualbits:refresh', data.refresh);
  }
  yield 'dispatch action';
}

export function main() {
  window.addEventListener('message', authentication, false);
}

index.test.js:

import { main } from '.';

const mLocalStorage = {
  _storage: {},
  getItem: jest.fn((key) => {
    return mLocalStorage._storage[key];
  }),
  setItem: jest.fn((key, value) => {
    mLocalStorage._storage[key] = value;
  }),
};
Object.defineProperty(window, 'localStorage', {
  value: mLocalStorage,
});

describe('61142462', () => {
  it('should save data into local storage', () => {
    let rval;
    jest.spyOn(window, 'addEventListener').mockImplementationOnce((event, handler, options) => {
      const gen = handler({ data: { action: 'authentication', access: '123', refresh: 'abc' } });
      rval = gen.next().value;
    });
    main();
    expect(rval).toBe('dispatch action');
    expect(window.addEventListener).toBeCalledWith('message', expect.any(Function), false);
    expect(mLocalStorage.setItem).toBeCalledWith('dualbits:access', '123');
    expect(mLocalStorage.setItem).toBeCalledWith('dualbits:refresh', 'abc');
  });

  it('should not save data into local storage', () => {
    let rval;
    jest.spyOn(window, 'addEventListener').mockImplementationOnce((event, handler, options) => {
      const gen = handler({ data: undefined });
      rval = gen.next().value;
    });
    // You can do the rest of part of this test case
  });
});

unit test results with coverage report:

 PASS  stackoverflow/61142462/index.test.js (8.196s)
  61142462
    ✓ should save data into local storage (7ms)
    ✓ should not save data into local storage

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |     100 |       50 |     100 |     100 |                   
 index.js |     100 |       50 |     100 |     100 | 2                 
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        9.536s

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

本文标签: javascriptHow to test documenteventListener with JestStack Overflow