snapshot of https://github.com/tldraw/tldraw.git (main, 2026-09-23; blobs > 131072B omitted)
Some checks failed
Deploy analytics worker / Deploy analytics worker to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
i18n upload strings / Upload latest strings (push) Failing after 1s
Deploy bemo / Deploy bemo to ${{ (github.ref == 'refs/heads/bemo-production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
Deploy grafana resources / ${{ github.event_name == 'push' && 'Deploy grafana resources' || 'Validate grafana resources (dry run)' }} (push) Failing after 0s
End to end tests (dotcom) / Check for relevant changes (push) Failing after 0s
End to end tests (examples) / Check for relevant changes (push) Failing after 0s
End to end tests (mermaid readability) / Check for relevant changes (push) Failing after 1s
End to end tests (perf) / Check for relevant changes (push) Failing after 0s
Publish editor extensions / Publish editor extensions (push) Failing after 1s
Publish SDK packages / Remove the publish-packages label (push) Has been skipped
Checks / Tests & checks (push) Has been cancelled
Checks / Build all projects (push) Has been cancelled
Deploy templates / Deploy templates (push) Has been cancelled
End to end tests (dotcom) / End to end tests (dotcom) (push) Has been cancelled
End to end tests (mermaid readability) / End to end tests (mermaid readability) (push) Has been cancelled
End to end tests (perf) / End to end tests (perf) (push) Has been cancelled
Deploy .com / Deploy dotcom to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Has been cancelled
End to end tests (examples) / End to end tests (examples) (push) Has been cancelled
Publish SDK packages / Publish SDK packages (push) Has been cancelled
Publish SDK packages / Tell user released version (push) Has been cancelled
Publish SDK packages / Publishes code templates to separate repositories (push) Has been cancelled
Publish SDK packages / Deploys the template demos with the new SDK version (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-23 16:12:52 +05:00
commit a774ac673a
4541 changed files with 770499 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
import path from 'path'
import { defineConfig } from 'vitest/config'
const svgTransform = {
name: 'svg-transform',
transform(_code: string, id: string) {
if (id.endsWith('.svg')) {
return {
code: 'export default {};',
map: null,
}
}
return undefined
},
}
export default defineConfig({
plugins: [svgTransform],
test: {
globals: true,
environment: 'jsdom',
// Persist transformed modules to node_modules/.vitest-cache so reruns skip re-transforming.
// Only helps a warm cache: a cold run (fresh clone, cleared node_modules) pays full price.
fsModuleCache: true,
// Worker threads start much faster than forked processes. Projects needing real process
// isolation (e.g. sync-worker, which passes node flags via execArgv) override this.
pool: 'threads',
setupFiles: [path.resolve(__dirname, './setup.ts')],
include: ['src/**/*.{test,spec}.{js,ts,jsx,tsx}'],
exclude: [
'**/test/__fixtures__/**',
'**/node_modules/**',
'**/dist/**',
'**/.tsbuild/**',
'**/.tsbuild-dev/**',
'**/.tsbuild-pub/**',
],
coverage: {
include: ['src/**/*.{ts,tsx}'],
exclude: ['**/*.test.*', '**/*.spec.*', '**/test/**', '**/__tests__/**'],
},
},
resolve: {
alias: {
'~': path.resolve(process.cwd(), 'src'),
},
},
ssr: {
noExternal: ['@tiptap/react'],
},
})

View File

@@ -0,0 +1,143 @@
import { equals, getObjectSubset, iterableEquality, subsetEquality } from '@jest/expect-utils'
import {
matcherHint,
printDiffOrStringify,
printExpected,
printReceived,
stringify,
} from 'jest-matcher-utils'
if (typeof window !== 'undefined') {
await import('vitest-canvas-mock')
}
// Crypto fallback for environments without a native WebCrypto implementation (e.g. the ai package).
// jsdom provides window.crypto with subtle crypto, so this only kicks in elsewhere.
if (typeof globalThis.crypto === 'undefined') {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { Crypto } = require('@peculiar/webcrypto')
globalThis.crypto = new Crypto()
}
// Image.decode polyfill - this should be handled by individual package setups,
// but including it here as a fallback
if (typeof HTMLImageElement !== 'undefined') {
if (!HTMLImageElement.prototype.decode) {
HTMLImageElement.prototype.decode = function () {
return Promise.resolve()
}
}
}
// Path2D polyfills
if (typeof Path2D !== 'undefined' && typeof Path2D.prototype.roundRect !== 'function') {
Path2D.prototype.roundRect = function (x, y, w, h, _) {
this.rect(x, y, w, h)
}
}
// CSS.supports polyfill for tests that use color spaces (e.g., highlight shapes)
if (typeof CSS === 'undefined') {
;(global as any).CSS = {}
}
if (typeof CSS.supports === 'undefined') {
CSS.supports = () => false
}
// Pointer capture polyfill. jsdom implements the PointerEvent constructor but not the pointer
// capture model, so setPointerCapture/releasePointerCapture/hasPointerCapture are missing
// (https://github.com/jsdom/jsdom/pull/2666). Our canvas event handlers capture the pointer on
// pointerdown/up, so stub them out to avoid throwing.
if (typeof Element !== 'undefined') {
Element.prototype.setPointerCapture ??= function () {
// noop
}
Element.prototype.releasePointerCapture ??= function () {
// noop
}
Element.prototype.hasPointerCapture ??= function () {
return false
}
}
// Captured before any test file installs fake timers.
const realSetTimeout = globalThis.setTimeout
const realSetImmediate = globalThis.setImmediate
// Drain deferred React work before vitest tears down jsdom: exportToSvg unmounts its root in a
// setTimeout(0) and every react-dom commit schedules a setImmediate that reads `window.event`.
// Landing after teardown, those throw "window is not defined" as an unhandled error (flaky CI).
if (typeof window !== 'undefined') {
afterAll(async () => {
// two passes: pass 1 fires pending timeouts and the setImmediate they enqueue; pass 2 covers
// the scheduler re-arming itself when it yields mid-work
for (let i = 0; i < 2; i++) {
await new Promise((resolve) => realSetTimeout(resolve, 0))
await new Promise((resolve) => realSetImmediate(resolve))
}
})
}
function convertNumbersInObject(obj: any, roundToNearest: number): any {
if (!obj) return obj
if (Array.isArray(obj)) {
return obj.map((x) => convertNumbersInObject(x, roundToNearest))
}
if (typeof obj === 'number') {
// || 0 to avoid -0
return Math.round(obj / roundToNearest) * roundToNearest || 0
}
if (typeof obj !== 'object') {
return obj
}
const r: any = {
__converted: true,
}
for (const k of Object.keys(obj)) {
r[k] = convertNumbersInObject(obj[k], roundToNearest)
}
return r
}
expect.extend({
toCloselyMatchObject(actual: any, expected: any, roundToNearest = 0.0001) {
const matcherName = 'toCloselyMatchObject'
const options = {
isNot: this.isNot,
promise: this.promise,
}
const EXPECTED_LABEL = 'Expected'
const RECEIVED_LABEL = 'Received'
const newActualObj = convertNumbersInObject(actual, roundToNearest)
const newExpectedObj = convertNumbersInObject(expected, roundToNearest)
const pass = equals(newActualObj, newExpectedObj, [iterableEquality, subsetEquality])
const message = pass
? () =>
matcherHint(matcherName, undefined, undefined, options) +
'\n\n' +
`Expected: not ${printExpected(expected)}` +
(stringify(expected) !== stringify(actual)
? `\nReceived: ${printReceived(actual)}`
: '')
: () =>
matcherHint(matcherName, undefined, undefined, options) +
'\n\n' +
printDiffOrStringify(
expected,
getObjectSubset(actual, expected),
EXPECTED_LABEL,
RECEIVED_LABEL,
true
)
return { message, pass }
},
})