import { describe, it, expect } from 'vitest'
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import { WysiwygBuilderPage } from '@/components/wysiwyg/WysiwygBuilderPage'
function getXY(el: HTMLElement) {
const style = el.getAttribute('style') || ''
const m = { left: /left:\s*(\d+)px/, top: /top:\s*(\d+)px/ }
const left = Number((style.match(m.left)?.[1]) || '0')
const top = Number((style.match(m.top)?.[1]) || '0')
return { left, top }
}
function getRotate(el: HTMLElement) {
const style = el.getAttribute('style') || ''
const m = /rotate\(([-\d.]+)deg\)/
const v = Number((style.match(m)?.[1]) || '0')
return v
}
describe('WYSIWYG - group actions drag/resize/rotate with snapping', () => {
it('drags two selected objects together with 8px snapping', async () => {
render()
// add two texts
const addText = () => fireEvent.click(screen.getByRole('button', { name: /^Add Text$/i }))
addText()
addText()
const objs = await screen.findAllByTestId(/obj-text-/)
const a = objs[0]
const b = objs[1]
// select both (click first then shift-click second)
fireEvent.mouseDown(a, { clientX: 60, clientY: 60 })
fireEvent.mouseUp(a)
fireEvent.mouseDown(b, { clientX: 80, clientY: 80, shiftKey: true })
// wait until selection reflects two items
await screen.findByText(/선택 2개/)
const canvas = screen.getByTestId('wysiwyg-canvas')
// drag second (selected) by ~13, expect snap to +16
fireEvent.mouseDown(b, { clientX: 120, clientY: 120 })
fireEvent.mouseMove(canvas, { clientX: 133, clientY: 133 })
fireEvent.mouseUp(canvas)
await waitFor(() => {
const xyA = getXY(a)
const xyB = getXY(b)
expect(xyA.left).toBe(76)
expect(xyA.top).toBe(76)
expect(xyB.left).toBe(76)
expect(xyB.top).toBe(76)
})
})
it('resizes group from east handle; both widths increase with snapping', async () => {
render()
const addText = () => fireEvent.click(screen.getByRole('button', { name: /^Add Text$/i }))
addText()
addText()
const objs = await screen.findAllByTestId(/obj-text-/)
const a = objs[0]
const b = objs[1]
// select both
fireEvent.mouseDown(a, { clientX: 60, clientY: 60 })
fireEvent.mouseUp(a)
fireEvent.mouseDown(b, { clientX: 80, clientY: 80, shiftKey: true })
// drag east handle of second by ~13 -> snap width +16
const idB = (b.getAttribute('data-testid') || '').replace('obj-', '')
const handleE = await screen.findByTestId(`resize-handle-e-${idB}`)
fireEvent.mouseDown(handleE, { clientX: 180, clientY: 80 })
const canvas = screen.getByTestId('wysiwyg-canvas')
fireEvent.mouseMove(canvas, { clientX: 193, clientY: 80 })
fireEvent.mouseUp(canvas)
// widths reflected in inline style
const styleA = a.getAttribute('style') || ''
const styleB = b.getAttribute('style') || ''
const wA = Number((styleA.match(/width:\s*(\d+)px/)?.[1]) || '0')
const wB = Number((styleB.match(/width:\s*(\d+)px/)?.[1]) || '0')
expect(wA).toBeGreaterThanOrEqual(176) // initial 160 -> +16
expect(wB).toBeGreaterThanOrEqual(176)
})
it('rotates group with 15deg snapping (no shift)', async () => {
render()
const addText = () => fireEvent.click(screen.getByRole('button', { name: /^Add Text$/i }))
addText()
addText()
const objs = await screen.findAllByTestId(/obj-text-/)
const a = objs[0]
const b = objs[1]
// select both
fireEvent.mouseDown(a)
fireEvent.mouseUp(a)
fireEvent.mouseDown(b, { shiftKey: true })
fireEvent.mouseUp(b)
const idB2 = (b.getAttribute('data-testid') || '').replace('obj-', '')
const rotateHandle = await screen.findByTestId(`rotate-handle-${idB2}`)
fireEvent.mouseDown(rotateHandle, { clientX: 100, clientY: 10 })
const canvas = screen.getByTestId('wysiwyg-canvas')
fireEvent.mouseMove(canvas, { clientX: 130, clientY: 10 }) // +30 -> snap 30 (15 step)
fireEvent.mouseUp(canvas)
const rA = getRotate(a)
const rB = getRotate(b)
expect(rA).toBe(30)
expect(rB).toBe(30)
})
})