]> git.proxmox.com Git - mirror_novnc.git/blob - tests/test.mouse.js
Merge branch 'optional-port' of https://github.com/bkylerussell/noVNC
[mirror_novnc.git] / tests / test.mouse.js
1 var assert = chai.assert;
2 var expect = chai.expect;
3
4 import sinon from '../vendor/sinon.js';
5
6 import Mouse from '../core/input/mouse.js';
7 import * as eventUtils from '../core/util/events.js';
8
9 /* jshint newcap: false, expr: true */
10 describe('Mouse Event Handling', function() {
11 "use strict";
12
13 sinon.stub(eventUtils, 'setCapture');
14 // This function is only used on target (the canvas)
15 // and for these tests we can assume that the canvas is 100x100
16 // located at coordinates 10x10
17 sinon.stub(Element.prototype, 'getBoundingClientRect').returns(
18 {left: 10, right: 110, top: 10, bottom: 110, width: 100, height: 100});
19 var target = document.createElement('canvas');
20
21 // The real constructors might not work everywhere we
22 // want to run these tests
23 var mouseevent, touchevent;
24 mouseevent = touchevent = function(typeArg, MouseEventInit) {
25 var e = { type: typeArg };
26 for (var key in MouseEventInit) {
27 e[key] = MouseEventInit[key];
28 }
29 e.stopPropagation = sinon.spy();
30 e.preventDefault = sinon.spy();
31 return e;
32 };
33
34 describe('Decode Mouse Events', function() {
35 it('should decode mousedown events', function(done) {
36 var mouse = new Mouse({
37 onMouseButton: function(x, y, down, bmask) {
38 expect(bmask).to.be.equal(0x01);
39 expect(down).to.be.equal(1);
40 done();
41 },
42 target: target
43 });
44 mouse._handleMouseDown(mouseevent('mousedown', { button: '0x01' }));
45 });
46 it('should decode mouseup events', function(done) {
47 var calls = 0;
48 var mouse = new Mouse({
49 onMouseButton: function(x, y, down, bmask) {
50 expect(bmask).to.be.equal(0x01);
51 if (calls++ === 1) {
52 expect(down).to.not.be.equal(1);
53 done();
54 }
55 },
56 target: target
57 });
58 mouse._handleMouseDown(mouseevent('mousedown', { button: '0x01' }));
59 mouse._handleMouseUp(mouseevent('mouseup', { button: '0x01' }));
60 });
61 it('should decode mousemove events', function(done) {
62 var mouse = new Mouse({
63 onMouseMove: function(x, y) {
64 // Note that target relative coordinates are sent
65 expect(x).to.be.equal(40);
66 expect(y).to.be.equal(10);
67 done();
68 },
69 target: target
70 });
71 mouse._handleMouseMove(mouseevent('mousemove',
72 { clientX: 50, clientY: 20 }));
73 });
74 it('should decode mousewheel events', function(done) {
75 var calls = 0;
76 var mouse = new Mouse({
77 onMouseButton: function(x, y, down, bmask) {
78 calls++;
79 expect(bmask).to.be.equal(1<<6);
80 if (calls === 1) {
81 expect(down).to.be.equal(1);
82 } else if (calls === 2) {
83 expect(down).to.not.be.equal(1);
84 done();
85 }
86 },
87 target: target
88 });
89 mouse._handleMouseWheel(mouseevent('mousewheel',
90 { deltaX: 50, deltaY: 0,
91 deltaMode: 0}));
92 });
93 });
94
95 describe('Double-click for Touch', function() {
96
97 beforeEach(function () { this.clock = sinon.useFakeTimers(); });
98 afterEach(function () { this.clock.restore(); });
99
100 it('should use same pos for 2nd tap if close enough', function(done) {
101 var calls = 0;
102 var mouse = new Mouse({
103 onMouseButton: function(x, y, down, bmask) {
104 calls++;
105 if (calls === 1) {
106 expect(down).to.be.equal(1);
107 expect(x).to.be.equal(68);
108 expect(y).to.be.equal(36);
109 } else if (calls === 3) {
110 expect(down).to.be.equal(1);
111 expect(x).to.be.equal(68);
112 expect(y).to.be.equal(36);
113 done();
114 }
115 },
116 target: target
117 });
118 // touch events are sent in an array of events
119 // with one item for each touch point
120 mouse._handleMouseDown(touchevent(
121 'touchstart', { touches: [{ clientX: 78, clientY: 46 }]}));
122 this.clock.tick(10);
123 mouse._handleMouseUp(touchevent(
124 'touchend', { touches: [{ clientX: 79, clientY: 45 }]}));
125 this.clock.tick(200);
126 mouse._handleMouseDown(touchevent(
127 'touchstart', { touches: [{ clientX: 67, clientY: 35 }]}));
128 this.clock.tick(10);
129 mouse._handleMouseUp(touchevent(
130 'touchend', { touches: [{ clientX: 66, clientY: 36 }]}));
131 });
132
133 it('should not modify 2nd tap pos if far apart', function(done) {
134 var calls = 0;
135 var mouse = new Mouse({
136 onMouseButton: function(x, y, down, bmask) {
137 calls++;
138 if (calls === 1) {
139 expect(down).to.be.equal(1);
140 expect(x).to.be.equal(68);
141 expect(y).to.be.equal(36);
142 } else if (calls === 3) {
143 expect(down).to.be.equal(1);
144 expect(x).to.not.be.equal(68);
145 expect(y).to.not.be.equal(36);
146 done();
147 }
148 },
149 target: target
150 });
151 mouse._handleMouseDown(touchevent(
152 'touchstart', { touches: [{ clientX: 78, clientY: 46 }]}));
153 this.clock.tick(10);
154 mouse._handleMouseUp(touchevent(
155 'touchend', { touches: [{ clientX: 79, clientY: 45 }]}));
156 this.clock.tick(200);
157 mouse._handleMouseDown(touchevent(
158 'touchstart', { touches: [{ clientX: 57, clientY: 35 }]}));
159 this.clock.tick(10);
160 mouse._handleMouseUp(touchevent(
161 'touchend', { touches: [{ clientX: 56, clientY: 36 }]}));
162 });
163
164 it('should not modify 2nd tap pos if not soon enough', function(done) {
165 var calls = 0;
166 var mouse = new Mouse({
167 onMouseButton: function(x, y, down, bmask) {
168 calls++;
169 if (calls === 1) {
170 expect(down).to.be.equal(1);
171 expect(x).to.be.equal(68);
172 expect(y).to.be.equal(36);
173 } else if (calls === 3) {
174 expect(down).to.be.equal(1);
175 expect(x).to.not.be.equal(68);
176 expect(y).to.not.be.equal(36);
177 done();
178 }
179 },
180 target: target
181 });
182 mouse._handleMouseDown(touchevent(
183 'touchstart', { touches: [{ clientX: 78, clientY: 46 }]}));
184 this.clock.tick(10);
185 mouse._handleMouseUp(touchevent(
186 'touchend', { touches: [{ clientX: 79, clientY: 45 }]}));
187 this.clock.tick(500);
188 mouse._handleMouseDown(touchevent(
189 'touchstart', { touches: [{ clientX: 67, clientY: 35 }]}));
190 this.clock.tick(10);
191 mouse._handleMouseUp(touchevent(
192 'touchend', { touches: [{ clientX: 66, clientY: 36 }]}));
193 });
194
195 it('should not modify 2nd tap pos if not touch', function(done) {
196 var calls = 0;
197 var mouse = new Mouse({
198 onMouseButton: function(x, y, down, bmask) {
199 calls++;
200 if (calls === 1) {
201 expect(down).to.be.equal(1);
202 expect(x).to.be.equal(68);
203 expect(y).to.be.equal(36);
204 } else if (calls === 3) {
205 expect(down).to.be.equal(1);
206 expect(x).to.not.be.equal(68);
207 expect(y).to.not.be.equal(36);
208 done();
209 }
210 },
211 target: target
212 });
213 mouse._handleMouseDown(mouseevent(
214 'mousedown', { button: '0x01', clientX: 78, clientY: 46 }));
215 this.clock.tick(10);
216 mouse._handleMouseUp(mouseevent(
217 'mouseup', { button: '0x01', clientX: 79, clientY: 45 }));
218 this.clock.tick(200);
219 mouse._handleMouseDown(mouseevent(
220 'mousedown', { button: '0x01', clientX: 67, clientY: 35 }));
221 this.clock.tick(10);
222 mouse._handleMouseUp(mouseevent(
223 'mouseup', { button: '0x01', clientX: 66, clientY: 36 }));
224 });
225
226 });
227
228 describe('Accumulate mouse wheel events with small delta', function() {
229
230 beforeEach(function () { this.clock = sinon.useFakeTimers(); });
231 afterEach(function () { this.clock.restore(); });
232
233 it('should accumulate wheel events if small enough', function () {
234 var callback = sinon.spy();
235 var mouse = new Mouse({ onMouseButton: callback, target: target });
236
237 mouse._handleMouseWheel(mouseevent(
238 'mousewheel', { clientX: 18, clientY: 40,
239 deltaX: 4, deltaY: 0, deltaMode: 0 }));
240 this.clock.tick(10);
241 mouse._handleMouseWheel(mouseevent(
242 'mousewheel', { clientX: 18, clientY: 40,
243 deltaX: 4, deltaY: 0, deltaMode: 0 }));
244
245 // threshold is 10
246 expect(mouse._accumulatedWheelDeltaX).to.be.equal(8);
247
248 this.clock.tick(10);
249 mouse._handleMouseWheel(mouseevent(
250 'mousewheel', { clientX: 18, clientY: 40,
251 deltaX: 4, deltaY: 0, deltaMode: 0 }));
252
253 expect(callback).to.have.callCount(2); // mouse down and up
254
255 this.clock.tick(10);
256 mouse._handleMouseWheel(mouseevent(
257 'mousewheel', { clientX: 18, clientY: 40,
258 deltaX: 4, deltaY: 9, deltaMode: 0 }));
259
260 expect(mouse._accumulatedWheelDeltaX).to.be.equal(4);
261 expect(mouse._accumulatedWheelDeltaY).to.be.equal(9);
262
263 expect(callback).to.have.callCount(2); // still
264 });
265
266 it('should not accumulate large wheel events', function () {
267 var callback = sinon.spy();
268 var mouse = new Mouse({ onMouseButton: callback, target: target });
269
270 mouse._handleMouseWheel(mouseevent(
271 'mousewheel', { clientX: 18, clientY: 40,
272 deltaX: 11, deltaY: 0, deltaMode: 0 }));
273 this.clock.tick(10);
274 mouse._handleMouseWheel(mouseevent(
275 'mousewheel', { clientX: 18, clientY: 40,
276 deltaX: 0, deltaY: 70, deltaMode: 0 }));
277 this.clock.tick(10);
278 mouse._handleMouseWheel(mouseevent(
279 'mousewheel', { clientX: 18, clientY: 40,
280 deltaX: 400, deltaY: 400, deltaMode: 0 }));
281
282 expect(callback).to.have.callCount(8); // mouse down and up
283 });
284
285 it('should send even small wheel events after a timeout', function () {
286 var callback = sinon.spy();
287 var mouse = new Mouse({ onMouseButton: callback, target: target });
288
289 mouse._handleMouseWheel(mouseevent(
290 'mousewheel', { clientX: 18, clientY: 40,
291 deltaX: 1, deltaY: 0, deltaMode: 0 }));
292 this.clock.tick(51); // timeout on 50 ms
293
294 expect(callback).to.have.callCount(2); // mouse down and up
295 });
296
297 it('should account for non-zero deltaMode', function () {
298 var callback = sinon.spy();
299 var mouse = new Mouse({ onMouseButton: callback, target: target });
300
301 mouse._handleMouseWheel(mouseevent(
302 'mousewheel', { clientX: 18, clientY: 40,
303 deltaX: 0, deltaY: 2, deltaMode: 1 }));
304
305 this.clock.tick(10);
306
307 mouse._handleMouseWheel(mouseevent(
308 'mousewheel', { clientX: 18, clientY: 40,
309 deltaX: 1, deltaY: 0, deltaMode: 2 }));
310
311 expect(callback).to.have.callCount(4); // mouse down and up
312 });
313 });
314
315 });