- 공용 ui_template_native_menu: 글 입력 칸 예외(isTextEditable) 삭제 - B09 attachRowMenu: 글 칸 위 return 삭제 - 시험: test_common_native_menu 기대값 · test_182 글 칸 줄 메뉴 시험 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018jonfdxn1Xit9bdkNJpE4G
87 lines
2.5 KiB
JavaScript
87 lines
2.5 KiB
JavaScript
/* 브라우저 기본 메뉴 막기(`ui_template/ui_template_native_menu.ts`) 단위검증 헬퍼 —
|
|
* 그 자리에서 트랜스파일해 Node 로 돌리고 값을 JSON 으로 냄. 가짜 창 · 가짜 요소로 판정. */
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript"));
|
|
|
|
const file = path.join(__dirname, "..", "..", "ui_template", "ui_template_native_menu.ts");
|
|
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, require);
|
|
const m = box.exports;
|
|
|
|
const targets = {
|
|
div: { tagName: "DIV" },
|
|
canvas: { tagName: "CANVAS" },
|
|
input: { tagName: "INPUT", type: "text" },
|
|
inputNoType: { tagName: "INPUT", type: "" },
|
|
number: { tagName: "INPUT", type: "number" },
|
|
readonly: { tagName: "INPUT", type: "text", readOnly: true },
|
|
checkbox: { tagName: "INPUT", type: "checkbox" },
|
|
range: { tagName: "INPUT", type: "range" },
|
|
textarea: { tagName: "TEXTAREA" },
|
|
editable: { tagName: "SPAN", isContentEditable: true },
|
|
textNode: { nodeType: 3 },
|
|
none: null,
|
|
};
|
|
|
|
// 가짜 창 — 캡처 듣기 하나를 받아 둠
|
|
function fakeWindow() {
|
|
const win = { calls: [] };
|
|
win.addEventListener = (type, fn, capture) => win.calls.push({ type, fn, capture });
|
|
return win;
|
|
}
|
|
function fire(win, target) {
|
|
const ev = { target, defaultPrevented: false, stopped: false };
|
|
ev.preventDefault = () => (ev.defaultPrevented = true);
|
|
ev.stopPropagation = () => (ev.stopped = true);
|
|
win.calls.forEach((c) => c.fn(ev));
|
|
return ev;
|
|
}
|
|
|
|
let on = true;
|
|
const win = fakeWindow();
|
|
m.blockNativeMenu(win, () => on);
|
|
const blocked = {};
|
|
for (const k of [
|
|
"div",
|
|
"canvas",
|
|
"input",
|
|
"readonly",
|
|
"textarea",
|
|
"editable",
|
|
"checkbox",
|
|
"textNode",
|
|
"none",
|
|
])
|
|
blocked[k] = fire(win, targets[k]).defaultPrevented;
|
|
on = false;
|
|
const off = fire(win, targets.div).defaultPrevented;
|
|
const stopped = fire(win, targets.div).stopped;
|
|
|
|
const route = (r) => m.NATIVE_MENU_ROUTE.test(r);
|
|
const routes = {};
|
|
for (const r of [
|
|
"a01-home",
|
|
"a06-login",
|
|
"b01-account",
|
|
"b05-profile",
|
|
"b11-loading",
|
|
"m01-master-data",
|
|
"m02-master-template",
|
|
"bogus",
|
|
])
|
|
routes[r] = route(r);
|
|
|
|
console.log(
|
|
JSON.stringify({
|
|
blocked,
|
|
off,
|
|
stopped,
|
|
listener: win.calls.map((c) => [c.type, c.capture]),
|
|
routes,
|
|
}),
|
|
);
|