user3348410
user3348410

Reputation: 2833

React testing library failed because of window undefined

i'm using react-test-library when i trying to run test i'm getting error:

   TypeError: Cannot read property 'apiBaseUrl' of undefined

    > 1 | let baseUrl = window.config.apiBaseUrl;
        |                             ^
      2 | export default baseUrl

here is my package.json:

{
    "name": "dstest",
    "version": "0.1.0",
    "private": true,
    "dependencies": {
     ....
    },
    "scripts": {
      "start": "node scripts/start.js",
      "build": "node scripts/build.js",
      "test": "react-scripts test"
    },
    "eslintConfig": {
      "plugins": [
        "react-pug"
      ],
      "extends": [
        "react-app",
        "plugin:react-pug/all"
      ]
    },
    "browserslist": {
      "production": [
        ">0.2%",
        "not dead",
        "not op_mini all"
      ],
      "development": [
        "last 1 chrome version",
        "last 1 firefox version",
        "last 1 safari version"
      ]
    },
    "devDependencies": {
      "@testing-library/react": "^9.5.0",
      "babel-plugin-transform-react-jsx": "^6.24.1",
      "jest-sonar-reporter": "^2.0.0",
      "babel-plugin-transform-react-pug": "^7.0.1"
    },
    "babel": {
      "presets": [
        "react-app"
      ],
      "plugins": [
        "transform-react-pug",
        "transform-react-jsx"
      ]
    },
    "jest": {
      "collectCoverageFrom": [
        "src/**/*.{js,jsx,ts,tsx}",
        "!src/**/*.d.ts",
        "!src/index.tsx",
        "!src/serviceWorker.ts"
      ],
      "coverageReporters": [
        "text",
        "lcov",
        "json"
      ]
    }
  }

and here is my test file:

import React from "react";
import { UserName } from "Containers";
import { render } from "@testing-library/react";
import { BrowserRouter as Router } from "react-router-dom";

it("renders without crashing", async () => {
  const wrapper = render(
    <Router>
      <UserName />
    </Router>
  );
  expect(wrapper);
  wrapper.unmount();
});

and here i'm getting this error when trying to run test script:

  ● Test suite failed to run

    TypeError: Cannot read property 'apiBaseUrl' of undefined

    > 1 | let baseUrl = window.config.apiBaseUrl;
        |                             ^
      2 | export default baseUrl
      3 |

      at Object.<anonymous> (src/ApiConfig/baseURL.js:1:29)
      at Object.<anonymous> (src/Store/Actions/getData/index.js:1:1)
      at Object.<anonymous> (src/Store/Actions/index.js:2:1)
      at Object.<anonymous> (src/Containers/Form/UserId/index.js:3:1)
      at Object.<anonymous> (src/Containers/index.js:2:1)
      at Object.<anonymous> (src/Containers/Form/UserName/index.test.js:2:1)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        0.065s

what i need to do?

Upvotes: 3

Views: 7689

Answers (3)

Burak
Burak

Reputation: 196

I had the same problem and beforeAll, beforeEach or jest.spyOn solutions did not fixed my problem. I fixed it by setting value in setupTests.js file.

window.config = { apiBaseUrl: "value" };

//setupTests.js

Upvotes: 2

Andrey Edounov
Andrey Edounov

Reputation: 31

With new version of jsdom you can do the following, no typescript errors:

import { JSDOM } from 'jsdom';

let windowSpy: any;
beforeEach(() => {
  windowSpy = jest.spyOn(global as any, 'window', 'get');
});
afterEach(() => {
  windowSpy.mockRestore();
});

describe('', () => {
  it ('', () => {
    const { window } = new JSDOM();
    windowSpy.mockImplementation(() => window);
    // now you have `window` in test environment
  });
});

Upvotes: 0

jean182
jean182

Reputation: 3505

I use enzyme but I believe that if you're using jest you can do something like this.

// at the top to save the current window object 
const currentWindowObject = global.window;

After that in your test block you need to declare a beforeAll, to mock that value and an afterAll to put the value as it was.

  beforeAll(() => {
    delete global.window.config;
    global.window.config = { apiBaseUrl: "your value" };
  });

  afterAll(() => {
    // Set the current window again.
    delete global.window.config;
    global.window = currentWindowObject;
  });

Also if you want to have that value available for all the tests and you want to keep it you could inject it in the setupTests.js file (if using react create app) or the file where you put your jest setup.

// Imports here
global.window.config = { apiBaseUrl: "your value" };

And you will have that available in all of your tests.

Upvotes: 0

Related Questions