Skip to content

test(firestore): migrate tests to Vitest - #10394

Open
Manvi1203 wants to merge 9 commits into
mainfrom
feature/vitest-firestore
Open

Manvi1203 wants to merge 9 commits into
mainfrom
feature/vitest-firestore

Conversation

@Manvi1203

@Manvi1203 Manvi1203 commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Migrates @firebase/firestore (packages/firestore) and integration/firestore unit, integration, and lite test suites (test/unit/**, test/integration/**, and test/lite/**) from Karma + Mocha + Chai + Sinon to Vitest across Node and Browser (Playwright Chromium, Firefox, and WebKit) environments.


Description

Test Runner Config, Setup & CI Workflows

File What Changed & Why
packages/firestore/vitest.config.mjs Replaces karma.conf.js and mocha. Extends shared config/vitest.base.mjs with node and browser Vitest projects, maps src/platform/* aliases (node, browser, node_lite, browser_lite), and injects build-time env flags (__FIRESTORE_TARGET_BACKEND__, __FIRESTORE_USE_MOCK_PERSISTENCE__) via Vite's define for browser tests.
integration/firestore/vitest.config.mjs Replaces Karma for the standalone integration/firestore package (tested under both memory and persistence modes).
packages/firestore/test/setup.ts Replaces the legacy Karma bootstrap.ts files (test/unit/bootstrap.ts, test/integration/bootstrap.ts, test/lite/bootstrap.ts). Registers both full Firestore (registerFirestore) and Lite (registerFirestoreLite) per Vitest worker, polyfills Buffer in the browser, and restores timers/mocks (vi.useRealTimers(), vi.restoreAllMocks()) after each test.
packages/firestore/scripts/run-tests.ts Invokes vitest CLI instead of nyc / mocha while preserving existing CLI flags (--platform, --persistence, --emulator, --prod).
packages/firestore/package.json & integration/firestore/package.json Updates test:* scripts (test:node, test:browser, test:firefox, test:webkit, test:lite:*) to use Vitest and Playwright browser providers.
.github/workflows/test-changed-firestore.yml & .github/workflows/test-changed-firestore-integration.yml Installs Playwright browsers (chromium, firefox, webkit) in CI where Karma browser launchers were previously used.

Firestore Test Harness & Custom Helpers

File What Changed & Why (Vitest Context)
packages/firestore/test/util/mocha_extensions.ts Provides custom chained test modifiers (it.skipEnterprise, it.skipEmulator, describe.skipClassic, etc.). Why it changed: In Mocha, it.skip and describe.skip are static function objects that can be mutated once at import time. In Vitest, .skip is a property getter that returns a newly wrapped function instance on every access. We added a getSkip() helper so chaining (e.g. it.skipEnterprise.skipEmulator(...)) re-attaches the custom modifiers onto newly returned .skip functions.
packages/firestore/test/util/equality_matcher.ts Replaces the custom Chai toEqual plugin override with Vitest's expect.addEqualityTesters(...) so Firestore types with .isEqual() (or custom EqualsFn matchers) work seamlessly inside expect(a).toEqual(b) and nested arrays/objects.
packages/firestore/test/util/helpers.ts & packages/firestore/test/integration/util/helpers.ts Replaces this.test.fullTitle() with expect.getState().currentTestName and ensures apiDescribe properly skips suites at definition time when persistence/backend flags disable them.
packages/firestore/test/integration/prime_backend.test.ts Why it changed: Mocha allowed a test file to contain only a top-level before() hook with zero it() blocks. Vitest fails if a .test.ts file has no test suite (Error: No test suite found in file). Wrapped beforeAll inside describe('Prime Backend', () => { ... it('primes backend', () => {}); }).

Mechanical Test Suite Migrations (~154 *.test.ts files )

All remaining files under packages/firestore/test/{unit,integration,lite}/** and integration/firestore/test/** are mechanical translations following the cheat sheet below.


Vitest Equivalents

Vitest uses a Jest-compatible expect and mocking API (vi) while keeping describe / it test structure:

Concept Legacy (Mocha + Chai + Sinon + Karma) New (Vitest + Playwright Browser)
Suite Lifecycle Hooks before(() => ...) / after(() => ...) beforeAll(() => ...) / afterAll(() => ...) (beforeEach / afterEach are unchanged)
Strict Equality (===) expect(x).to.equal(y) / expect(x).to.be.true expect(x).toBe(y) / expect(x).toBe(true)
Deep Structural Equality expect(x).to.deep.equal(y) expect(x).toEqual(y)
Floating-Point Approximation expect(x).to.be.closeTo(expected, delta) expect(x).toBeCloseTo(expected, precisionDigits)
Array Membership expect(arr).to.have.members([a, b]) expect(arr).toEqual(expect.arrayContaining([a, b]))
Async Promise Rejection await expect(promise).to.eventually.be.rejectedWith(/msg/) await expect(promise).rejects.toThrow(/msg/)
Async Callback Tests (done) it('test', done => { ... done(); }) it('test', () => new Promise<void>(resolve => { ... resolve(); })) (Vitest deprecates callback-style done in favor of Promises)
Spies, Stubs & Fake Timers sinon.spy(), sinon.stub(obj, 'm'), sinon.useFakeTimers() vi.fn(), vi.spyOn(obj, 'm'), vi.useFakeTimers()
Current Test Name this.test.fullTitle() (requires function() binding) expect.getState().currentTestName (works in arrow functions)

Other Changes

  1. Targeted onUnhandledError in vitest.config.mjs:
    In database.test.ts, the 4 onSnapshotResume malformed-bundle tests (bundle: 'BadData') trigger a synchronous BundleReaderImpl constructor rejection (Invalid bundle format: Reached the end of bundle when a length string is expected.) before getSyncEngine() finishes opening IndexedDB on the asyncQueue and attaches a .catch handler to reader.getMetadata(). Rather than disabling unhandled error tracking globally, config.test.onUnhandledError returns false only for that specific Invalid bundle format error so any genuine unhandled rejection in unit, lite, or integration tests still fails the test run.
  2. Shared Browser Context (isolate: false, fileParallelism: false):
    In the browser project, tests run in a shared Playwright browser context rather than parallel isolated iframes. This matches Karma's single-tab execution model and avoids cross-iframe IndexedDB lock contention (SimpleDb.delete) during persistence tests.
  3. Suite-Level Skipping (describe.skip):
    When a test file is conditionally disabled (e.g., large_document.test.ts when RUN_LARGE_DOC_TESTS is unset, or pipeline emulator tests when running against prod), Vitest requires the suite to be marked with .skip (apiDescribe.skip(...)) rather than returning early inside describe(...) with 0 registered tests (which Vitest flags as an empty suite error).

Performance Improvement

Environment Before (Mocha / Karma + Webpack) After (Vitest)
Node Unit Tests (test:node) ~32s (Mocha + ts-node) 9.84s (~3.2x faster)
Browser Unit Tests (test:browser:unit) ~95s (Karma + ~40s Webpack bundle) 57.76s (~1.6x faster)

@Manvi1203
Manvi1203 requested review from a team as code owners September 17, 2026 21:03
@changeset-bot

changeset-bot Bot commented Sep 17, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 57866bd

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request migrates the Firestore test suite from Karma and Mocha/Chai to Vitest, updating package scripts, test runners, and refactoring assertions across numerous test files. The reviewer identified several critical issues with the migration: running tests in debug mode with --inspect-brk directly on Vitest will fail; the platform check in base64.ts incorrectly excludes 'browser_lite'; vi should be explicitly imported in test/setup.ts for robustness; and multiple test files incorrectly use Vitest's toBeCloseTo with an absolute delta instead of a decimal precision argument, leading to either overly loose or overly strict assertions.

Comment thread packages/firestore/scripts/run-tests.ts Outdated
Comment thread packages/firestore/src/platform/base64.ts Outdated
Comment thread packages/firestore/test/setup.ts Outdated
Comment thread packages/firestore/test/integration/api/numeric_transforms.test.ts
Comment thread packages/firestore/test/unit/core/expressions/vector.test.ts Outdated
Comment thread packages/firestore/test/unit/core/expressions/arithmetic.test.ts Outdated
Comment thread packages/firestore/test/integration/api/pipeline.test.ts
@Manvi1203
Manvi1203 force-pushed the feature/vitest-firestore branch 3 times, most recently from b2918c3 to 854fd21 Compare September 17, 2026 21:29
@Manvi1203
Manvi1203 force-pushed the feature/vitest-firestore branch from 854fd21 to d5adfb2 Compare September 18, 2026 18:04
@Manvi1203

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request migrates the Firestore integration and unit tests from Karma, Mocha, and Chai to Vitest. This includes updating package scripts, replacing Chai assertions with Vitest's native matchers, and restructuring setup files. The review feedback highlights several opportunities to write more idiomatic Vitest assertions by replacing manual absolute difference calculations with the toBeCloseTo matcher, as well as removing a redundant registerFirestoreLite() call in the test setup.

Comment thread packages/firestore/test/setup.ts Outdated
Comment thread packages/firestore/test/integration/api/aggregation.test.ts Outdated
Comment thread packages/firestore/test/integration/api/pipeline.test.ts Outdated
Comment thread packages/firestore/test/integration/api/pipeline.test.ts Outdated
Comment thread packages/firestore/test/integration/api/pipeline.test.ts Outdated
Comment thread packages/firestore/test/integration/api/pipeline.test.ts Outdated
Comment thread packages/firestore/test/lite/pipeline.test.ts Outdated
Comment thread packages/firestore/test/lite/pipeline.test.ts Outdated
Comment thread packages/firestore/test/lite/pipeline.test.ts Outdated
Comment thread packages/firestore/test/lite/pipeline.test.ts Outdated
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.

1 participant