Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions docs/api/expect.md
Original file line number Diff line number Diff line change
Expand Up @@ -1559,23 +1559,19 @@ test('spy nth called with', () => {

## returned <Version>4.1.0</Version> {#returned}

- **Type:** `Assertion` (property, not a method)

Chai-style assertion that checks if a spy returned successfully at least once. This is equivalent to `toHaveReturned()`.
- **Type:** `(value: any) => void`

::: tip
This is a property assertion following sinon-chai conventions. Access it without parentheses: `expect(spy).to.have.returned`
:::
Chai-style assertion that checks if a spy returned a specific value at least once. This is equivalent to `toHaveReturnedWith(value)`.

```ts
import { expect, test, vi } from 'vitest'

test('spy returned', () => {
const spy = vi.fn(() => 'result')
const spy = vi.fn(() => 'value')

spy()

expect(spy).to.have.returned
expect(spy).to.have.returned('value')
})
```

Expand Down
3 changes: 1 addition & 2 deletions docs/guide/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -742,8 +742,7 @@ Vitest supports all common sinon-chai assertions:
| `spy.callCount(n)` | `callCount(n)` | Spy was called n times |
| `spy.calledWith(...)` | `calledWith(...)` | Spy was called with specific args |
| `spy.calledOnceWith(...)` | `calledOnceWith(...)` | Spy was called once with specific args |
| `spy.returned` | `returned` | Spy returned successfully |
| `spy.returnedWith(value)` | `returnedWith(value)` | Spy returned specific value |
Comment on lines -745 to -746
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this was oversight or hallucination. Probably no way back to remove returnedWith, so now returnedWith and returned are essentially same.

| `spy.returned(value)` | `returned` | Spy returned specific value |

See the [Chai-Style Spy Assertions](/api/expect#chai-style-spy-assertions) documentation for the complete list.

Expand Down
10 changes: 7 additions & 3 deletions packages/expect/src/chai-style-assertions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const ChaiStyleAssertions: ChaiPlugin = (chai, utils) => {
name: keyof Assertion,
delegateTo: keyof Assertion,
) {
utils.addChainableMethod(
utils.addMethod(
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chai's addChainableMethod uses Object.defineProperty({ get }) and addMethod uses simple assignment. Thus addMethod allows later addMethod to take over, but addChainableMethod breaks.

Not sure what was the purpose but ours aren't chainable anyways, so just switched to addMethod.

chai.Assertion.prototype,
name,
function (this: Chai.AssertionStatic & Assertion, ...args: any[]) {
Expand All @@ -56,13 +56,13 @@ export const ChaiStyleAssertions: ChaiPlugin = (chai, utils) => {
}
return jestMethod.call(this, ...args)
},
() => {},
)
}

// API to (somewhat) mirror sinon-chai
// https://github.com/chaijs/sinon-chai
defProperty('called', 'toHaveBeenCalled')
defProperty('calledOnce', 'toHaveBeenCalledOnce')
defProperty('returned', 'toHaveReturned')
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

defProperty uses defineProperty(get), so later call of addMethod('returned') by sinon-chai breaks.

defPropertyWithArgs('calledTwice', 'toHaveBeenCalledTimes', 2)
defPropertyWithArgs('calledThrice', 'toHaveBeenCalledTimes', 3)

Expand All @@ -71,10 +71,14 @@ export const ChaiStyleAssertions: ChaiPlugin = (chai, utils) => {
defMethod('calledOnceWith', 'toHaveBeenCalledExactlyOnceWith')
defMethod('lastCalledWith', 'toHaveBeenLastCalledWith')
defMethod('nthCalledWith', 'toHaveBeenNthCalledWith')
defMethod('returned', 'toHaveReturned')
defMethod('returnedWith', 'toHaveReturnedWith')
defMethod('returnedTimes', 'toHaveReturnedTimes')
defMethod('lastReturnedWith', 'toHaveLastReturnedWith')
defMethod('nthReturnedWith', 'toHaveNthReturnedWith')
defMethod('calledBefore', 'toHaveBeenCalledBefore')
defMethod('calledAfter', 'toHaveBeenCalledAfter')

// TODO: implement
// defMethod('thrown', 'toHaveThrown')
Comment on lines +82 to +83
Copy link
Copy Markdown
Collaborator Author

@hi-ogawa hi-ogawa Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we'd implement but just noted that they aren't fully ported yet.

}
8 changes: 4 additions & 4 deletions packages/expect/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -836,13 +836,13 @@ export interface ChaiMockAssertion {
nthCalledWith: <E extends any[]>(n: number, ...args: E) => void

/**
* Checks that a spy returned successfully at least once.
* Chai-style equivalent of `toHaveReturned`.
* Checks that a spy returned a specific value at least once.
* Chai-style equivalent of `toHaveReturnedWith`.
*
* @example
* expect(spy).to.have.returned
* expect(spy).to.have.returned('value')
*/
readonly returned: Assertion
returned: <E>(value: E) => void

/**
* Checks that a spy returned a specific value at least once.
Expand Down
61 changes: 61 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ catalog:
obug: ^2.1.1
pathe: ^2.0.3
playwright: ^1.58.2
sinon: ^21.0.3
sinon-chai: ^4.0.1
sirv: ^3.0.2
std-env: ^4.0.0-rc.1
strip-literal: ^3.1.0
Expand Down
2 changes: 2 additions & 0 deletions test/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
"obug": "^2.1.1",
"react": "^19.2.4",
"react-18": "npm:react@18.3.1",
"sinon": "catalog:",
"sinon-chai": "catalog:",
"temporal-polyfill": "~0.3.0",
"tinyrainbow": "catalog:",
"tinyspy": "^4.0.4",
Expand Down
Loading
Loading