keybind.test.ts 8.6 KB

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