- 헬퍼 동작 그대로(풀이 함수 본문은 옮겨 담음) · 제품 코드 안 고침 - 확인: 이 묶음 헬퍼를 쓰는 시험 279 개 전 279 통과 → 후 279 통과 (시험별 junit 대조 · 어긋남 0) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
92 lines
3.1 KiB
JavaScript
92 lines
3.1 KiB
JavaScript
/* 224-1a 배수 판 창구(rehome) — 진짜 `observeViewportSize`(B05_Profile_UI_Drainage_Parts.ts)를
|
|
* 가짜 창 둘 위에서 돌려 JSON 으로 냄.
|
|
* · 처음 = 판이 놓인 창(메인)의 관찰자
|
|
* · rehome = 옛 관찰자 끊고 지금 놓인 창(새 창)의 관찰자로 · 직전 크기 이어받아 배율 유지
|
|
* · disconnect = 지금 관찰자 끊음 */
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const { makeLoader } = require("./helper_ts_stub_loader.cjs");
|
|
|
|
const ROOT = path.join(__dirname, "..", "..");
|
|
const stub = new Proxy({}, { get: () => () => "" });
|
|
|
|
/** TS 한 장을 CommonJS 로 — 상대 경로는 진짜(공용 창 · 지도 셈만), 나머지는 빈 함수. */
|
|
const { loadTs } = makeLoader({
|
|
root: ROOT,
|
|
requireFor: (full) => (request) =>
|
|
/common_util_view_window|B04_PreProcess_UI_MapRender/.test(request)
|
|
? loadTs(path.join(path.dirname(full), `${request}.ts`))
|
|
: stub,
|
|
});
|
|
|
|
/** 가짜 창 — 관찰자를 모아 두고 크기를 바꿔 울림. */
|
|
function fakeWindow(name) {
|
|
const win = { name, observers: [] };
|
|
win.ResizeObserver = class {
|
|
constructor(fn) {
|
|
this.fn = fn;
|
|
this.live = false;
|
|
win.observers.push(this);
|
|
}
|
|
observe() {
|
|
this.live = true;
|
|
}
|
|
disconnect() {
|
|
this.live = false;
|
|
}
|
|
};
|
|
return win;
|
|
}
|
|
const main = fakeWindow("main");
|
|
const popup = fakeWindow("popup");
|
|
global.window = main;
|
|
|
|
const parts = loadTs(path.join(ROOT, "B05_Profile", "B05_Profile_UI_Drainage_Parts.ts"));
|
|
const doc = { defaultView: main };
|
|
let size = { width: 400, height: 300 };
|
|
const viewport = { ownerDocument: doc, getBoundingClientRect: () => ({ ...size }) };
|
|
const fire = (win) => win.observers.filter((o) => o.live).forEach((o) => o.fn());
|
|
|
|
let view = { scale: 2, offsetX: 10, offsetY: -5 };
|
|
const applied = [];
|
|
let redraws = 0;
|
|
const META = {
|
|
x_min: 0,
|
|
x_max: 4000,
|
|
y_min: 0,
|
|
y_max: 3000,
|
|
width_meters: 4000,
|
|
height_meters: 3000,
|
|
};
|
|
const watcher = parts.observeViewportSize(viewport, {
|
|
meta: () => META,
|
|
anchor: () => ({ width: 0, height: 0, ...view }),
|
|
apply: (next) => (applied.push(next), (view = next)),
|
|
redraw: () => (redraws += 1),
|
|
});
|
|
const out = { firstOwner: main.observers.length === 1 && popup.observers.length === 0 };
|
|
fire(main); // 처음 크기 기억
|
|
out.firstApplied = applied.length;
|
|
|
|
// 새 창으로 옮김 — 메인 관찰자 끊고 새 창 관찰자로
|
|
doc.defaultView = popup;
|
|
watcher.rehome();
|
|
out.mainLive = main.observers.some((o) => o.live);
|
|
out.popupLive = popup.observers.filter((o) => o.live).length;
|
|
size = { width: 800, height: 600 }; // 새 창에서 두 배로 커짐
|
|
fire(popup);
|
|
out.afterGrow = { applied: applied.length, ...view };
|
|
// 메인 창 관찰자가 울려도(이미 끊김) 아무 일 없음
|
|
fire(main);
|
|
out.mainIgnored = applied.length;
|
|
|
|
// 제자리 — 다시 메인
|
|
doc.defaultView = main;
|
|
watcher.rehome();
|
|
out.backPopupLive = popup.observers.some((o) => o.live);
|
|
out.backMainLive = main.observers.filter((o) => o.live).length;
|
|
watcher.disconnect();
|
|
out.afterDispose = [...main.observers, ...popup.observers].some((o) => o.live);
|
|
out.redraws = redraws;
|
|
process.stdout.write(JSON.stringify(out));
|