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