Files
core2026/app/game-frontend/e2e/touchDrag.ts
T
Hide_D 26920add19 fix: 모바일 터치 드래그 정렬 복구
NPC 정책 우선순위와 모바일 메인 패널 순서를 Ref와 같은 vuedraggable 기반으로 전환한다. 실제 모바일 Chromium 터치 제스처 회귀 검증을 추가한다.
2026-08-21 01:07:23 +00:00

78 lines
2.4 KiB
TypeScript

import type { Locator, Page } from '@playwright/test';
type TouchPoint = {
x: number;
y: number;
};
type TouchDragOptions = {
targetYRatio?: number;
};
const pointIn = async (locator: Locator, yRatio = 0.5): Promise<TouchPoint> => {
const box = await locator.boundingBox();
if (!box) {
throw new Error('Touch drag target has no visible bounding box');
}
return {
x: box.x + box.width / 2,
y: box.y + box.height * yRatio,
};
};
export const touchDrag = async (
page: Page,
source: Locator,
target: Locator,
options: TouchDragOptions = {}
): Promise<void> => {
await source.scrollIntoViewIfNeeded();
await target.scrollIntoViewIfNeeded();
const from = await pointIn(source);
const to = await pointIn(target, options.targetYRatio);
const cdp = await page.context().newCDPSession(page);
await page.evaluate(() => {
document.documentElement.removeAttribute('data-playwright-touch-trusted');
document.addEventListener(
'touchstart',
(event) => document.documentElement.setAttribute('data-playwright-touch-trusted', String(event.isTrusted)),
{ capture: true, once: true }
);
});
await cdp.send('Input.dispatchTouchEvent', {
type: 'touchStart',
touchPoints: [{ ...from, id: 0, radiusX: 1, radiusY: 1, force: 1 }],
});
await page.waitForTimeout(50);
const dispatchMove = async (ratio: number) => {
await cdp.send('Input.dispatchTouchEvent', {
type: 'touchMove',
touchPoints: [
{
x: from.x + (to.x - from.x) * ratio,
y: from.y + (to.y - from.y) * ratio,
id: 0,
radiusX: 1,
radiusY: 1,
force: 1,
},
],
});
};
await dispatchMove(0.05);
await page.waitForTimeout(100);
for (let step = 2; step <= 20; step += 1) {
await dispatchMove(step / 20);
await page.waitForTimeout(16);
}
await page.waitForTimeout(50);
await cdp.send('Input.dispatchTouchEvent', { type: 'touchEnd', touchPoints: [] });
const trusted = await page.evaluate(
() => document.documentElement.getAttribute('data-playwright-touch-trusted') === 'true'
);
if (!trusted) {
throw new Error('Chromium did not dispatch a trusted touchstart event');
}
};