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,78 @@
import { expect } from '@wdio/globals'
import type { Editor } from 'tldraw'
import { openEditor } from '../helpers/app'
import { drawTouchStroke } from '../helpers/stroke'
declare const editor: Editor
/**
* Guards the device-side contract behind 2D draw-shape encoding (#8963/#8879):
* tldraw drops the constant pressure channel (z) from mouse/trackpad/finger
* strokes, keyed off `isPenOrStylus` — which is inferred from the pressure the
* BROWSER reports for the input device (Drawing.ts). The unit tests pick the
* pressure values they feed in, so they verify the decision logic but not what
* real engines actually report for a finger.
*
* That engine contract is the fragile part: 3D Touch iPhones really did report
* varying force for plain finger touches. If an engine (re)introduces that,
* finger strokes silently flip back to 3D — losing the storage win and making
* stroke width track finger pressure — with no unit or Playwright test failing,
* because those layers synthesize their own pressure values. Drawing through
* the real OS touch pipeline and asserting the 2D encoding is the only
* automated check that can catch it.
*
* Skips (rather than fails) on builds whose schema predates the segment `dim`
* field, so the suite stays green until #8963 merges.
*/
describe('draw shape pressure encoding (#8963)', () => {
beforeEach(async () => {
await openEditor()
})
it('a finger-drawn stroke uses the 2D (no-pressure) encoding', async function () {
// Feature-detect the `dim` field: on builds that predate #8963 the segment
// validator rejects it, so probe with a throwaway shape and skip if absent.
const dimSupported = await browser.execute(() => {
try {
editor.createShapes([
{
id: 'shape:dimprobe',
type: 'draw',
props: { segments: [{ type: 'free', path: '', dim: 2 }] },
},
] as any)
editor.deleteShapes(['shape:dimprobe'] as any)
return true
} catch {
return false
}
})
if (!dimSupported) this.skip()
// Block body: a concise arrow would implicitly return the (circular)
// Editor instance, which can't be serialized over the WebDriver wire.
await browser.execute(() => {
editor.setCurrentTool('draw')
})
await drawTouchStroke({ from: { x: -80, y: -40 }, to: { x: 80, y: 40 } })
const segments = await browser.execute(() => {
const shape = editor.getCurrentPageShapes().find((s) => s.type === 'draw')
if (!shape) return null
return (shape as any).props.segments.map((s: any) => ({
dim: s.dim,
pathLength: s.path.length,
}))
})
// The stroke produced a real draw shape with encoded points...
expect(segments).not.toBeNull()
expect(segments!.length).toBeGreaterThan(0)
expect(segments!.every((s) => s.pathLength > 0)).toBe(true)
// ...and the engine reported finger input as non-pressure, so every
// segment took the 2D encoding. If this fails with dim undefined, the
// browser has started reporting varying pressure for plain touches and
// the classification in Drawing.ts needs revisiting.
expect(segments!.every((s) => s.dim === 2)).toBe(true)
})
})

View File

@@ -0,0 +1,49 @@
import { expect } from '@wdio/globals'
import type { Editor } from 'tldraw'
import { getSelectedShapeIds, getZoom, openEditor } from '../helpers/app'
import { pinchCanvas } from '../helpers/pinch'
declare const editor: Editor
/**
* Device-realistic pinch tests. These mirror the intent of the Playwright camera
* tests (apps/examples/e2e/tests/test-camera.spec.ts) but run through the real
* OS touch pipeline on a simulator/emulator, so they cover the browser's own
* gesture recogniser — the part synthetic CDP touch can't reach.
*/
describe('pinch to zoom', () => {
beforeEach(async () => {
await openEditor()
})
it('spreading two fingers zooms in', async () => {
expect(await getZoom()).toBe(1)
await pinchCanvas({ scale: 2.5 })
expect(await getZoom()).toBeGreaterThan(1)
})
it('pinching two fingers together zooms out', async () => {
expect(await getZoom()).toBe(1)
await pinchCanvas({ scale: 0.4 })
expect(await getZoom()).toBeLessThan(1)
})
it('a two-finger pinch does not change the selection', async () => {
// Place a shape under where the pinch lands, plus a second shape that we
// pre-select off to the side. The pinch must not steal the selection.
await browser.execute(() => {
editor.createShapes([
{ id: 'shape:a', type: 'geo', x: -400, y: -400, props: { w: 100, h: 100 } },
{ id: 'shape:b', type: 'geo', x: 0, y: 0, props: { w: 400, h: 400 } },
] as any)
editor.setSelectedShapes(['shape:a'] as any)
})
expect(await getSelectedShapeIds()).toEqual(['shape:a'])
await pinchCanvas({ scale: 2 })
// Selection is preserved and the gesture really did zoom.
expect(await getSelectedShapeIds()).toEqual(['shape:a'])
expect(await getZoom()).not.toBe(1)
})
})