[Bug]: mock window.location error in jest@30, is ok in jiest@29
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
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 |
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 😖
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.
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();
}
Same issue, but with mocking window
This is a jsdom issue. Please discuss this issue here: https://github.com/jsdom/jsdom/issues/3492
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.