keybind.test.ts 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. import { describe, test, expect } from "bun:test"
  2. import { Keybind } from "../src/util/keybind"
  3. describe("Keybind.toString", () => {
  4. test("should convert simple key to string", () => {
  5. const info: Keybind.Info = { ctrl: false, meta: false, shift: false, leader: false, name: "f" }
  6. expect(Keybind.toString(info)).toBe("f")
  7. })
  8. test("should convert ctrl modifier to string", () => {
  9. const info: Keybind.Info = { ctrl: true, meta: false, shift: false, leader: false, name: "x" }
  10. expect(Keybind.toString(info)).toBe("ctrl+x")
  11. })
  12. test("should convert leader key to string", () => {
  13. const info: Keybind.Info = { ctrl: false, meta: false, shift: false, leader: true, name: "f" }
  14. expect(Keybind.toString(info)).toBe("<leader> f")
  15. })
  16. test("should convert multiple modifiers to string", () => {
  17. const info: Keybind.Info = { ctrl: true, meta: true, shift: false, leader: false, name: "g" }
  18. expect(Keybind.toString(info)).toBe("ctrl+alt+g")
  19. })
  20. test("should convert all modifiers to string", () => {
  21. const info: Keybind.Info = { ctrl: true, meta: true, shift: true, leader: true, name: "h" }
  22. expect(Keybind.toString(info)).toBe("<leader> ctrl+alt+shift+h")
  23. })
  24. test("should convert shift modifier to string", () => {
  25. const info: Keybind.Info = {
  26. ctrl: false,
  27. meta: false,
  28. shift: true,
  29. leader: false,
  30. name: "return",
  31. }
  32. expect(Keybind.toString(info)).toBe("shift+return")
  33. })
  34. test("should convert function key to string", () => {
  35. const info: Keybind.Info = { ctrl: false, meta: false, shift: false, leader: false, name: "f2" }
  36. expect(Keybind.toString(info)).toBe("f2")
  37. })
  38. test("should convert special key to string", () => {
  39. const info: Keybind.Info = {
  40. ctrl: false,
  41. meta: false,
  42. shift: false,
  43. leader: false,
  44. name: "pgup",
  45. }
  46. expect(Keybind.toString(info)).toBe("pgup")
  47. })
  48. test("should handle empty name", () => {
  49. const info: Keybind.Info = { ctrl: true, meta: false, shift: false, leader: false, name: "" }
  50. expect(Keybind.toString(info)).toBe("ctrl")
  51. })
  52. test("should handle only modifiers", () => {
  53. const info: Keybind.Info = { ctrl: true, meta: true, shift: true, leader: true, name: "" }
  54. expect(Keybind.toString(info)).toBe("<leader> ctrl+alt+shift")
  55. })
  56. test("should handle only leader with no other parts", () => {
  57. const info: Keybind.Info = { ctrl: false, meta: false, shift: false, leader: true, name: "" }
  58. expect(Keybind.toString(info)).toBe("<leader>")
  59. })
  60. })
  61. describe("Keybind.match", () => {
  62. test("should match identical keybinds", () => {
  63. const a: Keybind.Info = { ctrl: true, meta: false, shift: false, leader: false, name: "x" }
  64. const b: Keybind.Info = { ctrl: true, meta: false, shift: false, leader: false, name: "x" }
  65. expect(Keybind.match(a, b)).toBe(true)
  66. })
  67. test("should not match different key names", () => {
  68. const a: Keybind.Info = { ctrl: true, meta: false, shift: false, leader: false, name: "x" }
  69. const b: Keybind.Info = { ctrl: true, meta: false, shift: false, leader: false, name: "y" }
  70. expect(Keybind.match(a, b)).toBe(false)
  71. })
  72. test("should not match different modifiers", () => {
  73. const a: Keybind.Info = { ctrl: true, meta: false, shift: false, leader: false, name: "x" }
  74. const b: Keybind.Info = { ctrl: false, meta: false, shift: false, leader: false, name: "x" }
  75. expect(Keybind.match(a, b)).toBe(false)
  76. })
  77. test("should match leader keybinds", () => {
  78. const a: Keybind.Info = { ctrl: false, meta: false, shift: false, leader: true, name: "f" }
  79. const b: Keybind.Info = { ctrl: false, meta: false, shift: false, leader: true, name: "f" }
  80. expect(Keybind.match(a, b)).toBe(true)
  81. })
  82. test("should not match leader vs non-leader", () => {
  83. const a: Keybind.Info = { ctrl: false, meta: false, shift: false, leader: true, name: "f" }
  84. const b: Keybind.Info = { ctrl: false, meta: false, shift: false, leader: false, name: "f" }
  85. expect(Keybind.match(a, b)).toBe(false)
  86. })
  87. test("should match complex keybinds", () => {
  88. const a: Keybind.Info = { ctrl: true, meta: true, shift: false, leader: false, name: "g" }
  89. const b: Keybind.Info = { ctrl: true, meta: true, shift: false, leader: false, name: "g" }
  90. expect(Keybind.match(a, b)).toBe(true)
  91. })
  92. test("should not match with one modifier different", () => {
  93. const a: Keybind.Info = { ctrl: true, meta: true, shift: false, leader: false, name: "g" }
  94. const b: Keybind.Info = { ctrl: true, meta: true, shift: true, leader: false, name: "g" }
  95. expect(Keybind.match(a, b)).toBe(false)
  96. })
  97. test("should match simple key without modifiers", () => {
  98. const a: Keybind.Info = { ctrl: false, meta: false, shift: false, leader: false, name: "a" }
  99. const b: Keybind.Info = { ctrl: false, meta: false, shift: false, leader: false, name: "a" }
  100. expect(Keybind.match(a, b)).toBe(true)
  101. })
  102. })
  103. describe("Keybind.parse", () => {
  104. test("should parse simple key", () => {
  105. const result = Keybind.parse("f")
  106. expect(result).toEqual([
  107. {
  108. ctrl: false,
  109. meta: false,
  110. shift: false,
  111. leader: false,
  112. name: "f",
  113. },
  114. ])
  115. })
  116. test("should parse leader key syntax", () => {
  117. const result = Keybind.parse("<leader>f")
  118. expect(result).toEqual([
  119. {
  120. ctrl: false,
  121. meta: false,
  122. shift: false,
  123. leader: true,
  124. name: "f",
  125. },
  126. ])
  127. })
  128. test("should parse ctrl modifier", () => {
  129. const result = Keybind.parse("ctrl+x")
  130. expect(result).toEqual([
  131. {
  132. ctrl: true,
  133. meta: false,
  134. shift: false,
  135. leader: false,
  136. name: "x",
  137. },
  138. ])
  139. })
  140. test("should parse multiple modifiers", () => {
  141. const result = Keybind.parse("ctrl+alt+u")
  142. expect(result).toEqual([
  143. {
  144. ctrl: true,
  145. meta: true,
  146. shift: false,
  147. leader: false,
  148. name: "u",
  149. },
  150. ])
  151. })
  152. test("should parse shift modifier", () => {
  153. const result = Keybind.parse("shift+f2")
  154. expect(result).toEqual([
  155. {
  156. ctrl: false,
  157. meta: false,
  158. shift: true,
  159. leader: false,
  160. name: "f2",
  161. },
  162. ])
  163. })
  164. test("should parse meta/alt modifier", () => {
  165. const result = Keybind.parse("meta+g")
  166. expect(result).toEqual([
  167. {
  168. ctrl: false,
  169. meta: true,
  170. shift: false,
  171. leader: false,
  172. name: "g",
  173. },
  174. ])
  175. })
  176. test("should parse leader with modifier", () => {
  177. const result = Keybind.parse("<leader>h")
  178. expect(result).toEqual([
  179. {
  180. ctrl: false,
  181. meta: false,
  182. shift: false,
  183. leader: true,
  184. name: "h",
  185. },
  186. ])
  187. })
  188. test("should parse multiple keybinds separated by comma", () => {
  189. const result = Keybind.parse("ctrl+c,<leader>q")
  190. expect(result).toEqual([
  191. {
  192. ctrl: true,
  193. meta: false,
  194. shift: false,
  195. leader: false,
  196. name: "c",
  197. },
  198. {
  199. ctrl: false,
  200. meta: false,
  201. shift: false,
  202. leader: true,
  203. name: "q",
  204. },
  205. ])
  206. })
  207. test("should parse shift+return combination", () => {
  208. const result = Keybind.parse("shift+return")
  209. expect(result).toEqual([
  210. {
  211. ctrl: false,
  212. meta: false,
  213. shift: true,
  214. leader: false,
  215. name: "return",
  216. },
  217. ])
  218. })
  219. test("should parse ctrl+j combination", () => {
  220. const result = Keybind.parse("ctrl+j")
  221. expect(result).toEqual([
  222. {
  223. ctrl: true,
  224. meta: false,
  225. shift: false,
  226. leader: false,
  227. name: "j",
  228. },
  229. ])
  230. })
  231. test("should handle 'none' value", () => {
  232. const result = Keybind.parse("none")
  233. expect(result).toEqual([])
  234. })
  235. test("should handle special keys", () => {
  236. const result = Keybind.parse("pgup")
  237. expect(result).toEqual([
  238. {
  239. ctrl: false,
  240. meta: false,
  241. shift: false,
  242. leader: false,
  243. name: "pgup",
  244. },
  245. ])
  246. })
  247. test("should handle function keys", () => {
  248. const result = Keybind.parse("f2")
  249. expect(result).toEqual([
  250. {
  251. ctrl: false,
  252. meta: false,
  253. shift: false,
  254. leader: false,
  255. name: "f2",
  256. },
  257. ])
  258. })
  259. test("should handle complex multi-modifier combination", () => {
  260. const result = Keybind.parse("ctrl+alt+g")
  261. expect(result).toEqual([
  262. {
  263. ctrl: true,
  264. meta: true,
  265. shift: false,
  266. leader: false,
  267. name: "g",
  268. },
  269. ])
  270. })
  271. test("should be case insensitive", () => {
  272. const result = Keybind.parse("CTRL+X")
  273. expect(result).toEqual([
  274. {
  275. ctrl: true,
  276. meta: false,
  277. shift: false,
  278. leader: false,
  279. name: "x",
  280. },
  281. ])
  282. })
  283. })