feat: upgrade chai to 4.5.0 and expose new assertion aliases#34178
Open
jennifer-shehane wants to merge 13 commits into
Open
feat: upgrade chai to 4.5.0 and expose new assertion aliases#34178jennifer-shehane wants to merge 13 commits into
jennifer-shehane wants to merge 13 commits into
Conversation
Upgrade the driver's chai dependency from 4.2.0 to 4.5.0, the latest v4 release. The 4.5.0 lockfile entry already existed (shared with other packages), so this consolidates the driver onto it and drops the orphaned 4.2.0 entry. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019BxGV9ZVJz7iJejFk7powF
Document the driver's chai 4.2.0 -> 4.5.0 dependency update under Dependency Updates. The upgrade is backward compatible for users: the driver's existing chai patch layer (custom inspect/objDisplay/getMessage) keeps assertion behavior and error-message formatting unchanged, and the bump only adds new assertion aliases. PR link is a placeholder to be filled in when the PR is opened. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019BxGV9ZVJz7iJejFk7powF
The chai upgrade adds new assertion aliases (.exists, .greaterThanOrEqual, .lessThanOrEqual, and .contain.oneOf), so frame it as a user-facing feature rather than a plain dependency update. PR link is a placeholder to be filled in when the PR is opened. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019BxGV9ZVJz7iJejFk7powF
Add TypeScript definitions for the assertion aliases introduced by the
chai 4.5 upgrade so they are available to users:
- expect(...).to.exists / should('exist')
- expect(...).to.be.greaterThanOrEqual(n) / should('be.greaterThanOrEqual', n)
- expect(...).to.be.lessThanOrEqual(n) / should('be.lessThanOrEqual', n)
- expect(...).to.contain.oneOf([...])
The BDD aliases are added to the bundled chai augmentation (cy-chai.d.ts)
and the should() string-chainer forms to the Chainer overloads
(cypress.d.ts), with matching dtslint examples in chainer-examples.ts.
Also add runtime smoke tests verifying the aliases are reachable through
Cypress's expect/assert/should surfaces. These are vanilla chai aliases,
so the tests only assert reachability, not chai's behavior.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019BxGV9ZVJz7iJejFk7powF
Keep comments describing present state rather than the upgrade that introduced the aliases. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019BxGV9ZVJz7iJejFk7powF
Add regression tests asserting the rendered values in assertion failure messages for functions and dates. These render differently under chai's built-in inspector ([Function foo], ISO-8601 dates) than under Cypress's inspector ([Function: foo], toUTCString), so the tests catch any change that would alter user-facing failure messages. Existing message-formatting tests only cover simple objects/strings, where both inspectors produce identical output, so they did not guard this. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019BxGV9ZVJz7iJejFk7powF
The function/date guards only exercise short values that never reach the
truncateThreshold, so they would not catch a change to how long values
are trimmed. Add cases for a long object and a long array, which chai's
inspector summarizes very differently ({ name: 'Joe', ...(1) } and
[ 1, 2, ...(5) ]) than Cypress's ({ Object (name, ...) } and
[ Array(15) ]).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019BxGV9ZVJz7iJejFk7powF
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019BxGV9ZVJz7iJejFk7powF
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019BxGV9ZVJz7iJejFk7powF
Cursor Bugbot risk assessment is no longer Low Risk. Auto-approval dismissed; manual review required.
Contributor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 7a4b7b8. Configure here.
cypress
|
||||||||||||||||||||||||||||||||||||||||
| Project |
cypress
|
| Branch Review |
claude/driver-chai-v4-upgrade-o4jd2t
|
| Run status |
|
| Run duration | 20m 12s |
| Commit |
|
| Committer | Claude |
| View all properties for this run ↗︎ | |
| Test results | |
|---|---|
|
|
0
|
|
|
10
|
|
|
1133
|
|
|
0
|
|
|
27530
|
| View all changes introduced in this branch ↗︎ | |
UI Coverage
64%
|
|
|---|---|
|
|
27
|
|
|
48
|
Accessibility
99%
|
|
|---|---|
|
|
0 critical
3 serious
1 moderate
0 minor
|
|
|
19
|
chai 4.3 reworded the error thrown when an .include/.deepInclude target is not a supported type, from "object tested must be an array, ..." to "the given combination of arguments (...) is invalid for this assertion. ...". Update the runner error-UI verifications to match. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019BxGV9ZVJz7iJejFk7powF
chai registers `.exists` as a separate property from `.exist`, but the
driver only overwrote `.exist` with its DOM-aware existence assertion
(attachment check + retry + custom messages). As a result
`expect($el).to.exists` / `should('not.exists')` on a jQuery/DOM subject
fell through to chai's vanilla nullish check, which always passes for a
jQuery wrapper. Overwrite `.exists` with the same assertion (with
matching save/restore) so both behave identically.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019BxGV9ZVJz7iJejFk7powF
@types/chai 5 documents the `_super` getter parameter, so the overwriteProperty calls type-check cleanly. The "_super is not documented" @ts-ignore is a no-op (and @ts-expect-error would fail as an unused directive), so remove the suppression entirely. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019BxGV9ZVJz7iJejFk7powF
Switch the remaining @ts-ignore comments in chai.ts to @ts-expect-error with the reason inline. Unlike @ts-ignore, @ts-expect-error fails if the suppressed error ever disappears, so these won't silently rot. Verified each still suppresses a real error under @types/chai 5 (getMessage overload assignment; makeMethodChainable not matching chainingBehavior). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019BxGV9ZVJz7iJejFk7powF
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

chaidependency-maintenance upgrade for the driver. There is no dedicated open issue; the prior chai-upgrade issues (#2529, #2863) are closed.Additional details
Upgrades the driver's bundled
chaifrom4.2.0to4.5.0(the latest 4.x release).chaiis the assertion library Cypress exposes to users viaexpect,assert,should, andcy.…should(...), so this is treated as a user-facing change.This is intended to be non-breaking. The driver overrides chai's value inspection (
chai.util.inspect/objDisplay/getMessage) with its own implementation, and chai's internals call those dynamically (util.getMessage(...)). As a result, chai 4.3+'s switch to theloupeinspector is bypassed — both the command-log message and the thrown error are formatted by Cypress's own inspector, so assertion failure messages and truncation are unchanged. See "Why this is safe" below.Internal: the
chai.tsTypeScript suppressions were converted from@ts-ignoreto@ts-expect-error(with inline reasons), and one suppression that@types/chai5 made unnecessary was dropped.Dependency diff (
chai4.2.0 → 4.5.0)assertion-error^1.1.0^1.1.0check-error^1.0.2^1.0.3deep-eql^3.0.1^4.1.3get-func-name^2.0.0^2.0.2loupe^2.3.6pathval^1.1.0^1.1.1type-detect^4.0.5^4.1.0chai changelog between the versions (release-by-release)
loupelibrary (this is the change Cypress neutralizes). ✅ (objDisplay/inspect now delegate to loupe)deep-eqlbumped from v3 to v4..oneOfcan be chained with.contain/.include(e.g.expect([1,2,3]).to.contain.oneOf([3,4,5])) and supports.deep. ✅alsolanguage chain. ✅.existsalias of.exist. ✅.greaterThanOrEqual(alias of.least/.gte) and.lessThanOrEqual(alias of.most/.lte). ✅AssertionErrornow carries anoperatorattribute (improves diffs in Jest, etc.)..closeTo/.approximatelyerror message now states, and a delta is requiredwhen the delta is omitted. ✅.includeinvalid-target message reworded to "the given combination of arguments (… and …) is invalid for this assertion. …". ✅.withinwithDatebounds now renders the range usingtoISOString()instead oftoUTCString(). ✅deep-eql,loupe,get-func-name,check-error,pathval), security/maintenance updates, and documentation fixes. Notably 4.3.8 included aversionexport correction and dev-dependency bumps. No assertion API changes.eqlcomparator can be supplied so deep assertions use a custom equality function instead of the built-in. ✅ (deep assertions now readflag(this, 'eql'), defaulting todeep-eql)??) for older runtimes.type-detectbumped to4.1.0anddeep-eqlbumped (adds correct comparison ofSymbol-keyed properties). No assertion API changes.deep-eqlv3 → v4 behavioral diff (verified empirically)Across 18 representative comparisons, the only behavior that changes for common values:
Errorobjects with the samename/messageare now deeply equal (they were not under v3). This is an edge-case bug fix — it turns a previously-failingdeep.equalinto a passing one, never the reverse.Symbol-keyed properties.Everything else tested (plain/nested objects, arrays,
NaN,+0/-0, dates, regexes,Map/Set, typed arrays,arguments, promises, functions) is identical between v3 and v4.Net user-facing changes in Cypress
.exists,.greaterThanOrEqual,.lessThanOrEqual, and.contain.oneOf. TypeScript definitions were added for all of them (BDD form incli/types/cy-chai.d.ts,should('…')string-chainer form incli/types/cypress.d.ts), with matchingdtslintexamples..existsgets Cypress's DOM-aware existence behavior: chai 4.3 registers.existsas a separate property from.exist, so the driver now applies its existence override (attachment check + retry + "to exist in the DOM" messaging) to both. Without this,expect($el).to.exists/should('not.exists')on a jQuery/DOM subject would fall through to chai's vanilla nullish check (a jQuery wrapper is nevernull). Raised by Cursor Bugbot.Error-comparison edge case above..include-target error, which is asserted by the runner error-UI tests (a fixture that callsassert.deepInclude()), so those expectations were updated to the new wording (is invalid for this assertion). The other reworded messages (.closeTomissing-delta,.withinwithDatebounds) are not asserted anywhere.Why this is safe (loupe is a no-op in Cypress)
The driver replaces chai's
inspect/objDisplay/getMessage, and chai'sassertion.jscallsutil.getMessage(...)dynamically, so every failure message — command-log and thrown error alike — is rendered by Cypress's own inspector. loupe is effectively dead code after the overrides. For reference, if loupe ever leaked, messages would differ like this (driver = what we keep, loupe = raw chai 4.5):[Function: foo][Function foo]Thu, 01 Jan 1970 00:00:00 GMT1970-01-01T00:00:00.000Z{ Object (name, age, ...) }{ name: 'Joe', age: 20, …(1) }[ Array(15) ][ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, …(5) ]New regression tests in
assertions.cy.js(uses Cypress value inspection) pin the "driver" column for functions, dates, and truncated objects/arrays, so a loupe leak would fail CI.Steps to test
expect(2).to.be.greaterThanOrEqual(1)/cy.wrap(2).should('be.greaterThanOrEqual', 2)pass.expect(1).to.be.lessThanOrEqual(2)/cy.wrap(1).should('be.lessThanOrEqual', 2)pass.expect(0).to.existspasses;expect(null).to.not.existspasses;cy.get('#missing').should('not.exists')retries and reports Cypress's "to exist in the DOM" message (not chai's nullish check).expect('Today is sunny').to.contain.oneOf(['sunny', 'cloudy'])passes.expected [Function: foo] to equal [Function: bar],expected [ Array(15) ] to equal null).cli/types/tests/chainer-examples.ts).How has the user experience changed?
No change to existing assertion behavior or failure messages. The only additions are the new optional assertion aliases listed above (with
.existsmatching.exist's DOM-aware behavior). No visual change.PR Tasks
cypress-documentation?🤖 Generated with Claude Code
Generated by Claude Code
Note
Medium Risk
Changes the shared assertion stack (including deep-eql v4) used in every spec; risk is mitigated by preserved Cypress chai overrides and new regression tests, but edge-case deep equality or rare misuse messages could still differ.
Overview
Upgrades the driver’s bundled chai from
4.2.0to4.5.0, exposing new optional assertion aliases (.exists,.greaterThanOrEqual,.lessThanOrEqual, and.contain.oneOf) throughexpect,assert, andcy.…should(...).Because chai 4.3+ registers
existsseparately fromexist, the driver now applies the same DOM-aware existence override to both properties soshould('not.exists')on missing elements still uses Cypress’s “in the DOM” messaging instead of chai’s nullish check.TypeScript is updated in
cy-chai.d.tsandcypress.d.ts(includingshould('be.greaterThanOrEqual', …)/ negated variants). New driver and type tests cover the aliases, DOM behavior forexists, and regression guards that assertion failure text still uses Cypress’s inspector (functions, dates, truncated objects/arrays) rather than chai’sloupeformatting.Reporter e2e expectations change for one chai
assertmisuse error string (is invalid for this assertion). The changelog documents the feature and the upgrade.Reviewed by Cursor Bugbot for commit 694ce83. Bugbot is set up for automated code reviews on this repo. Configure here.