// CDP 触摸手势驱动: 长按 400ms 激活 + 水平拖动, 观察 useRowDrag 行为 import WebSocket from 'ws' import { spawn } from 'node:child_process' const C = JSON.parse((await (await fetch('http://127.0.0.1:9223/json/version')).text())) const ws = new WebSocket(C.webSocketDebuggerUrl, { perMessageDeflate: false }) let id = 0 const pending = new Map() const send = (method, params = {}, sessionId) => new Promise((res) => { const i = ++id pending.set(i, res) ws.send(JSON.stringify({ id: i, method, params, sessionId })) }) ws.on('message', (d) => { const m = JSON.parse(d) if (m.id && pending.has(m.id)) { pending.get(m.id)(m.result); pending.delete(m.id) } if (m.method === 'Runtime.consoleAPICalled') { console.log('[console]', m.params.type, m.params.args.map((a) => a.value ?? a.description).join(' ')) } }) await new Promise((r) => ws.on('open', r)) const { targetId } = await send('Target.createTarget', { url: 'about:blank' }) const { sessionId } = await send('Target.attachToTarget', { targetId, flatten: true }) const S = (m, p) => send(m, p, sessionId) await S('Runtime.enable') await S('Page.enable') await S('Emulation.setDeviceMetricsOverride', { width: 400, height: 800, deviceScaleFactor: 2, mobile: true }) await S('Emulation.setTouchEmulationEnabled', { enabled: true, maxTouchPoints: 5 }) await S('Page.navigate', { url: 'http://127.0.0.1:5199/dragtest.html' }) await new Promise((r) => setTimeout(r, 3000)) const sleep = (ms) => new Promise((res) => setTimeout(res, ms)) const ev = async (expr) => (await S('Runtime.evaluate', { expression: expr, returnByValue: true })).result.value let rect = null for (let i = 0; i < 30 && !rect; i++) { await sleep(1000) const v = await ev(`(() => { const el = document.querySelector('[data-task-id="3"]'); return el ? JSON.stringify(el.getBoundingClientRect()) : null })()`) if (v) rect = JSON.parse(v) } if (!rect) { console.log('page never loaded'); ws.close(); process.exit(1) } console.log('row rect', JSON.stringify(rect)) const r = rect const x0 = r.left + r.width / 2 const y0 = r.top + r.height / 2 const touch = (type, x, y) => S('Input.dispatchTouchEvent', { type, touchPoints: type === 'touchEnd' ? [] : [{ x, y, id: 1 }], }) // 1) touchStart + 按住 500ms (激活长按) await touch('touchStart', x0, y0) console.log('--- touchStart, holding 500ms') await sleep(500) // 2) 水平拖动 +200px, 每步 +25px / 40ms (纯水平) for (let dx = 25; dx <= 200; dx += 25) { await touch('touchMove', x0 + dx, y0) await sleep(40) } console.log('--- moved to +200px (pure horizontal)') // 3) 带纵向分量的拖动 (模拟真实手指): +160px 横 / +40px 纵 await touch('touchMove', x0 + 60, y0 + 12) await sleep(40) await touch('touchMove', x0 + 120, y0 + 26) await sleep(40) await touch('touchMove', x0 + 160, y0 + 40) await sleep(40) await touch('touchEnd') await sleep(600) console.log('--- events on page:') console.log((await ev('window.__ev.join("\\n")'))) ws.close()