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