Files
Aislo/resources/tester/helper_280_6_select_release.cjs
T
eomsangdonandClaude Opus 5.5 9a8ff3ee86 feat(480 드롭다운): 마우스로 고른 뒤 한 박자 뒤 초점 뺌 — 키보드 고름 그대로 · 공용 진입 · CAD iframe · 종단 새 창 세 자리
- ui_template_native_menu.ts releaseSelectAfterPick — 창 캡처 pointerdown · keydown · change · 아직 그 select 에 초점일 때만 blur
- 시험 test_280_6_select_release 새로 · 옛 가짜 import 두 헬퍼(282-1 · 224-1c)에 새 함수 흉내

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 22:07:40 +09:00

77 lines
2.9 KiB
JavaScript

/* 280-6 드롭다운 초점 빼기(`ui_template/ui_template_native_menu.ts` `releaseSelectAfterPick`) 단위검증 헬퍼 —
* 그 자리에서 트랜스파일해 Node 로 돌리고 값을 JSON 으로 냄. 가짜 창 · 가짜 select · 가짜 타이머로 판정. */
const fs = require("fs");
const path = require("path");
const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript"));
const ROOT = path.join(__dirname, "..", "..");
const js = ts.transpileModule(
fs.readFileSync(path.join(ROOT, "ui_template", "ui_template_native_menu.ts"), "utf8"),
{ compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 } },
).outputText;
const box = { exports: {} };
new Function("exports", "module", "require", js)(box.exports, box, require);
const m = box.exports;
// 가짜 창 — 캡처 듣기 · 타이머(손으로 돌림) · 문서 하나
function setup() {
const listeners = [];
const timers = [];
const doc = { activeElement: null };
const win = {
addEventListener: (type, fn, capture) => listeners.push({ type, fn, capture }),
setTimeout: (fn) => timers.push(fn),
};
m.releaseSelectAfterPick(win);
const el = (tagName) => {
const node = { tagName, ownerDocument: doc, blurs: 0 };
node.blur = () => {
node.blurs += 1;
doc.activeElement = null;
};
return node;
};
const fire = (type, target) =>
listeners.filter((l) => l.type === type).forEach((l) => l.fn({ type, target }));
const tick = () => timers.splice(0).forEach((fn) => fn());
return { listeners, doc, el, fire, tick };
}
// 차례 하나 — 초점을 select 에 두고 입력들을 쏜 뒤 change · (처리) · 한 틱
function run(inputs, tag = "SELECT", moveFocus = false) {
const t = setup();
const target = t.el(tag);
t.doc.activeElement = target;
inputs.forEach((type) => t.fire(type, target));
t.fire("change", target);
const before = target.blurs; // 한 틱 전엔 안 뺌
if (moveFocus) t.doc.activeElement = t.el("INPUT");
t.tick();
return { before, blurs: target.blurs };
}
const src = (rel) => fs.readFileSync(path.join(ROOT, rel), "utf8");
const setupOnce = setup();
console.log(
JSON.stringify({
mouse: run(["pointerdown"]),
keyboard: run(["keydown"]),
none: run([]),
input: run(["pointerdown"], "INPUT"),
moved: run(["pointerdown"], "SELECT", true),
mouseThenKey: run(["pointerdown", "keydown"]),
keyThenMouse: run(["keydown", "pointerdown"]),
listeners: setupOnce.listeners.map((l) => [l.type, l.capture]),
wiring: {
main: /releaseSelectAfterPick\(window\)/.test(src("A00_Common/main.ts")),
cad: /releaseSelectAfterPick\(frame\.contentWindow\)/.test(
src("ui_template/cad_host/cad_host.ts"),
),
popout: /releaseSelectAfterPick\(next\)/.test(
src("A00_Common/design/design_profile_popout.ts"),
),
},
}),
);