test(editor): cover auto-layout padding editor
This commit is contained in:
parent
3eedd0740e
commit
031897c73a
|
|
@ -17,11 +17,15 @@ export function useCanvasVirtualReference(
|
|||
const canvas = canvasRef.value
|
||||
if (!point || !canvas) return null
|
||||
|
||||
const zoom = editor.state.zoom
|
||||
const panX = editor.state.panX
|
||||
const panY = editor.state.panY
|
||||
|
||||
return {
|
||||
getBoundingClientRect() {
|
||||
const rect = canvas.getBoundingClientRect()
|
||||
const x = rect.left + point.x * editor.state.zoom + editor.state.panX
|
||||
const y = rect.top + point.y * editor.state.zoom + editor.state.panY
|
||||
const x = rect.left + point.x * zoom + panX
|
||||
const y = rect.top + point.y * zoom + panY
|
||||
return new DOMRect(x, y, 0, 0)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,8 +78,6 @@ const paddingSideIcons = {
|
|||
left: IconLucidePanelLeft
|
||||
} satisfies Record<'top' | 'right' | 'bottom' | 'left', Component>
|
||||
|
||||
const paddingEditorRef = ref<HTMLElement | null>(null)
|
||||
|
||||
const paddingEditorAnchor = computed(() => {
|
||||
const edit = autoLayoutPaddingEdit.value
|
||||
if (!edit) return null
|
||||
|
|
@ -102,7 +100,9 @@ const paddingEditorIcon = computed(() => {
|
|||
watch(autoLayoutPaddingEdit, async (edit) => {
|
||||
if (!edit) return
|
||||
await nextTick()
|
||||
const input = paddingEditorRef.value?.querySelector<HTMLInputElement>('input')
|
||||
const input = document.querySelector<HTMLInputElement>(
|
||||
'[data-test-id="auto-layout-padding-editor"] input'
|
||||
)
|
||||
input?.focus()
|
||||
input?.select()
|
||||
})
|
||||
|
|
@ -145,7 +145,6 @@ const cursor = computed(() => toolCursor(store.state.activeTool, cursorOverride.
|
|||
<PopoverPortal>
|
||||
<PopoverContent
|
||||
v-if="autoLayoutPaddingEdit && paddingEditorReference"
|
||||
ref="paddingEditorRef"
|
||||
:reference="paddingEditorReference"
|
||||
side="top"
|
||||
align="center"
|
||||
|
|
@ -164,6 +163,12 @@ const cursor = computed(() => toolCursor(store.state.activeTool, cursorOverride.
|
|||
data-test-id="auto-layout-padding-input"
|
||||
@update:model-value="updateAutoLayoutPaddingEdit"
|
||||
@commit="(value: number) => commitAutoLayoutPaddingEdit(value)"
|
||||
@editing-change="
|
||||
(editing: boolean) =>
|
||||
!editing &&
|
||||
autoLayoutPaddingEdit &&
|
||||
commitAutoLayoutPaddingEdit(autoLayoutPaddingEdit.value)
|
||||
"
|
||||
>
|
||||
<template #icon>
|
||||
<component :is="paddingEditorIcon" class="size-3.5" />
|
||||
|
|
|
|||
115
tests/e2e/editor/auto-layout/padding-editor.spec.ts
Normal file
115
tests/e2e/editor/auto-layout/padding-editor.spec.ts
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
import { expect, test, type Page } from '@playwright/test'
|
||||
|
||||
import { CanvasHelper } from '#tests/helpers/canvas'
|
||||
|
||||
async function dblclickCanvas(page: Page, x: number, y: number) {
|
||||
const canvas = page.locator('[data-test-id="canvas-element"]')
|
||||
const box = await canvas.boundingBox()
|
||||
if (!box) throw new Error('Canvas has no bounding box')
|
||||
await canvas.dispatchEvent('dblclick', {
|
||||
clientX: box.x + x,
|
||||
clientY: box.y + y,
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
})
|
||||
}
|
||||
|
||||
async function setupAutoLayoutFrame(page: Page) {
|
||||
return page.evaluate(() => {
|
||||
const store = window.openPencil?.getStore?.()
|
||||
if (!store) throw new Error('OpenPencil store not initialized')
|
||||
|
||||
store.state.panX = 0
|
||||
store.state.panY = 0
|
||||
store.state.zoom = 1
|
||||
|
||||
const pageId = store.state.currentPageId
|
||||
const frame = store.graph.createNode('FRAME', pageId, {
|
||||
name: 'Padding editor frame',
|
||||
x: 160,
|
||||
y: 120,
|
||||
width: 280,
|
||||
height: 160,
|
||||
layoutMode: 'VERTICAL',
|
||||
itemSpacing: 8,
|
||||
paddingTop: 20,
|
||||
paddingRight: 20,
|
||||
paddingBottom: 20,
|
||||
paddingLeft: 20
|
||||
})
|
||||
store.graph.createNode('RECTANGLE', frame.id, {
|
||||
name: 'Child',
|
||||
x: 180,
|
||||
y: 140,
|
||||
width: 120,
|
||||
height: 40
|
||||
})
|
||||
store.select([frame.id])
|
||||
store.requestRender()
|
||||
return frame.id
|
||||
})
|
||||
}
|
||||
|
||||
async function framePaddingTop(page: Page, frameId: string) {
|
||||
return page.evaluate((id) => {
|
||||
const store = window.openPencil?.getStore?.()
|
||||
if (!store) throw new Error('OpenPencil store not initialized')
|
||||
return store.graph.getNode(id)?.paddingTop ?? null
|
||||
}, frameId)
|
||||
}
|
||||
|
||||
test('double-clicking an auto-layout padding handle opens a scrub editor', async ({ page }) => {
|
||||
await page.goto('/')
|
||||
const canvas = new CanvasHelper(page)
|
||||
await canvas.waitForInit()
|
||||
await canvas.clearCanvas()
|
||||
|
||||
const frameId = await setupAutoLayoutFrame(page)
|
||||
await canvas.waitForRender()
|
||||
|
||||
await canvas.hover(300, 130)
|
||||
await dblclickCanvas(page, 300, 130)
|
||||
|
||||
const editor = page.locator('[data-test-id="auto-layout-padding-editor"]')
|
||||
await expect(editor).toBeVisible()
|
||||
|
||||
await canvas.dragScrubInput(editor.locator('[data-test-id="auto-layout-padding-input"]'), 40)
|
||||
|
||||
await expect(editor).toHaveCount(0)
|
||||
const changedPadding = await framePaddingTop(page, frameId)
|
||||
expect(changedPadding).not.toBeNull()
|
||||
expect(changedPadding).toBeGreaterThan(20)
|
||||
|
||||
await canvas.undo()
|
||||
expect(await framePaddingTop(page, frameId)).toBe(20)
|
||||
canvas.assertNoErrors()
|
||||
})
|
||||
|
||||
test('auto-layout padding editor follows canvas pan while open', async ({ page }) => {
|
||||
await page.goto('/')
|
||||
const canvas = new CanvasHelper(page)
|
||||
await canvas.waitForInit()
|
||||
await canvas.clearCanvas()
|
||||
|
||||
await setupAutoLayoutFrame(page)
|
||||
await canvas.waitForRender()
|
||||
|
||||
await canvas.hover(300, 130)
|
||||
await dblclickCanvas(page, 300, 130)
|
||||
const editor = page.locator('[data-test-id="auto-layout-padding-editor"]')
|
||||
await expect(editor).toBeVisible()
|
||||
const before = await editor.boundingBox()
|
||||
if (!before) throw new Error('Padding editor has no bounding box')
|
||||
|
||||
await page.evaluate(() => {
|
||||
const store = window.openPencil?.getStore?.()
|
||||
if (!store) throw new Error('OpenPencil store not initialized')
|
||||
store.pan(40, 0)
|
||||
})
|
||||
await canvas.waitForRender()
|
||||
|
||||
const after = await editor.boundingBox()
|
||||
if (!after) throw new Error('Padding editor has no bounding box after pan')
|
||||
expect(after.x).toBeGreaterThan(before.x + 20)
|
||||
canvas.assertNoErrors()
|
||||
})
|
||||
Loading…
Reference in a new issue