`window` is not being exposed to Jest

后端 未结 6 1437
挽巷
挽巷 2021-02-12 16:50

I have a test that imports a component that in turn imports a helper file that uses the window object to pull out a query string parameter. I get the following erro

相关标签:
6条回答
  • 2021-02-12 17:13

    Here you can find examples of how to do this:

    https://www.codementor.io/pkodmad/dom-testing-react-application-jest-k4ll4f8sd

    For example:

    import {jsdom} from 'jsdom';
    
    const documentHTML = '<!doctype html><html><body><div id="root"></div></body></html>';
    global.document = jsdom(documentHTML);
    global.window = document.parentWindow;
    
    0 讨论(0)
  • 2021-02-12 17:15

    Not sure but i think you could do it with jest.fn()

    global.window = jest.fn(() => {
      location: { ... }
    })
    

    maybe even as window = jest.fn(...)

    0 讨论(0)
  • 2021-02-12 17:19

    https://github.com/facebook/jest/issues/2460#issuecomment-324630534

    It seems like the one of the contributer declared that he is not planning expose jsdom to global under the jest environment.

    However, you could use Object.defineProperty(window, 'location', {value: '…'} API to approach it, like the developer in Facebook do. In your case it could be like:

        Object.defineProperty(window, 'location', {
          value: {
            search: ...
          },
        })
    

    Good luck!

    0 讨论(0)
  • 2021-02-12 17:21

    Your problem relies on the configuration.

    In the moment you set:

    "testEnvironment": "jest-environment-node"
    

    you are changing the default configuration from jest which is browser-like to jest-environment-node (node-like) meaning that your test will be run under a NodeJs environment

    To solve it either you set your testEnvironment to jsdom
    Or you remove the testEnvironment from your config so it will take the default value in yourpackage.json:

     ...
      "jest": {
        "verbose": true,
        "collectCoverageFrom": [
          "src/js/helpers/preparePayload.js",
          "src/js/components-ni",
          "!**/node_modules/**",
          "!**/dist/**"
        ],
        "coverageThreshold": {
          "global": {
            "statements": 50,
            "branches": 50,
            "functions": 50,
            "lines": 75
          }
        }
      }
    

    This is what they say in the documentation:

    testEnvironment [string] # Default: "jsdom"

    The test environment that will be used for testing. The default environment in Jest is a browser-like environment through jsdom. If you are building a node service, you can use the node option to use a node-like environment instead.


    Do you need the `node` environment?

    As I could see, your tests are meant to be run under a browser-like environment.

    If you ever need an explicit node environment, better you isolate that case using @jest-environment:

    /**
     * @jest-environment node
     */
    
    test('use node in this test file', () => {
      expect(true).not.toBeNull();
    });
    

    or the other way around if you are meant to run the tests under node environment

    /**
     * @jest-environment jsdom
     */
    
    test('use jsdom in this test file', () => {
      const element = document.createElement('div');
      expect(element).not.toBeNull();
    });
    

    Conclusion

    With this you can avoid importing jsdom manually and setting global variables, jsdom will mock the DOM implementation automatically.

    If you need to change the environment for your tests use the notation @jest-environment

    0 讨论(0)
  • 2021-02-12 17:32

    You could try doing

    global.window = new jsdom.JSDOM().window;
    global.document = window.document;
    
    0 讨论(0)
  • 2021-02-12 17:35

    You can simply mock location:

    global.location = {search: 'someSearchString'}
    

    Also note, that global in your test is the global context for the file to test (global === window)

    Note this will only work if your module make the window.location call after the test has been finishing import all the modules.

    export default () => window.location
    

    So if your module looks like this:

    const  l = window.location
    export default l 
    

    it will not work. In this case you could mock the module using jest.mock.

    0 讨论(0)
提交回复
热议问题