From 5c0afbdbb7c7674855377318f69ddde34181a16a Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Thu, 3 Oct 2024 10:12:25 +0900 Subject: [PATCH 1/4] test: add repro fix(expect): preserve prototype in toMatchObject diff --- test/core/test/jest-expect.test.ts | 53 +++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/test/core/test/jest-expect.test.ts b/test/core/test/jest-expect.test.ts index 9f9bc6a7e112..aceb6cfb1b36 100644 --- a/test/core/test/jest-expect.test.ts +++ b/test/core/test/jest-expect.test.ts @@ -927,12 +927,12 @@ function trim(s: string): string { function getError(f: () => unknown) { try { f() - return expect.unreachable() } catch (error) { const processed = processError(error) return [stripVTControlCharacters(processed.message), stripVTControlCharacters(trim(processed.diff))] } + return expect.unreachable() } it('toMatchObject error diff', () => { @@ -1059,6 +1059,57 @@ it('toMatchObject error diff', () => { }", ] `) + + class Foo { + constructor(public value: number) {} + } + + class Bar { + constructor(public value: number) {} + } + + expect(new Foo(0)).toMatchObject(new Bar(0)) + expect(new Foo(0)).toMatchObject({ value: 0 }) + expect({ value: 0 }).toMatchObject(new Bar(0)) + + expect(getError(() => expect(new Foo(0)).toMatchObject(new Bar(1)))).toMatchInlineSnapshot(` + [ + "expected Foo{ value: +0 } to match object Bar{ value: 1 }", + "- Expected + + Received + + - Bar { + - "value": 1, + + Object { + + "value": 0, + }", + ] + `) + expect(getError(() => expect(new Foo(0)).toMatchObject({ value: 1 }))).toMatchInlineSnapshot(` + [ + "expected Foo{ value: +0 } to match object { value: 1 }", + "- Expected + + Received + + Object { + - "value": 1, + + "value": 0, + }", + ] + `) + expect(getError(() => expect({ value: 0 }).toMatchObject(new Bar(1)))).toMatchInlineSnapshot(` + [ + "expected { value: +0 } to match object Bar{ value: 1 }", + "- Expected + + Received + + - Bar { + - "value": 1, + + Object { + + "value": 0, + }", + ] + `) }) it('toHaveProperty error diff', () => { From be6abe87b83ee8923391f9b9985a7fc3da10ff4e Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Thu, 3 Oct 2024 11:16:58 +0900 Subject: [PATCH 2/4] refactor: minor --- packages/expect/src/jest-expect.ts | 1 + packages/expect/src/jest-utils.ts | 4 ++-- test/core/test/jest-expect.test.ts | 30 ++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/packages/expect/src/jest-expect.ts b/packages/expect/src/jest-expect.ts index 7252888c5631..e925e3c3316e 100644 --- a/packages/expect/src/jest-expect.ts +++ b/packages/expect/src/jest-expect.ts @@ -195,6 +195,7 @@ export const JestChaiExpect: ChaiPlugin = (chai, utils) => { const { subset: actualSubset, stripped } = getObjectSubset( actual, expected, + customTesters, ) if ((pass && isNot) || (!pass && !isNot)) { const msg = utils.getMessage(this, [ diff --git a/packages/expect/src/jest-utils.ts b/packages/expect/src/jest-utils.ts index 08d5687dfb27..2117fd98f3f7 100644 --- a/packages/expect/src/jest-utils.ts +++ b/packages/expect/src/jest-utils.ts @@ -676,7 +676,7 @@ export function getObjectKeys(object: object): Array { export function getObjectSubset( object: any, subset: any, - customTesters: Array = [], + customTesters: Array, ): { subset: any; stripped: number } { let stripped = 0 @@ -702,7 +702,7 @@ export function getObjectSubset( subsetEquality, ]) ) { - // Avoid unnecessary copy which might return Object instead of subclass. + // return "expected" subset to avoid showing irrelavant toMatchObject diff return subset } diff --git a/test/core/test/jest-expect.test.ts b/test/core/test/jest-expect.test.ts index aceb6cfb1b36..9da548721226 100644 --- a/test/core/test/jest-expect.test.ts +++ b/test/core/test/jest-expect.test.ts @@ -1060,6 +1060,7 @@ it('toMatchObject error diff', () => { ] `) + // https://github.com/vitest-dev/vitest/issues/6543 class Foo { constructor(public value: number) {} } @@ -1085,6 +1086,7 @@ it('toMatchObject error diff', () => { }", ] `) + expect(getError(() => expect(new Foo(0)).toMatchObject({ value: 1 }))).toMatchInlineSnapshot(` [ "expected Foo{ value: +0 } to match object { value: 1 }", @@ -1097,6 +1099,7 @@ it('toMatchObject error diff', () => { }", ] `) + expect(getError(() => expect({ value: 0 }).toMatchObject(new Bar(1)))).toMatchInlineSnapshot(` [ "expected { value: +0 } to match object Bar{ value: 1 }", @@ -1110,6 +1113,33 @@ it('toMatchObject error diff', () => { }", ] `) + + expect(getError(() => + expect({ + bad: new Bar(1), + good: new Bar(0), + }).toMatchObject({ + bad: new Foo(2), + good: new Foo(0), + }), + )).toMatchInlineSnapshot(` + [ + "expected { bad: Bar{ value: 1 }, …(1) } to match object { bad: Foo{ value: 2 }, …(1) }", + "- Expected + + Received + + Object { + - "bad": Foo { + - "value": 2, + + "bad": Object { + + "value": 1, + }, + "good": Foo { + "value": 0, + }, + }", + ] + `) }) it('toHaveProperty error diff', () => { From d939c1a2a4910a47092b6ed23c405dae81212b3d Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Thu, 3 Oct 2024 11:36:06 +0900 Subject: [PATCH 3/4] fix: preserve constructor in toMatchObject diff --- packages/expect/src/jest-utils.ts | 8 ++++++ test/core/test/jest-expect.test.ts | 44 ++++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/packages/expect/src/jest-utils.ts b/packages/expect/src/jest-utils.ts index 2117fd98f3f7..e0bb88e65e69 100644 --- a/packages/expect/src/jest-utils.ts +++ b/packages/expect/src/jest-utils.ts @@ -709,6 +709,14 @@ export function getObjectSubset( const trimmed: any = {} seenReferences.set(object, trimmed) + // preserve constructor for toMatchObject diff + if (typeof object.constructor === 'function' && typeof object.constructor.name === 'string') { + Object.defineProperty(trimmed, 'constructor', { + enumerable: false, + value: object.constructor, + }) + } + for (const key of getObjectKeys(object)) { if (hasPropertyInObject(subset, key)) { trimmed[key] = seenReferences.has(object[key]) diff --git a/test/core/test/jest-expect.test.ts b/test/core/test/jest-expect.test.ts index 9da548721226..0385e21bfe16 100644 --- a/test/core/test/jest-expect.test.ts +++ b/test/core/test/jest-expect.test.ts @@ -1062,11 +1062,11 @@ it('toMatchObject error diff', () => { // https://github.com/vitest-dev/vitest/issues/6543 class Foo { - constructor(public value: number) {} + constructor(public value: any) {} } class Bar { - constructor(public value: number) {} + constructor(public value: any) {} } expect(new Foo(0)).toMatchObject(new Bar(0)) @@ -1081,7 +1081,7 @@ it('toMatchObject error diff', () => { - Bar { - "value": 1, - + Object { + + Foo { + "value": 0, }", ] @@ -1093,8 +1093,9 @@ it('toMatchObject error diff', () => { "- Expected + Received - Object { + - Object { - "value": 1, + + Foo { + "value": 0, }", ] @@ -1116,30 +1117,49 @@ it('toMatchObject error diff', () => { expect(getError(() => expect({ - bad: new Bar(1), - good: new Bar(0), - }).toMatchObject({ - bad: new Foo(2), + bad: new Foo(1), good: new Foo(0), + }).toMatchObject({ + bad: new Bar(2), + good: new Bar(0), }), )).toMatchInlineSnapshot(` [ - "expected { bad: Bar{ value: 1 }, …(1) } to match object { bad: Foo{ value: 2 }, …(1) }", + "expected { bad: Foo{ value: 1 }, …(1) } to match object { bad: Bar{ value: 2 }, …(1) }", "- Expected + Received Object { - - "bad": Foo { + - "bad": Bar { - "value": 2, - + "bad": Object { + + "bad": Foo { + "value": 1, }, - "good": Foo { + "good": Bar { "value": 0, }, }", ] `) + + expect(getError(() => + expect(new Foo(new Foo(1))).toMatchObject(new Bar(new Bar(0))), + )).toMatchInlineSnapshot(` + [ + "expected Foo{ value: Foo{ value: 1 } } to match object Bar{ value: Bar{ value: +0 } }", + "- Expected + + Received + + - Bar { + - "value": Bar { + - "value": 0, + + Foo { + + "value": Foo { + + "value": 1, + }, + }", + ] + `) }) it('toHaveProperty error diff', () => { From f6013f9d45007cacc22b9ec3d8570864197aa017 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Thu, 3 Oct 2024 11:39:51 +0900 Subject: [PATCH 4/4] test: more --- test/core/test/jest-expect.test.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/core/test/jest-expect.test.ts b/test/core/test/jest-expect.test.ts index 0385e21bfe16..b97d1a7c6297 100644 --- a/test/core/test/jest-expect.test.ts +++ b/test/core/test/jest-expect.test.ts @@ -1160,6 +1160,25 @@ it('toMatchObject error diff', () => { }", ] `) + + expect(new Foo(new Foo(1))).toMatchObject(new Bar(new Foo(1))) + expect(getError(() => + expect(new Foo(new Foo(1))).toMatchObject(new Bar(new Foo(2))), + )).toMatchInlineSnapshot(` + [ + "expected Foo{ value: Foo{ value: 1 } } to match object Bar{ value: Foo{ value: 2 } }", + "- Expected + + Received + + - Bar { + + Foo { + "value": Foo { + - "value": 2, + + "value": 1, + }, + }", + ] + `) }) it('toHaveProperty error diff', () => {