Files
Aislo/resources/tester/helper_443_save_stops.cjs
T
eomsangdonandClaude Opus 5.5 e90b546ed9 fix(462 B05 B06 한 페이지): 시설 줄 페이지 한 벌 — 알약 · 비정규 측점 · 흙덮기 관 · 관 id 장부를 숨은 보기와 무관하게 · 관 옵션 넘김 세션 칸
- design_facility_lane 새 파일 — 페이지가 세움 · 관 알림 · B06 관 목록 · 구조물 · 종류 · 추가 측점 → 종단도 · 평면 마커 원천 한 곳
- B05 다리 = 목록 · 종류 · 저장만 · B06 종단도 = 읽기만 · 숨었다 보일 때 다시 셈 없음(편집 두 번 옮김 길 걷힘)
- 노선 따라감 = 시설 줄 follow(편집 안 옮김) · 사용자 고침만 계획고 편집 옮김
- pipeOptionQueue(메모리) → 세션 칸 pipe-option-queue
- 시험 test_271_facility_lane(R3 뒤집기 · B06 먼저 = B05 먼저 · 따라감) · 옮긴 자리 문자열 시험 맞춤

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 23:05:23 +09:00

110 lines
4.3 KiB
JavaScript

/* PLAN 443 단위검증 헬퍼 — 저장 누락 ① (H6 · M3 · M6).
* H6 구조물 저장 실패(409 · 그 밖) = 던짐 · 초안 남음 · 다음 [저장]이 줄에 안 막힘
* M3 상단측 차례 성공 = uphill 세션 비움 · 실패 = 그대로
* M6 확정 응답 failed_parts = 던짐(그 차례에서 멈춤)
* TS 를 그 자리에서 트랜스파일해 Node 로 돌림 · 서버 창구는 가짜. 짝 = `test_443_save_stops.py`. */
const fs = require("fs");
const path = require("path");
const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript"));
const ROOT = path.join(__dirname, "..", "..");
globalThis.window = { setTimeout, clearTimeout };
const anything = () =>
new Proxy({}, { get: (_target, key) => (key === "__esModule" ? false : () => undefined) });
function load(file, stubs) {
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, (r) => stubs[r] ?? anything());
return box.exports;
}
const settle = (promise) =>
promise.then(
() => "ok",
(error) => String(error.message),
);
async function run() {
const out = {};
// ── H6 구조물 ──
class StructureConflictError extends Error {}
let pending = [{ structure_id: "s1" }];
let mode = "conflict";
const puts = [];
const bridgeMod = load(path.join(ROOT, "B05_Profile", "B05_Profile_UI_Page_Structures.ts"), {
"./B05_Profile_Api_Structures": {
StructureConflictError,
fetchStructures: async () => ({ revision: 3, structures: [] }),
saveStructures: async (_p, revision, list) => {
puts.push(revision);
if (mode === "conflict") throw new StructureConflictError("409");
if (mode === "boom") throw new Error("서버 500");
return { revision: revision + 1 };
},
readPendingStructures: () => pending,
writePendingStructures: (_p, next) => (pending = next),
definitionStale: () => false,
staleDefinitionNotice: () => null,
},
"@ui/ui_template_elements": { showToast: () => undefined },
});
const quiet = new Proxy({}, { get: () => () => undefined });
const bridge = bridgeMod.createStructuresBridge({
projectId: "p1",
panel: () => ({ structures: quiet, values: () => ({}) }),
lane: quiet, // 시설 줄 한 벌(462)
isRestoring: () => false,
});
out.conflict = await settle(bridge.saveStructuresIfDirty());
out.pendingAfterConflict = pending;
mode = "boom";
out.boom = await settle(bridge.saveStructuresIfDirty()); // 앞 실패에 줄이 안 막힘
out.pendingAfterBoom = pending;
mode = "ok";
out.ok = await settle(bridge.saveStructuresIfDirty());
out.pendingAfterOk = pending;
out.puts = puts;
// ── M3 · M6 상단측 · 확정 하위 ──
const state = new Map();
let reply = {};
const bodies = [];
globalThis.fetch = async (_url, init) => {
bodies.push(JSON.parse(init.body));
return { ok: true, json: async () => reply };
};
const api = load(path.join(ROOT, "B05_Profile", "B05_Profile_Api_Fetch.ts"), {
"../A00_Common/b_page_state": {
readState: (name, p) => state.get(`${name}:${p}`) ?? null,
writeState: (name, value, p) => state.set(`${name}:${p}`, value),
clearState: (name, p) => state.delete(`${name}:${p}`),
},
"@config/config_frontend": { API_BASE_URL: "", API_TIMEOUT_MS: 1000 },
});
state.set("uphill:p1", { "40.000": "right" });
reply = { failed_parts: ["상단측 병합"] };
out.flushFailed = await settle(api.flushUphillOverrides("p1"));
out.uphillAfterFail = state.get("uphill:p1") ?? null;
reply = { failed_parts: [] };
out.flushOk = await settle(api.flushUphillOverrides("p1"));
out.uphillAfterOk = state.get("uphill:p1") ?? null;
out.sentAgain = await settle(api.flushUphillOverrides("p1")); // 비었으니 안 보냄
out.bodies = bodies;
reply = { failed_parts: ["비정규 측점 횡단"] };
out.partsFailed = await settle(api.saveRouteParts("p1", { irregular_stations: [] }));
return out;
}
run().then(
(out) => process.stdout.write(JSON.stringify(out)),
(error) => {
process.stderr.write(String(error.stack ?? error));
process.exit(1);
},
);