jest icon indicating copy to clipboard operation
jest copied to clipboard

[Bug]: mock window.location error in jest@30, is ok in jiest@29

Open liangskyli opened this issue 6 months ago • 4 comments

Version

30

Steps to reproduce

mock window.location error in jest@30, is ok in jiest@29 Object.defineProperty(window, 'location', { writable: true, value: { search: '?activityId=1&token=2&orgcode=3', href: 'http://localhost:8001/aaa/bb?activityId=1&token=2', hash: '', }, }); err info:

TypeError: Cannot redefine property: location
        at Function.defineProperty (<anonymous>)

Expected behavior

test ok, not appear TypeError: Cannot redefine property: location

Actual behavior

appear TypeError: Cannot redefine property: location

Additional context

No response

Environment

System:
    OS: Windows 10 10.0.19044
    CPU: (12) x64 Intel(R) Core(TM) i5-10500 CPU @ 3.10GHz
  Binaries:
    Node: 18.20.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.22 - C:\Program Files\nodejs\yarn.CMD
    npm: 10.5.0 - C:\Program Files\nodejs\npm.CMD
    pnpm: 8.6.10 - C:\Program Files\nodejs\pnpm.CMD
  npmPackages:
    jest: ^30.0.0 => 30.0.0

liangskyli avatar Jun 12 '25 07:06 liangskyli

Even when trying to spy on window.location you get an error in jest 30, but not jest 29

    const reload = jest.fn()

    jest.spyOn(window, "location", "get").mockImplementationOnce(() => ({
        reload: ({ reload }),
    }));

results in:

    Property `location` is not declared configurable

      103 |     const reload = jest.fn()
      104 |
    > 105 |     jest.spyOn(window, "location", "get").mockImplementationOnce(() => ({
          |          ^
      106 |         reload: ({ reload }),
      107 |     }));
      108 |

jsugarman avatar Jun 12 '25 08:06 jsugarman

I think the problem is in jest-environment-jsdom If I set our dependencies as

    "jest": "^30.0.0",
    "jest-environment-jsdom": "^30.0.0",

I see the error described above.

If I change the devDependencies as

    "jest": "^30.0.0",
    "jest-environment-jsdom": "^29.7.0",

The test passes 😖

colinbruce avatar Jun 12 '25 09:06 colinbruce

This is mentioned in the release notes:

https://jestjs.io/blog#known-issues

It wasn't clear how to make a abstract jsdom environment so I used yarn patch to apply the same patch to jsdom to make location configurable, which solved my issues.

lukpsaxo avatar Jun 12 '25 09:06 lukpsaxo

Some window.location mocking can be done by mocking jsdom's implementation methods, to work around the public interfaces' use of non-configurable properties. This is a dirty hack. For example, to mock the window.location.assign function:

    // Following web standards, many jsdom instance properties are read-only and
    // non-configurable, which interferes with mocking.  Instead, we can find
    // jsdom's implSymbol property to get at the JS logic underlying its Web IDL
    // instances.
    const implSymbol = Reflect.ownKeys(window.location).find((i) => typeof i === 'symbol')!;
    const assign = jest
      .spyOn((window.location as any)[implSymbol], 'assign')
      .mockImplementation(() => {});

    try {
      // Do the test.
    } finally {
      assign.mockRestore();
    }

joshkel avatar Jun 12 '25 15:06 joshkel

Same issue, but with mocking window

Netail avatar Jun 17 '25 12:06 Netail

This is a jsdom issue. Please discuss this issue here: https://github.com/jsdom/jsdom/issues/3492

cpojer avatar Jun 17 '25 14:06 cpojer

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

github-actions[bot] avatar Jul 18 '25 00:07 github-actions[bot]