Skip to content

Commit a1b5f0f

Browse files
hi-ogawacodex
andauthored
fix: make expect(..., message) consistent as error message prefix (#10068)
Co-authored-by: Codex <noreply@openai.com>
1 parent 65c9d55 commit a1b5f0f

File tree

5 files changed

+135
-24
lines changed

5 files changed

+135
-24
lines changed

packages/expect/src/jest-extend.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,7 @@ function JestExtendPlugin(
106106
const thenable = result as PromiseLike<SyncExpectationResult>
107107
return thenable.then(({ pass, message, actual, expected, meta }) => {
108108
if ((pass && isNot) || (!pass && !isNot)) {
109-
const errorMessage = customMessage != null
110-
? customMessage
111-
: message()
109+
const errorMessage = (customMessage ? `${customMessage}: ` : '') + message()
112110
throw new JestExtendError(
113111
errorMessage,
114112
actual,
@@ -122,9 +120,7 @@ function JestExtendPlugin(
122120
const { pass, message, actual, expected, meta } = result as SyncExpectationResult
123121

124122
if ((pass && isNot) || (!pass && !isNot)) {
125-
const errorMessage = customMessage != null
126-
? customMessage
127-
: message()
123+
const errorMessage = (customMessage ? `${customMessage}: ` : '') + message()
128124
throw new JestExtendError(
129125
errorMessage,
130126
actual,

packages/vitest/src/integrations/snapshot/chai.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export const SnapshotPlugin: ChaiPlugin = (chai, utils) => {
8989
received: utils.flag(this, 'object'),
9090
...normalizeArguments(propertiesOrHint, hint),
9191
})
92-
return assertMatchResult(result)
92+
return assertMatchResult(result, chai.util.flag(this, 'message'))
9393
}),
9494
)
9595
}
@@ -108,7 +108,9 @@ export const SnapshotPlugin: ChaiPlugin = (chai, utils) => {
108108
filepath,
109109
hint,
110110
})
111-
const assertPromise = resultPromise.then(result => assertMatchResult(result))
111+
const assertPromise = resultPromise.then(result =>
112+
assertMatchResult(result, chai.util.flag(this, 'message')),
113+
)
112114
return recordAsyncExpect(
113115
getTest(this),
114116
assertPromise,
@@ -134,7 +136,7 @@ export const SnapshotPlugin: ChaiPlugin = (chai, utils) => {
134136
isInline: true,
135137
...normalizeInlineArguments(propertiesOrInlineSnapshot, inlineSnapshotOrHint, hint),
136138
})
137-
return assertMatchResult(result)
139+
return assertMatchResult(result, chai.util.flag(this, 'message'))
138140
}),
139141
)
140142
utils.addMethod(
@@ -149,7 +151,7 @@ export const SnapshotPlugin: ChaiPlugin = (chai, utils) => {
149151
received: getError(received, promise),
150152
...normalizeArguments(propertiesOrHint, hint),
151153
})
152-
return assertMatchResult(result)
154+
return assertMatchResult(result, chai.util.flag(this, 'message'))
153155
}),
154156
)
155157
utils.addMethod(
@@ -169,7 +171,7 @@ export const SnapshotPlugin: ChaiPlugin = (chai, utils) => {
169171
isInline: true,
170172
...normalizeInlineArguments(undefined, inlineSnapshotOrHint, hint),
171173
})
172-
return assertMatchResult(result)
174+
return assertMatchResult(result, chai.util.flag(this, 'message'))
173175
}),
174176
)
175177
utils.addMethod(chai.expect, 'addSnapshotSerializer', addSerializer)
@@ -221,7 +223,6 @@ function toMatchSnapshotImpl(options: {
221223
message: options.hint,
222224
isInline: options.isInline,
223225
inlineSnapshot: options.inlineSnapshot,
224-
errorMessage: chai.util.flag(assertion, 'message'),
225226
// pass `assertionName` for inline snapshot stack probing
226227
assertionName,
227228
// set by async assertion (e.g. resolves/rejects) for inline snapshot stack probing
@@ -246,7 +247,6 @@ async function toMatchFileSnapshotImpl(options: {
246247
return getSnapshotClient().match({
247248
received: options.received,
248249
message: options.hint,
249-
errorMessage: chai.util.flag(assertion, 'message'),
250250
rawSnapshot: {
251251
file: rawSnapshotFile,
252252
content: rawSnapshotContent ?? undefined,
@@ -255,9 +255,10 @@ async function toMatchFileSnapshotImpl(options: {
255255
})
256256
}
257257

258-
function assertMatchResult(result: SyncExpectationResult): void {
258+
function assertMatchResult(result: SyncExpectationResult, customMessage?: string): void {
259259
if (!result.pass) {
260-
throw Object.assign(new Error(result.message()), {
260+
const errorMessage = (customMessage ? `${customMessage}: ` : '') + result.message()
261+
throw Object.assign(new Error(errorMessage), {
261262
actual: result.actual,
262263
expected: result.expected,
263264
diffOptions: {

test/core/test/expect-poll.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,12 @@ test('toBeDefined', async () => {
122122
}))
123123
})
124124

125+
test('custom message', async () => {
126+
await expect(() =>
127+
expect.poll(() => 1, { timeout: 100, interval: 10, message: 'custom' }).toBe(2),
128+
).rejects.toMatchInlineSnapshot(`[AssertionError: custom: expected 1 to be 2 // Object.is equality]`)
129+
})
130+
125131
test('should set _isLastPollAttempt flag on last call', async () => {
126132
const fn = vi.fn(function (this: object) {
127133
return chai.util.flag(this, '_isLastPollAttempt')

test/core/test/expect.test.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -397,21 +397,21 @@ describe('Temporal equality', () => {
397397
describe('expect with custom message', () => {
398398
describe('built-in matchers', () => {
399399
test('sync matcher throws custom message on failure', () => {
400-
expect(() => expect(1, 'custom message').toBe(2)).toThrow('custom message')
400+
expect(() => expect(1, 'custom message').toBe(2)).toThrowErrorMatchingInlineSnapshot(`[AssertionError: custom message: expected 1 to be 2 // Object.is equality]`)
401401
})
402402

403403
test('async rejects matcher throws custom message on failure', async ({ expect }) => {
404404
const asyncAssertion = expect(Promise.reject(new Error('test error')), 'custom async message').rejects.toBe(2)
405-
await expect(asyncAssertion).rejects.toThrow('custom async message')
405+
await expect(asyncAssertion).rejects.toMatchInlineSnapshot(`[AssertionError: custom async message: expected Error: test error to be 2 // Object.is equality]`)
406406
})
407407

408408
test('async resolves matcher throws custom message on failure', async ({ expect }) => {
409409
const asyncAssertion = expect(Promise.resolve(1), 'custom async message').resolves.toBe(2)
410-
await expect(asyncAssertion).rejects.toThrow('custom async message')
410+
await expect(asyncAssertion).rejects.toMatchInlineSnapshot(`[AssertionError: custom async message: expected 1 to be 2 // Object.is equality]`)
411411
})
412412

413413
test('not matcher throws custom message on failure', () => {
414-
expect(() => expect(1, 'custom message').not.toBe(1)).toThrow('custom message')
414+
expect(() => expect(1, 'custom message').not.toBe(1)).toThrowErrorMatchingInlineSnapshot(`[AssertionError: custom message: expected 1 not to be 1 // Object.is equality]`)
415415
})
416416
})
417417

@@ -426,7 +426,7 @@ describe('expect with custom message', () => {
426426
}
427427
},
428428
})
429-
expect(() => (expect('bar', 'custom message') as any).toBeFoo()).toThrow('custom message')
429+
expect(() => (expect('bar', 'custom message') as any).toBeFoo()).toThrowErrorMatchingInlineSnapshot(`[Error: custom message: bar is foo]`)
430430
})
431431

432432
test('sync custom matcher passes with custom message when assertion succeeds', ({ expect }) => {
@@ -453,7 +453,7 @@ describe('expect with custom message', () => {
453453
},
454454
})
455455
const asyncAssertion = (expect(Promise.resolve('bar'), 'custom async message') as any).toBeFoo()
456-
await expect(asyncAssertion).rejects.toThrow('custom async message')
456+
await expect(asyncAssertion).rejects.toMatchInlineSnapshot(`[Error: custom async message: bar is not foo]`)
457457
})
458458

459459
test('async custom matcher with not throws custom message on failure', async ({ expect }) => {
@@ -467,17 +467,17 @@ describe('expect with custom message', () => {
467467
},
468468
})
469469
const asyncAssertion = (expect(Promise.resolve('foo'), 'custom async message') as any).not.toBeFoo()
470-
await expect(asyncAssertion).rejects.toThrow('custom async message')
470+
await expect(asyncAssertion).rejects.toMatchInlineSnapshot(`[Error: custom async message: foo is not foo]`)
471471
})
472472
})
473473

474474
describe('edge cases', () => {
475475
test('empty custom message falls back to default matcher message', () => {
476-
expect(() => expect(1, '').toBe(2)).toThrow('expected 1 to be 2 // Object.is equality')
476+
expect(() => expect(1, '').toBe(2)).toThrowErrorMatchingInlineSnapshot(`[AssertionError: expected 1 to be 2 // Object.is equality]`)
477477
})
478478

479479
test('undefined custom message falls back to default matcher message', () => {
480-
expect(() => expect(1, undefined as any).toBe(2)).toThrow('expected 1 to be 2 // Object.is equality')
480+
expect(() => expect(1, undefined as any).toBe(2)).toThrowErrorMatchingInlineSnapshot(`[AssertionError: expected 1 to be 2 // Object.is equality]`)
481481
})
482482
})
483483
})

test/snapshots/test/custom-matcher.test.ts

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,3 +403,111 @@ test('raw file snapshot', async () => {
403403
`)
404404
expect(result.fs.readFile('raw.txt')).toMatchInlineSnapshot(`"crazy long"`)
405405
})
406+
407+
test('outer expect message is prefixed by jest-extend for Snapshots wrappers', async () => {
408+
const result = await runInlineTests({
409+
'basic.test.ts': `
410+
import { test, expect, Snapshots } from 'vitest'
411+
412+
const {
413+
toMatchInlineSnapshot,
414+
} = Snapshots
415+
416+
expect.extend({
417+
toMatchTrimmedInlineSnapshot(received: string, inlineSnapshot?: string) {
418+
return toMatchInlineSnapshot.call(this, received.slice(0, 5), inlineSnapshot)
419+
},
420+
})
421+
422+
test('custom snapshot matcher', () => {
423+
expect('abcdefghij', 'outer message').toMatchTrimmedInlineSnapshot(\`"wrong"\`)
424+
})
425+
426+
test('builtin', () => {
427+
expect('abcdefghij', 'outer message').toMatchInlineSnapshot(\`"wrong"\`)
428+
})
429+
430+
test('builtin properties mismatch', () => {
431+
expect({ value: 1 }, 'outer message').toMatchSnapshot({
432+
value: expect.any(String),
433+
})
434+
})
435+
`,
436+
}, {
437+
update: 'none',
438+
})
439+
expect(result.stderr).toMatchInlineSnapshot(`
440+
"
441+
⎯⎯⎯⎯⎯⎯⎯ Failed Tests 3 ⎯⎯⎯⎯⎯⎯⎯
442+
443+
FAIL basic.test.ts > custom snapshot matcher
444+
Error: outer message: Snapshot \`custom snapshot matcher 1\` mismatched
445+
446+
Expected: ""wrong""
447+
Received: ""abcde""
448+
449+
❯ basic.test.ts:15:41
450+
13|
451+
14| test('custom snapshot matcher', () => {
452+
15| expect('abcdefghij', 'outer message').toMatchTrimmedInlineSnapshot(\`…
453+
| ^
454+
16| })
455+
17|
456+
457+
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/3]⎯
458+
459+
FAIL basic.test.ts > builtin
460+
Error: outer message: Snapshot \`builtin 1\` mismatched
461+
462+
Expected: ""wrong""
463+
Received: ""abcdefghij""
464+
465+
❯ basic.test.ts:19:41
466+
17|
467+
18| test('builtin', () => {
468+
19| expect('abcdefghij', 'outer message').toMatchInlineSnapshot(\`"wrong"…
469+
| ^
470+
20| })
471+
21|
472+
473+
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/3]⎯
474+
475+
FAIL basic.test.ts > builtin properties mismatch
476+
Error: outer message: Snapshot properties mismatched
477+
478+
- Expected
479+
+ Received
480+
481+
{
482+
- "value": Any<String>,
483+
+ "value": 1,
484+
}
485+
486+
❯ basic.test.ts:23:41
487+
21|
488+
22| test('builtin properties mismatch', () => {
489+
23| expect({ value: 1 }, 'outer message').toMatchSnapshot({
490+
| ^
491+
24| value: expect.any(String),
492+
25| })
493+
494+
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/3]⎯
495+
496+
"
497+
`)
498+
expect(result.errorTree()).toMatchInlineSnapshot(`
499+
Object {
500+
"basic.test.ts": Object {
501+
"builtin": Array [
502+
"outer message: Snapshot \`builtin 1\` mismatched",
503+
],
504+
"builtin properties mismatch": Array [
505+
"outer message: Snapshot properties mismatched",
506+
],
507+
"custom snapshot matcher": Array [
508+
"outer message: Snapshot \`custom snapshot matcher 1\` mismatched",
509+
],
510+
},
511+
}
512+
`)
513+
})

0 commit comments

Comments
 (0)