# Testing signals — excalidraw/excalidraw

> Canonical page: https://codevetter.com/unpack/excalidraw/testing-signals

# Testing signals — excalidraw/excalidraw

Scanned commit 31df3e6ef245c646b18a055ccf858cd6117c7768 (2026-09-22). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

Tests are Vitest 3 on jsdom, with Testing Library, vitest-canvas-mock, and fake-indexeddb. Coverage thresholds are enforced (lines 60, branches 70, functions 63, statements 60). The editor and element packages are heavily tested, including snapshots; the collaboration suite is a single file that mocks Firebase and socket.io and its own comment says multi-client cases are missing. CI runs unit tests on master pushes, and lint, types, prettier, and coverage on pull requests.
- vitest.config.mts sets environment jsdom, globals, setupFiles ./setupTests.ts, sequence.hooks parallel, hideSkippedTests, and coverage reporters text, json-summary, json, html, lcovonly with ignoreEmptyLines false. Thresholds: lines 60, branches 70, functions 63, statements 60. Root scripts: yarn test and yarn test:app invoke vitest; yarn test:update passes --update; yarn test:coverage and yarn test:ui exist. — [vitest.config.mts#L75-98](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/vitest.config.mts#L75-L98) [package.json#L68-77](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/package.json#L68-L77)
- setupTests.ts loads vitest-canvas-mock, @testing-library/jest-dom, the editor polyfill, fake-indexeddb/auto, a localStorage polyfill, and stubs setPointerCapture, matchMedia, and FontFace. It replaces @excalidraw/common throttleRAF with mockThrottleRAF. DOM dumps on Testing Library failures are suppressed unless VITE_DEBUG_DOM is true or 1. — [setupTests.ts#L1-80](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/setupTests.ts#L1-L80)
- Editor interaction tests live in packages/excalidraw/tests (App, history, export, clipboard, drag create, selection, laser, lasso, library, mermaid, search, wheel, regression, plus data/restore.test.ts and data/reconcile.test.ts). Element geometry tests live in packages/element/tests (binding, elbow arrows, frames, fractional index, text wrapping, z-index). Math tests are in packages/math/tests. Common tests cover colors, binary heap, keys, queue, and url. — [packages/excalidraw/tests/history.test.tsx](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/tests/history.test.tsx) [packages/excalidraw/tests/data/reconcile.test.ts](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/tests/data/reconcile.test.ts) [packages/element/tests/fractionalIndex.test.ts](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/element/tests/fractionalIndex.test.ts) [packages/element/tests/elbowArrow.test.tsx](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/element/tests/elbowArrow.test.tsx) [packages/math/tests/curve.test.ts](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/math/tests/curve.test.ts)
- App-level tests are only excalidraw-app/tests/collab.test.tsx, LanguageList.test.tsx, and MobileMenu.test.tsx (with a snapshot). collab.test renders the whole ExcalidrawApp and listens to h.store.onStoreIncrementEmitter. It mocks socket.io-client as a no-op emitter and stubs firebase load/save. The file comment says the suite should be extended to two simultaneous clients and that this is not done. — [excalidraw-app/tests/collab.test.tsx#L1-80](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/excalidraw-app/tests/collab.test.tsx#L1-L80)
- CI does not run the full yarn test:all. Push-to-master runs only yarn test:app. Pull requests run prettier (test:other), eslint --max-warnings=0 (test:code), and tsc (test:typecheck) in lint.yml, and separately yarn test:coverage with davelosert/vitest-coverage-report-action. Node is pinned to 20.x in those workflows while package.json engines say >=18 and the Docker build uses node 24. — [.github/workflows/test.yml#L1-19](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/.github/workflows/test.yml#L1-L19) [.github/workflows/lint.yml#L1-22](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/.github/workflows/lint.yml#L1-L22) [.github/workflows/test-coverage-pr.yml#L1-25](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/.github/workflows/test-coverage-pr.yml#L1-L25) [package.json#L46-72](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/package.json#L46-L72) [Dockerfile#L1](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/Dockerfile#L1)
- Many editor tests snapshot rendered output under packages/excalidraw/tests/__snapshots__ (App, history, export, selection, drag, mermaid, context menu) and packages/excalidraw/components/__snapshots__/App.test.tsx.snap. yarn test:update is the documented way to refresh them (CLAUDE.md). — [CLAUDE.md#L13-24](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/CLAUDE.md#L13-L24) [packages/excalidraw/tests/__snapshots__/history.test.tsx.snap](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap) [packages/excalidraw/components/__snapshots__/App.test.tsx.snap](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/components/__snapshots__/App.test.tsx.snap)
- Dev and test builds expose the live editor on window.h (state, setState, app, history, store, fonts). Tests reach it as const { h } = window after render. That hook is not installed in production because componentDidMount guards it with isTestEnv() || isDevEnv(). — [packages/excalidraw/components/App.tsx#L3814-3846](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/components/App.tsx#L3814-L3846) [excalidraw-app/tests/collab.test.tsx#L17](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/excalidraw-app/tests/collab.test.tsx#L17)
- There are no automated tests for firebase-project rules, the Docker/nginx image, the real Socket.IO server, VITE_APP_AI_BACKEND, Sentry release upload, or the self-unregistering public/service-worker.js. Firebase and socket modules are mocked out of the only collab test. — [excalidraw-app/tests/collab.test.tsx#L30-64](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/excalidraw-app/tests/collab.test.tsx#L30-L64) [firebase-project/firestore.rules](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/firebase-project/firestore.rules) [public/service-worker.js](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/public/service-worker.js)
- tsconfig.json typechecks packages and excalidraw-app only (strict, noEmit, jsx react-jsx). examples and the top-level tests folder are excluded, so example apps are not part of yarn test:typecheck. — [tsconfig.json#L1-39](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/tsconfig.json#L1-L39)
- Fractional-index invariants are part of the test contract: reconcile.ts calls validateFractionalIndices with shouldThrow when isTestEnv() or isDevEnv(), including bound-text checks and a reconciliationContext of local versus remote elements. A bad index in a test fails the test instead of being repaired quietly. — [packages/excalidraw/data/reconcile.ts#L46-68](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/data/reconcile.ts#L46-L68)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
