Files
Aislo/resources/tester/test_354_1_masshaul_own_panel.py
T
eomsangdonandClaude Opus 5.5 50c40d564e fix(B05 종단도): 392-2 유토 판 [창 분할] 층 z6 — 고정 Y축 띠 밑에 가려지던 것
- 10-14 판 자리(판 좌상단)로 되살리며 축 띠(z5 · 불투명) 아래로 들어가 안 보이던 것 · 누름은 축이 통과시켜 시험에선 안 잡힘
- 화면 확인(밝음 · 어두움) · test_354_1 에 z6 판정

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Se7ytqbohmBQnfYpwYFnYf
2026-10-17 17:45:25 +09:00

143 lines
6.5 KiB
Python

# -*- coding: utf-8 -*-
"""354-1 → 392-2 유토곡선 판 = 10-14 판(9edaec82e) 되살림(요구 242-10).
- 유토곡선 = 종단 칸(bodyWrap) 바닥 덮는 판(absolute · z5) · 자기 판(종단 열 아래 칸) 지움.
- 메인 판 끌기 = 종단 · 유토 · 표 세 영역 같은 비율 · 놓을 때 유토 · 표 높이 확정(commitHeight).
- 유토 손잡이 = 판 위 경계 밖(bottom = 판 높이) · 표 손잡이와 ±44 px 나란히 · 접기 = 숨김.
- 표 판 = 열린 유토 위에 쌓임(setBottomOffset).
- 남김 = 유토 [창 분할](판 안 좌상단 = 펼친 때만 보임) · 367-1 늘 전체 맞춤 · 325-2 뿌리 안 판정.
"""
import json
import os
import re
import subprocess
from pathlib import Path
HERE = os.path.dirname(os.path.abspath(__file__))
ROOT = Path(HERE).parents[1]
def read(rel: str) -> str:
return (ROOT / rel).read_text(encoding="utf-8")
def css_block(css: str, selector: str) -> str:
m = re.search(r"(?:^|\n)" + re.escape(selector) + r" \{([^}]*)\}", css)
assert m, selector
return m.group(1)
# 진짜 높이 나눔(createHeightCascade) — 메인 끌기 중 세 영역 비례
NODE = r"""
const path = require("path"), fs = require("fs");
const root = process.argv[1];
const ts = require(path.join(root, "config", "node_modules", "typescript"));
const src = fs.readFileSync(path.join(root, "B05_Profile", "B05_Profile_UI_Profile_Heights.ts"), "utf8");
const js = ts.transpileModule(src, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 } }).outputText;
const exp = {};
new Function("exports", "require", "window", js)(exp, (id) =>
id.includes("MassHaul") ? { MASSHAUL_MIN_HEIGHT: 160 }
: id.includes("TableOverlay") ? { TABLE_OVERLAY_MIN_HEIGHT: 120 }
: id.includes("Structures_Marks") ? { STRUCTURE_LANE_HEIGHT_PX: 40 } : { frameOf: () => 0 },
{ innerHeight: 900 });
const el = () => { const n = { hidden: false, style: { height: "" }, parent: null };
n.append = (k) => ((k.parent = n), k);
n.contains = (o) => { for (let a = o; a; a = a.parent) if (a === n) return true; return false; };
return n; };
function run(bodyH) {
const rootEl = el(); rootEl.offsetHeight = bodyH + 100;
const body = rootEl.append(el()); body.clientHeight = bodyH;
const mass = body.append(el()), table = body.append(el());
const seen = { handle: 0, offset: null };
const c = exp.createHeightCascade({
root: rootEl, body,
massHaul: { overlay: mass, desiredHeight: () => 200, syncHandle: () => seen.handle++ },
tableOverlay: { overlay: table, isOpen: () => true, desiredHeight: () => 200,
setBottomOffset: (v) => (seen.offset = v) },
isMainDragging: () => true, isSubDragging: () => false,
// 끌기 시작 = 종단 400 · 유토 200 · 표 200
mainDragRef: () => ({ chart: 400, mass: 200, table: 200 }),
isMainDragCooldown: () => true, hasDetail: () => true,
});
const { chartHeight } = c.apply(false);
return { chart: chartHeight, mass: mass.style.height, table: table.style.height, ...seen };
}
// 본문 − 알약 40 − 손잡이 띠 13 = 나눌 자리 · 800 → 1.0 배 · 1200 → 1.5 배
process.stdout.write(JSON.stringify({ same: run(853), grow: run(1253) }));
"""
def test_메인_끌기_세_영역_같은_비율():
res = subprocess.run(
["node", "-e", NODE, str(ROOT)],
capture_output=True,
text=True,
encoding="utf-8",
check=True,
)
out = json.loads(res.stdout)
assert out["same"] == {
"chart": 400,
"mass": "200px",
"table": "200px",
"handle": 1,
"offset": 200,
}
# 1.5 배 — 셋 다 같은 비율 · 표는 유토 위에 쌓임(바닥 간격 = 유토 높이)
assert out["grow"] == {
"chart": 600,
"mass": "300px",
"table": "300px",
"handle": 1,
"offset": 300,
}
def test_놓을_때_높이_확정_뿌리_안_판정():
drag = read("B05_Profile/B05_Profile_UI_Profile_Drag.ts")
assert "if (massDocked()) massHaul.commitHeight(massHaul.overlay.offsetHeight);" in drag
assert "if (tableOverlay.isOpen()) tableOverlay.commitHeight(" in drag
# 325-2 「열림 && 뿌리 안」 한 곳 · 하한에 유토 최소
assert drag.count("massHaul.overlay.hidden") == 1
assert "root.contains(massHaul.overlay)" in drag
assert "const massMin = massDocked() ? MASSHAUL_MIN_HEIGHT : 0;" in drag
heights = read("B05_Profile/B05_Profile_UI_Profile_Heights.ts")
assert '{ key: "mass", ref: Math.max(1, dragRef.mass), min: MASSHAUL_MIN_HEIGHT }' in heights
def test_종단_칸_바닥_덮는_판():
overlays = read("A00_Common/design/design_profile_overlays.ts")
assert "bodyWrap.append(massHaul.overlay, massHaul.handle);" in overlays
assert "b05-route-profile__column" not in overlays
assert "massHaul.attachScrollSync" not in overlays # 367-1 측점 연계 없앰
profile = read("A00_Common/design/design_profile.ts")
assert "content.append(bodyWrap);" in profile
assert sum(1 for _ in profile.splitlines()) <= 700
css = read("B05_Profile/B05_Profile_UI_Style_MassHaul.css")
panel = css_block(css, ".b05-profile__masshaul-overlay")
assert "position: absolute;" in panel and "bottom: 0;" in panel and "z-index: 5;" in panel
assert "masshaul-head" not in css and "is-collapsed:not(.is-popout)" not in css
def test_손잡이_자리_접기_숨김():
css = read("B05_Profile/B05_Profile_UI_Style_MassHaul.css")
assert "left: calc(50% + 44px);" in css_block(css, ".b05-profile__masshaul-handle")
assert "left: calc(50% - 44px);" in css_block(css, ".b05-profile__table-handle")
mass = read("B05_Profile/B05_Profile_UI_Profile_MassHaul.ts")
# 손잡이 = 판 위 경계 밖 · 접으면 바닥 · 접기 = 판 숨김
assert 'handle.style.bottom = open ? `${overlay.offsetHeight}px` : "0px";' in mass
assert "overlay.hidden = !open;" in mass and "overlay.hidden = !next;" in mass
table = read("B05_Profile/B05_Profile_UI_Profile_TableOverlay.ts")
assert "overlay.style.bottom = `${bottomOffset}px`;" in table
def test_창_분할_판_좌상단():
popout = read("A00_Common/design/design_profile_popout.ts")
assert "massOverlay.append(button);" in popout
assert "home: () => massHandle.before(massOverlay)," in popout
page = read("A00_Common/design/design_page.css")
button = css_block(page, ".b05-profile__masshaul-overlay > .b05-subpanel__popout")
# 고정 Y축(z5) 위 — 아래면 단추가 축 띠에 가려짐
assert "position: absolute;" in button and "z-index: 6;" in button