]> git.proxmox.com Git - mirror_novnc.git/blame - tests/test.keyboard.js
Move keyboard handling in to Keyboard class
[mirror_novnc.git] / tests / test.keyboard.js
CommitLineData
f00b6fb6 1var assert = chai.assert;
2var expect = chai.expect;
3
f7363fd2 4import { Keyboard } from '../core/input/devices.js';
dfae3209
SR
5import keysyms from '../core/input/keysymdef.js';
6import * as KeyboardUtil from '../core/input/util.js';
7
31f169e8 8/* jshint newcap: false, expr: true */
f7363fd2 9describe('Key Event Handling', function() {
f00b6fb6 10 "use strict";
f00b6fb6 11
f7363fd2
PO
12 // The real KeyboardEvent constructor might not work everywhere we
13 // want to run these tests
14 function keyevent(typeArg, KeyboardEventInit) {
15 var e = { type: typeArg };
16 for (var key in KeyboardEventInit) {
17 e[key] = KeyboardEventInit[key];
18 }
19 e.stopPropagation = sinon.spy();
20 e.preventDefault = sinon.spy();
21 return e;
22 };
f00b6fb6 23
f7363fd2
PO
24 describe('Decode Keyboard Events', function() {
25 it('should decode keydown events', function(done) {
26 var kbd = new Keyboard({
27 onKeyEvent: function(keysym, code, down) {
28 expect(keysym).to.be.equal(0x61);
29 expect(code).to.be.equal('KeyA');
30 expect(down).to.be.equal(true);
31 done();
32 }});
33 kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a'}));
34 });
35 it('should decode keyup events', function(done) {
36 var calls = 0;
37 var kbd = new Keyboard({
38 onKeyEvent: function(keysym, code, down) {
39 expect(keysym).to.be.equal(0x61);
40 expect(code).to.be.equal('KeyA');
41 if (calls++ === 1) {
42 expect(down).to.be.equal(false);
43 done();
44 }
45 }});
46 kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a'}));
47 kbd._handleKeyUp(keyevent('keyup', {code: 'KeyA', key: 'a'}));
48 });
49
50 describe('Legacy keypress Events', function() {
51 it('should wait for keypress when needed', function() {
52 var callback = sinon.spy();
53 var kbd = new Keyboard({onKeyEvent: callback});
54 kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', keyCode: 0x41}));
55 expect(callback).to.not.have.been.called;
56 });
57 it('should decode keypress events', function(done) {
58 var kbd = new Keyboard({
59 onKeyEvent: function(keysym, code, down) {
60 expect(keysym).to.be.equal(0x61);
61 expect(code).to.be.equal('KeyA');
62 expect(down).to.be.equal(true);
63 done();
64 }});
65 kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', keyCode: 0x41}));
66 kbd._handleKeyPress(keyevent('keypress', {code: 'KeyA', charCode: 0x61}));
f00b6fb6 67 });
f00b6fb6 68 });
f00b6fb6 69
f7363fd2
PO
70 describe('suppress the right events at the right time', function() {
71 it('should suppress anything with a valid key', function() {
72 var kbd = new Keyboard({});
73 var evt = keyevent('keydown', {code: 'KeyA', key: 'a'});
74 kbd._handleKeyDown(evt);
75 expect(evt.preventDefault).to.have.been.called;
76 evt = keyevent('keyup', {code: 'KeyA', key: 'a'});
77 kbd._handleKeyUp(evt);
78 expect(evt.preventDefault).to.have.been.called;
79 });
80 it('should not suppress keys without key', function() {
81 var kbd = new Keyboard({});
82 var evt = keyevent('keydown', {code: 'KeyA', keyCode: 0x41});
83 kbd._handleKeyDown(evt);
84 expect(evt.preventDefault).to.not.have.been.called;
85 });
86 it('should suppress the following keypress event', function() {
87 var kbd = new Keyboard({});
88 var evt = keyevent('keydown', {code: 'KeyA', keyCode: 0x41});
89 kbd._handleKeyDown(evt);
90 var evt = keyevent('keypress', {code: 'KeyA', charCode: 0x41});
91 kbd._handleKeyPress(evt);
92 expect(evt.preventDefault).to.have.been.called;
f00b6fb6 93 });
94 });
f00b6fb6 95 });
96
f00b6fb6 97 describe('Track Key State', function() {
f7363fd2
PO
98 it('should send release using the same keysym as the press', function(done) {
99 var kbd = new Keyboard({
100 onKeyEvent: function(keysym, code, down) {
101 expect(keysym).to.be.equal(0x61);
102 expect(code).to.be.equal('KeyA');
103 if (!down) {
104 done();
105 }
106 }});
107 kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a'}));
108 kbd._handleKeyUp(keyevent('keyup', {code: 'KeyA', key: 'b'}));
f00b6fb6 109 });
f7363fd2
PO
110 it('should do nothing on keyup events if no keys are down', function() {
111 var callback = sinon.spy();
112 var kbd = new Keyboard({onKeyEvent: callback});
113 kbd._handleKeyUp(keyevent('keyup', {code: 'KeyA', key: 'a'}));
114 expect(callback).to.not.have.been.called;
115 });
116 it('should send a key release for each key press with the same code', function() {
117 var callback = sinon.spy();
118 var kbd = new Keyboard({onKeyEvent: callback});
119 kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a'}));
120 kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'b'}));
121 kbd._handleKeyUp(keyevent('keyup', {code: 'KeyA'}));
122 expect(callback.callCount).to.be.equal(4);
f00b6fb6 123 });
f7363fd2 124 });
f00b6fb6 125
f7363fd2
PO
126 describe('Escape Modifiers', function() {
127 var origNavigator;
128 beforeEach(function () {
129 // window.navigator is a protected read-only property in many
130 // environments, so we need to redefine it whilst running these
131 // tests.
132 origNavigator = Object.getOwnPropertyDescriptor(window, "navigator");
133 if (origNavigator === undefined) {
134 // Object.getOwnPropertyDescriptor() doesn't work
135 // properly in any version of IE
136 this.skip();
137 }
138
139 Object.defineProperty(window, "navigator", {value: {}});
140 if (window.navigator.platform !== undefined) {
141 // Object.defineProperty() doesn't work properly in old
142 // versions of Chrome
143 this.skip();
144 }
145
146 window.navigator.platform = "Windows x86_64";
147 });
148 afterEach(function () {
149 Object.defineProperty(window, "navigator", origNavigator);
150 });
151
152 it('should generate fake undo/redo events on press when a char modifier is down', function() {
f00b6fb6 153 var times_called = 0;
f7363fd2
PO
154 var kbd = new Keyboard({
155 onKeyEvent: function(keysym, code, down) {
156 switch(times_called++) {
157 case 0:
158 expect(keysym).to.be.equal(0xFFE3);
159 expect(code).to.be.equal('ControlLeft');
160 expect(down).to.be.equal(true);
161 break;
162 case 1:
163 expect(keysym).to.be.equal(0xFFE9);
164 expect(code).to.be.equal('AltLeft');
165 expect(down).to.be.equal(true);
166 break;
167 case 2:
168 expect(keysym).to.be.equal(0xFFE9);
169 expect(code).to.be.equal('Unidentified');
170 expect(down).to.be.equal(false);
171 break;
172 case 3:
173 expect(keysym).to.be.equal(0xFFE3);
174 expect(code).to.be.equal('Unidentified');
175 expect(down).to.be.equal(false);
176 break;
177 case 4:
178 expect(keysym).to.be.equal(0x61);
179 expect(code).to.be.equal('KeyA');
180 expect(down).to.be.equal(true);
181 break;
182 case 5:
183 expect(keysym).to.be.equal(0xFFE9);
184 expect(code).to.be.equal('Unidentified');
185 expect(down).to.be.equal(true);
186 break;
187 case 6:
188 expect(keysym).to.be.equal(0xFFE3);
189 expect(code).to.be.equal('Unidentified');
190 expect(down).to.be.equal(true);
191 break;
192 }
193 }});
194 // First the modifier combo
195 kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control'}));
196 kbd._handleKeyDown(keyevent('keydown', {code: 'AltLeft', key: 'Alt'}));
197 // Next a normal character
198 kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a'}));
199 expect(times_called).to.be.equal(7);
200 });
201 it('should no do anything on key release', function() {
f00b6fb6 202 var times_called = 0;
f7363fd2
PO
203 var kbd = new Keyboard({
204 onKeyEvent: function(keysym, code, down) {
205 switch(times_called++) {
206 case 7:
207 expect(keysym).to.be.equal(0x61);
208 expect(code).to.be.equal('KeyA');
209 expect(down).to.be.equal(false);
210 break;
211 }
212 }});
213 // First the modifier combo
214 kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control'}));
215 kbd._handleKeyDown(keyevent('keydown', {code: 'AltLeft', key: 'Alt'}));
216 // Next a normal character
217 kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a'}));
218 kbd._handleKeyUp(keyevent('keyup', {code: 'KeyA', key: 'a'}));
219 expect(times_called).to.be.equal(8);
220 });
221 it('should not consider a char modifier to be down on the modifier key itself', function() {
f00b6fb6 222 var times_called = 0;
f7363fd2
PO
223 var kbd = new Keyboard({
224 onKeyEvent: function(keysym, code, down) {
225 switch(times_called++) {
226 case 0:
227 expect(keysym).to.be.equal(0xFFE3);
228 expect(code).to.be.equal('ControlLeft');
229 expect(down).to.be.equal(true);
230 break;
231 case 1:
232 expect(keysym).to.be.equal(0xFFE9);
233 expect(code).to.be.equal('AltLeft');
234 expect(down).to.be.equal(true);
235 break;
236 case 2:
237 expect(keysym).to.be.equal(0xFFE3);
238 expect(code).to.be.equal('ControlLeft');
239 expect(down).to.be.equal(true);
240 break;
241 }
242 }});
243 // First the modifier combo
244 kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control'}));
245 kbd._handleKeyDown(keyevent('keydown', {code: 'AltLeft', key: 'Alt'}));
246 // Then one of the keys again
247 kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control'}));
f00b6fb6 248 expect(times_called).to.be.equal(3);
f00b6fb6 249 });
250 });
251});