/** * @jest-environment jsdom */ import InputDriver, { keyFromKeyboardEvent, } from "../../src/content/InputDriver"; import { expect } from "chai"; import Key from "../../src/shared/settings/Key"; describe("InputDriver", () => { let target: HTMLElement; let driver: InputDriver; beforeEach(() => { target = document.createElement("div"); document.body.appendChild(target); driver = new InputDriver(target); }); afterEach(() => { target.remove(); }); it("register callbacks", (done) => { driver.onKey((key: Key): boolean => { expect(key.key).to.equal("a"); expect(key.ctrl).to.be.true; expect(key.shift).to.be.false; expect(key.alt).to.be.false; expect(key.meta).to.be.false; done(); return true; }); target.dispatchEvent( new KeyboardEvent("keydown", { key: "a", ctrlKey: true, shiftKey: false, altKey: false, metaKey: false, }) ); }); it("invoke callback once", () => { let a = 0, b = 0; driver.onKey((key: Key): boolean => { if (key.key == "a") { ++a; } else { key.key == "b"; ++b; } return true; }); const events = [ new KeyboardEvent("keydown", { key: "a" }), new KeyboardEvent("keydown", { key: "b" }), new KeyboardEvent("keypress", { key: "a" }), new KeyboardEvent("keyup", { key: "a" }), new KeyboardEvent("keypress", { key: "b" }), new KeyboardEvent("keyup", { key: "b" }), ]; for (const e of events) { target.dispatchEvent(e); } expect(a).to.equal(1); expect(b).to.equal(1); }); it("propagates and stop handler chain", () => { let a = 0, b = 0, c = 0; driver.onKey((_key: Key): boolean => { a++; return false; }); driver.onKey((_key: Key): boolean => { b++; return true; }); driver.onKey((_key: Key): boolean => { c++; return true; }); target.dispatchEvent(new KeyboardEvent("keydown", { key: "b" })); expect(a).to.equal(1); expect(b).to.equal(1); expect(c).to.equal(0); }); it("does not invoke only meta keys", () => { driver.onKey((_key: Key): boolean => { expect.fail(); return false; }); target.dispatchEvent(new KeyboardEvent("keydown", { key: "Shift" })); target.dispatchEvent(new KeyboardEvent("keydown", { key: "Control" })); target.dispatchEvent(new KeyboardEvent("keydown", { key: "Alt" })); target.dispatchEvent(new KeyboardEvent("keydown", { key: "OS" })); }); it("ignores events from input elements", () => { ["input", "textarea", "select"].forEach((name) => { const input = window.document.createElement(name); const driver = new InputDriver(input); driver.onKey((_key: Key): boolean => { expect.fail(); return false; }); input.dispatchEvent(new KeyboardEvent("keydown", { key: "x" })); }); }); it("ignores events from contenteditable elements", () => { const div = window.document.createElement("div"); const driver = new InputDriver(div); driver.onKey((_key: Key): boolean => { expect.fail(); return false; }); div.setAttribute("contenteditable", ""); div.dispatchEvent(new KeyboardEvent("keydown", { key: "x" })); div.setAttribute("contenteditable", "true"); div.dispatchEvent(new KeyboardEvent("keydown", { key: "x" })); }); }); describe("#keyFromKeyboardEvent", () => { it("returns from keyboard input Ctrl+X", () => { const k = keyFromKeyboardEvent( new KeyboardEvent("keydown", { key: "x", shiftKey: false, ctrlKey: true, altKey: false, metaKey: true, }) ); expect(k.key).to.equal("x"); expect(k.shift).to.be.false; expect(k.ctrl).to.be.true; expect(k.alt).to.be.false; expect(k.meta).to.be.true; }); it("returns from keyboard input Shift+Esc", () => { const k = keyFromKeyboardEvent( new KeyboardEvent("keydown", { key: "Escape", shiftKey: true, ctrlKey: false, altKey: false, metaKey: true, }) ); expect(k.key).to.equal("Esc"); expect(k.shift).to.be.true; expect(k.ctrl).to.be.false; expect(k.alt).to.be.false; expect(k.meta).to.be.true; }); it("returns from keyboard input Ctrl+$", () => { // $ required shift pressing on most keyboards const k = keyFromKeyboardEvent( new KeyboardEvent("keydown", { key: "$", shiftKey: true, ctrlKey: true, altKey: false, metaKey: false, }) ); expect(k.key).to.equal("$"); expect(k.shift).to.be.false; expect(k.ctrl).to.be.true; expect(k.alt).to.be.false; expect(k.meta).to.be.false; }); it("returns from keyboard input Crtl+Space", () => { const k = keyFromKeyboardEvent( new KeyboardEvent("keydown", { key: " ", shiftKey: false, ctrlKey: true, altKey: false, metaKey: false, }) ); expect(k.key).to.equal("Space"); expect(k.shift).to.be.false; expect(k.ctrl).to.be.true; expect(k.alt).to.be.false; expect(k.meta).to.be.false; }); });