[Docs]: `expect.extend` documented as if it was immutable but it's in fact mutable
Version
1.46.1
Steps to reproduce
The following code ends up in an infinite loop as jest's expect is mutable - the documentation of Playwright however does not mention this and since it uses the pattern export const expect = baseExpect.extend() one would assume it's by default immutable (the original is not changed).
import {
expect as baseExpect,
MatcherReturnType,
Page,
} from '@playwright/test';
export const expect = baseExpect.extend({
toHaveURL: async (
page: Page,
...args: Parameters<PageAssertions['toHaveURL']>
) => {
try {
// one would assume this calls the original method but instead it actually calls the extended method in a loop
await baseExpect.toHaveURL(...args);
// do some stuff
return {
pass: true,
message: () => '',
};
} catch (error) {
const matcherError = error as { matcherResult: MatcherReturnType };
if (matcherError.matcherResult) {
return matcherError.matcherResult;
}
throw error;
}
},
});
PS: I know the recommendation would be to just not overwrite the base matchers but people will always try nonetheless 😅
Expected behavior
Either the expect should be adjusted to be immutable or this should be mentioned in the docs.
Actual behavior
The expect is mutable and calling expect.extend modifies the original expect.
Additional context
No response
Environment
System:
OS: macOS 14.5
Memory: 78.63 MB / 32.00 GB
Binaries:
Node: 18.14.2 - ~/.asdf/installs/nodejs/18.14.2/bin/node
Yarn: 1.22.19 - ~/.asdf/shims/yarn
npm: 9.5.0 - ~/.asdf/plugins/nodejs/shims/npm
Languages:
Bash: 3.2.57 - /bin/bash
Sounds good! Feel free to open a pull request with a small docs addition for this.
Anther instance of folks being surprised by the behaviour here: https://github.com/microsoft/playwright/issues/32340
Hey @Skn0tt, would I be able to be assigned to this as my first contribution? Thanks!
It seems that it is not the case anymore (1.56.1). i.e. built-in expect can be overridden and the original remains accessible and intact.
You can use the base expect as follows, even from within the expect.extend
await baseExpect(page).toHaveURL(url);
Should we add a note in the documentation? I'm not sure if it's good to encourage overriding assertion.
Ah yes, we fixed this through https://github.com/microsoft/playwright/pull/32366. I don't think we need to mention it in the documentation - the API is designed so it looks immutable, and it now is indeed immutable.