Files
koreader-mirror/spec/unit/externalkeyboard_layout_spec.lua
okaykoaandFrans de Jonge 0f4836ecad Add layout framework for external keyboard text input (#16024)
Fixes #13278.

* Add correct external keyboard punctuation key names
* Compose physical-keyboard text via a layout and TextInput
* Expand to multiple possible layers
* Add XKB conversion script
* Give ourselves some dead key support
* Add license identifier
* Improve AltGr
* Group the layouts together
* And add the common layouts
* Expand with regular US international (with regular non-AltGr dead keys)
* Add some other scripts (that should do it)
* [fix] Avoid rotating up/down in external keyboards along with the device orientation
* Log keyboard layout in case of issues
* Also listen to PrintScr 'cause that's what the thing is for, isn't it

---------

Co-authored-by: Frans de Jonge <fransdejonge@gmail.com>
2026-09-16 20:33:07 +02:00

114 lines
4.7 KiB
Lua

local KeyboardLayout = dofile("plugins/externalkeyboard.koplugin/keyboard_layout.lua")
describe("ExternalKeyboard layout resolver (us)", function()
local function r(name, shift)
return KeyboardLayout.resolve("us", name, { Shift = shift or false })
end
it("case-folds letters", function()
assert.are.equal("a", r("A"))
assert.are.equal("A", r("A", true))
assert.are.equal("z", r("Z"))
assert.are.equal("Z", r("Z", true))
end)
it("passes digits through and maps shifted digits to symbols", function()
assert.are.equal("1", r("1"))
assert.are.equal("!", r("1", true))
assert.are.equal("@", r("2", true))
assert.are.equal(")", r("0", true))
end)
it("maps base and shifted punctuation", function()
assert.are.equal(";", r(";"))
assert.are.equal(":", r(";", true))
assert.are.equal("/", r("/"))
assert.are.equal("?", r("/", true))
assert.are.equal("-", r("-"))
assert.are.equal("_", r("-", true))
assert.are.equal("[", r("["))
assert.are.equal("{", r("[", true))
assert.are.equal("`", r("`"))
assert.are.equal("~", r("`", true))
assert.are.equal('"', r("'", true))
end)
it("resolves space at both levels", function()
assert.are.equal(" ", r(" "))
assert.are.equal(" ", r(" ", true))
end)
it("uses an AltGr level when a layout defines one", function()
assert.is_nil(KeyboardLayout.resolve("us", "1", { AltGr = true }))
assert.is_nil(KeyboardLayout.resolve("us", "1", { Shift = true, AltGr = true }))
end)
it("uses AltGr for generated layouts", function()
KeyboardLayout.layouts.test_altgr = {
["1"] = { "1", "!", "@", "#" },
}
assert.are.equal("@", KeyboardLayout.resolve("test_altgr", "1", { AltGr = true }))
assert.are.equal("#", KeyboardLayout.resolve("test_altgr", "1", { Shift = true, AltGr = true }))
end)
it("uses AltGr for the shipped US international layout", function()
assert.are.equal("é", KeyboardLayout.resolve("us-altgr-intl", "E", { AltGr = true }))
assert.are.equal("É", KeyboardLayout.resolve("us-altgr-intl", "E", { Shift = true, AltGr = true }))
end)
it("resolves the ISO extra key", function()
KeyboardLayout.layouts.test_lsgt = {
["<"] = { "<", ">" },
}
assert.are.equal("<", KeyboardLayout.resolve("test_lsgt", "<"))
assert.are.equal(">", KeyboardLayout.resolve("test_lsgt", "<", { Shift = true }))
end)
it("composes generated dead keys", function()
KeyboardLayout.layouts.test_dead = {
["'"] = { { dead = "dead_acute" } },
["^"] = { { dead = "dead_circumflex" } },
["E"] = { "e", "E" },
["X"] = { "x", "X" },
[" "] = { " " },
}
assert.is_nil(KeyboardLayout.resolve("test_dead", "'"))
assert.are.equal("é", KeyboardLayout.resolve("test_dead", "E"))
assert.is_nil(KeyboardLayout.resolve("test_dead", "'"))
assert.are.equal("\194\180", KeyboardLayout.resolve("test_dead", " "))
assert.is_nil(KeyboardLayout.resolve("test_dead", "^"))
assert.are.equal("x\204\130", KeyboardLayout.resolve("test_dead", "X"))
end)
it("does not apply a pending dead key after changing layouts", function()
KeyboardLayout.layouts.test_dead = {
["'"] = { { dead = "dead_acute" } },
}
assert.is_nil(KeyboardLayout.resolve("test_dead", "'"))
assert.are.equal("e", KeyboardLayout.resolve("us", "E"))
assert.are.equal("e", KeyboardLayout.resolve("test_dead", "E"))
end)
it("returns nil for keys it does not handle", function()
assert.is_nil(r("F1"))
assert.is_nil(r("Home"))
assert.is_nil(r("Up"))
end)
it("returns nil for an unknown layout", function()
assert.is_nil(KeyboardLayout.resolve("dvorak", "1", { Shift = true }))
end)
it("returns nil while a shortcut modifier is held", function()
KeyboardLayout.layouts.test_altgr_shortcuts = {
["E"] = { "e", "E", "€", "¢" },
}
assert.are.equal("€", KeyboardLayout.resolve("test_altgr_shortcuts", "E", { AltGr = true }))
assert.are.equal("¢", KeyboardLayout.resolve("test_altgr_shortcuts", "E", { AltGr = true, Shift = true }))
assert.is_nil(KeyboardLayout.resolve("us", "U", { Ctrl = true }))
assert.is_nil(KeyboardLayout.resolve("us", "A", { Alt = true }))
assert.is_nil(KeyboardLayout.resolve("us", "C", { Meta = true }))
assert.is_nil(KeyboardLayout.resolve("us", "1", { Ctrl = true, Shift = true }))
end)
end)