openpencil/tests/e2e/copy-paste.spec.ts
Danila Poyarkov 14b796a40d Add 8 E2E test suites for release sanity coverage
83 new tests across 8 files:
- design-panel: selection → properties panel, fill/stroke/effect add, visibility toggle, multi-select
- code-panel: JSX output, OpenPencil/Tailwind toggle, copy button, empty state
- components: create component (⌘⌥K), create instance, propagation, detach
- copy-paste: store copy/paste, ⌘D duplicate, cut, multi-select duplicate
- multi-page: add/switch/delete pages, rename, last-page protection
- text-editing: text tool, text node creation, typography section, frame tool
- keyboard-shortcuts: all 9 tool keys, ⌘A/Escape/Backspace, ]/[, ⌘G/⌘⇧G, ⌘\, ⌘Z/⌘⇧Z
- context-menu: right-click items, duplicate/visibility/lock/delete/group/component, Copy as submenu
2026-03-07 13:23:32 +03:00

136 lines
3.6 KiB
TypeScript

import { expect, test, type Page } from '@playwright/test'
import { CanvasHelper } from '../helpers/canvas'
let page: Page
let canvas: CanvasHelper
test.describe.configure({ mode: 'serial' })
test.beforeAll(async ({ browser }) => {
page = await browser.newPage()
await page.goto('/')
canvas = new CanvasHelper(page)
await canvas.waitForInit()
})
test.afterAll(async () => {
await page.close()
})
function getPageChildCount() {
return page.evaluate(() => {
const store = window.__OPEN_PENCIL_STORE__!
return store.graph.getChildren(store.state.currentPageId).length
})
}
function getSelectedCount() {
return page.evaluate(() => window.__OPEN_PENCIL_STORE__!.state.selectedIds.size)
}
function getSelectedNodes() {
return page.evaluate(() => {
const store = window.__OPEN_PENCIL_STORE__!
return [...store.state.selectedIds].map((id) => {
const n = store.graph.getNode(id)!
return { id: n.id, name: n.name, type: n.type, x: n.x, y: n.y, width: n.width, height: n.height, fills: n.fills }
})
})
}
test('copy + paste via store duplicates a shape', async () => {
await canvas.drawRect(100, 100, 120, 80)
await canvas.waitForRender()
const countBefore = await getPageChildCount()
await page.evaluate(() => {
const store = window.__OPEN_PENCIL_STORE__!
const data = new DataTransfer()
store.writeCopyData(data)
const html = data.getData('text/html')
if (html) store.pasteFromHTML(html)
})
await canvas.waitForRender()
const countAfter = await getPageChildCount()
expect(countAfter).toBe(countBefore + 1)
})
test('pasted node is offset from original', async () => {
const nodes = await getSelectedNodes()
expect(nodes).toHaveLength(1)
const pasted = nodes[0]
expect(pasted.name).toBe('Rectangle')
})
test('⌘D duplicates in place', async () => {
// Clear canvas and start fresh
await canvas.clearCanvas()
await canvas.drawRect(200, 200, 100, 80)
await canvas.waitForRender()
const countBefore = await getPageChildCount()
await canvas.duplicate()
const countAfter = await getPageChildCount()
expect(countAfter).toBe(countBefore + 1)
expect(await getSelectedCount()).toBe(1)
})
test('duplicate preserves fills', async () => {
// Set a custom fill on the selected node
await page.evaluate(() => {
const store = window.__OPEN_PENCIL_STORE__!
const id = [...store.state.selectedIds][0]
store.updateNodeWithUndo(id, {
fills: [{ type: 'SOLID', color: { r: 0, g: 0.5, b: 1, a: 1 }, opacity: 1, visible: true, blendMode: 'NORMAL' }]
}, 'Set fill')
})
await canvas.waitForRender()
await canvas.duplicate()
const nodes = await getSelectedNodes()
expect(nodes[0].fills[0].color.b).toBeCloseTo(1, 1)
})
test('cut removes original', async () => {
await canvas.clearCanvas()
await canvas.drawRect(100, 100, 80, 60)
await canvas.waitForRender()
expect(await getPageChildCount()).toBe(1)
// Cut via store
await page.evaluate(() => {
const store = window.__OPEN_PENCIL_STORE__!
const data = new DataTransfer()
store.writeCopyData(data)
store.deleteSelected()
})
await canvas.waitForRender()
expect(await getPageChildCount()).toBe(0)
})
test('multi-select duplicate creates copies of all', async () => {
await canvas.clearCanvas()
await canvas.drawRect(100, 100, 60, 60)
await canvas.drawRect(200, 100, 60, 60)
await canvas.selectAll()
await canvas.waitForRender()
expect(await getSelectedCount()).toBe(2)
const countBefore = await getPageChildCount()
await canvas.duplicate()
const countAfter = await getPageChildCount()
expect(countAfter).toBe(countBefore + 2)
canvas.assertNoErrors()
})