Describe the bug
Here is a regular test testing against a proxy:
// V3 ✅
// V4 ✅
it("v1", () => {
const target = {
page: 2,
pageSize: 30,
foo: "bar",
};
const handler = {
get(target, prop) {
return target[prop];
},
};
const proxy = new Proxy(target, handler);
expect(proxy).toEqual(
expect.objectContaining({
page: 2,
foo: "bar",
}),
);
});
This passes in both V3 and V4.
If we change our handler implementation to:
const handler = {
get(target, prop) {
return "world";
},
};
ie. all fields will return 'world' no matter what, then we get apparently broken behaviour.
V4 erroneously passes the test. It appears to ignore the proxy implementation.
// This test should be failing.
// V3 ❌ (correct)
// V4 ✅ (incorrect)
it("v2", () => {
const target = {
page: 2,
pageSize: 30,
foo: "bar",
};
const handler = {
get(target, prop) {
return "world";
},
};
const proxy = new Proxy(target, handler);
expect(proxy).toEqual(
expect.objectContaining({
page: 2,
foo: "bar",
}),
);
});
V4 erroneously fails the test
// This test should be passing.
// V3 ✅ (correct)
// V4 ❌ (incorrect)
it("v2 - inverse", () => {
const target = {
page: 2,
pageSize: 30,
foo: "bar",
};
const handler = {
get(target, prop) {
return "world";
},
};
const proxy = new Proxy(target, handler);
expect(proxy).toEqual(
expect.objectContaining({
page: "world",
foo: "world",
}),
);
});
FAIL src/objectContaining.test.ts > proxy > v2 - inverse
AssertionError: expected { page: 'world', …(2) } to deeply equal ObjectContaining{…}
- Expected
+ Received
- ObjectContaining {
+ {
"foo": "world",
"page": "world",
+ "pageSize": "world",
}
❯ src/objectContaining.test.ts:116:19
114|
115| const proxy = new Proxy(target, handler);
116| expect(proxy).toEqual(
| ^
117| expect.objectContaining({
118| page: "world",
It seems to be tripping up on the extra property pageSize that is not in the objectContaining.
Note that it doesn't have a problem with the values of foo and page.
V4 erroneously fails the test 2
// This test should be passing.
// V3 ✅ (correct)
// V4 ❌ (incorrect)
it("v2 - inverse 2", () => {
const target = {
page: 2,
pageSize: 30,
foo: "bar",
};
const handler = {
get(target, prop) {
return "world";
},
};
const proxy = new Proxy(target, handler);
expect(proxy).toEqual(
expect.objectContaining({
page: "world",
foo: "world",
pageSize: "world",
}),
);
});
});
FAIL src/objectContaining.test.ts > proxy > v2 - inverse 2
AssertionError: expected { page: 'world', …(2) } to deeply equal ObjectContaining{…}
- Expected
+ Received
- ObjectContaining {
+ {
"foo": "world",
"page": "world",
"pageSize": "world",
}
❯ src/objectContaining.test.ts:141:19
139|
140| const proxy = new Proxy(target, handler);
141| expect(proxy).toEqual(
| ^
142| expect.objectContaining({
143| page: "world",
This further demonstrates that it's not the values that it is apparently tripping up on - but there is some equality checking fail here.
Reproduction
https://github.com/dwjohnston/vitest-broken-proxies
Other notes:
I initially discovered this migrating a vue project from vitest 3 to 4.
A vue test like this:
it("v2", () => {
const p2 = reactive({
page: computed(() => 2),
pageSize: computed(() => 30),
foo: computed(() => "bar"),
});
expect(p2).toEqual(
expect.objectContaining({
page: 2,
foo: "bar",
}),
);
});
Will fail in the same manner.
System Info
System:
OS: macOS 15.6.1
CPU: (12) arm64 Apple M4 Pro
Memory: 97.77 MB / 24.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 22.21.1 - /Users/davidjohnston/.nvm/versions/node/v22.21.1/bin/node
npm: 11.6.2 - /Users/davidjohnston/.nvm/versions/node/v22.21.1/bin/npm
pnpm: 10.16.1 - /Users/davidjohnston/Library/pnpm/pnpm
bun: 1.2.21 - /Users/davidjohnston/.bun/bin/bun
Browsers:
Brave Browser: 143.1.85.120
Chrome: 144.0.7559.59
Edge: 144.0.3719.82
Firefox: 147.0.1
Safari: 18.6
npmPackages:
vitest: 4.0.17 => 4.0.17
Used Package Manager
npm
Validations
Describe the bug
Here is a regular test testing against a proxy:
This passes in both V3 and V4.
If we change our
handlerimplementation to:ie. all fields will return 'world' no matter what, then we get apparently broken behaviour.
V4 erroneously passes the test. It appears to ignore the proxy implementation.
V4 erroneously fails the test
It seems to be tripping up on the extra property
pageSizethat is not in theobjectContaining.Note that it doesn't have a problem with the values of
fooandpage.V4 erroneously fails the test 2
This further demonstrates that it's not the values that it is apparently tripping up on - but there is some equality checking fail here.
Reproduction
https://github.com/dwjohnston/vitest-broken-proxies
Other notes:
I initially discovered this migrating a vue project from vitest 3 to 4.
A vue test like this:
Will fail in the same manner.
System Info
System: OS: macOS 15.6.1 CPU: (12) arm64 Apple M4 Pro Memory: 97.77 MB / 24.00 GB Shell: 5.9 - /bin/zsh Binaries: Node: 22.21.1 - /Users/davidjohnston/.nvm/versions/node/v22.21.1/bin/node npm: 11.6.2 - /Users/davidjohnston/.nvm/versions/node/v22.21.1/bin/npm pnpm: 10.16.1 - /Users/davidjohnston/Library/pnpm/pnpm bun: 1.2.21 - /Users/davidjohnston/.bun/bin/bun Browsers: Brave Browser: 143.1.85.120 Chrome: 144.0.7559.59 Edge: 144.0.3719.82 Firefox: 147.0.1 Safari: 18.6 npmPackages: vitest: 4.0.17 => 4.0.17Used Package Manager
npm
Validations