]>
git.proxmox.com Git - mirror_novnc.git/blob - tests/test.keyboard.js
1 var assert
= chai
.assert
;
2 var expect
= chai
.expect
;
4 import sinon
from '../vendor/sinon.js';
6 import Keyboard
from '../core/input/keyboard.js';
9 return navigator
&& !!(/trident/i).exec(navigator
.userAgent
);
12 return navigator
&& !!(/edge/i).exec(navigator
.userAgent
);
15 /* jshint newcap: false, expr: true */
16 describe('Key Event Handling', function() {
19 // The real KeyboardEvent constructor might not work everywhere we
20 // want to run these tests
21 function keyevent(typeArg
, KeyboardEventInit
) {
22 var e
= { type
: typeArg
};
23 for (var key
in KeyboardEventInit
) {
24 e
[key
] = KeyboardEventInit
[key
];
26 e
.stopPropagation
= sinon
.spy();
27 e
.preventDefault
= sinon
.spy();
31 describe('Decode Keyboard Events', function() {
32 it('should decode keydown events', function(done
) {
33 if (isIE() || isEdge()) this.skip();
34 var kbd
= new Keyboard(document
);
35 kbd
.onkeyevent = function(keysym
, code
, down
) {
36 expect(keysym
).to
.be
.equal(0x61);
37 expect(code
).to
.be
.equal('KeyA');
38 expect(down
).to
.be
.equal(true);
41 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', key
: 'a'}));
43 it('should decode keyup events', function(done
) {
44 if (isIE() || isEdge()) this.skip();
46 var kbd
= new Keyboard(document
);
47 kbd
.onkeyevent = function(keysym
, code
, down
) {
48 expect(keysym
).to
.be
.equal(0x61);
49 expect(code
).to
.be
.equal('KeyA');
51 expect(down
).to
.be
.equal(false);
55 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', key
: 'a'}));
56 kbd
._handleKeyUp(keyevent('keyup', {code
: 'KeyA', key
: 'a'}));
59 describe('Legacy keypress Events', function() {
60 it('should wait for keypress when needed', function() {
61 var kbd
= new Keyboard(document
);
62 kbd
.onkeyevent
= sinon
.spy();
63 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', keyCode
: 0x41}));
64 expect(kbd
.onkeyevent
).to
.not
.have
.been
.called
;
66 it('should decode keypress events', function(done
) {
67 var kbd
= new Keyboard(document
);
68 kbd
.onkeyevent = function(keysym
, code
, down
) {
69 expect(keysym
).to
.be
.equal(0x61);
70 expect(code
).to
.be
.equal('KeyA');
71 expect(down
).to
.be
.equal(true);
74 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', keyCode
: 0x41}));
75 kbd
._handleKeyPress(keyevent('keypress', {code
: 'KeyA', charCode
: 0x61}));
77 it('should ignore keypress with different code', function() {
78 var kbd
= new Keyboard(document
);
79 kbd
.onkeyevent
= sinon
.spy();
80 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', keyCode
: 0x41}));
81 kbd
._handleKeyPress(keyevent('keypress', {code
: 'KeyB', charCode
: 0x61}));
82 expect(kbd
.onkeyevent
).to
.not
.have
.been
.called
;
84 it('should handle keypress with missing code', function(done
) {
85 var kbd
= new Keyboard(document
);
86 kbd
.onkeyevent = function(keysym
, code
, down
) {
87 expect(keysym
).to
.be
.equal(0x61);
88 expect(code
).to
.be
.equal('KeyA');
89 expect(down
).to
.be
.equal(true);
92 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', keyCode
: 0x41}));
93 kbd
._handleKeyPress(keyevent('keypress', {charCode
: 0x61}));
95 it('should guess key if no keypress and numeric key', function(done
) {
96 var kbd
= new Keyboard(document
);
97 kbd
.onkeyevent = function(keysym
, code
, down
) {
98 expect(keysym
).to
.be
.equal(0x32);
99 expect(code
).to
.be
.equal('Digit2');
100 expect(down
).to
.be
.equal(true);
103 kbd
._handleKeyDown(keyevent('keydown', {code
: 'Digit2', keyCode
: 0x32}));
105 it('should guess key if no keypress and alpha key', function(done
) {
106 var kbd
= new Keyboard(document
);
107 kbd
.onkeyevent = function(keysym
, code
, down
) {
108 expect(keysym
).to
.be
.equal(0x61);
109 expect(code
).to
.be
.equal('KeyA');
110 expect(down
).to
.be
.equal(true);
113 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', keyCode
: 0x41, shiftKey
: false}));
115 it('should guess key if no keypress and alpha key (with shift)', function(done
) {
116 var kbd
= new Keyboard(document
);
117 kbd
.onkeyevent = function(keysym
, code
, down
) {
118 expect(keysym
).to
.be
.equal(0x41);
119 expect(code
).to
.be
.equal('KeyA');
120 expect(down
).to
.be
.equal(true);
123 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', keyCode
: 0x41, shiftKey
: true}));
125 it('should not guess key if no keypress and unknown key', function(done
) {
126 var kbd
= new Keyboard(document
);
127 kbd
.onkeyevent = function(keysym
, code
, down
) {
128 expect(keysym
).to
.be
.equal(0);
129 expect(code
).to
.be
.equal('KeyA');
130 expect(down
).to
.be
.equal(true);
133 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', keyCode
: 0x09}));
137 describe('suppress the right events at the right time', function() {
138 beforeEach(function () {
139 if (isIE() || isEdge()) this.skip();
141 it('should suppress anything with a valid key', function() {
142 var kbd
= new Keyboard(document
, {});
143 var evt
= keyevent('keydown', {code
: 'KeyA', key
: 'a'});
144 kbd
._handleKeyDown(evt
);
145 expect(evt
.preventDefault
).to
.have
.been
.called
;
146 evt
= keyevent('keyup', {code
: 'KeyA', key
: 'a'});
147 kbd
._handleKeyUp(evt
);
148 expect(evt
.preventDefault
).to
.have
.been
.called
;
150 it('should not suppress keys without key', function() {
151 var kbd
= new Keyboard(document
, {});
152 var evt
= keyevent('keydown', {code
: 'KeyA', keyCode
: 0x41});
153 kbd
._handleKeyDown(evt
);
154 expect(evt
.preventDefault
).to
.not
.have
.been
.called
;
156 it('should suppress the following keypress event', function() {
157 var kbd
= new Keyboard(document
, {});
158 var evt
= keyevent('keydown', {code
: 'KeyA', keyCode
: 0x41});
159 kbd
._handleKeyDown(evt
);
160 var evt
= keyevent('keypress', {code
: 'KeyA', charCode
: 0x41});
161 kbd
._handleKeyPress(evt
);
162 expect(evt
.preventDefault
).to
.have
.been
.called
;
167 describe('Fake keyup', function() {
168 it('should fake keyup events for virtual keyboards', function(done
) {
169 if (isIE() || isEdge()) this.skip();
171 var kbd
= new Keyboard(document
);
172 kbd
.onkeyevent = function(keysym
, code
, down
) {
175 expect(keysym
).to
.be
.equal(0x61);
176 expect(code
).to
.be
.equal('Unidentified');
177 expect(down
).to
.be
.equal(true);
180 expect(keysym
).to
.be
.equal(0x61);
181 expect(code
).to
.be
.equal('Unidentified');
182 expect(down
).to
.be
.equal(false);
186 kbd
._handleKeyDown(keyevent('keydown', {code
: 'Unidentified', key
: 'a'}));
189 describe('iOS', function() {
191 beforeEach(function () {
192 // window.navigator is a protected read-only property in many
193 // environments, so we need to redefine it whilst running these
195 origNavigator
= Object
.getOwnPropertyDescriptor(window
, "navigator");
196 if (origNavigator
=== undefined) {
197 // Object.getOwnPropertyDescriptor() doesn't work
198 // properly in any version of IE
202 Object
.defineProperty(window
, "navigator", {value
: {}});
203 if (window
.navigator
.platform
!== undefined) {
204 // Object.defineProperty() doesn't work properly in old
205 // versions of Chrome
209 window
.navigator
.platform
= "iPhone 9.0";
211 afterEach(function () {
212 Object
.defineProperty(window
, "navigator", origNavigator
);
215 it('should fake keyup events on iOS', function(done
) {
216 if (isIE() || isEdge()) this.skip();
218 var kbd
= new Keyboard(document
);
219 kbd
.onkeyevent = function(keysym
, code
, down
) {
222 expect(keysym
).to
.be
.equal(0x61);
223 expect(code
).to
.be
.equal('KeyA');
224 expect(down
).to
.be
.equal(true);
227 expect(keysym
).to
.be
.equal(0x61);
228 expect(code
).to
.be
.equal('KeyA');
229 expect(down
).to
.be
.equal(false);
233 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', key
: 'a'}));
238 describe('Track Key State', function() {
239 beforeEach(function () {
240 if (isIE() || isEdge()) this.skip();
242 it('should send release using the same keysym as the press', function(done
) {
243 var kbd
= new Keyboard(document
);
244 kbd
.onkeyevent = function(keysym
, code
, down
) {
245 expect(keysym
).to
.be
.equal(0x61);
246 expect(code
).to
.be
.equal('KeyA');
251 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', key
: 'a'}));
252 kbd
._handleKeyUp(keyevent('keyup', {code
: 'KeyA', key
: 'b'}));
254 it('should send the same keysym for multiple presses', function() {
256 var kbd
= new Keyboard(document
);
257 kbd
.onkeyevent = function(keysym
, code
, down
) {
258 expect(keysym
).to
.be
.equal(0x61);
259 expect(code
).to
.be
.equal('KeyA');
260 expect(down
).to
.be
.equal(true);
263 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', key
: 'a'}));
264 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', key
: 'b'}));
265 expect(count
).to
.be
.equal(2);
267 it('should do nothing on keyup events if no keys are down', function() {
268 var kbd
= new Keyboard(document
);
269 kbd
.onkeyevent
= sinon
.spy();
270 kbd
._handleKeyUp(keyevent('keyup', {code
: 'KeyA', key
: 'a'}));
271 expect(kbd
.onkeyevent
).to
.not
.have
.been
.called
;
274 describe('Legacy Events', function() {
275 it('should track keys using keyCode if no code', function(done
) {
276 var kbd
= new Keyboard(document
);
277 kbd
.onkeyevent = function(keysym
, code
, down
) {
278 expect(keysym
).to
.be
.equal(0x61);
279 expect(code
).to
.be
.equal('Platform65');
284 kbd
._handleKeyDown(keyevent('keydown', {keyCode
: 65, key
: 'a'}));
285 kbd
._handleKeyUp(keyevent('keyup', {keyCode
: 65, key
: 'b'}));
287 it('should ignore compositing code', function() {
288 var kbd
= new Keyboard(document
);
289 kbd
.onkeyevent = function(keysym
, code
, down
) {
290 expect(keysym
).to
.be
.equal(0x61);
291 expect(code
).to
.be
.equal('Unidentified');
293 kbd
._handleKeyDown(keyevent('keydown', {keyCode
: 229, key
: 'a'}));
295 it('should track keys using keyIdentifier if no code', function(done
) {
296 var kbd
= new Keyboard(document
);
297 kbd
.onkeyevent = function(keysym
, code
, down
) {
298 expect(keysym
).to
.be
.equal(0x61);
299 expect(code
).to
.be
.equal('Platform65');
304 kbd
._handleKeyDown(keyevent('keydown', {keyIdentifier
: 'U+0041', key
: 'a'}));
305 kbd
._handleKeyUp(keyevent('keyup', {keyIdentifier
: 'U+0041', key
: 'b'}));
310 describe('Shuffle modifiers on macOS', function() {
312 beforeEach(function () {
313 // window.navigator is a protected read-only property in many
314 // environments, so we need to redefine it whilst running these
316 origNavigator
= Object
.getOwnPropertyDescriptor(window
, "navigator");
317 if (origNavigator
=== undefined) {
318 // Object.getOwnPropertyDescriptor() doesn't work
319 // properly in any version of IE
323 Object
.defineProperty(window
, "navigator", {value
: {}});
324 if (window
.navigator
.platform
!== undefined) {
325 // Object.defineProperty() doesn't work properly in old
326 // versions of Chrome
330 window
.navigator
.platform
= "Mac x86_64";
332 afterEach(function () {
333 Object
.defineProperty(window
, "navigator", origNavigator
);
336 it('should change Alt to AltGraph', function() {
338 var kbd
= new Keyboard(document
);
339 kbd
.onkeyevent = function(keysym
, code
, down
) {
342 expect(keysym
).to
.be
.equal(0xFF7E);
343 expect(code
).to
.be
.equal('AltLeft');
346 expect(keysym
).to
.be
.equal(0xFE03);
347 expect(code
).to
.be
.equal('AltRight');
351 kbd
._handleKeyDown(keyevent('keydown', {code
: 'AltLeft', key
: 'Alt', location
: 1}));
352 kbd
._handleKeyDown(keyevent('keydown', {code
: 'AltRight', key
: 'Alt', location
: 2}));
353 expect(count
).to
.be
.equal(2);
355 it('should change left Super to Alt', function(done
) {
356 var kbd
= new Keyboard(document
);
357 kbd
.onkeyevent = function(keysym
, code
, down
) {
358 expect(keysym
).to
.be
.equal(0xFFE9);
359 expect(code
).to
.be
.equal('MetaLeft');
362 kbd
._handleKeyDown(keyevent('keydown', {code
: 'MetaLeft', key
: 'Meta', location
: 1}));
364 it('should change right Super to left Super', function(done
) {
365 var kbd
= new Keyboard(document
);
366 kbd
.onkeyevent = function(keysym
, code
, down
) {
367 expect(keysym
).to
.be
.equal(0xFFEB);
368 expect(code
).to
.be
.equal('MetaRight');
371 kbd
._handleKeyDown(keyevent('keydown', {code
: 'MetaRight', key
: 'Meta', location
: 2}));
375 describe('Escape AltGraph on Windows', function() {
377 beforeEach(function () {
378 // window.navigator is a protected read-only property in many
379 // environments, so we need to redefine it whilst running these
381 origNavigator
= Object
.getOwnPropertyDescriptor(window
, "navigator");
382 if (origNavigator
=== undefined) {
383 // Object.getOwnPropertyDescriptor() doesn't work
384 // properly in any version of IE
388 Object
.defineProperty(window
, "navigator", {value
: {}});
389 if (window
.navigator
.platform
!== undefined) {
390 // Object.defineProperty() doesn't work properly in old
391 // versions of Chrome
395 window
.navigator
.platform
= "Windows x86_64";
397 afterEach(function () {
398 Object
.defineProperty(window
, "navigator", origNavigator
);
401 it('should generate fake undo/redo events on press when AltGraph is down', function() {
402 var times_called
= 0;
403 var kbd
= new Keyboard(document
);
404 kbd
.onkeyevent = function(keysym
, code
, down
) {
405 switch(times_called
++) {
407 expect(keysym
).to
.be
.equal(0xFFE3);
408 expect(code
).to
.be
.equal('ControlLeft');
409 expect(down
).to
.be
.equal(true);
412 expect(keysym
).to
.be
.equal(0xFFEA);
413 expect(code
).to
.be
.equal('AltRight');
414 expect(down
).to
.be
.equal(true);
417 expect(keysym
).to
.be
.equal(0xFFEA);
418 expect(code
).to
.be
.equal('AltRight');
419 expect(down
).to
.be
.equal(false);
422 expect(keysym
).to
.be
.equal(0xFFE3);
423 expect(code
).to
.be
.equal('ControlLeft');
424 expect(down
).to
.be
.equal(false);
427 expect(keysym
).to
.be
.equal(0x61);
428 expect(code
).to
.be
.equal('KeyA');
429 expect(down
).to
.be
.equal(true);
432 expect(keysym
).to
.be
.equal(0xFFE3);
433 expect(code
).to
.be
.equal('ControlLeft');
434 expect(down
).to
.be
.equal(true);
437 expect(keysym
).to
.be
.equal(0xFFEA);
438 expect(code
).to
.be
.equal('AltRight');
439 expect(down
).to
.be
.equal(true);
443 // First the modifier combo
444 kbd
._handleKeyDown(keyevent('keydown', {code
: 'ControlLeft', key
: 'Control', location
: 1}));
445 kbd
._handleKeyDown(keyevent('keydown', {code
: 'AltRight', key
: 'Alt', location
: 2}));
446 // Next a normal character
447 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', key
: 'a'}));
448 expect(times_called
).to
.be
.equal(7);
450 it('should no do anything on key release', function() {
451 var times_called
= 0;
452 var kbd
= new Keyboard(document
);
453 kbd
.onkeyevent = function(keysym
, code
, down
) {
454 switch(times_called
++) {
456 expect(keysym
).to
.be
.equal(0x61);
457 expect(code
).to
.be
.equal('KeyA');
458 expect(down
).to
.be
.equal(false);
462 // First the modifier combo
463 kbd
._handleKeyDown(keyevent('keydown', {code
: 'ControlLeft', key
: 'Control', location
: 1}));
464 kbd
._handleKeyDown(keyevent('keydown', {code
: 'AltRight', key
: 'Alt', location
: 2}));
465 // Next a normal character
466 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', key
: 'a'}));
467 kbd
._handleKeyUp(keyevent('keyup', {code
: 'KeyA', key
: 'a'}));
468 expect(times_called
).to
.be
.equal(8);
470 it('should not consider a char modifier to be down on the modifier key itself', function() {
471 var times_called
= 0;
472 var kbd
= new Keyboard(document
);
473 kbd
.onkeyevent = function(keysym
, code
, down
) {
474 switch(times_called
++) {
476 expect(keysym
).to
.be
.equal(0xFFE3);
477 expect(code
).to
.be
.equal('ControlLeft');
478 expect(down
).to
.be
.equal(true);
481 expect(keysym
).to
.be
.equal(0xFFE9);
482 expect(code
).to
.be
.equal('AltLeft');
483 expect(down
).to
.be
.equal(true);
486 expect(keysym
).to
.be
.equal(0xFFE3);
487 expect(code
).to
.be
.equal('ControlLeft');
488 expect(down
).to
.be
.equal(true);
492 // First the modifier combo
493 kbd
._handleKeyDown(keyevent('keydown', {code
: 'ControlLeft', key
: 'Control', location
: 1}));
494 kbd
._handleKeyDown(keyevent('keydown', {code
: 'AltLeft', key
: 'Alt', location
: 1}));
495 // Then one of the keys again
496 kbd
._handleKeyDown(keyevent('keydown', {code
: 'ControlLeft', key
: 'Control', location
: 1}));
497 expect(times_called
).to
.be
.equal(3);