feat(종단보기): 345-3 노선 편집 → 종단 보기 가운데 위 본문(페이지 수명) · 종단도 판 흐름 배치 · [노선 반영] 뒤 새로고침 없이 다시 세움 · Ctrl+Z · Y 는 마지막에 만진 판 · 「계획노선」 칸 · 편집 단추 지움
- mountRouteEditor(parent, host, …) — 덮개 · 전체 화면 · 닫기 걷음 · 이력 · 키 듣기 = host 보임 · 숨김 · 떠남 · 칸 크기 = ResizeObserver - [취소] → [반영 전으로](이력 처음으로 · 되돌리기로 다시 살림) · [확인] → [노선 반영] · 대기 막 = 화면 전체(노선 재탐색) - [노선 반영] 끝 = 초안 · 결과 · 옛 노선 · 종단면 캐시 비움 → remountRoute(location.reload 없앰) - R 라벨 = 칸 안 절대 위치 · 오른쪽 횡단 미리보기 = 접는 칸 · [3D] 단추 = 평면 머리 도구줄 - 새 _RouteEdit_UndoOwner(누른 판 기억) · 종단도 Ctrl+Z 줄이 물음 - 시험: test_345_3_route_body 5 · 칸 · 겉틀 시험 고쳐 씀 · 관련 411 통과(옛 3 실패 그대로) · typecheck 통과 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VmC34fsxxbweEG3RUjs3Mn
This commit is contained in:
@@ -176,9 +176,6 @@ const panel = design.createDesignPanel(
|
||||
parts: {
|
||||
structures: { root: node("section"), listRoot: node() },
|
||||
settings: { nodes: [text("a")] },
|
||||
route: {
|
||||
plannedRouteButton: text("plan"),
|
||||
},
|
||||
crossView: { row: text("cross-row") },
|
||||
standardSlot: text("std"),
|
||||
},
|
||||
@@ -189,7 +186,7 @@ const panel = design.createDesignPanel(
|
||||
const byTitle = (title) =>
|
||||
panel.root.querySelectorAll(".ui-collapsible").find((s) => titleOf(s) === title);
|
||||
out.profileFirst = folds(panel.root);
|
||||
const route = byTitle("계획노선");
|
||||
const route = byTitle("페이지 설정"); // 345-3 계획노선 칸 지움 — 접힌 채 서는 칸
|
||||
press(panel.root, route); // 사용자가 폄(공용 attachCollapsible)
|
||||
panel.setView("cross");
|
||||
out.crossFirst = folds(panel.root);
|
||||
@@ -197,7 +194,7 @@ press(panel.root, byTitle("B06_View_Title"));
|
||||
panel.setView("profile");
|
||||
panel.setView("cross");
|
||||
out.afterRedraw = folds(panel.root);
|
||||
out.sameRouteNode = byTitle("계획노선") === route;
|
||||
out.sameRouteNode = byTitle("페이지 설정") === route;
|
||||
|
||||
// ── B07 도면 목록 ─────────────────────────────────────────────────────────────
|
||||
const b07 = loadTs(path.join(ROOT, "B07_DesignDetail", "B07_DesignDetail_UI_Panels.ts"));
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/* 345-3 Ctrl+Z · Y 한 판만 헬퍼 — `_RouteEdit_History`(평면 이력 단추 · 단축키)와 `_RouteEdit_UndoOwner` 를
|
||||
* 트랜스파일해 가짜 창(window)에서 돌림. 종단도 쪽 듣는 자리는 `_Profile_Panel_Tools` 와 같은 꼴
|
||||
* (`undoOwner() === "plan"` 이면 안 받음)로 흉내. 결과는 JSON 한 벌(표준출력).
|
||||
*/
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript"));
|
||||
|
||||
const ROOT = path.join(__dirname, "..", "..");
|
||||
const listeners = {};
|
||||
global.window = {
|
||||
addEventListener: (type, fn) => (listeners[type] ??= new Set()).add(fn),
|
||||
removeEventListener: (type, fn) => listeners[type]?.delete(fn),
|
||||
};
|
||||
const fire = (type, event) => [...(listeners[type] ?? [])].forEach((fn) => fn(event));
|
||||
|
||||
const cache = new Map();
|
||||
function loadTs(file) {
|
||||
const full = path.resolve(file);
|
||||
if (cache.has(full)) return cache.get(full);
|
||||
const js = ts.transpileModule(fs.readFileSync(full, "utf8"), {
|
||||
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 },
|
||||
}).outputText;
|
||||
const box = { exports: {} };
|
||||
cache.set(full, box.exports);
|
||||
const localRequire = (request) =>
|
||||
request.startsWith(".")
|
||||
? loadTs(`${path.resolve(path.dirname(full), request)}.ts`)
|
||||
: require(request);
|
||||
new Function("exports", "module", "require", js)(box.exports, box, localRequire);
|
||||
return box.exports;
|
||||
}
|
||||
|
||||
const page = path.join(ROOT, "B05_Profile");
|
||||
const { bindHistoryControls } = loadTs(path.join(page, "B05_Profile_UI_RouteEdit_History.ts"));
|
||||
const { undoOwner } = loadTs(path.join(page, "B05_Profile_UI_RouteEdit_UndoOwner.ts"));
|
||||
|
||||
const button = () => ({ disabled: false, addEventListener: () => undefined });
|
||||
const buttons = { '[data-act="undo"]': button(), '[data-act="redo"]': button() };
|
||||
const overlay = { querySelector: (sel) => buttons[sel] };
|
||||
const plan = [];
|
||||
const history = {
|
||||
undo: () => (plan.push("undo"), { tag: "u" }),
|
||||
redo: () => (plan.push("redo"), { tag: "r" }),
|
||||
canUndo: () => true,
|
||||
canRedo: () => true,
|
||||
};
|
||||
const controls = bindHistoryControls({
|
||||
overlay,
|
||||
getHistory: () => history,
|
||||
restore: () => undefined,
|
||||
});
|
||||
|
||||
// 종단도 듣는 자리 흉내 — `_Profile_Panel_Tools` 의 Ctrl+Z 줄과 같은 거름.
|
||||
const profile = [];
|
||||
window.addEventListener("keydown", (event) => {
|
||||
if (!(event.ctrlKey && event.key === "z")) return;
|
||||
if (undoOwner() === "plan") return;
|
||||
profile.push(event.shiftKey ? "redo" : "undo");
|
||||
});
|
||||
|
||||
const key = (k, shift = false) =>
|
||||
fire("keydown", { ctrlKey: true, key: k, code: "", shiftKey: shift, preventDefault() {} });
|
||||
const press = (cls) =>
|
||||
fire("pointerdown", { target: { closest: (sel) => (sel === `.${cls}` ? {} : null) } });
|
||||
const snap = () => ({ plan: [...plan], profile: [...profile], owner: undoOwner() });
|
||||
|
||||
const out = {};
|
||||
key("z"); // 듣기 전 — 종단도만
|
||||
out.beforeListen = snap();
|
||||
controls.listen(true);
|
||||
key("z"); // 아직 아무 판도 안 만짐 — 종단도
|
||||
out.untouched = snap();
|
||||
press("b05-routeedit");
|
||||
key("z");
|
||||
key("y");
|
||||
out.afterPlanPress = snap();
|
||||
press("b05-route-profile");
|
||||
key("z");
|
||||
out.afterProfilePress = snap();
|
||||
press("b05-routeedit");
|
||||
controls.listen(false); // 보기 숨김 — 평면 이력은 안 들음
|
||||
key("z");
|
||||
out.hidden = snap();
|
||||
controls.listen(true);
|
||||
key("z", true); // 다시 보임 · 마지막에 만진 판 = 평면 · Shift+Z = 다시하기
|
||||
out.shown = snap();
|
||||
controls.dispose();
|
||||
key("z");
|
||||
out.disposed = snap();
|
||||
console.log(JSON.stringify(out));
|
||||
@@ -197,9 +197,6 @@ const built = panel.createDesignPanel(
|
||||
parts: {
|
||||
structures: sample(),
|
||||
settings: { nodes: [text("a"), text("b")] },
|
||||
route: {
|
||||
plannedRouteButton: text("plan"),
|
||||
},
|
||||
crossView: { row: text("cross-row") },
|
||||
standardSlot: text("std"),
|
||||
},
|
||||
|
||||
@@ -42,15 +42,16 @@ def out():
|
||||
def test_B05_B06_첫_그림_접힘(out):
|
||||
assert out["profileFirst"] == {
|
||||
"페이지 설정": True,
|
||||
"계획노선": True,
|
||||
}
|
||||
assert out["crossFirst"]["B06_View_Title"] is True
|
||||
assert out["crossFirst"]["B06_Std_Title"] is True # 옛 기본 접힘 그대로
|
||||
|
||||
|
||||
def test_B05_B06_편_뒤_다시_그림_유지(out):
|
||||
assert out["crossFirst"]["계획노선"] is False # 편 것 → 보기 바꿔도 그대로
|
||||
assert out["afterRedraw"]["계획노선"] is False
|
||||
assert (
|
||||
out["crossFirst"]["페이지 설정"] is False
|
||||
) # 편 것 → 보기 바꿔도 그대로(345-3 계획노선 칸 지움)
|
||||
assert out["afterRedraw"]["페이지 설정"] is False
|
||||
assert out["afterRedraw"]["B06_View_Title"] is False
|
||||
assert out["sameRouteNode"] is True
|
||||
|
||||
|
||||
@@ -64,6 +64,6 @@ def test_배선_3D_상주_없음_죽은_길_지움():
|
||||
for gone in ("beginMoveSelected", "deleteSelected", "updateSelected", "panel.setSelected"):
|
||||
assert gone not in view
|
||||
assert "selected-point" not in _read("B05_Profile/B05_Profile_UI_Panel_Sections.ts")
|
||||
assert "selectedNodes" not in _read("B05_Profile/B05_Profile_UI_Panel_Route.ts")
|
||||
assert not (ROOT / "B05_Profile/B05_Profile_UI_Panel_Route.ts").exists() # 345-3 칸째 지움
|
||||
assert "beginMoveSelected" not in _read("B05_Profile/B05_Profile_UI_Viewer.ts")
|
||||
assert len(view.splitlines()) <= 700
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
"""345-3 노선 편집 → 종단 보기 가운데 위 본문 — Ctrl+Z · Y 는 마지막에 만진 판 하나 · 종단도 판 흐름 배치 ·
|
||||
왼쪽 「계획노선」 칸 · 편집 단추 지움 · [노선 반영] 뒤 새로고침 없이 다시 세움.
|
||||
|
||||
Ctrl+Z 몫은 Node 헬퍼 `helper_345_3_undo_owner.cjs` 가 진짜 `_RouteEdit_History` · `_UndoOwner` 로 돌림 ·
|
||||
배선 · CSS 는 글로 봄(화면 확인은 브레인).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
ROOT = HERE.parents[1]
|
||||
|
||||
|
||||
def _read(rel: str) -> str:
|
||||
return (ROOT / rel).read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def _block(css: str, selector: str) -> str:
|
||||
found = re.search(rf"^{re.escape(selector)} \{{([^}}]*)\}}", css, re.M)
|
||||
assert found, selector
|
||||
return found.group(1)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def out() -> dict:
|
||||
run = subprocess.run(
|
||||
["node", str(HERE / "helper_345_3_undo_owner.cjs")],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
check=True,
|
||||
)
|
||||
return json.loads(run.stdout)
|
||||
|
||||
|
||||
def test_Ctrl_Z_는_마지막에_만진_판_하나(out):
|
||||
assert out["beforeListen"] == {"plan": [], "profile": ["undo"], "owner": "profile"}
|
||||
assert out["untouched"]["plan"] == [] and out["untouched"]["profile"] == ["undo", "undo"]
|
||||
# 평면을 누른 뒤 — 평면만(종단도 안 움직임)
|
||||
assert out["afterPlanPress"]["plan"] == ["undo", "redo"]
|
||||
assert out["afterPlanPress"]["profile"] == ["undo", "undo"]
|
||||
# 종단 판을 누른 뒤 — 종단도만
|
||||
assert out["afterProfilePress"]["plan"] == ["undo", "redo"]
|
||||
assert out["afterProfilePress"]["profile"] == ["undo", "undo", "undo"]
|
||||
# 보기 숨김(평면 안 들음) — 평면을 마지막에 만졌어도 종단도가 받음
|
||||
assert out["hidden"]["owner"] == "profile"
|
||||
assert out["hidden"]["profile"] == ["undo", "undo", "undo", "undo"]
|
||||
# 다시 보임 — 평면 · Shift+Z = 다시하기
|
||||
assert out["shown"]["plan"] == ["undo", "redo", "redo"]
|
||||
assert out["shown"]["profile"] == out["hidden"]["profile"]
|
||||
# 떠남 — 평면 단축키 뗌
|
||||
assert out["disposed"]["plan"] == out["shown"]["plan"]
|
||||
|
||||
|
||||
def test_종단도_Ctrl_Z_줄이_평면을_묻는다():
|
||||
tools = _read("B05_Profile/B05_Profile_UI_Profile_Panel_Tools.ts")
|
||||
at = tools.index('if (isCtrlKey(event, "z")) {')
|
||||
assert 'if (undoOwner() === "plan") return;' in tools[at : at + 160]
|
||||
history = _read("B05_Profile/B05_Profile_UI_RouteEdit_History.ts")
|
||||
assert 'undoOwner() !== "plan"' in history
|
||||
assert (
|
||||
'window.addEventListener("keydown", onKey);\n\n return' not in history
|
||||
) # 만들 때 안 붙음
|
||||
|
||||
|
||||
def test_편집기는_본문_페이지_수명():
|
||||
view = _read("A00_Common/design/design_view_profile.ts")
|
||||
assert "mountRouteEditor(mainContent, host, activeProjectId, rebuildAfterReplan," in view
|
||||
assert "tools: [view3d.modal.button]," in view
|
||||
assert "openRouteEditModal" not in view and "location.reload()" not in view
|
||||
assert len(view.splitlines()) <= 700
|
||||
|
||||
|
||||
def test_종단도_판은_두_보기_모두_흐름():
|
||||
css = _read("A00_Common/design/design_page.css")
|
||||
rule = _block(css, ".design-page__main > .design-page__profile > .b05-route-profile")
|
||||
assert "position: relative;" in rule and "flex: none;" in rule
|
||||
assert '[data-view="cross"] > .design-page__profile > .b05-route-profile' not in css
|
||||
|
||||
|
||||
def test_계획노선_칸_편집_단추_지움():
|
||||
sections = _read("B05_Profile/B05_Profile_UI_Panel_Sections.ts")
|
||||
assert '"planned-route"' not in sections and "plannedRouteButton" not in sections
|
||||
panel = _read("B05_Profile/B05_Profile_UI_Panel.ts")
|
||||
assert "onEditPlannedRoute" not in panel and "createRoutePart" not in panel
|
||||
assert not (ROOT / "B05_Profile/B05_Profile_UI_Panel_Route.ts").exists()
|
||||
@@ -1,4 +1,10 @@
|
||||
"""계획노선 편집 겉틀 = 공용 모달 조각(PLAN 127-1) — 배경 · 제목줄은 공용 클래스, 닫기 규칙은 그대로."""
|
||||
"""계획노선 편집 겉틀 — 345-3 부터 모달이 아니라 종단 보기 가운데 위 본문(PLAN 127-1 의 공용 모달 조각은 걷음).
|
||||
|
||||
· 덮개(`ui-modal__backdrop`) · 전체 화면 · 닫기 단추 없음 · 부모를 받아 붙음(`document.body` 아님)
|
||||
· [취소] → [반영 전으로](이력 처음으로) · [확인] → [노선 반영] · 머리 끝 `tools` 자리([3D])
|
||||
· 오른쪽 횡단 미리보기 = 접는 칸 · 재계산 대기 막은 화면 전체(fixed) · R 라벨은 칸 안 절대 위치
|
||||
· 바깥 누름 · Esc 로 안 닫힘(모달 아님)
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -15,34 +21,54 @@ def _block(css: str, selector: str) -> str:
|
||||
return found.group(1)
|
||||
|
||||
|
||||
def test_겉틀은_공용_모달_조각():
|
||||
chrome = (PAGE / "B05_Profile_UI_RouteEdit_Chrome.ts").read_text(encoding="utf-8")
|
||||
assert 'import "@ui/ui_template_modal.css";' in chrome
|
||||
assert '"ui-modal__backdrop b05-routeedit"' in chrome
|
||||
assert '<div class="ui-modal__top b05-routeedit__head">' in chrome
|
||||
assert "<h3>계획노선 편집</h3>" in chrome
|
||||
assert "<strong>계획노선 편집</strong>" not in chrome
|
||||
def _read(name: str) -> str:
|
||||
return (PAGE / name).read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_겉틀은_본문_칸():
|
||||
chrome = _read("B05_Profile_UI_RouteEdit_Chrome.ts")
|
||||
assert "ui-modal" not in chrome
|
||||
assert "document.body.append" not in chrome
|
||||
assert "parent.append(overlay);" in chrome
|
||||
assert 'overlay.className = "b05-routeedit";' in chrome
|
||||
assert "b05-routeedit__close" not in chrome and 'data-slot="close"' not in chrome
|
||||
assert '"tools"' in chrome and "replaceWith(...tools)" in chrome
|
||||
assert ">반영 전으로</button>" in chrome and ">노선 반영</button>" in chrome
|
||||
assert ">취소</button>" not in chrome and ">확인</button>" not in chrome
|
||||
# 시험 · 배선이 집는 자리는 남김
|
||||
for hook in (
|
||||
'data-act="apply"',
|
||||
'data-act="cancel"',
|
||||
"b05-routeedit__close",
|
||||
"b05-routeedit__measure-close",
|
||||
):
|
||||
for hook in ('data-act="apply"', 'data-act="cancel"', "b05-routeedit__measure-close"):
|
||||
assert hook in chrome
|
||||
assert 'data-act="side-toggle"' in chrome and "is-collapsed" in chrome
|
||||
|
||||
|
||||
def test_겹치는_CSS는_공용에_맡김():
|
||||
css = (PAGE / "B05_Profile_UI_Style_RouteEdit.css").read_text(encoding="utf-8")
|
||||
overlay = _block(css, ".b05-routeedit")
|
||||
for prop in ("position:", "z-index:", "background:", "align-items:"):
|
||||
assert prop not in overlay
|
||||
head = _block(css, ".b05-routeedit__head")
|
||||
for prop in ("display:", "align-items:", "gap:"):
|
||||
assert prop not in head
|
||||
def test_CSS_덮개_걷음_대기막은_전체():
|
||||
css = _read("B05_Profile_UI_Style_RouteEdit.css")
|
||||
root = _block(css, ".b05-routeedit")
|
||||
assert "position: relative;" in root and "flex: 1 1 auto;" in root
|
||||
assert "z-index" not in root and "background" not in root
|
||||
busy = _block(css, ".b05-routeedit__busy")
|
||||
assert "position: fixed;" in busy and "z-index: var(--z-modal, 1000);" in busy
|
||||
label = _block(css, ".b05-routeedit__label")
|
||||
assert "position: absolute;" in label and "position: fixed" not in label
|
||||
assert "display: none;" in _block(
|
||||
css, ".b05-routeedit__side-wrap.is-collapsed > .b05-routeedit__side"
|
||||
)
|
||||
assert "@media (width < 1500px)" not in css # 접기는 단추로(처음만 폭으로)
|
||||
|
||||
|
||||
def test_바깥_누름_Esc_로_안_닫힘():
|
||||
main = (PAGE / "B05_Profile_UI_RouteEdit.ts").read_text(encoding="utf-8")
|
||||
assert "openModal" not in main
|
||||
assert "Escape" not in main
|
||||
def test_페이지_수명_닫기_없음():
|
||||
main = _read("B05_Profile_UI_RouteEdit.ts")
|
||||
assert "openModal" not in main and "Escape" not in main
|
||||
assert "openRouteEditModal" not in main
|
||||
assert "export async function mountRouteEditor(" in main
|
||||
assert 'window.addEventListener("resize"' not in main # 칸 크기는 ResizeObserver
|
||||
assert "new ResizeObserver(" in main
|
||||
assert "host.onDispose(dispose);" in main
|
||||
assert "historyControls.listen(host.visible());" in main
|
||||
assert "history?.reset();" in main # [반영 전으로]
|
||||
assert len(main.splitlines()) <= 700
|
||||
label = _read("B05_Profile_UI_RouteEdit_Label.ts")
|
||||
assert "document.body.append" not in label and "container.append(root);" in label
|
||||
assert "container: overlay," in main
|
||||
apply = _read("B05_Profile_UI_RouteEdit_Apply.ts")
|
||||
assert "close" not in apply.split("export function bindRouteApply", 1)[1]
|
||||
|
||||
@@ -98,13 +98,25 @@ def test_진행_단계_두_칸이_보기를_따라감():
|
||||
|
||||
|
||||
def test_초기화_계획노선_편집은_다시_세움():
|
||||
"""[초기화] · 계획노선 편집 [확인] = 새 초기값 — 옛 캐시를 다 버리고 페이지를 통째로 다시 읽는다(PLAN 77)."""
|
||||
"""[초기화] · [노선 반영](옛 계획노선 편집 [확인]) = 새 초기값 — 옛 캐시를 다 버리고 페이지를 통째로 다시 읽는다(PLAN 77)."""
|
||||
reset = _read("A00_Common/design/design_reset.ts")
|
||||
assert "clearDrafts(projectId);" in reset and "clearResults(projectId);" in reset
|
||||
assert "location.reload()" in reset
|
||||
assert "openRouteEditModal(activeProjectId, () => location.reload()" in _read(
|
||||
"A00_Common/design/design_view_profile.ts"
|
||||
)
|
||||
view = _read("A00_Common/design/design_view_profile.ts")
|
||||
assert "location.reload()" not in view # [노선 반영]은 새로고침 대신 다시 세움(345-3)
|
||||
rebuild = view[view.index("const rebuildAfterReplan") :]
|
||||
rebuild = rebuild[: rebuild.index("};")]
|
||||
for step in (
|
||||
"clearRouteLatestCache(activeProjectId);",
|
||||
"invalidateSectionDetail(activeProjectId);",
|
||||
"remountRoute(currentRoute());",
|
||||
):
|
||||
assert step in rebuild
|
||||
assert rebuild.index("invalidateSectionDetail") < rebuild.index("remountRoute(")
|
||||
assert "mountRouteEditor(mainContent, host, activeProjectId, rebuildAfterReplan," in view
|
||||
apply = _read("B05_Profile/B05_Profile_UI_RouteEdit_Apply.ts")
|
||||
assert apply.index("clearDrafts(projectId);") < apply.index("await params.onApplied();")
|
||||
assert "clearResults(projectId);" in apply
|
||||
|
||||
|
||||
def test_종단_보기_확정은_횡단_보기를_숨긴_채_세움():
|
||||
|
||||
@@ -59,9 +59,8 @@ def results():
|
||||
def test_보기를_오가도_좌측_패널_단추_구조물_배치는_같은_노드(results):
|
||||
assert results["sameNodes"] == {"cross": True, "back": True}
|
||||
# 보기마다 새로 만들지 않는다 — 칸은 처음 보일 때 한 번만 서고 뒤로는 숨김 · 보임만.
|
||||
assert (
|
||||
results["childCount"] == 1 + 3 + 2
|
||||
) # 아래 고정 영역 + 종단 칸 셋 + 횡단 칸 둘(345-2 선택 포인트 지움)
|
||||
# 아래 고정 영역 + 종단 칸 둘 + 횡단 칸 둘(345-2 선택 포인트 · 345-3 계획노선 칸 지움)
|
||||
assert results["childCount"] == 1 + 2 + 2
|
||||
|
||||
|
||||
def test_구조물_배치는_두_보기_모두_맨_위_같은_DOM(results):
|
||||
@@ -81,7 +80,6 @@ def test_보기마다_제_칸만_보인다(results):
|
||||
assert views["profile"]["shownTitles"] == [
|
||||
"구조물 배치",
|
||||
"페이지 설정",
|
||||
"계획노선",
|
||||
]
|
||||
assert views["cross"]["shownTitles"] == ["구조물 배치", "횡단 보기 설정", "표준 횡단면 설정"]
|
||||
assert views["back"]["shownTitles"] == views["profile"]["shownTitles"]
|
||||
|
||||
Reference in New Issue
Block a user