Files
Aislo/resources/tester/helper_323_9_save_redraw.cjs
T
eomsangdonandClaude Opus 5.5 0dc6769d6b test(508-1d 빨강 가림 1/2): 낡은 가짜 모듈 넷 지금 코드에 맞춤 · 공용 불러오기로 · 낡은 기대 둘 맞춤
- 54_9 알약: 구조물 표 불러오기(322-1) 못 찾음 → makeLoader 기본 풀이
- 398_2 · 408: 곡선 판 가둠(505-3) ResizeObserver · 판 찾기 가짜 더함 → makeLoader
- 323_9: 라우터 draft 길 import.meta.glob(302-1) 가짜 · 옛 풀이 그대로 requireFor · 기대 = 노선 그대로 [저장] 가림막 없음(498-3 D1)
- test_app_settings: CAD 명령 153 → 154(488-3 IMPORT)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 17:43:27 +09:00

160 lines
6.2 KiB
JavaScript

/* PLAN 323-9 ① — B06 [저장] 뒤 카드 = 서버 새 상세. 진짜 `design_save.ts`(저장 차례) ·
* `B06_Section_UI_Page_Persist.ts`(횡단 뒤처리) · `B06_Section_Section_Store.ts`(상세 캐시)를 Node 로 돌림.
* 서버 창구만 가짜 — 상세는 저장 전(옛 자리) · 저장 뒤(새 자리) 두 벌.
*/
const path = require("path");
const { makeLoader, memoryStorage } = require("./helper_ts_stub_loader.cjs");
const CATALOG = require("./helper_322_catalog_module.cjs"); // 구조물 표(322-1)
const ROOT = path.join(__dirname, "..", "..");
globalThis.window = { sessionStorage: memoryStorage(), localStorage: memoryStorage() };
globalThis.sessionStorage = globalThis.window.sessionStorage;
const calls = [];
let server = "옛 자리 4+5";
const detail = () => ({ cross_sections: [], longitudinal: { stations: [] }, tag: server });
const B06 = path.join(ROOT, "B06_Section");
const STUBS = {
"@ui/ui_template_elements": {
showToast: (_text, kind) => calls.push(`toast:${kind}`),
showLoadingOverlay: () => calls.push("overlay:on"),
hideLoadingOverlay: () => calls.push("overlay:off"),
},
// 노선 저장(346-3) — 이 시험은 노선이 그대로인 [저장]만 봄
[path.join(ROOT, "B05_Profile", "B05_Profile_UI_RouteEdit_Apply.ts")]: {
pendingRouteSave: async () => null,
},
[path.join(B06, "B06_Section_Api_Fetch.ts")]: {
fetchSectionDetail: async () => (calls.push(`fetch:${server}`), detail()),
saveSections: async () => calls.push("cross:save"),
confirmSections: async () => calls.push("cross:confirm"),
sectionConfirmBody: () => ({}),
warnSectionSave: () => undefined,
},
};
// 472-6 한 본문 창구 — 서버가 차례대로 정본을 쓰는 동안 가게가 바뀜(바뀜 신호 = 저장 도중) → 횡단 저장
let duringSave = async () => undefined;
STUBS[path.join(ROOT, "A00_Common", "design", "design_save_api.ts")] = {
SAVE_PART_KEYS: [
"settings",
"pipes",
"structures",
"plusStations",
"alignment",
"culvertOptions",
"uphill",
"cross",
],
DesignSaveError: class extends Error {},
postDesignSave: async (_p, _r, confirm, parts) => {
await duringSave();
if (parts.cross?.body) calls.push(confirm ? "cross:confirm" : "cross:save");
return { waited: false, steps: {} };
},
};
// 라우터(302-1 draft 길 `import.meta.glob`) — 이 로더로 못 읽음 · 저장 차례는 지금 길만 봄
STUBS[path.join(ROOT, "A00_Common", "router.ts")] = {
currentRoute: () => "",
remountRoute: () => undefined,
navigateTo: () => undefined,
setLeaveGuard: () => undefined,
};
const anyModule = () => new Proxy({}, { get: () => () => undefined });
const { loadTs } = makeLoader({
root: ROOT,
fileStub: (full) => STUBS[full],
requireFor: (full) => (request) => {
if (STUBS[request]) return STUBS[request];
if (CATALOG.isCatalogRequest(request)) return CATALOG;
if (request.endsWith(".json")) return require(path.join(path.dirname(full), request));
if (request.endsWith(".css")) return {};
if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`));
if (request.startsWith("@")) return anyModule();
return require(request);
},
});
// 측점 열쇠 한 벌(344-3 · 346-2)은 진짜로 — 빈 대역은 열쇠 목록을 못 냄
STUBS["@util/common_util_station_key"] = loadTs(
path.join(ROOT, "common_util", "common_util_station_key.ts"),
);
// 상단측 차례 본문(463 · 지표 조건 · 확정 지표면 GET · 확정 POST) — 이 시험은 횡단 뒤처리만 봄
const B05_FETCH = path.join(ROOT, "B05_Profile", "B05_Profile_Api_Fetch.ts");
STUBS[B05_FETCH] = {
...loadTs(B05_FETCH),
flushRouteParts: async () => undefined,
routePartsBody: async () => ({}),
};
const { saveDesign, savingDesign } = loadTs(
path.join(ROOT, "A00_Common", "design", "design_save.ts"),
);
const { crossSaveParts } = loadTs(path.join(B06, "B06_Section_UI_Page_Persist.ts"));
const { invalidateSectionDetail, loadSectionDetail } = loadTs(
path.join(B06, "B06_Section_Section_Store.ts"),
);
(async () => {
const P = "p1";
const R = 7;
// 횡단 보기 = 바뀜 신호마다 `refreshDetailForStructures` 와 같은 차례(최신만 · 저장 도중 안 그림)
let shown = null;
let seq = 0;
const refresh = async () => {
const mine = ++seq;
if (savingDesign(P)) return calls.push("refresh:skip");
const got = await loadSectionDetail(P, R);
if (mine === seq) shown = got.tag;
};
await refresh(); // 저장 전 화면(캐시 = 옛 서버)
const before = shown;
const ctx = {
projectId: P,
routeId: () => R,
detail: () => null,
context: () => null,
standardValues: () => undefined,
flushCulvertOptions: async () => undefined,
patchSources: () =>
Object.fromEntries(
["rockOffsets", "cutSlopeRatios", "stationWidths", "inletStructures", "basinAdjustments"]
.concat(["revetAdjusts", "extraCounts", "extraSpans", "fordAdjusts", "boxAdjusts"])
.concat(["linkFlags"])
.map((key) => [key, new Map()]),
),
reconcileDesigns: async () => undefined,
redraw: refresh,
};
const parts = crossSaveParts(ctx);
calls.length = 0;
const savingSeen = [];
// 관 · 구조물 초안이 정본으로 나가며 가게가 바뀜 → 바뀜 신호(저장 도중)
duringSave = async () => {
server = "새 자리 4+8 · 47+0";
savingSeen.push(savingDesign(P));
await refresh();
};
const ok = await saveDesign({
projectId: P,
routeId: () => R,
parts: {
// 구조물 · 추가 측점 — 초안 없음 · 이 시험은 안 봄(진짜는 서버 GET)
structures: () => null,
plusStations: () => null,
...parts.parts,
},
crossPart: (confirm) => parts.crossPart(confirm),
// 뒤처리 = 한 벌(`design_shared` saveSharedDesign done) 차례 그대로 — 공용 캐시를 한 번 비운 뒤 보기 몫(416 M1 ·
// 횡단 보기 done 은 비우지 않고 다시 그리기만)
done: async () => {
savingSeen.push(savingDesign(P));
invalidateSectionDetail(P);
await parts.done(false);
},
failed: (error) => calls.push(`failed:${error}`),
});
process.stdout.write(
JSON.stringify({ ok, before, after: shown, savingSeen, calls, savingIdle: savingDesign(P) }),
);
})();