refactor(b06): 구조물 패널 선택 배선 떼기 — wireStructureSelection 새 파일(152-1)
- B06_Section_UI_Page_Structures_Panel.ts 699 → 540줄 · 동작 그대로 - 선택 배선 = B06_Section_UI_Page_Structures_Selection.ts - 문자열 시험 3개 새 파일 읽기로 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F3mdb91125mPoC6tpsQx4P
This commit is contained in:
@@ -53,11 +53,11 @@ import {
|
||||
rememberRockBoundaryDefault,
|
||||
type StandardPanelController,
|
||||
} from "../../B06_Section/B06_Section_UI_Standard_Panel";
|
||||
import { createB06StructuresPanel } from "../../B06_Section/B06_Section_UI_Page_Structures_Panel";
|
||||
import {
|
||||
createB06StructuresPanel,
|
||||
isWallSelecting,
|
||||
wireStructureSelection,
|
||||
} from "../../B06_Section/B06_Section_UI_Page_Structures_Panel";
|
||||
} from "../../B06_Section/B06_Section_UI_Page_Structures_Selection";
|
||||
import "../../B06_Section/B06_Section_UI_Style.css";
|
||||
import "../../B06_Section/B06_Section_UI_Style_Cross.css";
|
||||
import "../../B06_Section/B06_Section_UI_Style_Cross_Controls.css";
|
||||
|
||||
@@ -54,8 +54,6 @@ import {
|
||||
setAdjustSideSlots,
|
||||
} from "./B06_Section_UI_Adjust_Dock";
|
||||
import type { SectionDetailResponse } from "./B06_Section_Api_Fetch";
|
||||
import type { StationControls } from "./B06_Section_UI_Page_Station_Controls";
|
||||
import type { RevetPick } from "./B06_Section_UI_Cross_Culvert";
|
||||
import { withSpecDefaults } from "./B06_Section_UI_Page_Structures_Spec";
|
||||
|
||||
const PIPE_ADD_GUIDE = "계곡 통과 시설을 넣고 빼려면 프로젝트를 먼저 여세요.";
|
||||
@@ -540,160 +538,3 @@ export function createB06StructuresPanel(deps: B06StructuresPanelDeps): B06Struc
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 횡단도 선택 → 좌측 폼 연동 배선. 벽(기슭막이)·세월교·BOX 선택이 일어나면 그
|
||||
* 구조물의 **소유 측점** 시설을 좌측 폼에 올린다(2026-08-29 일원화 3단계).
|
||||
* 제어 객체의 select를 감싸기만 한다 — 조작·저장 경로는 그대로다.
|
||||
*/
|
||||
/** 지금 처리 중인 선택이 **도면에서 벽·구체를 찍은 것**인가 — 카드 선택 리스너가
|
||||
* 이 값으로 "카드만 고른 경우"를 가려낸다(2026-08-29 사용자: 측점 선택 때 구조물이
|
||||
* 자동으로 골라지면 안 된다). 같은 턴에서만 참이다. */
|
||||
let wallSelecting = false;
|
||||
|
||||
export function isWallSelecting(): boolean {
|
||||
return wallSelecting;
|
||||
}
|
||||
|
||||
function markWallSelecting(): void {
|
||||
wallSelecting = true;
|
||||
queueMicrotask(() => {
|
||||
wallSelecting = false;
|
||||
});
|
||||
}
|
||||
|
||||
export function wireStructureSelection(
|
||||
stationControls: StationControls,
|
||||
detail: () => SectionDetailResponse | null,
|
||||
panel: B06StructuresPanel,
|
||||
/** 고른 부재를 세션에 남긴다(2026-09-04). 해제(null)는 부르지 않는다 — 조정창 닫기가
|
||||
* 카드(측점) 선택까지 지우면 안 된다. 측점 해제는 카드 선택 리스너가 따로 적는다. */
|
||||
remember?: (chainageM: number, key: string) => void,
|
||||
/** 폼에서 고른 벽을 카드 조정창에도 세움(54-30 · 목록 넘김 `applyStructurePick` 과 같은 차례). */
|
||||
refreshCard?: (chainageM: number) => void,
|
||||
/** 폼에 올린 시설로 보기를 옮김 — 목록에서 고른 길(54-47). */
|
||||
reveal?: (chainageM: number) => void,
|
||||
): { syncInletStructure: () => void } {
|
||||
const ownerChainageOf = (chainageM: number): number => {
|
||||
const sectionAt = detail()?.cross_sections.find(
|
||||
(entry) => Math.abs(entry.chainage_m - chainageM) < 0.01,
|
||||
);
|
||||
return (sectionAt && stationControls.structureSpan.ownerOf(sectionAt)?.chainage_m) ?? chainageM;
|
||||
};
|
||||
|
||||
// 유입구 "구조" ↔ B06 유입측 형식 — 폼에서 고르면 조정값에 반영하고, 시설을 폼에
|
||||
// 올릴 때는 조정값을 폼으로 되읽는다(2026-08-29 지시 5 병합).
|
||||
const sectionAt = (chainageM: number) =>
|
||||
detail()?.cross_sections.find((entry) => Math.abs(entry.chainage_m - chainageM) < 0.01);
|
||||
panel.facility.onInletStructureChange((value) => {
|
||||
const chainageM = panel.currentChainage();
|
||||
if (chainageM === null) return;
|
||||
stationControls.inletStructure.set(chainageM, value);
|
||||
});
|
||||
/** 폼에 올라온 시설의 유입측 형식을 폼 드롭다운에 되싣는다. */
|
||||
const syncInletStructure = (): void => {
|
||||
const chainageM = panel.currentChainage();
|
||||
const target = chainageM === null ? undefined : sectionAt(chainageM);
|
||||
if (target) panel.facility.setInletStructure(stationControls.inletStructure.valueFor(target));
|
||||
};
|
||||
|
||||
const origRevet = stationControls.revetOffset.select;
|
||||
stationControls.revetOffset.select = (chainageM, key) => {
|
||||
// 다른 카드 부재를 고르는 중에 옛 카드가 제 선택을 푸는 것 — 폼 · 선택 칸은 새 것 몫(53-1)
|
||||
const nested = wallSelecting;
|
||||
// 푸는 것은 고름이 아님 — 표시를 켜면 뒤이은 카드 고름이 선택 칸에 안 적힘(53-1)
|
||||
if (key) markWallSelecting();
|
||||
origRevet(chainageM, key);
|
||||
if (key) remember?.(ownerChainageOf(chainageM), key);
|
||||
if (key) panel.showAtChainage(ownerChainageOf(chainageM));
|
||||
else if (!nested) {
|
||||
remember?.(ownerChainageOf(chainageM), ""); // 푼 부재가 B05 ↔ B06 오갈 때 다시 안 열림
|
||||
panel.releasePipe();
|
||||
}
|
||||
if (key) syncInletStructure();
|
||||
// 폼이 이 시설로 갈아 끼워진 뒤에 이식을 다시 돌린다 — 목적지 칸이 그제야 선다.
|
||||
refreshAdjustSlots();
|
||||
};
|
||||
|
||||
// 관 상자 칸을 고치거나 고르면 그 부분을 고름 — 횡단에서 누른 것과 같은 길(54-30)
|
||||
const keyOf = (box: HTMLElement): RevetPick | null => {
|
||||
const id = box.dataset.specContainer;
|
||||
if (id === "inlet" || id === "outlet" || id === "pipe") return id;
|
||||
return id === "soil_add" ? `extra${Number(box.dataset.specIndex)}` : null;
|
||||
};
|
||||
const pickBox = (box: HTMLElement): void => {
|
||||
const chainageM = panel.currentChainage();
|
||||
const target = chainageM === null ? undefined : sectionAt(chainageM);
|
||||
const key = keyOf(box);
|
||||
if (!key || !target?.culvert || stationControls.revetOffset.highlightFor(target) === key)
|
||||
return;
|
||||
stationControls.revetOffset.select(target.chainage_m, key);
|
||||
refreshCard?.(target.chainage_m);
|
||||
};
|
||||
// 그 측점 카드 · 알약으로 감(목록에서 고른 길 · 54-47) — 같은 칸을 잇달아 고치면 한 번만(다시 그려도 칸 이름으로)
|
||||
const fieldOf = (el: HTMLElement): string => {
|
||||
const box = el.closest<HTMLElement>("fieldset[data-spec-container]");
|
||||
const item = el.closest<HTMLElement>("[data-spec-item]")?.dataset.specItem;
|
||||
return `${box?.dataset.specContainer}:${box?.dataset.specIndex}:${item}`;
|
||||
};
|
||||
let revealed: string | null = null;
|
||||
const revealAt = (chainageM: number, field: string | null): void => {
|
||||
if (field && field === revealed) return;
|
||||
revealed = field;
|
||||
reveal?.(chainageM);
|
||||
};
|
||||
panel.root.addEventListener("focusin", (event) => {
|
||||
if (fieldOf(event.target as HTMLElement) !== revealed) revealed = null;
|
||||
});
|
||||
panel.root.addEventListener("change", ({ target: el }) => {
|
||||
const box = (el as HTMLElement).closest<HTMLElement>("fieldset[data-spec-container]");
|
||||
const chainageM = panel.currentChainage();
|
||||
if (!box || chainageM === null) return;
|
||||
revealAt(chainageM, fieldOf(el as HTMLElement));
|
||||
// 단 수 칸은 고른 단을 지킴(단 수 바꿈 뒤 강조 유지) — 새 단은 다시 그린 뒤 아래에서 고름
|
||||
if (!(el as HTMLElement).closest('[data-spec-item="outlet.tiers"]')) pickBox(box);
|
||||
});
|
||||
// 상자가 새로 서면(단 늘림 · [추가]) 그 상자를 고름 — 같은 시설을 다시 그린 때만
|
||||
let painted: { chainageM: number | null; keys: Set<string> } | null = null;
|
||||
panel.root.addEventListener("specpaint", () => {
|
||||
const chainageM = panel.currentChainage();
|
||||
const boxes = [...panel.root.querySelectorAll<HTMLElement>("fieldset[data-spec-container]")];
|
||||
const before = painted?.chainageM === chainageM ? painted.keys : null;
|
||||
painted = { chainageM, keys: new Set(boxes.map(fieldOf)) };
|
||||
const born = before ? boxes.filter((box) => !before.has(fieldOf(box))).at(-1) : undefined;
|
||||
if (!born || chainageM === null) return;
|
||||
revealAt(chainageM, null);
|
||||
pickBox(born);
|
||||
});
|
||||
|
||||
const origFord = stationControls.ford.select;
|
||||
stationControls.ford.select = (chainageM, role) => {
|
||||
const nested = wallSelecting;
|
||||
if (role) markWallSelecting();
|
||||
origFord(chainageM, role);
|
||||
if (role) remember?.(chainageM, role);
|
||||
if (role) panel.showAtChainage(chainageM);
|
||||
else if (!nested) {
|
||||
remember?.(chainageM, "");
|
||||
panel.releasePipe();
|
||||
}
|
||||
// 폼이 이 시설로 갈아 끼워진 뒤에 이식을 다시 돌린다 — 날개벽 칸이 그제야 선다
|
||||
// (배관 기슭막이와 같은 순서, 2026-08-30 사용자 지시 1).
|
||||
refreshAdjustSlots();
|
||||
};
|
||||
const origBox = stationControls.box.select;
|
||||
stationControls.box.select = (chainageM, role) => {
|
||||
const nested = wallSelecting;
|
||||
if (role) markWallSelecting();
|
||||
origBox(chainageM, role);
|
||||
if (role) remember?.(chainageM, role);
|
||||
if (role) panel.showAtChainage(chainageM);
|
||||
else if (!nested) {
|
||||
remember?.(chainageM, "");
|
||||
panel.releasePipe();
|
||||
}
|
||||
// 폼이 이 시설로 갈아 끼워진 뒤에 이식을 다시 돌린다 — 날개벽 칸이 그제야 선다.
|
||||
refreshAdjustSlots();
|
||||
};
|
||||
return { syncInletStructure };
|
||||
}
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
/* =============================================================================
|
||||
* B06_Section_UI_Page_Structures_Selection.ts
|
||||
* 횡단도 선택 → 좌측 폼 연동 배선(`wireStructureSelection`) — `_Page_Structures_Panel.ts`
|
||||
* 에서 떼어 냄(700줄). 폼 · 목록 패널 자체는 그 파일 몫.
|
||||
* ========================================================================== */
|
||||
|
||||
import { refreshAdjustSlots } from "./B06_Section_UI_Adjust_Dock";
|
||||
import type { SectionDetailResponse } from "./B06_Section_Api_Fetch";
|
||||
import type { StationControls } from "./B06_Section_UI_Page_Station_Controls";
|
||||
import type { RevetPick } from "./B06_Section_UI_Cross_Culvert";
|
||||
import type { B06StructuresPanel } from "./B06_Section_UI_Page_Structures_Panel";
|
||||
|
||||
/**
|
||||
* 횡단도 선택 → 좌측 폼 연동 배선. 벽(기슭막이)·세월교·BOX 선택이 일어나면 그
|
||||
* 구조물의 **소유 측점** 시설을 좌측 폼에 올린다(2026-08-29 일원화 3단계).
|
||||
* 제어 객체의 select를 감싸기만 한다 — 조작·저장 경로는 그대로다.
|
||||
*/
|
||||
/** 지금 처리 중인 선택이 **도면에서 벽·구체를 찍은 것**인가 — 카드 선택 리스너가
|
||||
* 이 값으로 "카드만 고른 경우"를 가려낸다(2026-08-29 사용자: 측점 선택 때 구조물이
|
||||
* 자동으로 골라지면 안 된다). 같은 턴에서만 참이다. */
|
||||
let wallSelecting = false;
|
||||
|
||||
export function isWallSelecting(): boolean {
|
||||
return wallSelecting;
|
||||
}
|
||||
|
||||
function markWallSelecting(): void {
|
||||
wallSelecting = true;
|
||||
queueMicrotask(() => {
|
||||
wallSelecting = false;
|
||||
});
|
||||
}
|
||||
|
||||
export function wireStructureSelection(
|
||||
stationControls: StationControls,
|
||||
detail: () => SectionDetailResponse | null,
|
||||
panel: B06StructuresPanel,
|
||||
/** 고른 부재를 세션에 남긴다(2026-09-04). 해제(null)는 부르지 않는다 — 조정창 닫기가
|
||||
* 카드(측점) 선택까지 지우면 안 된다. 측점 해제는 카드 선택 리스너가 따로 적는다. */
|
||||
remember?: (chainageM: number, key: string) => void,
|
||||
/** 폼에서 고른 벽을 카드 조정창에도 세움(54-30 · 목록 넘김 `applyStructurePick` 과 같은 차례). */
|
||||
refreshCard?: (chainageM: number) => void,
|
||||
/** 폼에 올린 시설로 보기를 옮김 — 목록에서 고른 길(54-47). */
|
||||
reveal?: (chainageM: number) => void,
|
||||
): { syncInletStructure: () => void } {
|
||||
const ownerChainageOf = (chainageM: number): number => {
|
||||
const sectionAt = detail()?.cross_sections.find(
|
||||
(entry) => Math.abs(entry.chainage_m - chainageM) < 0.01,
|
||||
);
|
||||
return (sectionAt && stationControls.structureSpan.ownerOf(sectionAt)?.chainage_m) ?? chainageM;
|
||||
};
|
||||
|
||||
// 유입구 "구조" ↔ B06 유입측 형식 — 폼에서 고르면 조정값에 반영하고, 시설을 폼에
|
||||
// 올릴 때는 조정값을 폼으로 되읽는다(2026-08-29 지시 5 병합).
|
||||
const sectionAt = (chainageM: number) =>
|
||||
detail()?.cross_sections.find((entry) => Math.abs(entry.chainage_m - chainageM) < 0.01);
|
||||
panel.facility.onInletStructureChange((value) => {
|
||||
const chainageM = panel.currentChainage();
|
||||
if (chainageM === null) return;
|
||||
stationControls.inletStructure.set(chainageM, value);
|
||||
});
|
||||
/** 폼에 올라온 시설의 유입측 형식을 폼 드롭다운에 되싣는다. */
|
||||
const syncInletStructure = (): void => {
|
||||
const chainageM = panel.currentChainage();
|
||||
const target = chainageM === null ? undefined : sectionAt(chainageM);
|
||||
if (target) panel.facility.setInletStructure(stationControls.inletStructure.valueFor(target));
|
||||
};
|
||||
|
||||
const origRevet = stationControls.revetOffset.select;
|
||||
stationControls.revetOffset.select = (chainageM, key) => {
|
||||
// 다른 카드 부재를 고르는 중에 옛 카드가 제 선택을 푸는 것 — 폼 · 선택 칸은 새 것 몫(53-1)
|
||||
const nested = wallSelecting;
|
||||
// 푸는 것은 고름이 아님 — 표시를 켜면 뒤이은 카드 고름이 선택 칸에 안 적힘(53-1)
|
||||
if (key) markWallSelecting();
|
||||
origRevet(chainageM, key);
|
||||
if (key) remember?.(ownerChainageOf(chainageM), key);
|
||||
if (key) panel.showAtChainage(ownerChainageOf(chainageM));
|
||||
else if (!nested) {
|
||||
remember?.(ownerChainageOf(chainageM), ""); // 푼 부재가 B05 ↔ B06 오갈 때 다시 안 열림
|
||||
panel.releasePipe();
|
||||
}
|
||||
if (key) syncInletStructure();
|
||||
// 폼이 이 시설로 갈아 끼워진 뒤에 이식을 다시 돌린다 — 목적지 칸이 그제야 선다.
|
||||
refreshAdjustSlots();
|
||||
};
|
||||
|
||||
// 관 상자 칸을 고치거나 고르면 그 부분을 고름 — 횡단에서 누른 것과 같은 길(54-30)
|
||||
const keyOf = (box: HTMLElement): RevetPick | null => {
|
||||
const id = box.dataset.specContainer;
|
||||
if (id === "inlet" || id === "outlet" || id === "pipe") return id;
|
||||
return id === "soil_add" ? `extra${Number(box.dataset.specIndex)}` : null;
|
||||
};
|
||||
const pickBox = (box: HTMLElement): void => {
|
||||
const chainageM = panel.currentChainage();
|
||||
const target = chainageM === null ? undefined : sectionAt(chainageM);
|
||||
const key = keyOf(box);
|
||||
if (!key || !target?.culvert || stationControls.revetOffset.highlightFor(target) === key)
|
||||
return;
|
||||
stationControls.revetOffset.select(target.chainage_m, key);
|
||||
refreshCard?.(target.chainage_m);
|
||||
};
|
||||
// 그 측점 카드 · 알약으로 감(목록에서 고른 길 · 54-47) — 같은 칸을 잇달아 고치면 한 번만(다시 그려도 칸 이름으로)
|
||||
const fieldOf = (el: HTMLElement): string => {
|
||||
const box = el.closest<HTMLElement>("fieldset[data-spec-container]");
|
||||
const item = el.closest<HTMLElement>("[data-spec-item]")?.dataset.specItem;
|
||||
return `${box?.dataset.specContainer}:${box?.dataset.specIndex}:${item}`;
|
||||
};
|
||||
let revealed: string | null = null;
|
||||
const revealAt = (chainageM: number, field: string | null): void => {
|
||||
if (field && field === revealed) return;
|
||||
revealed = field;
|
||||
reveal?.(chainageM);
|
||||
};
|
||||
panel.root.addEventListener("focusin", (event) => {
|
||||
if (fieldOf(event.target as HTMLElement) !== revealed) revealed = null;
|
||||
});
|
||||
panel.root.addEventListener("change", ({ target: el }) => {
|
||||
const box = (el as HTMLElement).closest<HTMLElement>("fieldset[data-spec-container]");
|
||||
const chainageM = panel.currentChainage();
|
||||
if (!box || chainageM === null) return;
|
||||
revealAt(chainageM, fieldOf(el as HTMLElement));
|
||||
// 단 수 칸은 고른 단을 지킴(단 수 바꿈 뒤 강조 유지) — 새 단은 다시 그린 뒤 아래에서 고름
|
||||
if (!(el as HTMLElement).closest('[data-spec-item="outlet.tiers"]')) pickBox(box);
|
||||
});
|
||||
// 상자가 새로 서면(단 늘림 · [추가]) 그 상자를 고름 — 같은 시설을 다시 그린 때만
|
||||
let painted: { chainageM: number | null; keys: Set<string> } | null = null;
|
||||
panel.root.addEventListener("specpaint", () => {
|
||||
const chainageM = panel.currentChainage();
|
||||
const boxes = [...panel.root.querySelectorAll<HTMLElement>("fieldset[data-spec-container]")];
|
||||
const before = painted?.chainageM === chainageM ? painted.keys : null;
|
||||
painted = { chainageM, keys: new Set(boxes.map(fieldOf)) };
|
||||
const born = before ? boxes.filter((box) => !before.has(fieldOf(box))).at(-1) : undefined;
|
||||
if (!born || chainageM === null) return;
|
||||
revealAt(chainageM, null);
|
||||
pickBox(born);
|
||||
});
|
||||
|
||||
const origFord = stationControls.ford.select;
|
||||
stationControls.ford.select = (chainageM, role) => {
|
||||
const nested = wallSelecting;
|
||||
if (role) markWallSelecting();
|
||||
origFord(chainageM, role);
|
||||
if (role) remember?.(chainageM, role);
|
||||
if (role) panel.showAtChainage(chainageM);
|
||||
else if (!nested) {
|
||||
remember?.(chainageM, "");
|
||||
panel.releasePipe();
|
||||
}
|
||||
// 폼이 이 시설로 갈아 끼워진 뒤에 이식을 다시 돌린다 — 날개벽 칸이 그제야 선다
|
||||
// (배관 기슭막이와 같은 순서, 2026-08-30 사용자 지시 1).
|
||||
refreshAdjustSlots();
|
||||
};
|
||||
const origBox = stationControls.box.select;
|
||||
stationControls.box.select = (chainageM, role) => {
|
||||
const nested = wallSelecting;
|
||||
if (role) markWallSelecting();
|
||||
origBox(chainageM, role);
|
||||
if (role) remember?.(chainageM, role);
|
||||
if (role) panel.showAtChainage(chainageM);
|
||||
else if (!nested) {
|
||||
remember?.(chainageM, "");
|
||||
panel.releasePipe();
|
||||
}
|
||||
// 폼이 이 시설로 갈아 끼워진 뒤에 이식을 다시 돌린다 — 날개벽 칸이 그제야 선다.
|
||||
refreshAdjustSlots();
|
||||
};
|
||||
return { syncInletStructure };
|
||||
}
|
||||
@@ -97,7 +97,7 @@ def test_좌측_관_상자_강조_스크롤() -> None:
|
||||
assert 'body.classList.add("is-active");' in dock
|
||||
assert 'if (scroll) body.scrollIntoView({ block: "nearest" });' in dock
|
||||
# 관 상자 칸을 고치면 관을 고름 — 횡단에서 누른 것과 같은 길
|
||||
page = _src("B06_Section/B06_Section_UI_Page_Structures_Panel.ts")
|
||||
page = _src("B06_Section/B06_Section_UI_Page_Structures_Selection.ts")
|
||||
assert 'if (id === "inlet" || id === "outlet" || id === "pipe") return id;' in page
|
||||
css = _src("B06_Section/B06_Section_UI_Style_Cross_Areas.css")
|
||||
assert ".b06-chart__culvert-pipe.is-active {" in css
|
||||
|
||||
@@ -49,7 +49,7 @@ def test_폼을_다시_그리면_강조_다시() -> None:
|
||||
|
||||
def test_상자_칸을_고치면_그_부분을_고름() -> None:
|
||||
"""54-30 — 칸 고침 = 횡단에서 그 벽을 누른 것과 같은 길 · 단 수 칸은 고른 단을 지킴."""
|
||||
page = _src("B06_Section/B06_Section_UI_Page_Structures_Panel.ts")
|
||||
page = _src("B06_Section/B06_Section_UI_Page_Structures_Selection.ts")
|
||||
assert '[data-spec-item="outlet.tiers"]' in page
|
||||
assert "`extra${Number(box.dataset.specIndex)}`" in page
|
||||
assert "refreshCard?.(target.chainage_m);" in page
|
||||
|
||||
@@ -61,6 +61,7 @@ def test_거리_정의는_한_곳뿐이고_옛_0_05는_없다():
|
||||
("design_view_cross.ts", "A00_Common/design"),
|
||||
("B05_Profile_UI_Selection.ts", "B05_Profile"),
|
||||
("B06_Section_UI_Page_Structures_Panel.ts", "B06_Section"),
|
||||
("B06_Section_UI_Page_Structures_Selection.ts", "B06_Section"),
|
||||
("B06_Section_UI_Page_Structure_Pick.ts", "B06_Section"),
|
||||
("B05_Profile_UI_Structure_Pick_Session.ts", "B05_Profile"),
|
||||
):
|
||||
@@ -187,7 +188,9 @@ def test_B05_되살리기_같은_측점_관보다_구조물_id가_먼저(out):
|
||||
|
||||
# ── 배선 ───────────────────────────────────────────────────────────────
|
||||
def test_횡단도_벽_구체_눌러도_폼은_같은_길_하나():
|
||||
panel = _read("B06_Section", "B06_Section_UI_Page_Structures_Panel.ts")
|
||||
panel = _read("B06_Section", "B06_Section_UI_Page_Structures_Panel.ts") + _read(
|
||||
"B06_Section", "B06_Section_UI_Page_Structures_Selection.ts"
|
||||
)
|
||||
assert "showPipeAt" not in panel # 관 전용 길을 없앰
|
||||
assert panel.count("panel.showAtChainage(") == 3 # 기슭막이 · 세월교 · BOX
|
||||
assert panel.count("panel.releasePipe()") == 3 # 벽 선택을 풀 때는 관 폼만 비움
|
||||
|
||||
Reference in New Issue
Block a user