React.js with testing-library/react TypeError: Cannot read properties of null (reading '_location')
Asked Answered
A

1

6

I am getting a TypeError when running my tests:

TypeError: Cannot read properties of null (reading '_location')
    at Window.get location [as location] (my_files\characterbuilder\node_modules\jest-environment-jsdom\node_modules\jsdom\lib\jsdom\browser\Window.js:375:79)
    at FetchInterceptor.<anonymous> (my_files\characterbuilder\node_modules\@mswjs\interceptors\src\interceptors\fetch\index.ts:52:9)
    at step (my_files\characterbuilder\node_modules\@mswjs\interceptors\lib\interceptors\fetch\index.js:59:23)
    at Object.next (my_files\characterbuilder\node_modules\@mswjs\interceptors\lib\interceptors\fetch\index.js:40:53)
    at fulfilled (my_files\characterbuilder\node_modules\@mswjs\interceptors\lib\interceptors\fetch\index.js:31:58)
    at runNextTicks (node:internal/process/task_queues:60:5)
    at processImmediate (node:internal/timers:447:9)

The relevant get location in the Window.js:

get location() {
      return idlUtils.wrapperForImpl(idlUtils.implForWrapper(window._document)._location);
}

the relevant code in the mentioned index.js:

protected checkEnvironment() {
    return (
      typeof globalThis !== 'undefined' &&
      typeof globalThis.fetch !== 'undefined'
    )
  }

  protected setup() {
    const pureFetch = globalThis.fetch

    invariant(
      !(pureFetch as any)[IS_PATCHED_MODULE],
      'Failed to patch the "fetch" module: already patched.'
    )

    globalThis.fetch = async (input, init) => {
      const request = new Request(input, init)

      const url = typeof input === 'string' ? input : input.url
      const method = request.method

      this.log('[%s] %s', method, url)

      const body = await request.clone().arrayBuffer()

      const requestUrl = new URL(
        url,
        typeof location !== 'undefined' ? location.origin : undefined
      )

      const isomorphicRequest = new IsomorphicRequest(requestUrl, {
        body,
        method,
        headers: new Headers(request.headers),
        credentials: request.credentials,
      })

      const interactiveIsomorphicRequest = new InteractiveIsomorphicRequest(
        isomorphicRequest
      )

      this.log('isomorphic request', interactiveIsomorphicRequest)

      this.log(
        'emitting the "request" event for %d listener(s)...',
        this.emitter.listenerCount('request')
      )
      this.emitter.emit('request', interactiveIsomorphicRequest)

      this.log('awaiting for the mocked response...')

      const [middlewareException, mockedResponse] = await until(async () => {
        await this.emitter.untilIdle('request', ({ args: [request] }) => {
          return request.id === interactiveIsomorphicRequest.id
        })
        this.log('all request listeners have been resolved!')

        const [mockedResponse] =
          await interactiveIsomorphicRequest.respondWith.invoked()
        this.log('event.respondWith called with:', mockedResponse)

        return mockedResponse
      })

      if (middlewareException) {
        console.error(`${request.method} ${request.url} net::ERR_FAILED`)
        const error = Object.assign(new TypeError('Failed to fetch'), {
          cause: middlewareException,
        })
        return Promise.reject(error)
      }

      if (mockedResponse) {
        this.log('received mocked response:', mockedResponse)

        const isomorphicResponse = toIsoResponse(mockedResponse)
        this.log('derived isomorphic response:', isomorphicResponse)

        this.emitter.emit(
          'response',
          interactiveIsomorphicRequest,
          isomorphicResponse
        )

        const response = new Response(mockedResponse.body, {
          ...isomorphicResponse,
          // `Response.headers` cannot be instantiated with the `Headers` polyfill.
          // Apparently, it halts if the `Headers` class contains unknown properties
          // (i.e. the internal `Headers.map`).
          headers: flattenHeadersObject(mockedResponse.headers || {}),
        })

        // Set the "response.url" property to equal the intercepted request URL.
        Object.defineProperty(response, 'url', {
          writable: false,
          enumerable: true,
          configurable: false,
          value: interactiveIsomorphicRequest.url.href,
        })

        return response
      }

      this.log('no mocked response received!')

      return pureFetch(request).then(async (response) => {
        const cloneResponse = response.clone()
        this.log('original fetch performed', cloneResponse)

        this.emitter.emit(
          'response',
          interactiveIsomorphicRequest,
          await normalizeFetchResponse(cloneResponse)
        )
        return response
      })
    }

I haven't changed anything in either of these files since starting my react app. If necessary I also have a link to the entire repository. The linked dev branch is the branch that I am encountering the issue on. The application code is in App.js and the tests are in App.test.js. The mock server is in setupServer.js.

I am trying to run the tests automatically in GitHub before merging dev into master, and while all tests pass, I am still getting an error code 1 as return value:

Run npm test

> [email protected] test
> react-scripts test

PASS src/App.test.js
  App component
    ✓ renders race dropdown (140 ms)
    ✓ selects a race and renders subrace dropdown (141 ms)
    ✓ renders class dropdown (28 ms)
    ✓ selects a class and renders subclass dropdown (104 ms)
    ✓ rolls stats and displays rolled values (136 ms)
    ✓ selects class and checks if proficiencies are displayed correctly (72 ms)
    ✓ selects class and the max amount of proficiencies, then checks if selecting more proficiencies is allowed (74 ms)
    ✓ checks if proficiency checkboxes all start disabled when no class has been selected (36 ms)

Test Suites: 1 passed, 1 total
Tests:       8 passed, 8 total
Snapshots:   0 total
Time:        2.628 s
Ran all test suites.
/home/runner/work/characterbuilder/characterbuilder/node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/browser/Window.js:375
      return idlUtils.wrapperForImpl(idlUtils.implForWrapper(window._document)._location);
                                                                              ^

TypeError: Cannot read properties of null (reading '_location')
    at Window.get location [as location] (/home/runner/work/characterbuilder/characterbuilder/node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/browser/Window.js:375:79)
    at FetchInterceptor.<anonymous> (/home/runner/work/characterbuilder/characterbuilder/node_modules/@mswjs/interceptors/src/interceptors/fetch/index.ts:52:9)
    at step (/home/runner/work/characterbuilder/characterbuilder/node_modules/@mswjs/interceptors/lib/interceptors/fetch/index.js:59:23)
    at Object.next (/home/runner/work/characterbuilder/characterbuilder/node_modules/@mswjs/interceptors/lib/interceptors/fetch/index.js:40:53)
    at fulfilled (/home/runner/work/characterbuilder/characterbuilder/node_modules/@mswjs/interceptors/lib/interceptors/fetch/index.js:31:58)
    at runNextTicks (node:internal/process/task_queues:60:5)
    at processImmediate (node:internal/timers:447:9)

Node.js v18.16.0
Error: Process completed with exit code 1.

The github workflow/ action file looks as follows:

name: Continuous Integration

on:
  push:
    branches:
      - dev

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
      
      - name: Install dependencies
        run: npm ci
      
      - name: Install
        run: npm install
      
      - name: run tests
        run: npm test

I have tried multiple solutions that I found on the internet. I have added window.URL.createObjectURL = function () {}; and jest.spyOn(window, "close").mockImplementation(jest.fn()); to the setupTests.js and I have also read of people on the internet saying that it was because of a fireEvent in one of the tests, so I have also tried it with only a single test that doesn't really test anything to see if that would cause the tests to complete successfully.

Appanage answered 12/6, 2023 at 8:16 Comment(2)
I've just run into this exact issue. Did you get to the bottom of it in the end?Mantelletta
Unfortunately I was unable to find a solution...Appanage
I
0

I encountered the exact same error, but I solved it by moving the polyfill of fetch from whatwg-fetch to cross-fetch. In my case, it was due to mswjs/interceptors not being able to detect whatwg-fetch. Perhaps you may want to review the polyfill of the fetch you are using in jest. This may not be much help, but I hope it is helpful.

The version of my library is as follows

Intosh answered 20/12, 2023 at 7:51 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.