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