]>
git.proxmox.com Git - mirror_novnc.git/blob - tests/test.keyboard.js
cb273c33e0297fee904f02cbe395c3578c433aa0
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 describe('Key Event Handling', function() {
18 // The real KeyboardEvent constructor might not work everywhere we
19 // want to run these tests
20 function keyevent(typeArg
, KeyboardEventInit
) {
21 var e
= { type
: typeArg
};
22 for (var key
in KeyboardEventInit
) {
23 e
[key
] = KeyboardEventInit
[key
];
25 e
.stopPropagation
= sinon
.spy();
26 e
.preventDefault
= sinon
.spy();
30 describe('Decode Keyboard Events', function() {
31 it('should decode keydown events', function(done
) {
32 if (isIE() || isEdge()) this.skip();
33 var kbd
= new Keyboard(document
);
34 kbd
.onkeyevent = function(keysym
, code
, down
) {
35 expect(keysym
).to
.be
.equal(0x61);
36 expect(code
).to
.be
.equal('KeyA');
37 expect(down
).to
.be
.equal(true);
40 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', key
: 'a'}));
42 it('should decode keyup events', function(done
) {
43 if (isIE() || isEdge()) this.skip();
45 var kbd
= new Keyboard(document
);
46 kbd
.onkeyevent = function(keysym
, code
, down
) {
47 expect(keysym
).to
.be
.equal(0x61);
48 expect(code
).to
.be
.equal('KeyA');
50 expect(down
).to
.be
.equal(false);
54 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', key
: 'a'}));
55 kbd
._handleKeyUp(keyevent('keyup', {code
: 'KeyA', key
: 'a'}));
58 describe('Legacy keypress Events', function() {
59 it('should wait for keypress when needed', function() {
60 var kbd
= new Keyboard(document
);
61 kbd
.onkeyevent
= sinon
.spy();
62 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', keyCode
: 0x41}));
63 expect(kbd
.onkeyevent
).to
.not
.have
.been
.called
;
65 it('should decode keypress events', function(done
) {
66 var kbd
= new Keyboard(document
);
67 kbd
.onkeyevent = function(keysym
, code
, down
) {
68 expect(keysym
).to
.be
.equal(0x61);
69 expect(code
).to
.be
.equal('KeyA');
70 expect(down
).to
.be
.equal(true);
73 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', keyCode
: 0x41}));
74 kbd
._handleKeyPress(keyevent('keypress', {code
: 'KeyA', charCode
: 0x61}));
76 it('should ignore keypress with different code', function() {
77 var kbd
= new Keyboard(document
);
78 kbd
.onkeyevent
= sinon
.spy();
79 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', keyCode
: 0x41}));
80 kbd
._handleKeyPress(keyevent('keypress', {code
: 'KeyB', charCode
: 0x61}));
81 expect(kbd
.onkeyevent
).to
.not
.have
.been
.called
;
83 it('should handle keypress with missing code', function(done
) {
84 var kbd
= new Keyboard(document
);
85 kbd
.onkeyevent = function(keysym
, code
, down
) {
86 expect(keysym
).to
.be
.equal(0x61);
87 expect(code
).to
.be
.equal('KeyA');
88 expect(down
).to
.be
.equal(true);
91 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', keyCode
: 0x41}));
92 kbd
._handleKeyPress(keyevent('keypress', {charCode
: 0x61}));
94 it('should guess key if no keypress and numeric key', function(done
) {
95 var kbd
= new Keyboard(document
);
96 kbd
.onkeyevent = function(keysym
, code
, down
) {
97 expect(keysym
).to
.be
.equal(0x32);
98 expect(code
).to
.be
.equal('Digit2');
99 expect(down
).to
.be
.equal(true);
102 kbd
._handleKeyDown(keyevent('keydown', {code
: 'Digit2', keyCode
: 0x32}));
104 it('should guess key if no keypress and alpha key', function(done
) {
105 var kbd
= new Keyboard(document
);
106 kbd
.onkeyevent = function(keysym
, code
, down
) {
107 expect(keysym
).to
.be
.equal(0x61);
108 expect(code
).to
.be
.equal('KeyA');
109 expect(down
).to
.be
.equal(true);
112 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', keyCode
: 0x41, shiftKey
: false}));
114 it('should guess key if no keypress and alpha key (with shift)', function(done
) {
115 var kbd
= new Keyboard(document
);
116 kbd
.onkeyevent = function(keysym
, code
, down
) {
117 expect(keysym
).to
.be
.equal(0x41);
118 expect(code
).to
.be
.equal('KeyA');
119 expect(down
).to
.be
.equal(true);
122 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', keyCode
: 0x41, shiftKey
: true}));
124 it('should not guess key if no keypress and unknown key', function(done
) {
125 var kbd
= new Keyboard(document
);
126 kbd
.onkeyevent = function(keysym
, code
, down
) {
127 expect(keysym
).to
.be
.equal(0);
128 expect(code
).to
.be
.equal('KeyA');
129 expect(down
).to
.be
.equal(true);
132 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', keyCode
: 0x09}));
136 describe('suppress the right events at the right time', function() {
137 beforeEach(function () {
138 if (isIE() || isEdge()) this.skip();
140 it('should suppress anything with a valid key', function() {
141 var kbd
= new Keyboard(document
, {});
142 var evt
= keyevent('keydown', {code
: 'KeyA', key
: 'a'});
143 kbd
._handleKeyDown(evt
);
144 expect(evt
.preventDefault
).to
.have
.been
.called
;
145 evt
= keyevent('keyup', {code
: 'KeyA', key
: 'a'});
146 kbd
._handleKeyUp(evt
);
147 expect(evt
.preventDefault
).to
.have
.been
.called
;
149 it('should not suppress keys without key', function() {
150 var kbd
= new Keyboard(document
, {});
151 var evt
= keyevent('keydown', {code
: 'KeyA', keyCode
: 0x41});
152 kbd
._handleKeyDown(evt
);
153 expect(evt
.preventDefault
).to
.not
.have
.been
.called
;
155 it('should suppress the following keypress event', function() {
156 var kbd
= new Keyboard(document
, {});
157 var evt
= keyevent('keydown', {code
: 'KeyA', keyCode
: 0x41});
158 kbd
._handleKeyDown(evt
);
159 var evt
= keyevent('keypress', {code
: 'KeyA', charCode
: 0x41});
160 kbd
._handleKeyPress(evt
);
161 expect(evt
.preventDefault
).to
.have
.been
.called
;
166 describe('Fake keyup', function() {
167 it('should fake keyup events for virtual keyboards', function(done
) {
168 if (isIE() || isEdge()) this.skip();
170 var kbd
= new Keyboard(document
);
171 kbd
.onkeyevent = function(keysym
, code
, down
) {
174 expect(keysym
).to
.be
.equal(0x61);
175 expect(code
).to
.be
.equal('Unidentified');
176 expect(down
).to
.be
.equal(true);
179 expect(keysym
).to
.be
.equal(0x61);
180 expect(code
).to
.be
.equal('Unidentified');
181 expect(down
).to
.be
.equal(false);
185 kbd
._handleKeyDown(keyevent('keydown', {code
: 'Unidentified', key
: 'a'}));
188 describe('iOS', function() {
190 beforeEach(function () {
191 // window.navigator is a protected read-only property in many
192 // environments, so we need to redefine it whilst running these
194 origNavigator
= Object
.getOwnPropertyDescriptor(window
, "navigator");
195 if (origNavigator
=== undefined) {
196 // Object.getOwnPropertyDescriptor() doesn't work
197 // properly in any version of IE
201 Object
.defineProperty(window
, "navigator", {value
: {}});
202 if (window
.navigator
.platform
!== undefined) {
203 // Object.defineProperty() doesn't work properly in old
204 // versions of Chrome
208 window
.navigator
.platform
= "iPhone 9.0";
210 afterEach(function () {
211 Object
.defineProperty(window
, "navigator", origNavigator
);
214 it('should fake keyup events on iOS', function(done
) {
215 if (isIE() || isEdge()) this.skip();
217 var kbd
= new Keyboard(document
);
218 kbd
.onkeyevent = function(keysym
, code
, down
) {
221 expect(keysym
).to
.be
.equal(0x61);
222 expect(code
).to
.be
.equal('KeyA');
223 expect(down
).to
.be
.equal(true);
226 expect(keysym
).to
.be
.equal(0x61);
227 expect(code
).to
.be
.equal('KeyA');
228 expect(down
).to
.be
.equal(false);
232 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', key
: 'a'}));
237 describe('Track Key State', function() {
238 beforeEach(function () {
239 if (isIE() || isEdge()) this.skip();
241 it('should send release using the same keysym as the press', function(done
) {
242 var kbd
= new Keyboard(document
);
243 kbd
.onkeyevent = function(keysym
, code
, down
) {
244 expect(keysym
).to
.be
.equal(0x61);
245 expect(code
).to
.be
.equal('KeyA');
250 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', key
: 'a'}));
251 kbd
._handleKeyUp(keyevent('keyup', {code
: 'KeyA', key
: 'b'}));
253 it('should send the same keysym for multiple presses', function() {
255 var kbd
= new Keyboard(document
);
256 kbd
.onkeyevent = function(keysym
, code
, down
) {
257 expect(keysym
).to
.be
.equal(0x61);
258 expect(code
).to
.be
.equal('KeyA');
259 expect(down
).to
.be
.equal(true);
262 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', key
: 'a'}));
263 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', key
: 'b'}));
264 expect(count
).to
.be
.equal(2);
266 it('should do nothing on keyup events if no keys are down', function() {
267 var kbd
= new Keyboard(document
);
268 kbd
.onkeyevent
= sinon
.spy();
269 kbd
._handleKeyUp(keyevent('keyup', {code
: 'KeyA', key
: 'a'}));
270 expect(kbd
.onkeyevent
).to
.not
.have
.been
.called
;
273 describe('Legacy Events', function() {
274 it('should track keys using keyCode if no code', function(done
) {
275 var kbd
= new Keyboard(document
);
276 kbd
.onkeyevent = function(keysym
, code
, down
) {
277 expect(keysym
).to
.be
.equal(0x61);
278 expect(code
).to
.be
.equal('Platform65');
283 kbd
._handleKeyDown(keyevent('keydown', {keyCode
: 65, key
: 'a'}));
284 kbd
._handleKeyUp(keyevent('keyup', {keyCode
: 65, key
: 'b'}));
286 it('should ignore compositing code', function() {
287 var kbd
= new Keyboard(document
);
288 kbd
.onkeyevent = function(keysym
, code
, down
) {
289 expect(keysym
).to
.be
.equal(0x61);
290 expect(code
).to
.be
.equal('Unidentified');
292 kbd
._handleKeyDown(keyevent('keydown', {keyCode
: 229, key
: 'a'}));
294 it('should track keys using keyIdentifier if no code', function(done
) {
295 var kbd
= new Keyboard(document
);
296 kbd
.onkeyevent = function(keysym
, code
, down
) {
297 expect(keysym
).to
.be
.equal(0x61);
298 expect(code
).to
.be
.equal('Platform65');
303 kbd
._handleKeyDown(keyevent('keydown', {keyIdentifier
: 'U+0041', key
: 'a'}));
304 kbd
._handleKeyUp(keyevent('keyup', {keyIdentifier
: 'U+0041', key
: 'b'}));
309 describe('Shuffle modifiers on macOS', function() {
311 beforeEach(function () {
312 // window.navigator is a protected read-only property in many
313 // environments, so we need to redefine it whilst running these
315 origNavigator
= Object
.getOwnPropertyDescriptor(window
, "navigator");
316 if (origNavigator
=== undefined) {
317 // Object.getOwnPropertyDescriptor() doesn't work
318 // properly in any version of IE
322 Object
.defineProperty(window
, "navigator", {value
: {}});
323 if (window
.navigator
.platform
!== undefined) {
324 // Object.defineProperty() doesn't work properly in old
325 // versions of Chrome
329 window
.navigator
.platform
= "Mac x86_64";
331 afterEach(function () {
332 Object
.defineProperty(window
, "navigator", origNavigator
);
335 it('should change Alt to AltGraph', function() {
337 var kbd
= new Keyboard(document
);
338 kbd
.onkeyevent = function(keysym
, code
, down
) {
341 expect(keysym
).to
.be
.equal(0xFF7E);
342 expect(code
).to
.be
.equal('AltLeft');
345 expect(keysym
).to
.be
.equal(0xFE03);
346 expect(code
).to
.be
.equal('AltRight');
350 kbd
._handleKeyDown(keyevent('keydown', {code
: 'AltLeft', key
: 'Alt', location
: 1}));
351 kbd
._handleKeyDown(keyevent('keydown', {code
: 'AltRight', key
: 'Alt', location
: 2}));
352 expect(count
).to
.be
.equal(2);
354 it('should change left Super to Alt', function(done
) {
355 var kbd
= new Keyboard(document
);
356 kbd
.onkeyevent = function(keysym
, code
, down
) {
357 expect(keysym
).to
.be
.equal(0xFFE9);
358 expect(code
).to
.be
.equal('MetaLeft');
361 kbd
._handleKeyDown(keyevent('keydown', {code
: 'MetaLeft', key
: 'Meta', location
: 1}));
363 it('should change right Super to left Super', function(done
) {
364 var kbd
= new Keyboard(document
);
365 kbd
.onkeyevent = function(keysym
, code
, down
) {
366 expect(keysym
).to
.be
.equal(0xFFEB);
367 expect(code
).to
.be
.equal('MetaRight');
370 kbd
._handleKeyDown(keyevent('keydown', {code
: 'MetaRight', key
: 'Meta', location
: 2}));
374 describe('Escape AltGraph on Windows', function() {
376 beforeEach(function () {
377 // window.navigator is a protected read-only property in many
378 // environments, so we need to redefine it whilst running these
380 origNavigator
= Object
.getOwnPropertyDescriptor(window
, "navigator");
381 if (origNavigator
=== undefined) {
382 // Object.getOwnPropertyDescriptor() doesn't work
383 // properly in any version of IE
387 Object
.defineProperty(window
, "navigator", {value
: {}});
388 if (window
.navigator
.platform
!== undefined) {
389 // Object.defineProperty() doesn't work properly in old
390 // versions of Chrome
394 window
.navigator
.platform
= "Windows x86_64";
396 afterEach(function () {
397 Object
.defineProperty(window
, "navigator", origNavigator
);
400 it('should generate fake undo/redo events on press when AltGraph is down', function() {
401 var times_called
= 0;
402 var kbd
= new Keyboard(document
);
403 kbd
.onkeyevent = function(keysym
, code
, down
) {
404 switch(times_called
++) {
406 expect(keysym
).to
.be
.equal(0xFFE3);
407 expect(code
).to
.be
.equal('ControlLeft');
408 expect(down
).to
.be
.equal(true);
411 expect(keysym
).to
.be
.equal(0xFFEA);
412 expect(code
).to
.be
.equal('AltRight');
413 expect(down
).to
.be
.equal(true);
416 expect(keysym
).to
.be
.equal(0xFFEA);
417 expect(code
).to
.be
.equal('AltRight');
418 expect(down
).to
.be
.equal(false);
421 expect(keysym
).to
.be
.equal(0xFFE3);
422 expect(code
).to
.be
.equal('ControlLeft');
423 expect(down
).to
.be
.equal(false);
426 expect(keysym
).to
.be
.equal(0x61);
427 expect(code
).to
.be
.equal('KeyA');
428 expect(down
).to
.be
.equal(true);
431 expect(keysym
).to
.be
.equal(0xFFE3);
432 expect(code
).to
.be
.equal('ControlLeft');
433 expect(down
).to
.be
.equal(true);
436 expect(keysym
).to
.be
.equal(0xFFEA);
437 expect(code
).to
.be
.equal('AltRight');
438 expect(down
).to
.be
.equal(true);
442 // First the modifier combo
443 kbd
._handleKeyDown(keyevent('keydown', {code
: 'ControlLeft', key
: 'Control', location
: 1}));
444 kbd
._handleKeyDown(keyevent('keydown', {code
: 'AltRight', key
: 'Alt', location
: 2}));
445 // Next a normal character
446 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', key
: 'a'}));
447 expect(times_called
).to
.be
.equal(7);
449 it('should no do anything on key release', function() {
450 var times_called
= 0;
451 var kbd
= new Keyboard(document
);
452 kbd
.onkeyevent = function(keysym
, code
, down
) {
453 switch(times_called
++) {
455 expect(keysym
).to
.be
.equal(0x61);
456 expect(code
).to
.be
.equal('KeyA');
457 expect(down
).to
.be
.equal(false);
461 // First the modifier combo
462 kbd
._handleKeyDown(keyevent('keydown', {code
: 'ControlLeft', key
: 'Control', location
: 1}));
463 kbd
._handleKeyDown(keyevent('keydown', {code
: 'AltRight', key
: 'Alt', location
: 2}));
464 // Next a normal character
465 kbd
._handleKeyDown(keyevent('keydown', {code
: 'KeyA', key
: 'a'}));
466 kbd
._handleKeyUp(keyevent('keyup', {code
: 'KeyA', key
: 'a'}));
467 expect(times_called
).to
.be
.equal(8);
469 it('should not consider a char modifier to be down on the modifier key itself', function() {
470 var times_called
= 0;
471 var kbd
= new Keyboard(document
);
472 kbd
.onkeyevent = function(keysym
, code
, down
) {
473 switch(times_called
++) {
475 expect(keysym
).to
.be
.equal(0xFFE3);
476 expect(code
).to
.be
.equal('ControlLeft');
477 expect(down
).to
.be
.equal(true);
480 expect(keysym
).to
.be
.equal(0xFFE9);
481 expect(code
).to
.be
.equal('AltLeft');
482 expect(down
).to
.be
.equal(true);
485 expect(keysym
).to
.be
.equal(0xFFE3);
486 expect(code
).to
.be
.equal('ControlLeft');
487 expect(down
).to
.be
.equal(true);
491 // First the modifier combo
492 kbd
._handleKeyDown(keyevent('keydown', {code
: 'ControlLeft', key
: 'Control', location
: 1}));
493 kbd
._handleKeyDown(keyevent('keydown', {code
: 'AltLeft', key
: 'Alt', location
: 1}));
494 // Then one of the keys again
495 kbd
._handleKeyDown(keyevent('keydown', {code
: 'ControlLeft', key
: 'Control', location
: 1}));
496 expect(times_called
).to
.be
.equal(3);