如何使用 Jest 测试 document.eventListener

Lau*_*ris 8 javascript testing frontend jestjs redux

我有事件侦听器,它将调用处理身份验证的函数。我想测试一下,如果该函数接收到错误的数据,它将返回一个数据,如果没有,将返回另一个数据。

但我不明白如何模拟该功能并对此做出期望。

这就是听众:

window.addEventListener('message', authentication, false);
Run Code Online (Sandbox Code Playgroud)

我想根据结果做出期望的函数:

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));
}
Run Code Online (Sandbox Code Playgroud)

到目前为止所做的是模拟窗口全局变量和 addEventListener 方法。我也实现了这个期望:

expect(window.addEventListener).toHaveBeenCalledWith(
  'message',
  authentication,
  false
);
Run Code Online (Sandbox Code Playgroud)

sli*_*wp2 20

您可以使用mockFn.mockImplementationOnce(fn)来模拟window.addEventListener方法并控制事件处理程序的执行(authentication您的案例的函数)的执行。

\n\n

例如

\n\n

index.js:

\n\n
export function* authentication({ data }) {\n  if (data.action === \'authentication\') {\n    localStorage.setItem(\'dualbits:access\', data.access);\n    localStorage.setItem(\'dualbits:refresh\', data.refresh);\n  }\n  yield \'dispatch action\';\n}\n\nexport function main() {\n  window.addEventListener(\'message\', authentication, false);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

index.test.js:

\n\n
import { main } from \'.\';\n\nconst mLocalStorage = {\n  _storage: {},\n  getItem: jest.fn((key) => {\n    return mLocalStorage._storage[key];\n  }),\n  setItem: jest.fn((key, value) => {\n    mLocalStorage._storage[key] = value;\n  }),\n};\nObject.defineProperty(window, \'localStorage\', {\n  value: mLocalStorage,\n});\n\ndescribe(\'61142462\', () => {\n  it(\'should save data into local storage\', () => {\n    let rval;\n    jest.spyOn(window, \'addEventListener\').mockImplementationOnce((event, handler, options) => {\n      const gen = handler({ data: { action: \'authentication\', access: \'123\', refresh: \'abc\' } });\n      rval = gen.next().value;\n    });\n    main();\n    expect(rval).toBe(\'dispatch action\');\n    expect(window.addEventListener).toBeCalledWith(\'message\', expect.any(Function), false);\n    expect(mLocalStorage.setItem).toBeCalledWith(\'dualbits:access\', \'123\');\n    expect(mLocalStorage.setItem).toBeCalledWith(\'dualbits:refresh\', \'abc\');\n  });\n\n  it(\'should not save data into local storage\', () => {\n    let rval;\n    jest.spyOn(window, \'addEventListener\').mockImplementationOnce((event, handler, options) => {\n      const gen = handler({ data: undefined });\n      rval = gen.next().value;\n    });\n    // You can do the rest of part of this test case\n  });\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

带有覆盖率报告的单元测试结果:

\n\n
 PASS  stackoverflow/61142462/index.test.js (8.196s)\n  61142462\n    \xe2\x9c\x93 should save data into local storage (7ms)\n    \xe2\x9c\x93 should not save data into local storage\n\n----------|---------|----------|---------|---------|-------------------\nFile      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s \n----------|---------|----------|---------|---------|-------------------\nAll files |     100 |       50 |     100 |     100 |                   \n index.js |     100 |       50 |     100 |     100 | 2                 \n----------|---------|----------|---------|---------|-------------------\nTest Suites: 1 passed, 1 total\nTests:       2 passed, 2 total\nSnapshots:   0 total\nTime:        9.536s\n
Run Code Online (Sandbox Code Playgroud)\n\n

源代码: https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/61142462

\n