Merge remote-tracking branch 'origin/sub_laptop_3' into main_laptop_1

This commit is contained in:
2026-10-29 18:42:58 +09:00
12 changed files with 300 additions and 10 deletions
@@ -9,6 +9,7 @@ const { makeLoader } = require("./helper_ts_stub_loader.cjs");
const ROOT = path.join(__dirname, "..", "..");
const B05 = path.join(ROOT, "B05_Profile");
let handlers = null;
let iconOpen = null; // 445-C1 아이콘 누름 흉내 — 정보 창을 열어야 `show` 가 불림
const shows = [];
const STUBS = {
"./B05_Profile_UI_RouteEdit_Label": {
@@ -18,6 +19,12 @@ const STUBS = {
},
centerDirectionOf: () => null,
},
"./B05_Profile_UI_RouteEdit_CurveIcon": {
createCurveIcon: (_canvas, onOpen) => {
iconOpen = onOpen;
return { update: () => {}, destroy: () => {} };
},
},
"@ui/ui_template_elements": { showToast: () => {} }, // 곡선 삭제 경고(430)
};
@@ -118,6 +125,7 @@ function editor(snap) {
const pick = (k) => {
state.picked = k;
made.sync();
iconOpen(); // 아이콘 누름 = 열림(열린 채 다른 교각점 = 이어서 열림)
};
const lastShow = () => shows[shows.length - 1];
return { state, status, handlers: () => handlers, drawn, arcOf, mc, pick, lastShow, markEdited };
@@ -17,6 +17,9 @@ const STUBS = {
},
centerDirectionOf: () => null,
},
"./B05_Profile_UI_RouteEdit_CurveIcon": {
createCurveIcon: () => ({ update: () => {}, destroy: () => {} }), // 445-C1 근처 아이콘(화면 없음)
},
"@ui/ui_template_elements": { showToast: () => {} }, // 곡선 삭제 경고(430)
};
+84
View File
@@ -0,0 +1,84 @@
"""445-C1 B05 교각점 정보 = 근처 아이콘 — 규칙(`logic/B05_Profile_RouteEdit_CurveIcon.ts`)을 Node 로 돌려 판정 +
배선 글 대조(`_CurveBar` 가 열림을 봄 · 닫기는 고름도 풂 · 아이콘은 부품 상자 유리 꼴).
./venv/Scripts/python.exe -m pytest resources/tester/test_445_curve_icon.py -q
"""
import json
import subprocess
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[2]
B05 = ROOT / "B05_Profile"
LOGIC = B05 / "logic" / "B05_Profile_RouteEdit_CurveIcon.ts"
TS = ROOT / "config" / "node_modules" / "typescript"
DRIVER = r"""
const fs = require("fs");
const ts = require(process.argv[1]);
const js = ts.transpileModule(fs.readFileSync(process.argv[2], "utf8"), {
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 },
}).outputText;
const m = { exports: {} };
new Function("exports", "module", js)(m.exports, m);
const L = m.exports;
console.log(JSON.stringify({
near: L.NEAR_PX,
nearIn: L.isNear(L.NEAR_PX, false),
nearOut: L.isNear(L.NEAR_PX + 1, false),
nearOnIcon: L.isNear(500, true),
keepOpenOther: L.openAfterPick(true, 3),
closedStaysClosed: L.openAfterPick(false, 3),
releaseCloses: L.openAfterPick(true, -1),
noPick: L.iconVisible(-1, false, true, false),
picked_near: L.iconVisible(2, false, true, false),
picked_far: L.iconVisible(2, false, false, false),
picked_far_touch: L.iconVisible(2, false, false, true),
open_near: L.iconVisible(2, true, true, false),
}));
"""
@pytest.fixture(scope="module")
def got() -> dict:
run = subprocess.run( # noqa: S603 — 고정 실행 파일
["node", "-e", DRIVER, str(TS), str(LOGIC)],
capture_output=True,
text=True,
encoding="utf-8",
timeout=60,
)
assert run.returncode == 0, run.stderr
return json.loads(run.stdout)
def test_근처_판정(got) -> None:
assert got["near"] == 40
assert got["nearIn"] is True and got["nearOut"] is False
assert got["nearOnIcon"] is True # 아이콘 위는 멀어도 근처
def test_창_열림_이어감(got) -> None:
assert got["keepOpenOther"] is True # 열린 채 다른 교각점 = 열린 채
assert got["closedStaysClosed"] is False # 닫힘 = 닫힌 채
assert got["releaseCloses"] is False # 고름 풂 = 닫힘
def test_아이콘_보임(got) -> None:
assert got["noPick"] is False
assert got["picked_near"] is True and got["picked_far"] is False
assert got["picked_far_touch"] is True # 터치 = 고르면 늘 보임
assert got["open_near"] is False # 창이 열리면 아이콘 숨김
def test_배선_글() -> None:
bar = (B05 / "B05_Profile_UI_RouteEdit_CurveBar.ts").read_text(encoding="utf-8")
assert "openAfterPick" in bar and "icon.update(" in bar
assert "onClose: () => params.onUnselect()" in bar # 닫기 = 창 닫고 고름도 풂
# 닫힘이면 창을 숨기고 아이콘만 — 창 show 보다 앞
assert bar.index("if (!open) {") < bar.index("label.show({")
icon = (B05 / "B05_Profile_UI_RouteEdit_CurveIcon.ts").read_text(encoding="utf-8")
assert 'variant: "glass"' in icon and "createIconButton" in icon # 부품 상자 유리 꼴
assert "document.createElement" not in icon.split("export function")[1] # 날 요소 없음
+1
View File
@@ -78,6 +78,7 @@ def test_상태():
assert '.ui-icon-btn:is(:hover, [data-state="hover"]):not(:disabled)' in css
assert '.ui-icon-btn:is(:active, [data-state="active"]):not(:disabled)' in css
assert '.ui-icon-btn[aria-pressed="true"]' in css and ".ui-icon-btn:disabled" in css
assert '.ui-icon-btn--glass:is(:hover, [data-state="hover"]):not(:disabled)' in css # 445-C1
src = _text(UI / "ui_template_button.ts")
assert 'title: opts.title, "aria-label": opts.title' in src