import { expect, test, useEditorSetup } from '#tests/e2e/fixtures' import { getSelectedNodes } from '#tests/helpers/store' const editor = useEditorSetup() function getPageChildCount() { return editor.page.evaluate(() => { const store = window.openPencil?.getStore?.() if (!store) throw new Error('OpenPencil store not initialized') return store.graph.getChildren(store.state.currentPageId).length }) } function getSelectedCount() { return editor.page.evaluate(() => { const store = window.openPencil?.getStore?.() if (!store) throw new Error('OpenPencil store not initialized') return store.state.selectedIds.size }) } test('copy + paste via store duplicates a shape', async () => { await editor.canvas.drawRect(100, 100, 120, 80) await editor.canvas.waitForRender() const countBefore = await getPageChildCount() await editor.page.evaluate(async () => { const store = window.openPencil?.getStore?.() if (!store) throw new Error('OpenPencil store not initialized') const data = new DataTransfer() await store.writeCopyData(data) const html = data.getData('text/html') if (html) await store.pasteFromHTML(html) }) await editor.canvas.waitForRender() const countAfter = await getPageChildCount() expect(countAfter).toBe(countBefore + 1) }) test('pasted node is offset from original', async () => { const nodes = await getSelectedNodes(editor.page) 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 editor.canvas.clearCanvas() await editor.canvas.drawRect(200, 200, 100, 80) await editor.canvas.waitForRender() const countBefore = await getPageChildCount() await editor.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 editor.page.evaluate(() => { const store = window.openPencil?.getStore?.() if (!store) throw new Error('OpenPencil store not initialized') 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 editor.canvas.waitForRender() await editor.canvas.duplicate() const nodes = await getSelectedNodes(editor.page) expect(nodes[0].fills[0].color.b).toBeCloseTo(1, 1) }) test('cut removes original', async () => { await editor.canvas.clearCanvas() await editor.canvas.drawRect(100, 100, 80, 60) await editor.canvas.waitForRender() expect(await getPageChildCount()).toBe(1) // Cut via store await editor.page.evaluate(() => { const store = window.openPencil?.getStore?.() if (!store) throw new Error('OpenPencil store not initialized') const data = new DataTransfer() store.writeCopyData(data) store.deleteSelected() }) await editor.canvas.waitForRender() expect(await getPageChildCount()).toBe(0) }) test('multiple pastes can all be undone', async () => { await editor.canvas.clearCanvas() await editor.canvas.drawRect(100, 100, 80, 60) await editor.canvas.waitForRender() expect(await getPageChildCount()).toBe(1) // Duplicate 3 times via Cmd+D (synchronous, no clipboard issues) for (let i = 0; i < 3; i++) { await editor.canvas.duplicate() await editor.canvas.waitForRender() } expect(await getPageChildCount()).toBe(4) // 1 original + 3 duplicates // Undo all 3 duplicates for (let i = 0; i < 3; i++) { await editor.canvas.undo() await editor.canvas.waitForRender() } expect(await getPageChildCount()).toBe(1) // back to original only }) test('multi-select duplicate creates copies of all', async () => { await editor.canvas.clearCanvas() await editor.canvas.drawRect(100, 100, 60, 60) await editor.canvas.drawRect(200, 100, 60, 60) await editor.canvas.selectAll() await editor.canvas.waitForRender() expect(await getSelectedCount()).toBe(2) const countBefore = await getPageChildCount() await editor.canvas.duplicate() const countAfter = await getPageChildCount() expect(countAfter).toBe(countBefore + 2) editor.canvas.assertNoErrors() })