fix(B06): 목록 고름도 늘 고름 기록 — 같은 카드 안 구조물도 오감 · 새로 고침 뒤 그 폼(231-2)
- 목록 · 알약 · 형상 고름은 노면공이 아니어도 그 구조물 id 를 고름 한 칸에 적음 · 측점 고름이 연 것은 측점만(189-1) - 새 시험 test_231_2 · test_231_1 · test_177_4 기대값 맞춤 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STqEqztUthVFBmEP18wBSz
This commit is contained in:
@@ -227,9 +227,10 @@ export function createB06StructuresPanel(deps: B06StructuresPanelDeps): B06Struc
|
||||
preferredId = null;
|
||||
// 알약은 카드 뒤에 — 카드 측점이 알약을 갈아 끼우거나 끄지 않게(53-2)
|
||||
deps.markStructure?.(id, !openingAtStation); // 측점 고름이 연 것 = 카드 하나 · 범위 테두리 없음(231-1)
|
||||
// 카드 고름 리스너를 안 거치니 세션 고름은 여기서(B05 로 가도 그 노면공)
|
||||
// 목록 · 알약 · 형상 고름은 늘 고름 한 칸에 그 구조물 — 같은 카드라 카드 리스너가 안 돌아도
|
||||
// 오감 · 새로 고침 뒤 그 폼(188-1 · 231-2) · 측점 고름이 연 것은 측점만(카드 리스너 몫 · 189-1)
|
||||
const at = { chainageM: focusOf(structure), structureId: id };
|
||||
if (pave) selectDesign(deps.projectId, at, { from: "b06" });
|
||||
if (!openingAtStation) selectDesign(deps.projectId, at, { from: "b06" });
|
||||
},
|
||||
getInterval: deps.stationInterval,
|
||||
// 관 추가 — 정본은 [저장]·[확정]에서 나간다. 화면 목록·알약은 바로 세운다.
|
||||
|
||||
@@ -249,9 +249,10 @@ view.listener = (stationId) => {
|
||||
view.selectMark(mark, false);
|
||||
};
|
||||
|
||||
async function build(list) {
|
||||
/** 새로 세움 — keep = 새로 고침(F5 · 세션은 남고 화면 · 폼은 처음부터). */
|
||||
async function build(list, keep = false) {
|
||||
current.structures = list;
|
||||
store.clear();
|
||||
if (!keep) store.clear();
|
||||
form.id = null;
|
||||
form.pipe = null;
|
||||
view.selected = null;
|
||||
@@ -305,6 +306,12 @@ async function roundTrip() {
|
||||
restore();
|
||||
}
|
||||
|
||||
/** 새로 고침(F5) — 첫 마운트 `load().then(restoreStructurePick)` 차례(231-2). */
|
||||
async function refresh() {
|
||||
await build(current.structures, true);
|
||||
restore();
|
||||
}
|
||||
|
||||
function snap() {
|
||||
const mark = marks.find((entry) => entry.structure_id === view.spanMarkId);
|
||||
const pave = mark && isPavement(mark.structure_id);
|
||||
@@ -320,6 +327,11 @@ function snap() {
|
||||
|
||||
const cardPick = (at) => view.selectStation(cardAt(at).station_id);
|
||||
const listPick = (id) => loadForm(structures.find((entry) => entry.structure_id === id));
|
||||
/** 좌측 목록 관 줄 — B05 패널 `onSelectPipe`(loadPipeForm → onPipeSelect). */
|
||||
const listPipe = (at) => {
|
||||
loadPipeForm(at);
|
||||
binding.onPipeSelect(at);
|
||||
};
|
||||
|
||||
/** B05 3D 부재 고름 — 진짜 `wireStructurePick` 에 B05 와 같은 거름(design_view_profile). */
|
||||
function pick3d(chainageM) {
|
||||
@@ -378,6 +390,38 @@ function pick3d(chainageM) {
|
||||
out.pick3dBare = { sid: snap().sid, form: snap().form };
|
||||
await roundTrip();
|
||||
out.pick3dAfter = snap();
|
||||
|
||||
// 231-2 목록 고름도 늘 고름 기록 — 카드 120 → 목록 관 · 표지 · 옹벽 → 오감 · 새로 고침
|
||||
await build([PAVE, WALL, SIGN]);
|
||||
cardPick(120);
|
||||
listPipe(80.17);
|
||||
out.listPipe = snap();
|
||||
await roundTrip();
|
||||
out.listPipeTrip = snap();
|
||||
await refresh();
|
||||
out.listPipeF5 = snap();
|
||||
|
||||
await build([PAVE, SIGN]);
|
||||
cardPick(120);
|
||||
listPick("sign"); // 같은 카드 120 — 카드 리스너 안 돎
|
||||
out.listSign = snap();
|
||||
await roundTrip();
|
||||
out.listSignTrip = snap();
|
||||
await refresh();
|
||||
out.listSignF5 = snap();
|
||||
|
||||
await build([PAVE, WALL]);
|
||||
cardPick(120);
|
||||
listPick("wall");
|
||||
out.listWall = snap();
|
||||
await roundTrip();
|
||||
out.listWallTrip = snap();
|
||||
|
||||
await build([PAVE, SIGN]);
|
||||
cardPick(120);
|
||||
listPick("pave");
|
||||
await refresh();
|
||||
out.listPaveF5 = snap();
|
||||
process.stdout.write(JSON.stringify(out));
|
||||
})().catch((error) => {
|
||||
process.stderr.write(String(error?.stack ?? error));
|
||||
|
||||
@@ -71,4 +71,5 @@ def test_스크롤만_길은_리스너를_안_거침():
|
||||
assert "if (revealOnly) sectionView.revealStation(nearest.station_id);" in cross
|
||||
panel = _read("B06_Section", "B06_Section_UI_Page_Structures_Panel.ts")
|
||||
assert "const pave = !coverable(structure);" in panel
|
||||
assert 'if (pave) selectDesign(deps.projectId, at, { from: "b06" });' in panel
|
||||
# 목록 고름은 노면공뿐 아니라 늘 고름 기록(231-2)
|
||||
assert 'if (!openingAtStation) selectDesign(deps.projectId, at, { from: "b06" });' in panel
|
||||
|
||||
@@ -57,9 +57,9 @@ def test_범위_안_카드_고름_오감해도_노면공_안_켬_폼_그대로(o
|
||||
def test_같은_카드_목록_고름_뒤_오감도_노면공_안_켬(out) -> None:
|
||||
assert out["signPick"]["form"] == "sign"
|
||||
after = out["signAfter"]
|
||||
assert after["form"] != "pave"
|
||||
assert after["form"] == "sign" # 목록 고름도 기록 — 오감 뒤 그 폼(231-2)
|
||||
assert after["paveLayer"] is None
|
||||
assert after["span"] is None
|
||||
assert after["span"] != "pave"
|
||||
assert after["card"] == 120
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""231-2 목록 고름도 늘 고름 기록 — 조사 AD 2안.
|
||||
|
||||
까닭: B06 목록 고름은 노면공일 때만 고름 한 칸에 적고 그 밖은 카드 리스너에 맡겼음 → 같은 카드 안 구조물을
|
||||
목록으로 고르면 리스너가 안 돌아 기록이 「측점만」 그대로 → 오감 · 새로 고침 뒤 그 폼이 사라짐.
|
||||
고침: 목록 · 알약 · 형상 고름은 늘 그 구조물 id 를 적음 · 측점 고름(카드 · 다시 세움)이 연 것은 측점만(189-1).
|
||||
B05 목록은 원래 늘 적음(`rememberPick(…, structure_id)`). 헬퍼 = `helper_231_1_pave_reload.cjs`.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
import pytest
|
||||
|
||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
ROOT = os.path.abspath(os.path.join(HERE, "..", ".."))
|
||||
|
||||
pytestmark = pytest.mark.skipif(
|
||||
not os.path.isdir(os.path.join(ROOT, "config", "node_modules")),
|
||||
reason="프론트엔드 의존성 미설치",
|
||||
)
|
||||
|
||||
|
||||
def _read(*parts: str) -> str:
|
||||
with open(os.path.join(ROOT, *parts), encoding="utf-8") as handle:
|
||||
return handle.read()
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def out() -> dict:
|
||||
proc = subprocess.run( # noqa: S603 — 고정 실행 파일
|
||||
["node", os.path.join(HERE, "helper_231_1_pave_reload.cjs")],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
timeout=60,
|
||||
)
|
||||
assert proc.returncode == 0, proc.stderr
|
||||
return json.loads(proc.stdout)
|
||||
|
||||
|
||||
def test_카드_120_뒤_목록_관_오감_새로고침_관_폼(out) -> None:
|
||||
for key in ("listPipe", "listPipeTrip", "listPipeF5"):
|
||||
got = out[key]
|
||||
assert got["form"] == "pipe-80.17", key
|
||||
assert got["card"] == 80.17, key
|
||||
assert got["paveLayer"] is None, key
|
||||
|
||||
|
||||
def test_같은_카드_목록_표지는_기록되고_오감_새로고침_뒤_그대로(out) -> None:
|
||||
sign = {"form": "sign", "paveLayer": None, "span": "sign", "card": 120, "sid": "sign"}
|
||||
assert out["listSign"] == sign
|
||||
assert out["listSignTrip"] == sign
|
||||
assert out["listSignF5"] == sign
|
||||
|
||||
|
||||
def test_목록_옹벽은_기준_카드_오감_뒤_그대로(out) -> None:
|
||||
wall = {"form": "wall", "paveLayer": None, "span": "wall", "card": 100, "sid": "wall"}
|
||||
assert out["listWall"] == wall
|
||||
assert out["listWallTrip"] == wall
|
||||
|
||||
|
||||
def test_목록_노면공은_새로고침_뒤도_범위_그대로(out) -> None:
|
||||
assert out["listPaveF5"] == {
|
||||
"form": "pave",
|
||||
"paveLayer": "pave",
|
||||
"span": "pave",
|
||||
"card": None,
|
||||
"sid": "pave",
|
||||
}
|
||||
|
||||
|
||||
def test_측점_고름이_연_것은_측점만(out) -> None:
|
||||
assert out["wallCard"]["sid"] is None # 카드 하나(189-1)
|
||||
assert out["wallAfter"]["sid"] is None # 다시 세움도
|
||||
assert out["cardAfter"]["sid"] is None
|
||||
|
||||
|
||||
def test_배선() -> None:
|
||||
panel = _read("B06_Section", "B06_Section_UI_Page_Structures_Panel.ts")
|
||||
assert 'if (!openingAtStation) selectDesign(deps.projectId, at, { from: "b06" });' in panel
|
||||
assert "if (pave) selectDesign(" not in panel
|
||||
profile = _read("A00_Common", "design", "design_view_profile.ts")
|
||||
# B05 목록은 원래 늘 그 구조물 id 를 적음
|
||||
assert "rememberPick(structureAnchorM(structure), structure.structure_id ?? null)" in profile
|
||||
Reference in New Issue
Block a user