Merge remote-tracking branch 'origin/sub_laptop_3' into main_laptop_1
This commit is contained in:
@@ -227,7 +227,7 @@ const NEW = (dy) => [
|
||||
setLoading: () => undefined,
|
||||
clear: () => undefined,
|
||||
}),
|
||||
bridge: () => ({ irregularStations: () => [] }),
|
||||
bridge: () => ({ irregularStations: () => [], stationsReady: () => true }), // 시설 줄 입력 다 옴(473)
|
||||
visible: () => shown,
|
||||
});
|
||||
await sections.restoreSections(R2);
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/* 473 시설 줄 입력 차례(요구 272 · 새로고침 누가토량 흔들림) — 진짜 `design_facility_lane` · `design_profile_base` 를
|
||||
* Node 로 돌려 JSON 한 줄(`test_473_lane_ready.py` 가 판정). 종단도는 가짜(받은 것 기록).
|
||||
* node helper_473_lane_ready.cjs
|
||||
*/
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const ROOT = path.join(__dirname, "..", "..");
|
||||
const ts = require(path.join(ROOT, "config", "node_modules", "typescript"));
|
||||
const CATALOG = require(path.join(__dirname, "helper_322_catalog_module.cjs"));
|
||||
|
||||
function memoryStorage() {
|
||||
const map = new Map();
|
||||
return {
|
||||
getItem: (k) => (map.has(k) ? map.get(k) : null),
|
||||
setItem: (k, v) => map.set(k, String(v)),
|
||||
removeItem: (k) => map.delete(k),
|
||||
key: (i) => [...map.keys()][i] ?? null,
|
||||
get length() {
|
||||
return map.size;
|
||||
},
|
||||
};
|
||||
}
|
||||
globalThis.window = { sessionStorage: memoryStorage(), localStorage: memoryStorage() };
|
||||
globalThis.sessionStorage = globalThis.window.sessionStorage;
|
||||
globalThis.localStorage = globalThis.window.localStorage;
|
||||
|
||||
const anyModule = (extra = {}) =>
|
||||
new Proxy(extra, { get: (t, key) => (key in t ? t[key] : () => undefined) });
|
||||
const STUBS = {
|
||||
"config_frontend.ts": anyModule({
|
||||
CURRENT_PROJECT_ID_KEY: "frd_current_project_id",
|
||||
API_BASE_URL: "",
|
||||
API_TIMEOUT_MS: 1000,
|
||||
PIPE_TYPES: [],
|
||||
}),
|
||||
"ui_template_elements.ts": anyModule(),
|
||||
"B04_PreProcess_Api_Fetch.ts": anyModule(),
|
||||
// 소단 사본(467) — 끌어오는 줄이 import.meta 를 써 이 로더로 못 읽음 · 소단 몫은 test_272_berm_source(vite 묶음)
|
||||
"B06_Section_UI_Page_Persist.ts": anyModule({ bermSpansFromStructures: () => [] }),
|
||||
};
|
||||
|
||||
const cache = new Map();
|
||||
const resolve = (base) =>
|
||||
[base, `${base}.ts`, path.join(base, "index.ts")].find(
|
||||
(p) => fs.existsSync(p) && fs.statSync(p).isFile(),
|
||||
) ?? `${base}.ts`;
|
||||
function loadTs(full) {
|
||||
const stub = STUBS[path.basename(full)];
|
||||
if (stub) return stub;
|
||||
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,
|
||||
esModuleInterop: true,
|
||||
},
|
||||
}).outputText;
|
||||
const box = { exports: {} };
|
||||
cache.set(full, box.exports);
|
||||
const near = (request) => {
|
||||
if (CATALOG.isCatalogRequest(request)) return CATALOG;
|
||||
if (request.endsWith(".json"))
|
||||
return JSON.parse(fs.readFileSync(path.join(path.dirname(full), request), "utf8"));
|
||||
const alias = { "@util/": "common_util", "@ui/": "ui_template", "@config/": "config" };
|
||||
for (const [prefix, dir] of Object.entries(alias))
|
||||
if (request.startsWith(prefix))
|
||||
return loadTs(resolve(path.join(ROOT, dir, request.slice(prefix.length))));
|
||||
return loadTs(resolve(path.join(path.dirname(full), request)));
|
||||
};
|
||||
new Function("exports", "module", "require", js)(box.exports, box, near);
|
||||
return box.exports;
|
||||
}
|
||||
|
||||
const design = path.join(ROOT, "A00_Common", "design");
|
||||
const { createFacilityLane } = loadTs(path.join(design, "design_facility_lane.ts"));
|
||||
const ids = loadTs(path.join(design, "design_pipe_ids.ts"));
|
||||
const { listedBase } = loadTs(path.join(design, "design_profile_base.ts"));
|
||||
const TYPES = JSON.parse(
|
||||
fs.readFileSync(path.join(ROOT, "resources", "master_template", "구조물정의.json"), "utf8"),
|
||||
).types;
|
||||
|
||||
/** 가짜 종단도 — 측점을 받은 차례 기록. */
|
||||
function fakeProfile() {
|
||||
const writes = [];
|
||||
return {
|
||||
writes,
|
||||
setStructureTypes: () => undefined,
|
||||
setStructures: () => undefined,
|
||||
setIrregularStations: (stations) => writes.push(stations.map((s) => s.chainage_m)),
|
||||
setMinCoverPipes: () => undefined,
|
||||
resetStationEdit: () => undefined,
|
||||
};
|
||||
}
|
||||
|
||||
const PIPE = { id: "P389", chainage_m: 389, facility: "pipe" };
|
||||
/** 새로고침 차례 — 종류 표 · 구조물이 먼저, 관 알림(배수유역 받기)이 늦게. */
|
||||
function lateOrder(P) {
|
||||
ids.usePipeIds(P);
|
||||
const profile = fakeProfile();
|
||||
const lane = createFacilityLane(P, () => profile);
|
||||
lane.setTypes(TYPES);
|
||||
lane.setStored([]);
|
||||
lane.set({ structures: [] }, false);
|
||||
const beforePipes = {
|
||||
writes: profile.writes.length,
|
||||
ready: typeof lane.ready === "function" ? lane.ready() : null,
|
||||
};
|
||||
lane.set({ pipes: [PIPE] }, false);
|
||||
return {
|
||||
beforePipes,
|
||||
after: profile.writes,
|
||||
ready: typeof lane.ready === "function" ? lane.ready() : null,
|
||||
};
|
||||
}
|
||||
/** 빠른 차례 — 관 알림이 구조물보다 먼저. */
|
||||
function earlyOrder(P) {
|
||||
ids.usePipeIds(P);
|
||||
const profile = fakeProfile();
|
||||
const lane = createFacilityLane(P, () => profile);
|
||||
lane.setTypes(TYPES);
|
||||
lane.set({ pipes: [PIPE] }, false);
|
||||
const beforeStructures = profile.writes.length;
|
||||
lane.set({ structures: [] }, false);
|
||||
return { beforeStructures, after: profile.writes };
|
||||
}
|
||||
|
||||
const stored = { stations: [{ station_id: "s", chainage_m: 389 }], basePvi: [] };
|
||||
const out = {
|
||||
late: lateOrder("P473-late"),
|
||||
early: earlyOrder("P473-early"),
|
||||
// 심기 전(null) = 저장 기준 그대로 · 같은 객체
|
||||
listedNull: (() => {
|
||||
try {
|
||||
return listedBase(stored, { longitudinal: { stations: [] } }, null) === stored;
|
||||
} catch {
|
||||
return false; // 옛 코드 = null 을 못 받음
|
||||
}
|
||||
})(),
|
||||
};
|
||||
process.stdout.write(JSON.stringify(out));
|
||||
@@ -0,0 +1,68 @@
|
||||
"""473 새로고침 누가토량 흔들림(요구 272) — 시설 줄 입력이 다 오기 전 측점을 심지 않음.
|
||||
|
||||
옛 흠 = 관 알림(배수유역 받기)이 종류 표 · 구조물보다 늦으면 시설 줄이 「모름」을 빈 목록으로
|
||||
심음 → 종단도가 저장 관 측점(389)을 뺀 선으로 횡단 다시 셈 → 배지 −211.6 ㎥ 1 초 남짓 뒤 −204.2
|
||||
(새로고침 20 번 중 1 ~ 2).
|
||||
① 늦은 차례 — 관 알림 전 측점 안 씀 · 준비 아님 · 알림 뒤 한 번 [389]
|
||||
② 빠른 차례 — 구조물 받기 전 안 씀 · 받은 뒤 한 번 [389](들어온 차례 무관 같은 결과)
|
||||
③ 종단도 기준 — 심기 전(null) = 저장 기준 그대로
|
||||
④ 종단도 · 측점 다시 그림이 준비 전 빈 목록을 안 심음(자리 글)
|
||||
TS 셈은 `helper_473_lane_ready.cjs`.
|
||||
|
||||
./venv/Scripts/python.exe -m pytest resources/tester/test_473_lane_ready.py -q
|
||||
"""
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
HELPER = Path(__file__).with_name("helper_473_lane_ready.cjs")
|
||||
|
||||
pytestmark = pytest.mark.skipif(
|
||||
not (ROOT / "config" / "node_modules" / "typescript").is_dir(),
|
||||
reason="프론트엔드 의존성 미설치",
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def got() -> dict:
|
||||
run = subprocess.run( # noqa: S603 — 고정 실행 파일
|
||||
["node", str(HELPER)],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
timeout=120,
|
||||
)
|
||||
assert run.returncode == 0, run.stderr
|
||||
return json.loads(run.stdout)
|
||||
|
||||
|
||||
def test_관_알림_전_측점_안_심음(got) -> None:
|
||||
late = got["late"]
|
||||
assert late["beforePipes"] == {"writes": 0, "ready": False} # 옛 코드 = [] 를 먼저 심음
|
||||
assert late["after"] == [[389]]
|
||||
assert late["ready"] is True
|
||||
|
||||
|
||||
def test_들어온_차례_무관_같은_측점(got) -> None:
|
||||
early = got["early"]
|
||||
assert early["beforeStructures"] == 0
|
||||
assert early["after"] == got["late"]["after"]
|
||||
|
||||
|
||||
def test_심기_전_종단도_기준_저장분(got) -> None:
|
||||
assert got["listedNull"] is True
|
||||
|
||||
|
||||
def test_준비_전_빈_목록_안_심는_자리() -> None:
|
||||
profile = (ROOT / "A00_Common/design/design_profile.ts").read_text(encoding="utf-8")
|
||||
assert "listedBase(storedBase, detail, planted ? irregularStations : null)" in profile
|
||||
sections = (ROOT / "A00_Common/design/design_view_profile_sections.ts").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
assert "if (deps.bridge().stationsReady())" in sections
|
||||
render = (ROOT / "B05_Profile/B05_Profile_UI_Profile_Render.ts").read_text(encoding="utf-8")
|
||||
assert "planted ? oneStationList(graphData.stations, injected) : graphData.stations" in render
|
||||
Reference in New Issue
Block a user