* fix(editor): commit vector drags on pointer release - Commit vertex and Bézier handle edits immediately on release\n- Rebase active vector-edit state after graph commits\n- Use vector-specific input paths and cover Pen-created Bézier drags * test: reduce visual snapshot scope - Replace behavior screenshots with scene assertions\n- Capture renderer fixtures from bounded canvas regions\n- Remove obsolete full-viewport snapshots * fix(vector): harden edit cancellation and endpoint remapping - Restore temporary vector geometry on cancelled pointer drags\n- Commit Bézier handle releases consistently and guard stale handle state\n- Preserve valid endpoint indices when connecting vector vertices * fix(vector): cancel bend drags and satisfy formatting * fix(vector): guard stale handle references * fix(vector): guard stale overlay handle indices * fix(vector): validate overlay handle keys * refactor(vector): use typed handle selection ids * test(vector): align typed handle selection coverage
115 lines
3.5 KiB
TypeScript
115 lines
3.5 KiB
TypeScript
import { expect, test, useEditorSetupWithClear } from '#tests/e2e/fixtures'
|
|
|
|
const editor = useEditorSetupWithClear('/?test&no-chrome&no-rulers')
|
|
|
|
test('mixed vector regions keep open stroke segments', async () => {
|
|
await editor.page.evaluate(() => {
|
|
const store = window.openPencil?.getStore?.()
|
|
if (!store) throw new Error('OpenPencil store not initialized')
|
|
store.graph.createNode('VECTOR', store.state.currentPageId, {
|
|
name: 'Mixed region and open segment',
|
|
x: 160,
|
|
y: 110,
|
|
width: 300,
|
|
height: 160,
|
|
fills: [
|
|
{
|
|
type: 'SOLID',
|
|
color: { r: 0.23, g: 0.51, b: 0.96, a: 1 },
|
|
visible: true,
|
|
opacity: 1
|
|
}
|
|
],
|
|
strokes: [
|
|
{
|
|
color: { r: 0.95, g: 0.25, b: 0.15, a: 1 },
|
|
weight: 8,
|
|
opacity: 1,
|
|
visible: true,
|
|
align: 'CENTER'
|
|
}
|
|
],
|
|
vectorNetwork: {
|
|
vertices: [
|
|
{ x: 0, y: 0 },
|
|
{ x: 120, y: 0 },
|
|
{ x: 120, y: 120 },
|
|
{ x: 0, y: 120 },
|
|
{ x: 170, y: 60 },
|
|
{ x: 300, y: 60 }
|
|
],
|
|
segments: [
|
|
{ start: 0, end: 1, tangentStart: { x: 0, y: 0 }, tangentEnd: { x: 0, y: 0 } },
|
|
{ start: 1, end: 2, tangentStart: { x: 0, y: 0 }, tangentEnd: { x: 0, y: 0 } },
|
|
{ start: 2, end: 3, tangentStart: { x: 0, y: 0 }, tangentEnd: { x: 0, y: 0 } },
|
|
{ start: 3, end: 0, tangentStart: { x: 0, y: 0 }, tangentEnd: { x: 0, y: 0 } },
|
|
{ start: 4, end: 5, tangentStart: { x: 0, y: 0 }, tangentEnd: { x: 0, y: 0 } }
|
|
],
|
|
regions: [{ windingRule: 'NONZERO', loops: [[0, 1, 2, 3]] }]
|
|
}
|
|
})
|
|
store.clearSelection()
|
|
store.requestRender()
|
|
})
|
|
await editor.canvas.waitForRender()
|
|
editor.canvas.assertNoErrors()
|
|
const buffer = await editor.canvas.screenshotCanvasRegion()
|
|
expect(buffer).toMatchSnapshot('mixed-region-open-segment.png')
|
|
})
|
|
|
|
test('even-odd vector geometry preserves holes', async () => {
|
|
await editor.page.evaluate(() => {
|
|
const store = window.openPencil?.getStore?.()
|
|
if (!store) throw new Error('OpenPencil store not initialized')
|
|
const bytes: number[] = []
|
|
const pushFloat = (value: number) => {
|
|
const buffer = new ArrayBuffer(4)
|
|
new DataView(buffer).setFloat32(0, value, true)
|
|
bytes.push(...new Uint8Array(buffer))
|
|
}
|
|
const moveTo = (x: number, y: number) => {
|
|
bytes.push(1)
|
|
pushFloat(x)
|
|
pushFloat(y)
|
|
}
|
|
const lineTo = (x: number, y: number) => {
|
|
bytes.push(2)
|
|
pushFloat(x)
|
|
pushFloat(y)
|
|
}
|
|
const rectangle = (x: number, y: number, width: number, height: number) => {
|
|
moveTo(x, y)
|
|
lineTo(x + width, y)
|
|
lineTo(x + width, y + height)
|
|
lineTo(x, y + height)
|
|
bytes.push(0)
|
|
}
|
|
rectangle(0, 0, 240, 144)
|
|
rectangle(28, 28, 184, 88)
|
|
rectangle(48, 48, 144, 12)
|
|
|
|
store.graph.createNode('VECTOR', store.state.currentPageId, {
|
|
name: 'Even-odd card outline',
|
|
x: 160,
|
|
y: 110,
|
|
width: 240,
|
|
height: 144,
|
|
fills: [
|
|
{
|
|
type: 'SOLID',
|
|
color: { r: 0.23, g: 0.51, b: 0.96, a: 1 },
|
|
visible: true,
|
|
opacity: 1
|
|
}
|
|
],
|
|
fillGeometry: [{ windingRule: 'EVENODD', commandsBlob: new Uint8Array(bytes) }]
|
|
})
|
|
store.clearSelection()
|
|
store.requestRender()
|
|
})
|
|
await editor.canvas.waitForRender()
|
|
editor.canvas.assertNoErrors()
|
|
const buffer = await editor.canvas.screenshotCanvasRegion()
|
|
expect(buffer).toMatchSnapshot('even-odd-vector-holes.png')
|
|
})
|