]>
git.proxmox.com Git - mirror_novnc.git/blob - tests/test.keyboard.js
1 var assert
= chai
.assert
;
2 var expect
= chai
.expect
;
4 import keysyms
from '../core/input/keysymdef.js';
5 import * as KeyboardUtil
from '../core/input/util.js';
7 /* jshint newcap: false, expr: true */
8 describe('Key Event Pipeline Stages', function() {
10 describe('Decode Keyboard Events', function() {
11 it('should pass events to the next stage', function(done
) {
12 KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync(), function(evt
) {
13 expect(evt
).to
.be
.an
.object
;
15 }).keydown({keyCode
: 0x41});
17 it('should pass the right keysym through', function(done
) {
18 KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync(), function(evt
) {
19 expect(evt
.keysym
).to
.be
.deep
.equal(0x61);
21 }).keypress({keyCode
: 0x41});
23 it('should pass the right keyid through', function(done
) {
24 KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync(), function(evt
) {
25 expect(evt
).to
.have
.property('keyId', 0x41);
27 }).keydown({keyCode
: 0x41});
29 it('should not sync modifiers on a keypress', function() {
30 // Firefox provides unreliable modifier state on keypress events
32 KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync(), function(evt
) {
34 }).keypress({keyCode
: 0x41, ctrlKey
: true});
35 expect(count
).to
.be
.equal(1);
37 it('should sync modifiers if necessary', function(done
) {
39 KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync(), function(evt
) {
41 case 0: // fake a ctrl keydown
42 expect(evt
).to
.be
.deep
.equal({keysym
: 0xffe3, type
: 'keydown'});
46 expect(evt
).to
.be
.deep
.equal({keyId
: 0x41, type
: 'keydown', keysym
: 0x61});
50 }).keydown({keyCode
: 0x41, ctrlKey
: true});
52 it('should forward keydown events with the right type', function(done
) {
53 KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync(), function(evt
) {
54 expect(evt
).to
.be
.deep
.equal({keyId
: 0x41, type
: 'keydown'});
56 }).keydown({keyCode
: 0x41});
58 it('should forward keyup events with the right type', function(done
) {
59 KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync(), function(evt
) {
60 expect(evt
).to
.be
.deep
.equal({keyId
: 0x41, keysym
: 0x61, type
: 'keyup'});
62 }).keyup({keyCode
: 0x41});
64 it('should forward keypress events with the right type', function(done
) {
65 KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync(), function(evt
) {
66 expect(evt
).to
.be
.deep
.equal({keyId
: 0x41, keysym
: 0x61, type
: 'keypress'});
68 }).keypress({keyCode
: 0x41});
70 it('should generate stalls if a char modifier is down while a key is pressed', function(done
) {
72 KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync([0xfe03]), function(evt
) {
75 expect(evt
).to
.be
.deep
.equal({keysym
: 0xfe03, type
: 'keydown'});
78 case 1: // stall before processing the 'a' keydown
79 expect(evt
).to
.be
.deep
.equal({type
: 'stall'});
83 expect(evt
).to
.be
.deep
.equal({
92 }).keydown({keyCode
: 0x41, altGraphKey
: true});
95 describe('suppress the right events at the right time', function() {
96 it('should suppress anything while a shortcut modifier is down', function() {
97 var obj
= KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync(), function(evt
) {});
99 obj
.keydown({keyCode
: 0x11}); // press ctrl
100 expect(obj
.keydown({keyCode
: 'A'.charCodeAt()})).to
.be
.true;
101 expect(obj
.keydown({keyCode
: ' '.charCodeAt()})).to
.be
.true;
102 expect(obj
.keydown({keyCode
: '1'.charCodeAt()})).to
.be
.true;
103 expect(obj
.keydown({keyCode
: 0x3c})).to
.be
.true; // < key on DK Windows
104 expect(obj
.keydown({keyCode
: 0xde})).to
.be
.true; // Ø key on DK
106 it('should suppress non-character keys', function() {
107 var obj
= KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync(), function(evt
) {});
109 expect(obj
.keydown({keyCode
: 0x08}), 'a').to
.be
.true;
110 expect(obj
.keydown({keyCode
: 0x09}), 'b').to
.be
.true;
111 expect(obj
.keydown({keyCode
: 0x11}), 'd').to
.be
.true;
112 expect(obj
.keydown({keyCode
: 0x12}), 'e').to
.be
.true;
114 it('should not suppress shift', function() {
115 var obj
= KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync(), function(evt
) {});
117 expect(obj
.keydown({keyCode
: 0x10}), 'd').to
.be
.false;
119 it('should generate event for shift keydown', function() {
121 var obj
= KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync(), function(evt
) {
122 expect(evt
).to
.have
.property('keysym');
124 }).keydown({keyCode
: 0x10});
125 expect(called
).to
.be
.true;
127 it('should not suppress character keys', function() {
128 var obj
= KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync(), function(evt
) {});
130 expect(obj
.keydown({keyCode
: 'A'.charCodeAt()})).to
.be
.false;
131 expect(obj
.keydown({keyCode
: ' '.charCodeAt()})).to
.be
.false;
132 expect(obj
.keydown({keyCode
: '1'.charCodeAt()})).to
.be
.false;
133 expect(obj
.keydown({keyCode
: 0x3c})).to
.be
.false; // < key on DK Windows
134 expect(obj
.keydown({keyCode
: 0xde})).to
.be
.false; // Ø key on DK
136 it('should not suppress if a char modifier is down', function() {
137 var obj
= KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync([0xfe03]), function(evt
) {});
139 obj
.keydown({keyCode
: 0xe1}); // press altgr
140 expect(obj
.keydown({keyCode
: 'A'.charCodeAt()})).to
.be
.false;
141 expect(obj
.keydown({keyCode
: ' '.charCodeAt()})).to
.be
.false;
142 expect(obj
.keydown({keyCode
: '1'.charCodeAt()})).to
.be
.false;
143 expect(obj
.keydown({keyCode
: 0x3c})).to
.be
.false; // < key on DK Windows
144 expect(obj
.keydown({keyCode
: 0xde})).to
.be
.false; // Ø key on DK
147 describe('Keypress and keyup events', function() {
148 it('should always suppress event propagation', function() {
149 var obj
= KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync(), function(evt
) {});
151 expect(obj
.keypress({keyCode
: 'A'.charCodeAt()})).to
.be
.true;
152 expect(obj
.keypress({keyCode
: 0x3c})).to
.be
.true; // < key on DK Windows
153 expect(obj
.keypress({keyCode
: 0x11})).to
.be
.true;
155 expect(obj
.keyup({keyCode
: 'A'.charCodeAt()})).to
.be
.true;
156 expect(obj
.keyup({keyCode
: 0x3c})).to
.be
.true; // < key on DK Windows
157 expect(obj
.keyup({keyCode
: 0x11})).to
.be
.true;
159 it('should never generate stalls', function() {
160 var obj
= KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync(), function(evt
) {
161 expect(evt
.type
).to
.not
.be
.equal('stall');
164 obj
.keypress({keyCode
: 'A'.charCodeAt()});
165 obj
.keypress({keyCode
: 0x3c});
166 obj
.keypress({keyCode
: 0x11});
168 obj
.keyup({keyCode
: 'A'.charCodeAt()});
169 obj
.keyup({keyCode
: 0x3c});
170 obj
.keyup({keyCode
: 0x11});
173 describe('mark events if a char modifier is down', function() {
174 it('should not mark modifiers on a keydown event', function() {
175 var times_called
= 0;
176 var obj
= KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync([0xfe03]), function(evt
) {
177 switch (times_called
++) {
181 expect(evt
).to
.not
.have
.property('escape');
186 obj
.keydown({keyCode
: 0xe1}); // press altgr
187 obj
.keydown({keyCode
: 'A'.charCodeAt()});
190 it('should indicate on events if a single-key char modifier is down', function(done
) {
191 var times_called
= 0;
192 var obj
= KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync([0xfe03]), function(evt
) {
193 switch (times_called
++) {
197 expect(evt
).to
.be
.deep
.equal({
199 keyId
: 'A'.charCodeAt(),
200 keysym
: 'a'.charCodeAt(),
208 obj
.keydown({keyCode
: 0xe1}); // press altgr
209 obj
.keypress({keyCode
: 'A'.charCodeAt()});
211 it('should indicate on events if a multi-key char modifier is down', function(done
) {
212 var times_called
= 0;
213 var obj
= KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync([0xffe9, 0xffe3]), function(evt
) {
214 switch (times_called
++) {
220 expect(evt
).to
.be
.deep
.equal({
222 keyId
: 'A'.charCodeAt(),
223 keysym
: 'a'.charCodeAt(),
224 escape
: [0xffe9, 0xffe3]
231 obj
.keydown({keyCode
: 0x11}); // press ctrl
232 obj
.keydown({keyCode
: 0x12}); // press alt
233 obj
.keypress({keyCode
: 'A'.charCodeAt()});
235 it('should not consider a char modifier to be down on the modifier key itself', function() {
236 var obj
= KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync([0xfe03]), function(evt
) {
237 expect(evt
).to
.not
.have
.property('escape');
240 obj
.keydown({keyCode
: 0xe1}); // press altgr
244 describe('add/remove keysym', function() {
245 it('should remove keysym from keydown if a char key and no modifier', function() {
246 KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync(), function(evt
) {
247 expect(evt
).to
.be
.deep
.equal({keyId
: 0x41, type
: 'keydown'});
248 }).keydown({keyCode
: 0x41});
250 it('should not remove keysym from keydown if a shortcut modifier is down', function() {
251 var times_called
= 0;
252 KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync(), function(evt
) {
253 switch (times_called
++) {
255 expect(evt
).to
.be
.deep
.equal({keyId
: 0x41, keysym
: 0x61, type
: 'keydown'});
258 }).keydown({keyCode
: 0x41, ctrlKey
: true});
259 expect(times_called
).to
.be
.equal(2);
261 it('should not remove keysym from keydown if a char modifier is down', function() {
262 var times_called
= 0;
263 KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync([0xfe03]), function(evt
) {
264 switch (times_called
++) {
266 expect(evt
).to
.be
.deep
.equal({keyId
: 0x41, keysym
: 0x61, type
: 'keydown'});
269 }).keydown({keyCode
: 0x41, altGraphKey
: true});
270 expect(times_called
).to
.be
.equal(3);
272 it('should not remove keysym from keydown if key is noncharacter', function() {
273 KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync(), function(evt
) {
274 expect(evt
, 'bacobjpace').to
.be
.deep
.equal({keyId
: 0x09, keysym
: 0xff09, type
: 'keydown'});
275 }).keydown({keyCode
: 0x09});
277 KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync(), function(evt
) {
278 expect(evt
, 'ctrl').to
.be
.deep
.equal({keyId
: 0x11, keysym
: 0xffe3, type
: 'keydown'});
279 }).keydown({keyCode
: 0x11});
281 it('should never remove keysym from keypress', function() {
282 KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync(), function(evt
) {
283 expect(evt
).to
.be
.deep
.equal({keyId
: 0x41, keysym
: 0x61, type
: 'keypress'});
284 }).keypress({keyCode
: 0x41});
286 it('should never remove keysym from keyup', function() {
287 KeyboardUtil
.KeyEventDecoder(KeyboardUtil
.ModifierSync(), function(evt
) {
288 expect(evt
).to
.be
.deep
.equal({keyId
: 0x41, keysym
: 0x61, type
: 'keyup'});
289 }).keyup({keyCode
: 0x41});
292 // on keypress, keyup(?), always set keysym
293 // on keydown, only do it if we don't expect a keypress: if noncharacter OR modifier is down
296 describe('Verify that char modifiers are active', function() {
297 it('should pass keydown events through if there is no stall', function(done
) {
298 var obj
= KeyboardUtil
.VerifyCharModifier(function(evt
){
299 expect(evt
).to
.deep
.equal({type
: 'keydown', keyId
: 0x41, keysym
: 0x41});
301 })({type
: 'keydown', keyId
: 0x41, keysym
: 0x41});
303 it('should pass keyup events through if there is no stall', function(done
) {
304 var obj
= KeyboardUtil
.VerifyCharModifier(function(evt
){
305 expect(evt
).to
.deep
.equal({type
: 'keyup', keyId
: 0x41, keysym
: 0x41});
307 })({type
: 'keyup', keyId
: 0x41, keysym
: 0x41});
309 it('should pass keypress events through if there is no stall', function(done
) {
310 var obj
= KeyboardUtil
.VerifyCharModifier(function(evt
){
311 expect(evt
).to
.deep
.equal({type
: 'keypress', keyId
: 0x41, keysym
: 0x41});
313 })({type
: 'keypress', keyId
: 0x41, keysym
: 0x41});
315 it('should not pass stall events through', function(done
){
316 var obj
= KeyboardUtil
.VerifyCharModifier(function(evt
){
317 // should only be called once, for the keydown
318 expect(evt
).to
.deep
.equal({type
: 'keydown', keyId
: 0x41, keysym
: 0x41});
322 obj({type
: 'stall'});
323 obj({type
: 'keydown', keyId
: 0x41, keysym
: 0x41});
325 it('should merge keydown and keypress events if they come after a stall', function(done
) {
326 var next_called
= false;
327 var obj
= KeyboardUtil
.VerifyCharModifier(function(evt
){
328 // should only be called once, for the keydown
329 expect(next_called
).to
.be
.false;
331 expect(evt
).to
.deep
.equal({type
: 'keydown', keyId
: 0x41, keysym
: 0x44});
335 obj({type
: 'stall'});
336 obj({type
: 'keydown', keyId
: 0x41, keysym
: 0x42});
337 obj({type
: 'keypress', keyId
: 0x43, keysym
: 0x44});
338 expect(next_called
).to
.be
.false;
340 it('should preserve modifier attribute when merging if keysyms differ', function(done
) {
341 var next_called
= false;
342 var obj
= KeyboardUtil
.VerifyCharModifier(function(evt
){
343 // should only be called once, for the keydown
344 expect(next_called
).to
.be
.false;
346 expect(evt
).to
.deep
.equal({type
: 'keydown', keyId
: 0x41, keysym
: 0x44, escape
: [0xffe3]});
350 obj({type
: 'stall'});
351 obj({type
: 'keydown', keyId
: 0x41, keysym
: 0x42});
352 obj({type
: 'keypress', keyId
: 0x43, keysym
: 0x44, escape
: [0xffe3]});
353 expect(next_called
).to
.be
.false;
355 it('should not preserve modifier attribute when merging if keysyms are the same', function() {
356 var obj
= KeyboardUtil
.VerifyCharModifier(function(evt
){
357 expect(evt
).to
.not
.have
.property('escape');
360 obj({type
: 'stall'});
361 obj({type
: 'keydown', keyId
: 0x41, keysym
: 0x42});
362 obj({type
: 'keypress', keyId
: 0x43, keysym
: 0x42, escape
: [0xffe3]});
364 it('should not merge keydown and keypress events if there is no stall', function(done
) {
365 var times_called
= 0;
366 var obj
= KeyboardUtil
.VerifyCharModifier(function(evt
){
367 switch(times_called
) {
369 expect(evt
).to
.deep
.equal({type
: 'keydown', keyId
: 0x41, keysym
: 0x42});
372 expect(evt
).to
.deep
.equal({type
: 'keypress', keyId
: 0x43, keysym
: 0x44});
380 obj({type
: 'keydown', keyId
: 0x41, keysym
: 0x42});
381 obj({type
: 'keypress', keyId
: 0x43, keysym
: 0x44});
383 it('should not merge keydown and keypress events if separated by another event', function(done
) {
384 var times_called
= 0;
385 var obj
= KeyboardUtil
.VerifyCharModifier(function(evt
){
386 switch(times_called
) {
388 expect(evt
,1).to
.deep
.equal({type
: 'keydown', keyId
: 0x41, keysym
: 0x42});
391 expect(evt
,2).to
.deep
.equal({type
: 'keyup', keyId
: 0x43, keysym
: 0x44});
394 expect(evt
,3).to
.deep
.equal({type
: 'keypress', keyId
: 0x45, keysym
: 0x46});
402 obj({type
: 'stall'});
403 obj({type
: 'keydown', keyId
: 0x41, keysym
: 0x42});
404 obj({type
: 'keyup', keyId
: 0x43, keysym
: 0x44});
405 obj({type
: 'keypress', keyId
: 0x45, keysym
: 0x46});
409 describe('Track Key State', function() {
410 it('should do nothing on keyup events if no keys are down', function() {
411 var obj
= KeyboardUtil
.TrackKeyState(function(evt
) {
412 expect(true).to
.be
.false;
414 obj({type
: 'keyup', keyId
: 0x41});
416 it('should insert into the queue on keydown if no keys are down', function() {
417 var times_called
= 0;
419 var keysymsdown
= {};
420 var obj
= KeyboardUtil
.TrackKeyState(function(evt
) {
422 if (elem
.type
== 'keyup') {
423 expect(evt
).to
.have
.property('keysym');
424 expect (keysymsdown
[evt
.keysym
]).to
.not
.be
.undefined;
425 delete keysymsdown
[evt
.keysym
];
428 expect(evt
).to
.be
.deep
.equal(elem
);
429 expect (keysymsdown
[evt
.keysym
]).to
.not
.be
.undefined;
434 expect(elem
).to
.be
.null;
435 elem
= {type
: 'keydown', keyId
: 0x41, keysym
: 0x42};
436 keysymsdown
[0x42] = true;
438 expect(elem
).to
.be
.null;
439 elem
= {type
: 'keyup', keyId
: 0x41};
441 expect(elem
).to
.be
.null;
442 expect(times_called
).to
.be
.equal(2);
444 it('should insert into the queue on keypress if no keys are down', function() {
445 var times_called
= 0;
447 var keysymsdown
= {};
448 var obj
= KeyboardUtil
.TrackKeyState(function(evt
) {
450 if (elem
.type
== 'keyup') {
451 expect(evt
).to
.have
.property('keysym');
452 expect (keysymsdown
[evt
.keysym
]).to
.not
.be
.undefined;
453 delete keysymsdown
[evt
.keysym
];
456 expect(evt
).to
.be
.deep
.equal(elem
);
457 expect (keysymsdown
[evt
.keysym
]).to
.not
.be
.undefined;
462 expect(elem
).to
.be
.null;
463 elem
= {type
: 'keypress', keyId
: 0x41, keysym
: 0x42};
464 keysymsdown
[0x42] = true;
466 expect(elem
).to
.be
.null;
467 elem
= {type
: 'keyup', keyId
: 0x41};
469 expect(elem
).to
.be
.null;
470 expect(times_called
).to
.be
.equal(2);
472 it('should add keysym to last key entry if keyId matches', function() {
473 // this implies that a single keyup will release both keysyms
474 var times_called
= 0;
476 var keysymsdown
= {};
477 var obj
= KeyboardUtil
.TrackKeyState(function(evt
) {
479 if (elem
.type
== 'keyup') {
480 expect(evt
).to
.have
.property('keysym');
481 expect (keysymsdown
[evt
.keysym
]).to
.not
.be
.undefined;
482 delete keysymsdown
[evt
.keysym
];
485 expect(evt
).to
.be
.deep
.equal(elem
);
486 expect (keysymsdown
[evt
.keysym
]).to
.not
.be
.undefined;
491 expect(elem
).to
.be
.null;
492 elem
= {type
: 'keypress', keyId
: 0x41, keysym
: 0x42};
493 keysymsdown
[0x42] = true;
495 expect(elem
).to
.be
.null;
496 elem
= {type
: 'keypress', keyId
: 0x41, keysym
: 0x43};
497 keysymsdown
[0x43] = true;
499 expect(elem
).to
.be
.null;
500 elem
= {type
: 'keyup', keyId
: 0x41};
502 expect(times_called
).to
.be
.equal(4);
504 it('should create new key entry if keyId matches and keysym does not', function() {
505 // this implies that a single keyup will release both keysyms
506 var times_called
= 0;
508 var keysymsdown
= {};
509 var obj
= KeyboardUtil
.TrackKeyState(function(evt
) {
511 if (elem
.type
== 'keyup') {
512 expect(evt
).to
.have
.property('keysym');
513 expect (keysymsdown
[evt
.keysym
]).to
.not
.be
.undefined;
514 delete keysymsdown
[evt
.keysym
];
517 expect(evt
).to
.be
.deep
.equal(elem
);
518 expect (keysymsdown
[evt
.keysym
]).to
.not
.be
.undefined;
523 expect(elem
).to
.be
.null;
524 elem
= {type
: 'keydown', keyId
: 0, keysym
: 0x42};
525 keysymsdown
[0x42] = true;
527 expect(elem
).to
.be
.null;
528 elem
= {type
: 'keydown', keyId
: 0, keysym
: 0x43};
529 keysymsdown
[0x43] = true;
531 expect(times_called
).to
.be
.equal(2);
532 expect(elem
).to
.be
.null;
533 elem
= {type
: 'keyup', keyId
: 0};
535 expect(times_called
).to
.be
.equal(3);
536 elem
= {type
: 'keyup', keyId
: 0};
538 expect(times_called
).to
.be
.equal(4);
540 it('should merge key entry if keyIds are zero and keysyms match', function() {
541 // this implies that a single keyup will release both keysyms
542 var times_called
= 0;
544 var keysymsdown
= {};
545 var obj
= KeyboardUtil
.TrackKeyState(function(evt
) {
547 if (elem
.type
== 'keyup') {
548 expect(evt
).to
.have
.property('keysym');
549 expect (keysymsdown
[evt
.keysym
]).to
.not
.be
.undefined;
550 delete keysymsdown
[evt
.keysym
];
553 expect(evt
).to
.be
.deep
.equal(elem
);
554 expect (keysymsdown
[evt
.keysym
]).to
.not
.be
.undefined;
559 expect(elem
).to
.be
.null;
560 elem
= {type
: 'keydown', keyId
: 0, keysym
: 0x42};
561 keysymsdown
[0x42] = true;
563 expect(elem
).to
.be
.null;
564 elem
= {type
: 'keydown', keyId
: 0, keysym
: 0x42};
565 keysymsdown
[0x42] = true;
567 expect(times_called
).to
.be
.equal(2);
568 expect(elem
).to
.be
.null;
569 elem
= {type
: 'keyup', keyId
: 0};
571 expect(times_called
).to
.be
.equal(3);
573 it('should add keysym as separate entry if keyId does not match last event', function() {
574 // this implies that separate keyups are required
575 var times_called
= 0;
577 var keysymsdown
= {};
578 var obj
= KeyboardUtil
.TrackKeyState(function(evt
) {
580 if (elem
.type
== 'keyup') {
581 expect(evt
).to
.have
.property('keysym');
582 expect (keysymsdown
[evt
.keysym
]).to
.not
.be
.undefined;
583 delete keysymsdown
[evt
.keysym
];
586 expect(evt
).to
.be
.deep
.equal(elem
);
587 expect (keysymsdown
[evt
.keysym
]).to
.not
.be
.undefined;
592 expect(elem
).to
.be
.null;
593 elem
= {type
: 'keypress', keyId
: 0x41, keysym
: 0x42};
594 keysymsdown
[0x42] = true;
596 expect(elem
).to
.be
.null;
597 elem
= {type
: 'keypress', keyId
: 0x42, keysym
: 0x43};
598 keysymsdown
[0x43] = true;
600 expect(elem
).to
.be
.null;
601 elem
= {type
: 'keyup', keyId
: 0x41};
603 expect(times_called
).to
.be
.equal(4);
604 elem
= {type
: 'keyup', keyId
: 0x42};
606 expect(times_called
).to
.be
.equal(4);
608 it('should add keysym as separate entry if keyId does not match last event and first is zero', function() {
609 // this implies that separate keyups are required
610 var times_called
= 0;
612 var keysymsdown
= {};
613 var obj
= KeyboardUtil
.TrackKeyState(function(evt
) {
615 if (elem
.type
== 'keyup') {
616 expect(evt
).to
.have
.property('keysym');
617 expect (keysymsdown
[evt
.keysym
]).to
.not
.be
.undefined;
618 delete keysymsdown
[evt
.keysym
];
621 expect(evt
).to
.be
.deep
.equal(elem
);
622 expect (keysymsdown
[evt
.keysym
]).to
.not
.be
.undefined;
627 expect(elem
).to
.be
.null;
628 elem
= {type
: 'keydown', keyId
: 0, keysym
: 0x42};
629 keysymsdown
[0x42] = true;
631 expect(elem
).to
.be
.null;
632 elem
= {type
: 'keydown', keyId
: 0x42, keysym
: 0x43};
633 keysymsdown
[0x43] = true;
635 expect(elem
).to
.be
.null;
636 expect(times_called
).to
.be
.equal(2);
637 elem
= {type
: 'keyup', keyId
: 0};
639 expect(times_called
).to
.be
.equal(3);
640 elem
= {type
: 'keyup', keyId
: 0x42};
642 expect(times_called
).to
.be
.equal(4);
644 it('should add keysym as separate entry if keyId does not match last event and second is zero', function() {
645 // this implies that a separate keyups are required
646 var times_called
= 0;
648 var keysymsdown
= {};
649 var obj
= KeyboardUtil
.TrackKeyState(function(evt
) {
651 if (elem
.type
== 'keyup') {
652 expect(evt
).to
.have
.property('keysym');
653 expect (keysymsdown
[evt
.keysym
]).to
.not
.be
.undefined;
654 delete keysymsdown
[evt
.keysym
];
657 expect(evt
).to
.be
.deep
.equal(elem
);
658 expect (keysymsdown
[evt
.keysym
]).to
.not
.be
.undefined;
663 expect(elem
).to
.be
.null;
664 elem
= {type
: 'keydown', keyId
: 0x41, keysym
: 0x42};
665 keysymsdown
[0x42] = true;
667 expect(elem
).to
.be
.null;
668 elem
= {type
: 'keydown', keyId
: 0, keysym
: 0x43};
669 keysymsdown
[0x43] = true;
671 expect(elem
).to
.be
.null;
672 elem
= {type
: 'keyup', keyId
: 0x41};
674 expect(times_called
).to
.be
.equal(3);
675 elem
= {type
: 'keyup', keyId
: 0};
677 expect(times_called
).to
.be
.equal(4);
679 it('should pop matching key event on keyup', function() {
680 var times_called
= 0;
681 var obj
= KeyboardUtil
.TrackKeyState(function(evt
) {
682 switch (times_called
++) {
686 expect(evt
.type
).to
.be
.equal('keydown');
689 expect(evt
).to
.be
.deep
.equal({type
: 'keyup', keyId
: 0x42, keysym
: 0x62});
694 obj({type
: 'keydown', keyId
: 0x41, keysym
: 0x61});
695 obj({type
: 'keydown', keyId
: 0x42, keysym
: 0x62});
696 obj({type
: 'keydown', keyId
: 0x43, keysym
: 0x63});
697 obj({type
: 'keyup', keyId
: 0x42});
698 expect(times_called
).to
.equal(4);
700 it('should pop the first zero keyevent on keyup with zero keyId', function() {
701 var times_called
= 0;
702 var obj
= KeyboardUtil
.TrackKeyState(function(evt
) {
703 switch (times_called
++) {
707 expect(evt
.type
).to
.be
.equal('keydown');
710 expect(evt
).to
.be
.deep
.equal({type
: 'keyup', keyId
: 0, keysym
: 0x61});
715 obj({type
: 'keydown', keyId
: 0, keysym
: 0x61});
716 obj({type
: 'keydown', keyId
: 0, keysym
: 0x62});
717 obj({type
: 'keydown', keyId
: 0x41, keysym
: 0x63});
718 obj({type
: 'keyup', keyId
: 0x0});
719 expect(times_called
).to
.equal(4);
721 it('should pop the last keyevents keysym if no match is found for keyId', function() {
722 var times_called
= 0;
723 var obj
= KeyboardUtil
.TrackKeyState(function(evt
) {
724 switch (times_called
++) {
728 expect(evt
.type
).to
.be
.equal('keydown');
731 expect(evt
).to
.be
.deep
.equal({type
: 'keyup', keyId
: 0x44, keysym
: 0x63});
736 obj({type
: 'keydown', keyId
: 0x41, keysym
: 0x61});
737 obj({type
: 'keydown', keyId
: 0x42, keysym
: 0x62});
738 obj({type
: 'keydown', keyId
: 0x43, keysym
: 0x63});
739 obj({type
: 'keyup', keyId
: 0x44});
740 expect(times_called
).to
.equal(4);
742 describe('Firefox sends keypress even when keydown is suppressed', function() {
743 it('should discard the keypress', function() {
744 var times_called
= 0;
745 var obj
= KeyboardUtil
.TrackKeyState(function(evt
) {
746 expect(times_called
).to
.be
.equal(0);
750 obj({type
: 'keydown', keyId
: 0x41, keysym
: 0x42});
751 expect(times_called
).to
.be
.equal(1);
752 obj({type
: 'keypress', keyId
: 0x41, keysym
: 0x43});
755 describe('releaseAll', function() {
756 it('should do nothing if no keys have been pressed', function() {
757 var times_called
= 0;
758 var obj
= KeyboardUtil
.TrackKeyState(function(evt
) {
761 obj({type
: 'releaseall'});
762 expect(times_called
).to
.be
.equal(0);
764 it('should release the keys that have been pressed', function() {
765 var times_called
= 0;
766 var obj
= KeyboardUtil
.TrackKeyState(function(evt
) {
767 switch (times_called
++) {
769 expect(evt
).to
.be
.deep
.equal({type
: 'keyup', keyId
: 0, keysym
: 0x41});
772 expect(evt
).to
.be
.deep
.equal({type
: 'keyup', keyId
: 0, keysym
: 0x42});
776 obj({type
: 'keydown', keyId
: 0x41, keysym
: 0x41});
777 obj({type
: 'keydown', keyId
: 0x42, keysym
: 0x42});
778 expect(times_called
).to
.be
.equal(2);
779 obj({type
: 'releaseall'});
780 expect(times_called
).to
.be
.equal(4);
781 obj({type
: 'releaseall'});
782 expect(times_called
).to
.be
.equal(4);
788 describe('Escape Modifiers', function() {
789 describe('Keydown', function() {
790 it('should pass through when a char modifier is not down', function() {
791 var times_called
= 0;
792 KeyboardUtil
.EscapeModifiers(function(evt
) {
793 expect(times_called
).to
.be
.equal(0);
795 expect(evt
).to
.be
.deep
.equal({type
: 'keydown', keyId
: 0x41, keysym
: 0x42});
796 })({type
: 'keydown', keyId
: 0x41, keysym
: 0x42});
797 expect(times_called
).to
.be
.equal(1);
799 it('should generate fake undo/redo events when a char modifier is down', function() {
800 var times_called
= 0;
801 KeyboardUtil
.EscapeModifiers(function(evt
) {
802 switch(times_called
++) {
804 expect(evt
).to
.be
.deep
.equal({type
: 'keyup', keyId
: 0, keysym
: 0xffe9});
807 expect(evt
).to
.be
.deep
.equal({type
: 'keyup', keyId
: 0, keysym
: 0xffe3});
810 expect(evt
).to
.be
.deep
.equal({type
: 'keydown', keyId
: 0x41, keysym
: 0x42, escape
: [0xffe9, 0xffe3]});
813 expect(evt
).to
.be
.deep
.equal({type
: 'keydown', keyId
: 0, keysym
: 0xffe9});
816 expect(evt
).to
.be
.deep
.equal({type
: 'keydown', keyId
: 0, keysym
: 0xffe3});
819 })({type
: 'keydown', keyId
: 0x41, keysym
: 0x42, escape
: [0xffe9, 0xffe3]});
820 expect(times_called
).to
.be
.equal(5);
823 describe('Keyup', function() {
824 it('should pass through when a char modifier is down', function() {
825 var times_called
= 0;
826 KeyboardUtil
.EscapeModifiers(function(evt
) {
827 expect(times_called
).to
.be
.equal(0);
829 expect(evt
).to
.be
.deep
.equal({type
: 'keyup', keyId
: 0x41, keysym
: 0x42, escape
: [0xfe03]});
830 })({type
: 'keyup', keyId
: 0x41, keysym
: 0x42, escape
: [0xfe03]});
831 expect(times_called
).to
.be
.equal(1);
833 it('should pass through when a char modifier is not down', function() {
834 var times_called
= 0;
835 KeyboardUtil
.EscapeModifiers(function(evt
) {
836 expect(times_called
).to
.be
.equal(0);
838 expect(evt
).to
.be
.deep
.equal({type
: 'keyup', keyId
: 0x41, keysym
: 0x42});
839 })({type
: 'keyup', keyId
: 0x41, keysym
: 0x42});
840 expect(times_called
).to
.be
.equal(1);