Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QfHKQs7J3hQELKMWQMUJEy
88 lines
3.5 KiB
Python
88 lines
3.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""354-3 종단 그래프 스크롤 끊김 — 동기화 메아리 · 스크롤마다 유토 다시 셈.
|
|
|
|
- 메아리: scroll 은 다음 틀에 옴 → 동기 플래그로 못 막아 한 틀 전 값을 되씀 → 뒤로 튐 →
|
|
휠 이동이 접힘. 공용 `linkScrollLeft`(Wheel.ts)가 써 넣은 값으로 온 scroll 을 무시.
|
|
가짜 창(다음 틀 scroll) 재현 — 옛 잇기는 뒤로 튐 · 멈춤, 새 잇기는 4 경우 × 휠 쪽 둘 모두 튐 0.
|
|
- 유토 스크롤 그리기 = 열림 · 분배 맞춤 아님 · 붙음일 때만 · 한 틀 한 번 · 다시 셈 없음.
|
|
|
|
`helper_354_3_scroll_echo.cjs` 가 진짜 휠 · 잇기 TS 를 가짜 창 위에서 돌림.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import re
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
B05 = Path(HERE).parents[1] / "B05_Profile"
|
|
CASES = [
|
|
f"{driver}|table={table}|balance={balance}"
|
|
for driver in ("body", "mass")
|
|
for table in ("true", "false")
|
|
for balance in ("false", "true")
|
|
]
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def r():
|
|
proc = subprocess.run(
|
|
["node", os.path.join(HERE, "helper_354_3_scroll_echo.cjs")],
|
|
capture_output=True,
|
|
text=True,
|
|
encoding="utf-8",
|
|
timeout=60,
|
|
)
|
|
assert proc.returncode == 0, proc.stderr
|
|
return json.loads(proc.stdout)
|
|
|
|
|
|
def test_옛_잇기는_메아리로_뒤로_튐(r):
|
|
# 표 · 분배 끔(사용자 보고 경우)에서 휠 다섯 칸(1,200px) 중 210px 에서 멈춤
|
|
assert r["old|body|table=false|balance=false"]["back"] > 0
|
|
assert r["old|body|table=false|balance=false"]["end"] < 1200
|
|
# 분배 켜고 표 끔 = 잇기 없음 — 사용자 관찰(분배 켜면 매끄러움)과 같음
|
|
assert r["old|body|table=false|balance=true"] == {
|
|
"back": 0,
|
|
"end": 1200,
|
|
"lead": 1200,
|
|
"mass": 0,
|
|
"table": 0,
|
|
}
|
|
|
|
|
|
@pytest.mark.parametrize("case", CASES)
|
|
def test_새_잇기는_뒤로_튐_0_끝까지(r, case):
|
|
got = r[f"new|{case}"]
|
|
assert got["back"] == 0
|
|
assert got["end"] == 1200 and got["lead"] == 1200
|
|
table, balance = "table=true" in case, "balance=true" in case
|
|
assert got["table"] == (1200 if table else 0)
|
|
assert got["mass"] == (0 if balance else 1200)
|
|
|
|
|
|
def test_유토_표_같은_도우미():
|
|
for name in ("MassHaul", "TableOverlay"):
|
|
src = (B05 / f"B05_Profile_UI_Profile_{name}.ts").read_text(encoding="utf-8")
|
|
assert "linkScrollLeft(main, scroll" in src
|
|
assert "syncing" not in src
|
|
|
|
|
|
def test_유토_스크롤_그리기는_창_따를_때만_한_틀_한_번():
|
|
mass = (B05 / "B05_Profile_UI_Profile_MassHaul.ts").read_text(encoding="utf-8")
|
|
body = mass[mass.index("function drawWindow(") :]
|
|
body = body[: body.index("\n }\n")]
|
|
assert '!open || fitted || overlay.classList.contains("is-popout") || !lastSeries' in body
|
|
assert "windowState.frame" in body and "frameOf(overlay" in body
|
|
assert "draw(lastParams, true)" in body
|
|
# 다시 셈 없음 · 총괄값 · 범례는 계열이 바뀔 때만
|
|
assert re.search(r"reuse && lastSeries\s*\? lastSeries", mass)
|
|
assert "if (series !== lastSeries) emitSummary(series);" in mass
|
|
# 다시 그려도 제 자리 — 종단 값으로 되쓰는 것은 처음 · 맞춤 뒤 · 창 옮김 뒤만
|
|
assert "scroll.scrollLeft = syncedMain.scrollLeft" not in mass
|
|
render = (B05 / "B05_Profile_UI_Profile_Render.ts").read_text(encoding="utf-8")
|
|
assert "massHaul.drawWindow({" in render
|