Files
Aislo/resources/tester/helper_398_1_user_pick.cjs
T
eomsangdonandClaude Opus 5.5 0170801088 fix(B05·B06 한 페이지): 교점 옮기면 좌측 패널 열림 — 펴기는 사용자 고름만 (398-1)
- design_user_pick.ts 새 파일 — 사용자 고름 표시 한 칸(진짜 누름 안 · 묶음 차례 없음)
- design_shared onReveal 한 곳이 그 칸만 봄 — 폼(고름 · 우클릭 추가)은 그대로 펴기를 부름
- design_page_data pageBusy — 묶음 차례가 떠 있나
- 배수유역 다시 나눔 응답 · 방향키 · 끌기 · 묶음 다시 돎의 다시 칠하기 = 안 폄
- 시험 test_398_1_reveal_user_pick(헬퍼 helper_398_1_user_pick.cjs)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TteK8mfYZetk5P3bEZkyVZ
2026-10-17 20:47:37 +09:00

82 lines
3.7 KiB
JavaScript

/* PLAN 398-1 단위검증 헬퍼 — 진짜 `design_user_pick.ts` + 진짜 `design_page_data.ts`(묶음 차례 · 「계산 중」)로
* 좌측 패널 펴기 한 곳(`design_shared` onReveal 과 같은 식)을 길마다 셈. 짝 = `test_398_1_reveal_user_pick.py`.
* 브라우저가 처리 중인 이벤트(`window.event`)는 `globalThis.event` 로 흉내. */
const fs = require("fs");
const path = require("path");
const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript"));
const ROOT = path.join(__dirname, "..", "..");
const DESIGN = path.join(ROOT, "A00_Common", "design");
function load(file, stubs) {
const js = ts.transpileModule(fs.readFileSync(path.join(DESIGN, file), "utf8"), {
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 },
}).outputText;
const box = { exports: {} };
new Function("exports", "module", "require", js)(box.exports, box, (name) => {
if (!stubs[name]) throw new Error(`stub 없음: ${name}`);
return stubs[name];
});
return box.exports;
}
const data = load("design_page_data.ts", {
"./design_page_route": { setPageRouteId: () => undefined, pageRouteId: () => null },
"../../B04_PreProcess/B04_PreProcess_Api_Fetch": { fetchDetailPipePoints: async () => ({}) },
"../../B05_Profile/B05_Profile_Api_Structures": {
fetchStructures: async () => ({}),
dropStaleStructureTypes: async () => false,
},
});
const pick = load("design_user_pick.ts", { "./design_page_data": data });
const P = "p1";
let reveals = 0;
/** 폼이 고른 것을 실을 때마다 부르는 펴기(`design_shared` onReveal 그대로). */
const onReveal = () => pick.isUserPick(P) && (reveals += 1);
/** 브라우저가 그 이벤트를 처리하는 동안(그 마이크로태스크까지) — 끝나면 이벤트 없음. */
async function during(event, body) {
globalThis.event = event;
try {
await body();
} finally {
globalThis.event = undefined;
}
}
const trusted = (type) => ({ type, isTrusted: true });
const count = async (event, body) => {
const before = reveals;
await during(event, body);
return reveals - before;
};
(async () => {
const out = {};
// 사용자 고름 — 종단 알약 · 횡단 카드(click) · 3D 부재(pointerup) · 우클릭 추가(contextmenu)
out.click = await count(trusted("click"), () => onReveal());
out.pointerup = await count(trusted("pointerup"), () => onReveal());
out.contextmenu = await count(trusted("contextmenu"), () => onReveal());
// 누름 밖 — 배수유역 다시 나눔 응답 · 횡단 다시 그림(서버 응답 · 타이머)
out.outside = await count(undefined, () => onReveal());
// 방향키로 교점 옮김 · 끌기 도중(pointermove)
out.arrow = await count(trusted("keydown"), () => onReveal());
out.drag = await count(trusted("pointermove"), () => onReveal());
// 스크립트가 낸 가짜 누름
out.synthetic = await count({ type: "click", isTrusted: false }, () => onReveal());
// 교점 끌기 놓음 · 곡선 지우기 · 되돌리기 단추 — 묶음 차례가 떠 그 마이크로태스크에서 관 · 구조물 따라가며 다시 칠함
let finish;
out.pipelineRepaint = await count(trusted("pointerup"), async () => {
data.trackPageBusy(P, new Promise((resolve) => (finish = resolve)));
await Promise.resolve();
onReveal(); // follow → 폼 다시 실음
});
out.busyPick = await count(trusted("click"), () => onReveal()); // 차례가 도는 사이 고름은 안 폄
finish();
await new Promise((resolve) => setTimeout(resolve, 0));
out.afterRun = await count(trusted("click"), () => onReveal()); // 차례가 끝나면 다시 폄
process.stdout.write(JSON.stringify(out));
})().catch((error) => {
console.error(error);
process.exit(1);
});