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
79 lines
3.1 KiB
TypeScript
79 lines
3.1 KiB
TypeScript
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)
|
|
})
|
|
})
|