feat(device): B07 CAD 손가락 — 한 손가락 화면 옮기기 · 두 손가락 확대 · 길게 누름 정밀 십자선(손가락 위 70px) · 고름 반경 = 접촉 크기(최소 24px) · 자판 없는 명령 단추(Esc · Enter · 지움 · 되돌리기 · 다시 · 스냅) · user-scalable=no 뺌 · 100vh → 100dvh (기기대응 4-1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ji4nuyLVHcxrXWHTdb5nRD
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
"""B07 CAD 손가락(PLAN_기기대응 4-1 · `openwebcad/src/inputController/input-touch.ts`) — 빌드된 CAD 화면.
|
||||
|
||||
① 손가락 기기 = 명령 단추 6개(44px) · 마우스 기기 = 안 보임 ② 확대 막기(user-scalable=no) 없음
|
||||
③ 캔버스 touch-action none · 두 손가락 벌림 · 한 손가락 끌기가 페이지를 확대 · 밀지 않음(페이지 오류 0)
|
||||
"""
|
||||
|
||||
import urllib.request
|
||||
|
||||
import pytest
|
||||
|
||||
URL = "http://localhost:5174/b07-cad/"
|
||||
|
||||
|
||||
def _up() -> bool:
|
||||
try:
|
||||
urllib.request.urlopen(URL, timeout=2)
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def _touch(cdp, kind, points):
|
||||
cdp.send(
|
||||
"Input.dispatchTouchEvent",
|
||||
{
|
||||
"type": kind,
|
||||
"touchPoints": [{"x": x, "y": y, "id": i} for i, (x, y) in enumerate(points)],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.skipif(not _up(), reason="sub1 화면 서버(5174) 꺼짐")
|
||||
def test_cad_touch_bar_and_gestures():
|
||||
from playwright.sync_api import sync_playwright
|
||||
|
||||
with sync_playwright() as p:
|
||||
browser = p.chromium.launch(channel="msedge", headless=True)
|
||||
mouse = browser.new_page(viewport={"width": 1440, "height": 900})
|
||||
mouse.goto(URL)
|
||||
mouse.wait_for_selector(".cad-touch-bar", state="attached", timeout=20000)
|
||||
assert (
|
||||
mouse.evaluate("getComputedStyle(document.querySelector('.cad-touch-bar')).display")
|
||||
== "none"
|
||||
)
|
||||
|
||||
ctx = browser.new_context(
|
||||
viewport={"width": 1180, "height": 820}, has_touch=True, is_mobile=True
|
||||
)
|
||||
page = ctx.new_page()
|
||||
errors = []
|
||||
page.on("pageerror", lambda e: errors.append(str(e)))
|
||||
page.goto(URL)
|
||||
page.wait_for_selector(".cad-touch-bar", timeout=20000)
|
||||
sizes = page.evaluate(
|
||||
"[...document.querySelectorAll('.cad-touch-bar > button')].map(b => [b.offsetWidth, b.offsetHeight])"
|
||||
)
|
||||
assert len(sizes) == 6 and all(w >= 44 and h >= 44 for w, h in sizes), sizes
|
||||
assert "user-scalable" not in page.evaluate(
|
||||
"document.querySelector('meta[name=viewport]').content"
|
||||
)
|
||||
assert (
|
||||
page.evaluate(
|
||||
"getComputedStyle(document.querySelector('canvas[data-id=canvas]')).touchAction"
|
||||
)
|
||||
== "none"
|
||||
)
|
||||
|
||||
box = page.evaluate(
|
||||
"(() => { const r = document.querySelector('canvas[data-id=canvas]').getBoundingClientRect();"
|
||||
" return [r.left + r.width / 2, r.top + r.height / 2]; })()"
|
||||
)
|
||||
cx, cy = box
|
||||
cdp = ctx.new_cdp_session(page)
|
||||
_touch(cdp, "touchStart", [(cx, cy)]) # 한 손가락 끌기 = 화면 옮기기
|
||||
for i in range(1, 6):
|
||||
_touch(cdp, "touchMove", [(cx + i * 20, cy + i * 10)])
|
||||
_touch(cdp, "touchEnd", [])
|
||||
_touch(cdp, "touchStart", [(cx - 30, cy), (cx + 30, cy)]) # 벌림 = 도면 확대
|
||||
for i in range(1, 8):
|
||||
_touch(cdp, "touchMove", [(cx - 30 - i * 10, cy), (cx + 30 + i * 10, cy)])
|
||||
_touch(cdp, "touchEnd", [])
|
||||
page.locator(".cad-touch-bar > button").first.tap() # Esc
|
||||
page.wait_for_timeout(300)
|
||||
assert page.evaluate("visualViewport.scale") == 1
|
||||
assert page.evaluate("[scrollX, scrollY]") == [0, 0]
|
||||
assert not errors, errors
|
||||
browser.close()
|
||||
Reference in New Issue
Block a user