test.helper.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. // requires local modules: keysym, keysymdef, keyboard
  2. var assert = chai.assert;
  3. var expect = chai.expect;
  4. describe('Helpers', function() {
  5. "use strict";
  6. describe('keysymFromKeyCode', function() {
  7. it('should map known keycodes to keysyms', function() {
  8. expect(kbdUtil.keysymFromKeyCode(0x41, false), 'a').to.be.equal(0x61);
  9. expect(kbdUtil.keysymFromKeyCode(0x41, true), 'A').to.be.equal(0x41);
  10. expect(kbdUtil.keysymFromKeyCode(0xd, false), 'enter').to.be.equal(0xFF0D);
  11. expect(kbdUtil.keysymFromKeyCode(0x11, false), 'ctrl').to.be.equal(0xFFE3);
  12. expect(kbdUtil.keysymFromKeyCode(0x12, false), 'alt').to.be.equal(0xFFE9);
  13. expect(kbdUtil.keysymFromKeyCode(0xe1, false), 'altgr').to.be.equal(0xFE03);
  14. expect(kbdUtil.keysymFromKeyCode(0x1b, false), 'esc').to.be.equal(0xFF1B);
  15. expect(kbdUtil.keysymFromKeyCode(0x26, false), 'up').to.be.equal(0xFF52);
  16. });
  17. it('should return null for unknown keycodes', function() {
  18. expect(kbdUtil.keysymFromKeyCode(0xc0, false), 'DK æ').to.be.null;
  19. expect(kbdUtil.keysymFromKeyCode(0xde, false), 'DK ø').to.be.null;
  20. });
  21. });
  22. describe('keysyms.fromUnicode', function() {
  23. it('should map ASCII characters to keysyms', function() {
  24. expect(keysyms.fromUnicode('a'.charCodeAt())).to.have.property('keysym', 0x61);
  25. expect(keysyms.fromUnicode('A'.charCodeAt())).to.have.property('keysym', 0x41);
  26. });
  27. it('should map Latin-1 characters to keysyms', function() {
  28. expect(keysyms.fromUnicode('ø'.charCodeAt())).to.have.property('keysym', 0xf8);
  29. expect(keysyms.fromUnicode('é'.charCodeAt())).to.have.property('keysym', 0xe9);
  30. });
  31. it('should map characters that are in Windows-1252 but not in Latin-1 to keysyms', function() {
  32. expect(keysyms.fromUnicode('Š'.charCodeAt())).to.have.property('keysym', 0x01a9);
  33. });
  34. it('should map characters which aren\'t in Latin1 *or* Windows-1252 to keysyms', function() {
  35. expect(keysyms.fromUnicode('ŵ'.charCodeAt())).to.have.property('keysym', 0x1000175);
  36. });
  37. it('should return undefined for unknown codepoints', function() {
  38. expect(keysyms.fromUnicode('\n'.charCodeAt())).to.be.undefined;
  39. expect(keysyms.fromUnicode('\u1F686'.charCodeAt())).to.be.undefined;
  40. });
  41. });
  42. describe('substituteCodepoint', function() {
  43. it('should replace characters which don\'t have a keysym', function() {
  44. expect(kbdUtil.substituteCodepoint('Ș'.charCodeAt())).to.equal('Ş'.charCodeAt());
  45. expect(kbdUtil.substituteCodepoint('ș'.charCodeAt())).to.equal('ş'.charCodeAt());
  46. expect(kbdUtil.substituteCodepoint('Ț'.charCodeAt())).to.equal('Ţ'.charCodeAt());
  47. expect(kbdUtil.substituteCodepoint('ț'.charCodeAt())).to.equal('ţ'.charCodeAt());
  48. });
  49. it('should pass other characters through unchanged', function() {
  50. expect(kbdUtil.substituteCodepoint('T'.charCodeAt())).to.equal('T'.charCodeAt());
  51. });
  52. });
  53. describe('nonCharacterKey', function() {
  54. it('should recognize the right keys', function() {
  55. expect(kbdUtil.nonCharacterKey({keyCode: 0xd}), 'enter').to.be.defined;
  56. expect(kbdUtil.nonCharacterKey({keyCode: 0x08}), 'backspace').to.be.defined;
  57. expect(kbdUtil.nonCharacterKey({keyCode: 0x09}), 'tab').to.be.defined;
  58. expect(kbdUtil.nonCharacterKey({keyCode: 0x10}), 'shift').to.be.defined;
  59. expect(kbdUtil.nonCharacterKey({keyCode: 0x11}), 'ctrl').to.be.defined;
  60. expect(kbdUtil.nonCharacterKey({keyCode: 0x12}), 'alt').to.be.defined;
  61. expect(kbdUtil.nonCharacterKey({keyCode: 0xe0}), 'meta').to.be.defined;
  62. });
  63. it('should not recognize character keys', function() {
  64. expect(kbdUtil.nonCharacterKey({keyCode: 'A'}), 'A').to.be.null;
  65. expect(kbdUtil.nonCharacterKey({keyCode: '1'}), '1').to.be.null;
  66. expect(kbdUtil.nonCharacterKey({keyCode: '.'}), '.').to.be.null;
  67. expect(kbdUtil.nonCharacterKey({keyCode: ' '}), 'space').to.be.null;
  68. });
  69. });
  70. describe('getKeysym', function() {
  71. it('should prefer char', function() {
  72. expect(kbdUtil.getKeysym({char : 'a', charCode: 'Š'.charCodeAt(), keyCode: 0x42, which: 0x43})).to.have.property('keysym', 0x61);
  73. });
  74. it('should use charCode if no char', function() {
  75. expect(kbdUtil.getKeysym({char : '', charCode: 'Š'.charCodeAt(), keyCode: 0x42, which: 0x43})).to.have.property('keysym', 0x01a9);
  76. expect(kbdUtil.getKeysym({charCode: 'Š'.charCodeAt(), keyCode: 0x42, which: 0x43})).to.have.property('keysym', 0x01a9);
  77. expect(kbdUtil.getKeysym({char : 'hello', charCode: 'Š'.charCodeAt(), keyCode: 0x42, which: 0x43})).to.have.property('keysym', 0x01a9);
  78. });
  79. it('should use keyCode if no charCode', function() {
  80. expect(kbdUtil.getKeysym({keyCode: 0x42, which: 0x43, shiftKey: false})).to.have.property('keysym', 0x62);
  81. expect(kbdUtil.getKeysym({keyCode: 0x42, which: 0x43, shiftKey: true})).to.have.property('keysym', 0x42);
  82. });
  83. it('should use which if no keyCode', function() {
  84. expect(kbdUtil.getKeysym({which: 0x43, shiftKey: false})).to.have.property('keysym', 0x63);
  85. expect(kbdUtil.getKeysym({which: 0x43, shiftKey: true})).to.have.property('keysym', 0x43);
  86. });
  87. it('should substitute where applicable', function() {
  88. expect(kbdUtil.getKeysym({char : 'Ș'})).to.have.property('keysym', 0x1aa);
  89. });
  90. });
  91. describe('Modifier Sync', function() { // return a list of fake events necessary to fix modifier state
  92. describe('Toggle all modifiers', function() {
  93. var sync = kbdUtil.ModifierSync();
  94. it ('should do nothing if all modifiers are up as expected', function() {
  95. expect(sync.keydown({
  96. keyCode: 0x41,
  97. ctrlKey: false,
  98. altKey: false,
  99. altGraphKey: false,
  100. shiftKey: false,
  101. metaKey: false})
  102. ).to.have.lengthOf(0);
  103. });
  104. it ('should synthesize events if all keys are unexpectedly down', function() {
  105. var result = sync.keydown({
  106. keyCode: 0x41,
  107. ctrlKey: true,
  108. altKey: true,
  109. altGraphKey: true,
  110. shiftKey: true,
  111. metaKey: true
  112. });
  113. expect(result).to.have.lengthOf(5);
  114. var keysyms = {};
  115. for (var i = 0; i < result.length; ++i) {
  116. keysyms[result[i].keysym] = (result[i].type == 'keydown');
  117. }
  118. expect(keysyms[0xffe3]);
  119. expect(keysyms[0xffe9]);
  120. expect(keysyms[0xfe03]);
  121. expect(keysyms[0xffe1]);
  122. expect(keysyms[0xffe7]);
  123. });
  124. it ('should do nothing if all modifiers are down as expected', function() {
  125. expect(sync.keydown({
  126. keyCode: 0x41,
  127. ctrlKey: true,
  128. altKey: true,
  129. altGraphKey: true,
  130. shiftKey: true,
  131. metaKey: true
  132. })).to.have.lengthOf(0);
  133. });
  134. });
  135. describe('Toggle Ctrl', function() {
  136. var sync = kbdUtil.ModifierSync();
  137. it('should sync if modifier is suddenly down', function() {
  138. expect(sync.keydown({
  139. keyCode: 0x41,
  140. ctrlKey: true,
  141. })).to.be.deep.equal([{keysym: keysyms.lookup(0xffe3), type: 'keydown'}]);
  142. });
  143. it('should sync if modifier is suddenly up', function() {
  144. expect(sync.keydown({
  145. keyCode: 0x41,
  146. ctrlKey: false
  147. })).to.be.deep.equal([{keysym: keysyms.lookup(0xffe3), type: 'keyup'}]);
  148. });
  149. });
  150. describe('Toggle Alt', function() {
  151. var sync = kbdUtil.ModifierSync();
  152. it('should sync if modifier is suddenly down', function() {
  153. expect(sync.keydown({
  154. keyCode: 0x41,
  155. altKey: true,
  156. })).to.be.deep.equal([{keysym: keysyms.lookup(0xffe9), type: 'keydown'}]);
  157. });
  158. it('should sync if modifier is suddenly up', function() {
  159. expect(sync.keydown({
  160. keyCode: 0x41,
  161. altKey: false
  162. })).to.be.deep.equal([{keysym: keysyms.lookup(0xffe9), type: 'keyup'}]);
  163. });
  164. });
  165. describe('Toggle AltGr', function() {
  166. var sync = kbdUtil.ModifierSync();
  167. it('should sync if modifier is suddenly down', function() {
  168. expect(sync.keydown({
  169. keyCode: 0x41,
  170. altGraphKey: true,
  171. })).to.be.deep.equal([{keysym: keysyms.lookup(0xfe03), type: 'keydown'}]);
  172. });
  173. it('should sync if modifier is suddenly up', function() {
  174. expect(sync.keydown({
  175. keyCode: 0x41,
  176. altGraphKey: false
  177. })).to.be.deep.equal([{keysym: keysyms.lookup(0xfe03), type: 'keyup'}]);
  178. });
  179. });
  180. describe('Toggle Shift', function() {
  181. var sync = kbdUtil.ModifierSync();
  182. it('should sync if modifier is suddenly down', function() {
  183. expect(sync.keydown({
  184. keyCode: 0x41,
  185. shiftKey: true,
  186. })).to.be.deep.equal([{keysym: keysyms.lookup(0xffe1), type: 'keydown'}]);
  187. });
  188. it('should sync if modifier is suddenly up', function() {
  189. expect(sync.keydown({
  190. keyCode: 0x41,
  191. shiftKey: false
  192. })).to.be.deep.equal([{keysym: keysyms.lookup(0xffe1), type: 'keyup'}]);
  193. });
  194. });
  195. describe('Toggle Meta', function() {
  196. var sync = kbdUtil.ModifierSync();
  197. it('should sync if modifier is suddenly down', function() {
  198. expect(sync.keydown({
  199. keyCode: 0x41,
  200. metaKey: true,
  201. })).to.be.deep.equal([{keysym: keysyms.lookup(0xffe7), type: 'keydown'}]);
  202. });
  203. it('should sync if modifier is suddenly up', function() {
  204. expect(sync.keydown({
  205. keyCode: 0x41,
  206. metaKey: false
  207. })).to.be.deep.equal([{keysym: keysyms.lookup(0xffe7), type: 'keyup'}]);
  208. });
  209. });
  210. describe('Modifier keyevents', function() {
  211. it('should not sync a modifier on its own events', function() {
  212. expect(kbdUtil.ModifierSync().keydown({
  213. keyCode: 0x11,
  214. ctrlKey: false
  215. })).to.be.deep.equal([]);
  216. expect(kbdUtil.ModifierSync().keydown({
  217. keyCode: 0x11,
  218. ctrlKey: true
  219. }), 'B').to.be.deep.equal([]);
  220. })
  221. it('should update state on modifier keyevents', function() {
  222. var sync = kbdUtil.ModifierSync();
  223. sync.keydown({
  224. keyCode: 0x11,
  225. });
  226. expect(sync.keydown({
  227. keyCode: 0x41,
  228. ctrlKey: true,
  229. })).to.be.deep.equal([]);
  230. });
  231. it('should sync other modifiers on ctrl events', function() {
  232. expect(kbdUtil.ModifierSync().keydown({
  233. keyCode: 0x11,
  234. altKey: true
  235. })).to.be.deep.equal([{keysym: keysyms.lookup(0xffe9), type: 'keydown'}]);
  236. })
  237. });
  238. describe('sync modifiers on non-key events', function() {
  239. it('should generate sync events when receiving non-keyboard events', function() {
  240. expect(kbdUtil.ModifierSync().syncAny({
  241. altKey: true
  242. })).to.be.deep.equal([{keysym: keysyms.lookup(0xffe9), type: 'keydown'}]);
  243. });
  244. });
  245. describe('do not treat shift as a modifier key', function() {
  246. it('should not treat shift as a shortcut modifier', function() {
  247. expect(kbdUtil.hasShortcutModifier([], {0xffe1 : true})).to.be.false;
  248. });
  249. it('should not treat shift as a char modifier', function() {
  250. expect(kbdUtil.hasCharModifier([], {0xffe1 : true})).to.be.false;
  251. });
  252. });
  253. });
  254. });