Skip to content

Conversation

@ronnakamoto
Copy link
Contributor

@ronnakamoto ronnakamoto commented Oct 27, 2025

Description

This PR adds Chai-style assertion names for spy matchers, enabling users migrating from Mocha+Chai+Sinon to use familiar assertion syntax without rewriting their tests.

Resolves #8819

Users migrating from Mocha/Chai/Sinon to Vitest currently need to rewrite all their spy assertions from Chai-style (e.g., expect(spy).to.have.been.called) to Jest-style (e.g., expect(spy).toHaveBeenCalled()). This creates friction during migration and requires significant test refactoring.

This implementation provides Chai-style assertion names that delegate to existing Jest-style implementations, allowing both styles to coexist.

Added the following assertions that delegate to existing Jest-style implementations:

Property Assertions (no parentheses):

  • called -> toHaveBeenCalled
  • calledOnce -> toHaveBeenCalledOnce
  • calledTwice -> toHaveBeenCalledTimes(2)
  • calledThrice -> toHaveBeenCalledTimes(3)
  • returned -> toHaveReturned

Method Assertions (with parentheses):

  • callCount(n) -> toHaveBeenCalledTimes(n)
  • calledWith(...args) -> toHaveBeenCalledWith(...args)
  • calledOnceWith(...args) -> toHaveBeenCalledExactlyOnceWith(...args)
  • lastCalledWith(...args) -> toHaveBeenLastCalledWith(...args)
  • nthCalledWith(n, ...args) -> toHaveBeenNthCalledWith(n, ...args)
  • returnedWith(value) -> toHaveReturnedWith(value)
  • returnedTimes(n) -> toHaveReturnedTimes(n)
  • lastReturnedWith(value) -> toHaveLastReturnedWith(value)
  • nthReturnedWith(n, value) -> toHaveNthReturnedWith(n, value)
  • calledBefore(spy) -> toHaveBeenCalledBefore(spy)
  • calledAfter(spy) -> toHaveBeenCalledAfter(spy)

Tests

  • Run the tests with pnpm test:ci.

Documentation

  • Updated documentation

@netlify
Copy link

netlify bot commented Oct 27, 2025

Deploy Preview for vitest-dev ready!

Name Link
🔨 Latest commit 436a4fd
🔍 Latest deploy log https://app.netlify.com/projects/vitest-dev/deploys/69666f9cce8d570008649ef2
😎 Deploy Preview https://deploy-preview-8842--vitest-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

})
```

## Chai-Style Spy Assertions
Copy link
Member

Choose a reason for hiding this comment

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

This is a guide, not an API.

For an API we need all methods to be described similar to other to* assertions

The current doc can be moved to guides

```

::: tip
Vitest supports both `before`/`after` (Mocha-style) and `beforeAll`/`afterAll` (Jest-style) - they're aliases!
Copy link
Member

Choose a reason for hiding this comment

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

Vitest does not support before/after


### Assertions

Vitest includes Chai assertions by default, so most Chai assertions work without changes:
Copy link
Member

Choose a reason for hiding this comment

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

Let's remove the "most" part, all of them work the same way

```

::: tip
Notice the only difference: Chai-style assertions in Vitest use method calls `called()` instead of properties `called`. This is because Vitest implements these as methods that delegate to Jest-style matchers.
Copy link
Member

Choose a reason for hiding this comment

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

I think we still want them to be defined in the same way that sinon-chai does:

expect(spy).to.have.been.called
expect(spy).to.have.been.calledOnce
expect(spy).to.have.been.calledWith('arg1', 'arg2')

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Refactored to that format

vi.useRealTimers()
```

### Async Testing
Copy link
Member

Choose a reason for hiding this comment

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

I think this can be removed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done


// Chai-style assertion: called
// Delegates to: toHaveBeenCalled
def('called', 'toHaveBeenCalled')
Copy link
Member

Choose a reason for hiding this comment

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

this should be a property

}
}

// Chai-style assertion: called
Copy link
Member

Choose a reason for hiding this comment

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

All of the comments can be removed, they do not provide any value


// Chai-style assertion: calledTwice
// Wrapper that calls toHaveBeenCalledTimes(2)
utils.addMethod(
Copy link
Member

Choose a reason for hiding this comment

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

Why can't we use def for this? Maybe enhance it to support a property with specified arguments

* Chai-style equivalent of `toHaveBeenCalledTimes(2)`.
*
* @example
* expect(spy).to.have.been.calledTwice
Copy link
Member

Choose a reason for hiding this comment

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

All the examples show it as a property...

* Chai-style assertions for spy/mock testing.
* These provide sinon-chai compatible assertion names that delegate to Jest-style implementations.
*/
export interface ChaiStyleAssertion {
Copy link
Member

Choose a reason for hiding this comment

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

Let's name it something like ChaiMockAssertion or something

@sheremet-va sheremet-va added this to the 4.1.0 milestone Nov 17, 2025
@sheremet-va sheremet-va merged commit 841df9a into vitest-dev:main Jan 13, 2026
15 of 16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enhance Chai assertions

2 participants