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