Merge remote-tracking branch 'origin/sub_laptop_7' into main_laptop_1
# Conflicts: # B05_Profile/B05_Profile_UI_RouteEdit.ts # ui_template/ui_template_locale_b2.ts
This commit is contained in:
@@ -99,7 +99,7 @@ out.viewOf = {
|
||||
buildAlignment: () => null,
|
||||
store: { edits: () => ({}) },
|
||||
projectId: "p",
|
||||
pagePipeline: { pipelineGrade: () => undefined }, // 계산 묶음(346-1) — 묶음 없으면 아무 일 없음
|
||||
pagePipeline: { pipelineGrade: () => undefined, pipelineOwnsCross: () => false }, // 계산 묶음(346-1 · 365-4) — 묶음 없으면 아무 일 없음
|
||||
scheduleCrossPreview: () => s.previews++,
|
||||
draw: () => s.draws++,
|
||||
root: inPopup(),
|
||||
|
||||
@@ -177,6 +177,10 @@ async function savedBaseOf() {
|
||||
}
|
||||
|
||||
const store = load("A00_Common", "design", "design_store.ts");
|
||||
// B05 오른쪽 횡단 판(365-3) — 그림 조각만 가짜 · 값 고르기는 진짜
|
||||
STUBS["b_svg_zoom_pan"] = { attachSvgZoomPan: () => undefined };
|
||||
STUBS["B05_Profile_UI_RouteEdit_Cross_Draw"] = { CROSS_PLOT_PAD: {}, summarizeCross: () => "" };
|
||||
const pane = load("B05_Profile", "B05_Profile_UI_RouteEdit_Cross.ts");
|
||||
const r3 = (value) => (typeof value === "number" ? Math.round(value * 1000) / 1000 : null);
|
||||
|
||||
/** 묶음 새 노선 상세(카드가 그리는 것) — 측점 · 계획고 · 절 · 성토 면적. */
|
||||
@@ -199,6 +203,7 @@ async function run() {
|
||||
const savedBase = await savedBaseOf();
|
||||
const shop = store.useDesignStore(P, null);
|
||||
const holds = [];
|
||||
let unstable = 0;
|
||||
const link = () => ({
|
||||
pipelineSource: () => ({
|
||||
base: savedBase,
|
||||
@@ -215,6 +220,7 @@ async function run() {
|
||||
holds.push(saved === job.detail ? "saved" : saved ? "other" : "null");
|
||||
return async () => "saved";
|
||||
},
|
||||
onUnstable: () => (unstable += 1),
|
||||
};
|
||||
const open = (label) => {
|
||||
const bridge = pageMod.routeDraftBridge(P, link(), options);
|
||||
@@ -249,6 +255,76 @@ async function run() {
|
||||
stages: Object.keys(reopenRun.stages),
|
||||
};
|
||||
|
||||
// ⑤ 초안 동안 B06 고침 — 세션 칸(측점 열쇠) → pipelineCross → 카드(묶음 새 노선 상세)
|
||||
const pipe = pageMod.pagePipeline(P);
|
||||
const target = pipe.output("ground").stations.find((s) => s.kind === "grid" && s.chainageM > 30);
|
||||
const cell = (ground) => ({ [target.key]: { ground_type: ground, section_mode: "left_cut" } });
|
||||
const groundAt = () =>
|
||||
pageMod
|
||||
.pipelineDetail(P)
|
||||
.cross_sections.find((s) => Math.abs(s.chainage_m - target.chainageM) < 1e-3)?.design
|
||||
?.ground_type ?? null;
|
||||
const before = groundAt();
|
||||
page.writeState("crossdesign", cell("blasting_rock"), P, 7);
|
||||
let mark = runs().length;
|
||||
pageMod.pipelineCross(P);
|
||||
await settle(mark + 1);
|
||||
await tick(20);
|
||||
const edit = {
|
||||
key: target.key,
|
||||
before,
|
||||
after: groundAt(),
|
||||
input: pipe.input("cross").byKey[target.key]?.groundType ?? null,
|
||||
runs: runs().length - mark,
|
||||
sources: runs()[runs().length - 1].sources,
|
||||
};
|
||||
// ⑦ B05 오른쪽 횡단 판 = 묶음 그 측점(카드와 같은 계획고 · 면적)
|
||||
const card = pageMod.pipelineDetail(P).cross_sections;
|
||||
const panes = card.map((section) => {
|
||||
const shown = pane.pipelineCrossAt(pipe, section.chainage_m + 0.4, job.interval, undefined);
|
||||
return [
|
||||
r3(shown?.chainage_m) === r3(section.chainage_m),
|
||||
r3(shown?.design?.design_elevation_m) === r3(section.design?.design_elevation_m),
|
||||
r3(shown?.design?.cut_area_m2) === r3(section.design?.cut_area_m2),
|
||||
shown?.samples.length === section.samples.length,
|
||||
];
|
||||
});
|
||||
const paneCheck = {
|
||||
count: card.length,
|
||||
same: panes.filter((row) => row.every(Boolean)).length,
|
||||
elevation: r3(
|
||||
pane.pipelineCrossAt(pipe, target.chainageM, job.interval, undefined)?.design
|
||||
?.design_elevation_m,
|
||||
),
|
||||
};
|
||||
|
||||
// ⑥ 고리 — 같은 입력 = 0 바퀴 · 세션만 바뀜(알림 없음) = 1 바퀴 · 안 맞음 = 3 바퀴 뒤 알림
|
||||
mark = runs().length;
|
||||
const same = await pageMod.reconcilePagePipeline(P);
|
||||
const sameRuns = runs().length - mark;
|
||||
page.writeState("crossdesign", cell("ripping_rock"), P, 7);
|
||||
mark = runs().length;
|
||||
const once = await pageMod.reconcilePagePipeline(P);
|
||||
const loop = {
|
||||
same,
|
||||
sameRuns,
|
||||
once,
|
||||
onceRuns: runs().length - mark,
|
||||
onceGround: groundAt(),
|
||||
};
|
||||
let n = 0;
|
||||
const realStandard = STUBS["B06_Section_UI_Standard_Panel"].effectiveStandardCross;
|
||||
STUBS["B06_Section_UI_Standard_Panel"].effectiveStandardCross = () => ({
|
||||
...job.standard,
|
||||
n: (n += 1),
|
||||
});
|
||||
mark = runs().length;
|
||||
loop.unstable = await pageMod.reconcilePagePipeline(P);
|
||||
loop.unstableRuns = runs().length - mark;
|
||||
loop.alerts = unstable;
|
||||
STUBS["B06_Section_UI_Standard_Panel"].effectiveStandardCross = realStandard;
|
||||
await pageMod.reconcilePagePipeline(P);
|
||||
|
||||
// ④ 초안 버림 — 열 때 맡긴 초안 전 상세로 되돌림(저장 정본)
|
||||
again.bridge.edited(null);
|
||||
const dropRun = await settle(runs().length + 1);
|
||||
@@ -260,7 +336,60 @@ async function run() {
|
||||
};
|
||||
pageMod.disposePagePipeline(P);
|
||||
page.clearDrafts(P);
|
||||
return { kept, b05, b06, dropped };
|
||||
|
||||
// ⑨ 저장 노선 ▲▼ 한 번 = 횡단 한 벌(365-4) — 묶음 cross 가 다시 셈 창구를 부르고 그 상세 설계를 냄
|
||||
const Q = "proj-365b";
|
||||
window.localStorage.setItem("frd_current_project_id", Q);
|
||||
let refreshCalls = 0;
|
||||
const qBridge = pageMod.routeDraftBridge(Q, link(), {
|
||||
stationIntervalM: job.interval,
|
||||
savedCross: async (detail, _routeId, stations) => {
|
||||
if (!detailMod.detailCross(detail, stations)) return null;
|
||||
refreshCalls += 1;
|
||||
return detailMod.detailCross(detail, stations);
|
||||
},
|
||||
});
|
||||
pageMod.pipelineEarthwork(Q, { conversion: job.conversion });
|
||||
const qPipe = pageMod.pagePipeline(Q);
|
||||
await settle(runs().length + 1);
|
||||
await tick(20);
|
||||
const openCalls = refreshCalls;
|
||||
const key = alignment.chainageKey(savedBase.stations[3].chainage_m);
|
||||
mark = runs().length;
|
||||
pageMod.pipelineGrade(Q, { station_offsets: { [key]: 0.3 }, curve_radii: {} });
|
||||
const gradeRun = await settle(mark + 1);
|
||||
const firstKey = qPipe.output("ground").stations[0].key;
|
||||
const saved = {
|
||||
owns: pageMod.pipelineOwnsCross(Q),
|
||||
openCalls,
|
||||
gradeCalls: refreshCalls - openCalls,
|
||||
runs: runs().length - mark,
|
||||
sources: gradeRun.sources,
|
||||
fromDetail:
|
||||
qPipe.output("cross").byKey[firstKey]?.detail === job.detail.cross_sections[0].design,
|
||||
};
|
||||
|
||||
// ⑧ 중심점 좌우(356-3 꼴) — 노선 한 걸음 → 새 종단이 오면 계획고 맞춤 · 첫 차례는 cross 전에 밀림(무거운 셈 한 번)
|
||||
let graded = false;
|
||||
const stopShift = qPipe.subscribe((event) => {
|
||||
if (event.kind !== "stage" || event.stage !== "profile" || graded) return;
|
||||
if (event.generation !== qPipe.generation) return;
|
||||
graded = true;
|
||||
void Promise.resolve().then(() =>
|
||||
pageMod.pipelineGrade(Q, { station_offsets: { [key]: 0.1 }, curve_radii: {} }),
|
||||
);
|
||||
}, "중심점 좌우");
|
||||
mark = runs().length;
|
||||
qBridge.edited(draftOf(shift(1, 0, 1)));
|
||||
await settle(mark + 2);
|
||||
await tick(job.haulDelayMs + 30);
|
||||
stopShift();
|
||||
const shiftRuns = runs()
|
||||
.slice(mark)
|
||||
.map((r) => ({ outcome: r.outcome, cross: "cross" in r.stages, sources: r.sources }));
|
||||
pageMod.disposePagePipeline(Q);
|
||||
page.clearDrafts(Q);
|
||||
return { kept, b05, b06, dropped, edit, loop, pane: paneCheck, saved, shiftRuns };
|
||||
}
|
||||
|
||||
run()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* 계획노선 편집 창 **측점 반폭 선 길이**(계획서 22-1) 단위검증 헬퍼 —
|
||||
* `B05_Profile_UI_RouteEdit_Cross.ts` 를 트랜스파일해 Node 로 돌린다.
|
||||
* 서버 묻기 · 그림 조각은 가짜로 채운다 — 「무슨 반폭을 묻고 · 무슨 반폭으로 선을 잡나」만 본다.
|
||||
* 계산 묶음 · 그림 조각은 가짜로 채운다 — 「무슨 반폭으로 선을 잡나」만 본다(365-3 · 서버 길 없음 ·
|
||||
* 묶음 그 측점 원지반 표본 = 좌우 20 m).
|
||||
*/
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
@@ -56,7 +57,6 @@ globalThis.ResizeObserver = class {
|
||||
disconnect() {}
|
||||
};
|
||||
|
||||
const asked = [];
|
||||
const STUBS = {
|
||||
"../A00_Common/b_svg_zoom_pan": { attachSvgZoomPan: () => {} },
|
||||
"../common_util/common_util_station": { stationLabel: (m) => String(m) },
|
||||
@@ -65,17 +65,24 @@ const STUBS = {
|
||||
CROSS_PLOT_PAD: 0,
|
||||
summarizeCross: () => "",
|
||||
},
|
||||
// 서버 흉내 — 요청 반폭을 그대로 되돌려 주고, 없으면 기본 20.
|
||||
"./B05_Profile_Api_Replan": {
|
||||
fetchCrossPreview: async (_project, request) => {
|
||||
asked.push(request.cross_half_width_m ?? null);
|
||||
return {
|
||||
chainage_m: request.chainage_m,
|
||||
cross_half_width_m: request.cross_half_width_m ?? 20,
|
||||
samples: [],
|
||||
design: null,
|
||||
};
|
||||
},
|
||||
// 계산 묶음 흉내 — 측점 하나(100 m) · 원지반 표본 좌우 20 m
|
||||
"../A00_Common/design/design_pipeline_page": {
|
||||
pagePipeline: () => ({
|
||||
output: (name) =>
|
||||
name === "ground" ? { stations: [{ key: "grid:5", chainageM: 100 }] } : null,
|
||||
input: () => null,
|
||||
subscribe: () => () => undefined,
|
||||
}),
|
||||
},
|
||||
"../A00_Common/design/design_store": {
|
||||
useDesignStore: () => ({ subscribe: () => () => undefined }),
|
||||
},
|
||||
"./logic/B05_Profile_Pipeline_Detail": {
|
||||
stationSection: (station) => ({
|
||||
chainage_m: station.chainageM,
|
||||
label: null,
|
||||
samples: [-20, 0, 20].map((offset_m) => ({ offset_m, elevation_m: 100, valid: true })),
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -111,17 +118,17 @@ async function run() {
|
||||
const out = {};
|
||||
out.before = cross.watched();
|
||||
await cross.open(100);
|
||||
out.empty = { asked: asked.at(-1), watched: cross.watched() };
|
||||
out.empty = { watched: cross.watched() };
|
||||
session.setItem("aislo:draft:cross-display:p-1:3", "15");
|
||||
await cross.refresh();
|
||||
out.applied15 = { asked: asked.at(-1), watched: cross.watched() };
|
||||
out.applied15 = { watched: cross.watched() };
|
||||
session.setItem("aislo:draft:cross-display:p-1:12", "8.5");
|
||||
session.setItem("aislo:draft:cross-display:p-2:99", "40");
|
||||
await cross.refresh();
|
||||
out.latestRoute = { asked: asked.at(-1), watched: cross.watched() };
|
||||
out.latestRoute = { watched: cross.watched() };
|
||||
session.setItem("aislo:draft:cross-display:p-1:12", "abc");
|
||||
await cross.refresh();
|
||||
out.badValue = { asked: asked.at(-1), watched: cross.watched() };
|
||||
out.badValue = { watched: cross.watched() };
|
||||
return out;
|
||||
}
|
||||
run().then((out) => console.log(JSON.stringify(out)));
|
||||
|
||||
@@ -138,10 +138,6 @@ def test_수치지형도_서피스_없으면_라이다만(tmp_path):
|
||||
def test_허용_목록_밖_거절(bad):
|
||||
with pytest.raises(ValidationError):
|
||||
terrain_router.ElevationRequest(points=[(0.0, 0.0)], terrain=bad)
|
||||
with pytest.raises(ValidationError):
|
||||
terrain_router.CrossPreviewRequest(
|
||||
vertices=[{"x": 0, "y": 0}, {"x": 1, "y": 1}], chainage_m=0, terrain=bad
|
||||
)
|
||||
with pytest.raises(ValidationError):
|
||||
replan.RouteInitialRequest(terrain=bad)
|
||||
|
||||
@@ -167,8 +163,8 @@ def test_화면_고르기_배선():
|
||||
assert '<option value="sheet">수치지형도</option>' in chrome
|
||||
assert 'sources?.sources.includes("las") && !!sources?.sources.includes("sheet")' in main
|
||||
assert 'saved === "sheet" || saved === "las" ? saved : (context?.design ?? fallback)' in api
|
||||
# 모달 분석 셋(종단 띠는 345-5 에서 없앰)이 고른 지형을 실어 보냄 · [확인] 재계산은 안 실음
|
||||
assert api.count("terrain: analysisTerrain(projectId)") == 2
|
||||
# 모달 지반고가 고른 지형을 실어 보냄 · 횡단 미리보기 = 묶음(365-3) · [확인] 재계산은 안 실음
|
||||
assert api.count("terrain: analysisTerrain(projectId)") == 1
|
||||
assert "terrain: analysisTerrain(projectId)" in initial_api
|
||||
replan_fn = api.split("export async function replanRoute")[1].split("export ")[0]
|
||||
assert "terrain" not in replan_fn
|
||||
|
||||
@@ -359,30 +359,3 @@ def test_측점_셈_둘_다_스냅을_읽음(tmp_path: Path, monkeypatch) -> Non
|
||||
with pytest.raises(RuntimeError):
|
||||
sections.run_section_generation(tmp_path, "route.geojson", "f", "m", False)
|
||||
assert seen["station_snap"] is True
|
||||
|
||||
|
||||
def test_횡단_미리보기도_스냅(tmp_path: Path, monkeypatch) -> None:
|
||||
from B05_Profile import B05_Profile_Router_Terrain as terrain
|
||||
from common_util.common_util_route_polyline import build_planned_polyline
|
||||
|
||||
monkeypatch.setattr(terrain, "build_surface_sampler", lambda *_args, **_kw: _Flat())
|
||||
built = build_planned_polyline(_NODES, min_radius_m=40.0, simplify=False)
|
||||
points, chain = core._clean_polyline(np.asarray(built.vertices, dtype=np.float64))
|
||||
spans = core._design_curve_spans(points, chain, [c.as_dict() for c in built.curves])
|
||||
assert len(spans) == 1
|
||||
target = math.floor((spans[0][0] + spans[0][1]) / 2 + 0.5)
|
||||
assert target % 20 # 격자 밖 자리여야 견줄 뜻이 있음
|
||||
|
||||
def ask(snap: bool) -> float:
|
||||
request = terrain.CrossPreviewRequest(
|
||||
vertices=[{"x": x, "y": y} for x, y in _NODES],
|
||||
chainage_m=target,
|
||||
min_radius_m=40.0,
|
||||
station_interval_m=20.0,
|
||||
station_snap=snap,
|
||||
)
|
||||
params = {"source_filter": "f", "method": "m", "smooth": False}
|
||||
return terrain._cross_preview(tmp_path, params, request)["chainage_m"]
|
||||
|
||||
assert ask(True) == target
|
||||
assert ask(False) % 20 == 0
|
||||
|
||||
@@ -38,20 +38,20 @@ def out():
|
||||
def test_노선_초안_동안_카드는_새_노선_상세(out):
|
||||
cards = out["cards"]
|
||||
assert cards["before"] == "saved"
|
||||
assert cards["afterDraft"] == ["draft-profile-1", "draft-cross-1"]
|
||||
assert cards["afterDraft"] == ["draft-cross-1"] # profile 차례 중간 상세는 안 그림(365-4)
|
||||
assert cards["draftNow"] == "draft-cross-1"
|
||||
|
||||
|
||||
def test_숨은_동안은_안_그림(out):
|
||||
cards = out["cards"]
|
||||
assert cards["whileHidden"] == ["draft-profile-1", "draft-cross-1"]
|
||||
assert cards["whileHidden"] == ["draft-cross-1"]
|
||||
assert cards["hiddenNow"] == "draft-cross-2"
|
||||
|
||||
|
||||
def test_초안_버리면_저장_노선_카드(out):
|
||||
cards = out["cards"]
|
||||
assert cards["discarded"][-1] == "saved" and cards["savedNow"] == "saved"
|
||||
assert cards["afterStop"] == 3 # 끊은 뒤엔 안 그림
|
||||
assert cards["afterStop"] == 2 # 끊은 뒤엔 안 그림
|
||||
|
||||
|
||||
def test_알약은_따라간_누가거리(out):
|
||||
|
||||
@@ -5,6 +5,15 @@
|
||||
- 노선 초안 둔 채 다시 열기(새로고침 · B06 바로 열기 · 편집기 없음) = B05 길과 같은 초안 상세
|
||||
(측점 · 계획고 · 면적) · 측점을 가게에 다시 냄 · 초안 전 = 저장 상세(열 때 맡김) → 버리면 saved.
|
||||
- 초안 동안 측점 갈아끼움은 메모리만 — 세션 상세(저장 노선)를 새 측점 + 옛 설계로 덮지 않음.
|
||||
못박는 것(365-2)
|
||||
- 초안 동안 B06 고침(세션 칸 · 측점 열쇠) → `pipelineCross` → 묶음 cross 입력 · 카드에 보임.
|
||||
- 고리 — 같은 입력 = 0 바퀴 · 세션만 바뀜 = 1 바퀴 · 안 맞으면 3 바퀴 뒤 「계산 불안정」 한 번.
|
||||
못박는 것(365-3)
|
||||
- B05 오른쪽 횡단 판 = 묶음 그 측점 — 계획고 · 절토 면적 · 표본 = B06 카드 · 서버 길 없음.
|
||||
못박는 것(365-4)
|
||||
- 저장 노선 ▲▼ 한 번 = 횡단 한 벌 — 묶음 cross 가 다시 셈 창구(상세 설계) 한 번 · 종단도 예약 끔.
|
||||
- 중심점 좌우 = 노선 차례는 cross 전에 밀림 → cross 한 번(계획고 맞춤 차례만).
|
||||
- B06 다시 그림 = 겹친 신호(갈아끼움 · 묶음 cross · 초안) 한 번 · profile 차례는 안 그림.
|
||||
|
||||
짝: `helper_365_page_pipeline.cjs`(진짜 TS · 서버 창구만 가짜 · 틀 = 346-2 시험) ·
|
||||
`helper_365_swap_entry.ts` + `helper_365_swap.mjs`(진짜 상세 가게 · vite ssr).
|
||||
@@ -99,6 +108,58 @@ def test_365_1_초안_버림_저장_정본(r):
|
||||
assert d["restoreWhy"] == "saved"
|
||||
|
||||
|
||||
def test_365_2_초안_동안_횡단_고침_카드에(r):
|
||||
e = r["edit"]
|
||||
assert e["before"] != "blasting_rock"
|
||||
assert e["input"] == "blasting_rock" and e["after"] == "blasting_rock"
|
||||
assert e["runs"] == 1 and e["sources"] == ["cross"]
|
||||
|
||||
|
||||
def test_365_2_고리_바퀴_수(r):
|
||||
loop = r["loop"]
|
||||
assert loop["same"] == 0 and loop["sameRuns"] == 0 # 같은 입력 = 안 돎
|
||||
assert loop["once"] == 1 and loop["onceRuns"] == 1 and loop["onceGround"] == "ripping_rock"
|
||||
assert loop["unstable"] == -1 and loop["unstableRuns"] == 3 and loop["alerts"] == 1
|
||||
|
||||
|
||||
def test_365_3_평면_횡단_판_카드와_같음(r):
|
||||
p = r["pane"]
|
||||
assert p["count"] > 5 and p["same"] == p["count"]
|
||||
assert p["elevation"] is not None
|
||||
|
||||
|
||||
def test_365_3_서버_횡단_미리보기_길_없음():
|
||||
router = (ROOT / "B05_Profile/B05_Profile_Router_Terrain.py").read_text(encoding="utf-8")
|
||||
api = (ROOT / "B05_Profile/B05_Profile_Api_Replan.ts").read_text(encoding="utf-8")
|
||||
edit = (ROOT / "B05_Profile/B05_Profile_UI_RouteEdit.ts").read_text(encoding="utf-8")
|
||||
assert "cross-preview" not in router and "cross-preview" not in api
|
||||
assert "crossPreview.refresh()" not in edit # 묶음 cross 차례가 그림
|
||||
|
||||
|
||||
def test_365_4_저장_노선_계획고_횡단_한_벌(r):
|
||||
s = r["saved"]
|
||||
assert s["owns"] and s["openCalls"] == 1
|
||||
assert s["gradeCalls"] == 1 and s["runs"] == 1 and s["sources"] == ["grade"]
|
||||
assert s["fromDetail"] # 묶음 cross = 상세 설계 그대로(엔진 따로 안 셈)
|
||||
|
||||
|
||||
def test_365_4_중심점_좌우_횡단_한_번(r):
|
||||
runs = r["shiftRuns"]
|
||||
assert [x["outcome"] for x in runs] == ["dropped", "done"], runs
|
||||
assert [x["cross"] for x in runs] == [False, True]
|
||||
assert runs[1]["sources"] == ["route", "grade"] # 밀린 노선 범위 + 계획고 = 한 차례
|
||||
|
||||
|
||||
def test_365_4_다시_그림_한_번():
|
||||
swap = (ROOT / "B06_Section/B06_Section_UI_Page_Station_Swap.ts").read_text(encoding="utf-8")
|
||||
view = (ROOT / "A00_Common/design/design_view_cross.ts").read_text(encoding="utf-8")
|
||||
profile = (ROOT / "A00_Common/design/design_profile.ts").read_text(encoding="utf-8")
|
||||
assert 'event.stage !== "cross") return;' in swap # profile 차례 중간 상세는 안 그림
|
||||
body = view.split("async function refreshDetailForStructures")[1].split("loadSectionDetail")[0]
|
||||
assert "setTimeout(next, 0)" in body # 겹친 신호는 seq 가 앞 차례를 버림 = 한 번
|
||||
assert "if (!pagePipeline.pipelineOwnsCross(projectId)) scheduleCrossPreview();" in profile
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def swap(tmp_path_factory) -> dict:
|
||||
work = tmp_path_factory.mktemp("b365")
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""계획노선 편집 창 — **측점 반폭 선 길이**(계획서 22-1) 회귀검증.
|
||||
|
||||
파란 선 = 우측 패널 「횡단 반폭(m)」 적용값 양쪽. 적용한 적이 없으면 서버 기본값.
|
||||
선 길이는 서버가 덮은 반폭(= 횡단 미리보기 원지반 선 범위)을 그대로 쓴다.
|
||||
파란 선 = 우측 패널 「횡단 반폭(m)」 적용값 양쪽. 적용한 적이 없으면 원지반 선 범위
|
||||
(계산 묶음 그 측점 표본 · 365-3).
|
||||
Node 헬퍼(`helper_b05_routeedit_cross_width.cjs`)가 TS 를 트랜스파일해 돌린다.
|
||||
"""
|
||||
|
||||
@@ -31,21 +31,17 @@ def test_측점을_고르기_전에는_선이_없다(results):
|
||||
assert results["before"] is None
|
||||
|
||||
|
||||
def test_적용한_적_없으면_서버_기본값_양쪽(results):
|
||||
assert results["empty"]["asked"] is None
|
||||
def test_적용한_적_없으면_원지반_범위_양쪽(results):
|
||||
assert results["empty"]["watched"] == {"chainageM": 100, "leftM": 20, "rightM": 20}
|
||||
|
||||
|
||||
def test_적용값이_있으면_그_값_양쪽(results):
|
||||
assert results["applied15"]["asked"] == 15
|
||||
assert results["applied15"]["watched"] == {"chainageM": 100, "leftM": 15, "rightM": 15}
|
||||
|
||||
|
||||
def test_노선이_여럿이면_최신_노선_값_다른_프로젝트는_무시(results):
|
||||
assert results["latestRoute"]["asked"] == 8.5
|
||||
assert results["latestRoute"]["watched"]["leftM"] == 8.5
|
||||
|
||||
|
||||
def test_망가진_값은_기본값으로(results):
|
||||
assert results["badValue"]["asked"] is None
|
||||
assert results["badValue"]["watched"]["rightM"] == 20
|
||||
|
||||
Reference in New Issue
Block a user