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