mirror of
https://github.com/binaricat/Netcatty.git
synced 2026-11-11 08:42:45 +00:00
Co-authored-by: netcatty-bot <308658023+netcatty-bot@users.noreply.github.com>
100 lines
3.8 KiB
TypeScript
100 lines
3.8 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import { dirname, join } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import {
|
|
isModifierOnlyKeyDownEvent,
|
|
keepImeCommittedTextThroughModifierKeyDowns,
|
|
} from "./imeModifierKeyDownSeenGuard";
|
|
|
|
const runtimeSource = readFileSync(
|
|
join(dirname(fileURLToPath(import.meta.url)), "createXTermRuntime.ts"),
|
|
"utf8",
|
|
);
|
|
|
|
test("isModifierOnlyKeyDownEvent accepts both DOM key and classic keyCode shapes", () => {
|
|
assert.equal(isModifierOnlyKeyDownEvent({ key: "Shift", keyCode: 16 }), true);
|
|
assert.equal(isModifierOnlyKeyDownEvent({ key: "Shift" }), true);
|
|
assert.equal(isModifierOnlyKeyDownEvent({ key: "Control", keyCode: 17 }), true);
|
|
assert.equal(isModifierOnlyKeyDownEvent({ key: "Alt", keyCode: 18 }), true);
|
|
assert.equal(isModifierOnlyKeyDownEvent({ key: "Meta", keyCode: 91 }), true);
|
|
assert.equal(isModifierOnlyKeyDownEvent({ key: "CapsLock" }), true);
|
|
});
|
|
|
|
test("isModifierOnlyKeyDownEvent rejects real keys and IME process events", () => {
|
|
assert.equal(isModifierOnlyKeyDownEvent({ key: "a", keyCode: 65 }), false);
|
|
assert.equal(isModifierOnlyKeyDownEvent({ key: "Process", keyCode: 229 }), false);
|
|
assert.equal(isModifierOnlyKeyDownEvent({ key: "Enter", keyCode: 13 }), false);
|
|
assert.equal(isModifierOnlyKeyDownEvent({ key: "Dead", keyCode: 221 }), false);
|
|
});
|
|
|
|
type FakeCore = {
|
|
_keyDown: (event: Pick<KeyboardEvent, "key" | "keyCode">) => boolean;
|
|
_keyDownSeen: boolean;
|
|
_keyUp: () => void;
|
|
};
|
|
|
|
function createFakeCore(initialSeen = false): {
|
|
core: FakeCore;
|
|
term: { _core: FakeCore };
|
|
} {
|
|
const core: FakeCore = {
|
|
_keyDownSeen: initialSeen,
|
|
_keyDown(_event) {
|
|
// Mirrors xterm: every keydown arms the insertText dedupe guard.
|
|
this._keyDownSeen = true;
|
|
return true;
|
|
},
|
|
_keyUp() {
|
|
this._keyDownSeen = false;
|
|
},
|
|
};
|
|
return { core, term: { _core: core } };
|
|
}
|
|
|
|
test("keepImeCommittedTextThroughModifierKeyDowns preserves seen state across Shift keydown", () => {
|
|
// Sogou Shift commit: a previous real keydown armed the guard, and the
|
|
// Shift keydown must not re-arm (or clear) it before the composed input.
|
|
const { core, term } = createFakeCore(false);
|
|
keepImeCommittedTextThroughModifierKeyDowns(term as never);
|
|
core._keyDown({ key: "Shift", keyCode: 16 } as KeyboardEvent);
|
|
assert.equal(core._keyDownSeen, false);
|
|
});
|
|
|
|
test("keepImeCommittedTextThroughModifierKeyDowns keeps guard armed for real keydowns", () => {
|
|
const { core, term } = createFakeCore(false);
|
|
keepImeCommittedTextThroughModifierKeyDowns(term as never);
|
|
core._keyDown({ key: "a", keyCode: 65 } as KeyboardEvent);
|
|
assert.equal(core._keyDownSeen, true);
|
|
});
|
|
|
|
test("keepImeCommittedTextThroughModifierKeyDowns preserves an already-armed guard", () => {
|
|
const { core, term } = createFakeCore(true);
|
|
keepImeCommittedTextThroughModifierKeyDowns(term as never);
|
|
core._keyDown({ key: "Shift" } as KeyboardEvent);
|
|
assert.equal(core._keyDownSeen, true);
|
|
});
|
|
|
|
test("keepImeCommittedTextThroughModifierKeyDowns leaves non-modifier behavior intact", () => {
|
|
const { core, term } = createFakeCore(false);
|
|
keepImeCommittedTextThroughModifierKeyDowns(term as never);
|
|
core._keyDown({ key: "Process", keyCode: 229 } as KeyboardEvent);
|
|
assert.equal(core._keyDownSeen, true);
|
|
core._keyDown({ key: "Control", keyCode: 17 } as KeyboardEvent);
|
|
assert.equal(core._keyDownSeen, true, "Control still restored to true (was true)");
|
|
});
|
|
|
|
test("guard tolerates a terminal without an introspectable core", () => {
|
|
assert.doesNotThrow(() => {
|
|
keepImeCommittedTextThroughModifierKeyDowns({} as never);
|
|
});
|
|
});
|
|
|
|
test("runtime installs the guard when the terminal is created", () => {
|
|
assert.match(
|
|
runtimeSource,
|
|
/keepImeCommittedTextThroughModifierKeyDowns\(term\)/,
|
|
);
|
|
});
|