Merge remote-tracking branch 'origin/sub_laptop_2' into sub_laptop_5
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
/* 배수유역 관 보고(`B05_Profile_UI_Drainage_Report.ts`) 셈 단위검증 헬퍼 — TS 를 트랜스파일해 Node 로 돈다. */
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript"));
|
||||
|
||||
const file = path.join(__dirname, "..", "..", "B05_Profile", "B05_Profile_UI_Drainage_Report.ts");
|
||||
const js = ts.transpileModule(fs.readFileSync(file, "utf8"), {
|
||||
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 },
|
||||
}).outputText;
|
||||
const box = { exports: {} };
|
||||
new Function("exports", "module", "require", js)(box.exports, box, require);
|
||||
const { buildPipeReports } = box.exports;
|
||||
|
||||
const store = {
|
||||
get: (chainage) =>
|
||||
chainage === 100.5 ? { facility: "box_culvert", start_m: 95, end_m: 106, options: { h: 2 } } : null,
|
||||
};
|
||||
const basins = [
|
||||
{ chainage_m: 40, pipe_diameter_mm: 800, design_flow_m3s: 1.2, bridge_required: false },
|
||||
{ chainage_m: 100.5, pipe_diameter_mm: 1000, design_flow_m3s: 3.4, bridge_required: true },
|
||||
];
|
||||
const out = buildPipeReports(
|
||||
[
|
||||
{ chainage_m: 40.004, reason: "auto" },
|
||||
{ chainage_m: 100.499 },
|
||||
{ chainage_m: 200 },
|
||||
],
|
||||
basins,
|
||||
store,
|
||||
);
|
||||
process.stdout.write(JSON.stringify(out));
|
||||
@@ -0,0 +1,87 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""배수유역도 판이 종단 패널을 모르고 홀로 선다(계획서 24-2e).
|
||||
|
||||
- 배수유역 파일(`B05_Profile_UI_Drainage_*`)은 종단 패널(`_Profile_*`)이나 B06 을 가져오지 않는다 —
|
||||
종단쪽 일은 `_Panel_Types` 약속(콜백 · 창구)으로만 오간다.
|
||||
- 파일마다 700줄 이하.
|
||||
- 관 보고 만들기(`_Report`)는 상태 없이 같은 결과: ±0.5m 유역 매칭 · 세월교 유역은 관경 null ·
|
||||
시설 정보 · 출처 기본값 user.
|
||||
- `createDrainageSide` 가 켜고 끄는 창구를 낸다(두 보기에서 같은 판).
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
B05 = ROOT / "B05_Profile"
|
||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
def _drainage_files() -> list[Path]:
|
||||
return sorted(B05.glob("B05_Profile_UI_Drainage_*.ts"))
|
||||
|
||||
|
||||
def test_배수유역_파일은_종단_패널과_B06을_안_가져옴():
|
||||
files = _drainage_files()
|
||||
assert len(files) >= 10
|
||||
for path in files:
|
||||
source = path.read_text(encoding="utf-8")
|
||||
for line in source.splitlines():
|
||||
if not line.lstrip().startswith(("import ", "} from ", "export {", "export type {")):
|
||||
continue
|
||||
assert "UI_Profile_" not in line, (path.name, line)
|
||||
assert "B06_Section" not in line, (path.name, line)
|
||||
|
||||
|
||||
def test_배수유역_파일은_700줄_이하():
|
||||
for path in _drainage_files():
|
||||
lines = len(path.read_text(encoding="utf-8").splitlines())
|
||||
assert lines <= 700, (path.name, lines)
|
||||
|
||||
|
||||
def test_켜고_끄는_창구():
|
||||
side = (B05 / "B05_Profile_UI_Drainage_Side.ts").read_text(encoding="utf-8")
|
||||
for name in (
|
||||
"createDrainageSide",
|
||||
"createDrainageToggleButton",
|
||||
"setVisible",
|
||||
"onVisibleChange",
|
||||
):
|
||||
assert name in side
|
||||
assert "root.hidden" in side or "panel.root.hidden" in side
|
||||
types = (B05 / "B05_Profile_UI_Drainage_Panel_Types.ts").read_text(encoding="utf-8")
|
||||
assert "export interface DrainagePipeReport" in types
|
||||
assert "onPipesChanged?: (pipes: DrainagePipeReport[]) => void;" in types
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def reports():
|
||||
proc = subprocess.run(
|
||||
["node", os.path.join(HERE, "helper_b05_drainage_report.cjs")],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
timeout=60,
|
||||
)
|
||||
assert proc.returncode == 0, proc.stderr
|
||||
return json.loads(proc.stdout)
|
||||
|
||||
|
||||
def test_관_보고_유역_매칭과_기본값(reports):
|
||||
first, box, plain = reports
|
||||
# 누가거리는 소수 둘째 자리로 · 담당 유역의 관경 · 설계유량이 붙는다.
|
||||
assert first["chainage_m"] == 40 and first["effective_diameter_mm"] == 800
|
||||
assert first["design_flow_m3s"] == 1.2 and first["facility"] == "pipe"
|
||||
assert first["source"] == "auto"
|
||||
# 세월교 검토 유역은 관경만 null · 설계유량은 남김 · 시설 정보를 데려옴.
|
||||
assert box["chainage_m"] == 100.5 and box["effective_diameter_mm"] is None
|
||||
assert box["design_flow_m3s"] == 3.4
|
||||
assert box["facility"] == "box_culvert" and (box["start_m"], box["end_m"]) == (95, 106)
|
||||
assert box["options"] == {"h": 2} and box["source"] == "user"
|
||||
# 유역 없는 관 — 모두 null · 맨 배관.
|
||||
assert plain["effective_diameter_mm"] is None and plain["design_flow_m3s"] is None
|
||||
assert plain["facility"] == "pipe"
|
||||
@@ -192,3 +192,24 @@ def test_되돌리기_다시하기가_현재_추천을_함께_되살림(results)
|
||||
{"logic": "earthwork"},
|
||||
None,
|
||||
]
|
||||
|
||||
|
||||
def test_노선_추천_다듬기_23_3():
|
||||
"""구분선은 [노선 추천] 오른쪽 · 모달 지도는 편집 창 함수를 가져다 씀 · 모달이 라벨 패널 위."""
|
||||
page = os.path.join(HERE, "..", "..", "B05_Profile")
|
||||
|
||||
def read(name):
|
||||
return open(os.path.join(page, name), encoding="utf-8").read()
|
||||
|
||||
chrome = read("B05_Profile_UI_RouteEdit_Chrome.ts")
|
||||
rec = chrome.index('data-act="recommend"')
|
||||
divider = chrome.index("b05-routeedit__divider", rec)
|
||||
assert rec < divider < chrome.index('data-act="contour-minor"')
|
||||
assert chrome.count("b05-routeedit__divider") == 2
|
||||
shared = read("B05_Profile_UI_RouteEdit_Recommend_Map.ts")
|
||||
for name in ("bindRouteEditNavigation", "createMapRotation", "fitCanvas", "metricToScreen"):
|
||||
assert f"{name}(" in shared
|
||||
css = read("B05_Profile_UI_Style_RouteRecommend.css")
|
||||
assert "calc(var(--z-modal, 1000) + 2)" in css # 라벨 패널(+1) 위
|
||||
assert "writing-mode: vertical-lr" in css
|
||||
assert 'backdropClass: "b05-routerec-backdrop"' in read("B05_Profile_UI_RouteEdit_Recommend.ts")
|
||||
|
||||
Reference in New Issue
Block a user