Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QND7Co43B24zK2P937rdxt
155 lines
5.4 KiB
Python
155 lines
5.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""B05~B09 돋보기(계획서 218-1) 회귀검증 — 오른쪽 길게 누름 · Z 누름 동안 켬 · 크기 · 배율 · 복제 지움 · 페이지 다섯.
|
|
|
|
Node 헬퍼(`helper_218_1_loupe.cjs`)가 `ui_template/ui_template_loupe.ts` 를 트랜스파일해
|
|
가짜 창 · 가짜 시계 · 가짜 요소로 돌리고, 여기서 값을 판정함.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import re
|
|
import subprocess
|
|
|
|
import pytest
|
|
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
ROOT = os.path.dirname(os.path.dirname(HERE))
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def r():
|
|
proc = subprocess.run(
|
|
["node", os.path.join(HERE, "helper_218_1_loupe.cjs")],
|
|
capture_output=True,
|
|
text=True,
|
|
encoding="utf-8",
|
|
timeout=60,
|
|
)
|
|
assert proc.returncode == 0, proc.stderr
|
|
return json.loads(proc.stdout)
|
|
|
|
|
|
def _read(rel):
|
|
with open(os.path.join(ROOT, rel), encoding="utf-8") as f:
|
|
return f.read()
|
|
|
|
|
|
def test_크기_배율_상수(r):
|
|
assert r["consts"] == {"d": 240, "zoom": 2, "hold": 400, "refresh": 500}
|
|
assert r["capture"]["rootSize"] == ["240px", "240px"]
|
|
# 커서(500,400)가 원 가운데(120,120)에 2배로 옴
|
|
assert r["capture"]["stageTransform"] == "translate(-880px, -680px) scale(2)"
|
|
|
|
|
|
def test_창_캡처_단계로_들음(r):
|
|
assert r["listeners"] == [
|
|
[t, True]
|
|
for t in ("mousemove", "mousedown", "mouseup", "contextmenu", "keydown", "keyup", "blur")
|
|
]
|
|
|
|
|
|
def test_길게_누름_0_4초_넘어야_켜고_떼면_끔_메뉴는_안_뜸(r):
|
|
lg = r["long"]
|
|
assert lg["before"] == 0 # 0.399 초 = 아직
|
|
assert lg["on"] == "show" and lg["show"] == ["show", 300, 200]
|
|
assert lg["moved"] == ["move", 310, 205] # 커서 따라감
|
|
assert lg["off"] == "hide"
|
|
assert lg["menuPrevented"] and lg["menuStopped"] # 브라우저 · 우리 메뉴 둘 다 안 뜸
|
|
assert lg["nextStopped"] is False # 한 번만 먹음
|
|
|
|
|
|
def test_짧게_누르면_지금_우클릭_그대로(r):
|
|
assert r["short"] == {"log": 0, "menuPrevented": False, "menuStopped": False}
|
|
|
|
|
|
def test_왼쪽_단추_무시_창_밖에서_떼면_끔(r):
|
|
mm = r["mouseMisc"]
|
|
assert mm["left"] == 0
|
|
assert mm["lostBeforeHold"] == 0 # 0.4 초 전에 뗌 — 안 켬
|
|
assert mm["lostAfterHold"] == "hide"
|
|
|
|
|
|
def test_Z_누름_켬_뗌_끔(r):
|
|
k = r["key"]
|
|
assert k["on"] == "show" # 한글 자판(ㅋ)도 code KeyZ
|
|
assert k["repeatLen"] == 1 # 누르고 있는 동안 다시 안 그림
|
|
assert k["off"] == "hide"
|
|
assert k["noCombo"] # Ctrl · Alt · Meta 조합 · 다른 키는 안 켬
|
|
assert k["shift"] == "show"
|
|
assert k["fieldBlur"] == "show" # 칸 초점 빠짐으론 안 끔
|
|
assert k["blur"] == "hide" # 창이 초점을 잃으면 끔
|
|
|
|
|
|
def test_입력_칸에선_안_켬(r):
|
|
t = r["key"]["typing"]
|
|
for name in ("input", "inputNoType", "number", "textarea", "select", "editable"):
|
|
assert t[name] is False, name
|
|
assert t["checkbox"] and t["button"]
|
|
|
|
|
|
def test_B05_B09_밖이면_안_켬(r):
|
|
assert r["off"] == {"log": 0, "menuStopped": False}
|
|
|
|
|
|
def test_페이지_다섯_붙음(r):
|
|
on = [k for k, v in r["routes"].items() if v]
|
|
assert on == [
|
|
"b05-profile",
|
|
"b06-section",
|
|
"b07-design-detail",
|
|
"b08-quantity",
|
|
"b09-estimation",
|
|
]
|
|
main = _read("A00_Common/main.ts")
|
|
assert 'from "@ui/ui_template_loupe"' in main
|
|
assert re.search(r"initLoupe\(window, \(\) => LOUPE_ROUTE\.test\(currentRoute\(\)\)\)", main)
|
|
|
|
|
|
def test_화면_끝에서_안_잘림(r):
|
|
o = r["origin"]
|
|
assert o["mid"] == {"left": 380, "top": 280}
|
|
assert o["topLeft"] == {"left": 4, "top": 4}
|
|
assert o["bottomRight"] == {"left": 1000 - 240 - 4, "top": 800 - 240 - 4}
|
|
|
|
|
|
def test_화면_뜨기(r):
|
|
c = r["capture"]
|
|
assert (
|
|
c["rootClass"] == "ui-loupe"
|
|
and c["inert"]
|
|
and c["ariaHidden"] == "true"
|
|
and not c["hidden"]
|
|
)
|
|
assert c["pageBox"] == ["0px", "0px", "1000px", "800px"]
|
|
assert c["isClone"]
|
|
assert c["canvasDrawn"] == ["canvas2d"] and c["blankDrawn"] == 0
|
|
assert c["inputValue"] == "12.5" and c["checkChecked"]
|
|
assert c["scrollTop"] == 120
|
|
assert c["offscreenChildren"] == 0 and c["offscreenSize"] == ["100px", "100px"] # 보이는 영역만
|
|
assert c["rowKept"] == 1 # 표 줄은 칸 너비 때문에 그대로
|
|
assert c["svgKept"] == 1
|
|
assert c["frameTag"] == "CANVAS" and c["frameDrawn"] == [["cad", 5, 6, 300, 200]]
|
|
assert c["frameSize"] == [320, 240]
|
|
assert c["watching"] and c["observeOpts"]["subtree"] and c["scrollListen"]
|
|
|
|
|
|
def test_바뀌면_0_5초_뒤_다시_뜸_끄면_복제_지움(r):
|
|
h = r["hide"]
|
|
assert h["sameBefore"] and h["recaptured"]
|
|
assert h["nearEdge"] == "translate(4px, 4px)"
|
|
assert h["stageChildren"] == 0 # 복제 지움
|
|
assert h["hidden"] and h["disconnected"] and h["scrollListen"] is False
|
|
assert h["noRecaptureAfterHide"] == 0
|
|
assert h["reuseRoot"] == 1 # 원은 하나를 다시 씀
|
|
|
|
|
|
def test_테두리_그림자_토큰():
|
|
css = _read("ui_template/ui_template_loupe.css")
|
|
assert "--loupe-border: var(--color-accent)" in css
|
|
assert "--loupe-shadow: var(--shadow-lg)" in css
|
|
assert "border-radius: 50%" in css and "pointer-events: none" in css
|
|
assert ".ui-loupe__cross" in css
|
|
theme = _read("ui_template/ui_template_theme.css")
|
|
dark = theme[theme.index(':root[data-theme="dark"]') :]
|
|
assert "--color-accent" in dark and "--shadow-lg" in dark # 어두움에서도 토큰이 바뀜
|