mirror of
https://github.com/novnc/noVNC.git
synced 2026-05-26 23:19:41 +00:00
It is not allowed and only happens to work because babel doesn't strictly follow the specification. It doesn't seem necessary for the tests to run, so just remove it.
294 lines
12 KiB
JavaScript
294 lines
12 KiB
JavaScript
const expect = chai.expect;
|
|
|
|
import Mouse from '../core/input/mouse.js';
|
|
|
|
describe('Mouse Event Handling', function() {
|
|
"use strict";
|
|
|
|
// This function is only used on target (the canvas)
|
|
// and for these tests we can assume that the canvas is 100x100
|
|
// located at coordinates 10x10
|
|
sinon.stub(Element.prototype, 'getBoundingClientRect').returns(
|
|
{left: 10, right: 110, top: 10, bottom: 110, width: 100, height: 100});
|
|
const target = document.createElement('canvas');
|
|
|
|
// The real constructors might not work everywhere we
|
|
// want to run these tests
|
|
const mouseevent = (typeArg, MouseEventInit) => {
|
|
const e = { type: typeArg };
|
|
for (let key in MouseEventInit) {
|
|
e[key] = MouseEventInit[key];
|
|
}
|
|
e.stopPropagation = sinon.spy();
|
|
e.preventDefault = sinon.spy();
|
|
return e;
|
|
};
|
|
const touchevent = mouseevent;
|
|
|
|
describe('Decode Mouse Events', function() {
|
|
it('should decode mousedown events', function(done) {
|
|
const mouse = new Mouse(target);
|
|
mouse.onmousebutton = (x, y, down, bmask) => {
|
|
expect(bmask).to.be.equal(0x01);
|
|
expect(down).to.be.equal(1);
|
|
done();
|
|
};
|
|
mouse._handleMouseDown(mouseevent('mousedown', { button: '0x01' }));
|
|
});
|
|
it('should decode mouseup events', function(done) {
|
|
let calls = 0;
|
|
const mouse = new Mouse(target);
|
|
mouse.onmousebutton = (x, y, down, bmask) => {
|
|
expect(bmask).to.be.equal(0x01);
|
|
if (calls++ === 1) {
|
|
expect(down).to.not.be.equal(1);
|
|
done();
|
|
}
|
|
};
|
|
mouse._handleMouseDown(mouseevent('mousedown', { button: '0x01' }));
|
|
mouse._handleMouseUp(mouseevent('mouseup', { button: '0x01' }));
|
|
});
|
|
it('should decode mousemove events', function(done) {
|
|
const mouse = new Mouse(target);
|
|
mouse.onmousemove = (x, y) => {
|
|
// Note that target relative coordinates are sent
|
|
expect(x).to.be.equal(40);
|
|
expect(y).to.be.equal(10);
|
|
done();
|
|
};
|
|
mouse._handleMouseMove(mouseevent('mousemove',
|
|
{ clientX: 50, clientY: 20 }));
|
|
});
|
|
it('should decode mousewheel events', function(done) {
|
|
let calls = 0;
|
|
const mouse = new Mouse(target);
|
|
mouse.onmousebutton = (x, y, down, bmask) => {
|
|
calls++;
|
|
expect(bmask).to.be.equal(1<<6);
|
|
if (calls === 1) {
|
|
expect(down).to.be.equal(1);
|
|
} else if (calls === 2) {
|
|
expect(down).to.not.be.equal(1);
|
|
done();
|
|
}
|
|
};
|
|
mouse._handleMouseWheel(mouseevent('mousewheel',
|
|
{ deltaX: 50, deltaY: 0,
|
|
deltaMode: 0}));
|
|
});
|
|
});
|
|
|
|
describe('Double-click for Touch', function() {
|
|
|
|
beforeEach(function () { this.clock = sinon.useFakeTimers(); });
|
|
afterEach(function () { this.clock.restore(); });
|
|
|
|
it('should use same pos for 2nd tap if close enough', function(done) {
|
|
let calls = 0;
|
|
const mouse = new Mouse(target);
|
|
mouse.onmousebutton = (x, y, down, bmask) => {
|
|
calls++;
|
|
if (calls === 1) {
|
|
expect(down).to.be.equal(1);
|
|
expect(x).to.be.equal(68);
|
|
expect(y).to.be.equal(36);
|
|
} else if (calls === 3) {
|
|
expect(down).to.be.equal(1);
|
|
expect(x).to.be.equal(68);
|
|
expect(y).to.be.equal(36);
|
|
done();
|
|
}
|
|
};
|
|
// touch events are sent in an array of events
|
|
// with one item for each touch point
|
|
mouse._handleMouseDown(touchevent(
|
|
'touchstart', { touches: [{ clientX: 78, clientY: 46 }]}));
|
|
this.clock.tick(10);
|
|
mouse._handleMouseUp(touchevent(
|
|
'touchend', { touches: [{ clientX: 79, clientY: 45 }]}));
|
|
this.clock.tick(200);
|
|
mouse._handleMouseDown(touchevent(
|
|
'touchstart', { touches: [{ clientX: 67, clientY: 35 }]}));
|
|
this.clock.tick(10);
|
|
mouse._handleMouseUp(touchevent(
|
|
'touchend', { touches: [{ clientX: 66, clientY: 36 }]}));
|
|
});
|
|
|
|
it('should not modify 2nd tap pos if far apart', function(done) {
|
|
let calls = 0;
|
|
const mouse = new Mouse(target);
|
|
mouse.onmousebutton = (x, y, down, bmask) => {
|
|
calls++;
|
|
if (calls === 1) {
|
|
expect(down).to.be.equal(1);
|
|
expect(x).to.be.equal(68);
|
|
expect(y).to.be.equal(36);
|
|
} else if (calls === 3) {
|
|
expect(down).to.be.equal(1);
|
|
expect(x).to.not.be.equal(68);
|
|
expect(y).to.not.be.equal(36);
|
|
done();
|
|
}
|
|
};
|
|
mouse._handleMouseDown(touchevent(
|
|
'touchstart', { touches: [{ clientX: 78, clientY: 46 }]}));
|
|
this.clock.tick(10);
|
|
mouse._handleMouseUp(touchevent(
|
|
'touchend', { touches: [{ clientX: 79, clientY: 45 }]}));
|
|
this.clock.tick(200);
|
|
mouse._handleMouseDown(touchevent(
|
|
'touchstart', { touches: [{ clientX: 57, clientY: 35 }]}));
|
|
this.clock.tick(10);
|
|
mouse._handleMouseUp(touchevent(
|
|
'touchend', { touches: [{ clientX: 56, clientY: 36 }]}));
|
|
});
|
|
|
|
it('should not modify 2nd tap pos if not soon enough', function(done) {
|
|
let calls = 0;
|
|
const mouse = new Mouse(target);
|
|
mouse.onmousebutton = (x, y, down, bmask) => {
|
|
calls++;
|
|
if (calls === 1) {
|
|
expect(down).to.be.equal(1);
|
|
expect(x).to.be.equal(68);
|
|
expect(y).to.be.equal(36);
|
|
} else if (calls === 3) {
|
|
expect(down).to.be.equal(1);
|
|
expect(x).to.not.be.equal(68);
|
|
expect(y).to.not.be.equal(36);
|
|
done();
|
|
}
|
|
};
|
|
mouse._handleMouseDown(touchevent(
|
|
'touchstart', { touches: [{ clientX: 78, clientY: 46 }]}));
|
|
this.clock.tick(10);
|
|
mouse._handleMouseUp(touchevent(
|
|
'touchend', { touches: [{ clientX: 79, clientY: 45 }]}));
|
|
this.clock.tick(500);
|
|
mouse._handleMouseDown(touchevent(
|
|
'touchstart', { touches: [{ clientX: 67, clientY: 35 }]}));
|
|
this.clock.tick(10);
|
|
mouse._handleMouseUp(touchevent(
|
|
'touchend', { touches: [{ clientX: 66, clientY: 36 }]}));
|
|
});
|
|
|
|
it('should not modify 2nd tap pos if not touch', function(done) {
|
|
let calls = 0;
|
|
const mouse = new Mouse(target);
|
|
mouse.onmousebutton = (x, y, down, bmask) => {
|
|
calls++;
|
|
if (calls === 1) {
|
|
expect(down).to.be.equal(1);
|
|
expect(x).to.be.equal(68);
|
|
expect(y).to.be.equal(36);
|
|
} else if (calls === 3) {
|
|
expect(down).to.be.equal(1);
|
|
expect(x).to.not.be.equal(68);
|
|
expect(y).to.not.be.equal(36);
|
|
done();
|
|
}
|
|
};
|
|
mouse._handleMouseDown(mouseevent(
|
|
'mousedown', { button: '0x01', clientX: 78, clientY: 46 }));
|
|
this.clock.tick(10);
|
|
mouse._handleMouseUp(mouseevent(
|
|
'mouseup', { button: '0x01', clientX: 79, clientY: 45 }));
|
|
this.clock.tick(200);
|
|
mouse._handleMouseDown(mouseevent(
|
|
'mousedown', { button: '0x01', clientX: 67, clientY: 35 }));
|
|
this.clock.tick(10);
|
|
mouse._handleMouseUp(mouseevent(
|
|
'mouseup', { button: '0x01', clientX: 66, clientY: 36 }));
|
|
});
|
|
|
|
});
|
|
|
|
describe('Accumulate mouse wheel events with small delta', function() {
|
|
|
|
beforeEach(function () { this.clock = sinon.useFakeTimers(); });
|
|
afterEach(function () { this.clock.restore(); });
|
|
|
|
it('should accumulate wheel events if small enough', function () {
|
|
const mouse = new Mouse(target);
|
|
mouse.onmousebutton = sinon.spy();
|
|
|
|
mouse._handleMouseWheel(mouseevent(
|
|
'mousewheel', { clientX: 18, clientY: 40,
|
|
deltaX: 4, deltaY: 0, deltaMode: 0 }));
|
|
this.clock.tick(10);
|
|
mouse._handleMouseWheel(mouseevent(
|
|
'mousewheel', { clientX: 18, clientY: 40,
|
|
deltaX: 4, deltaY: 0, deltaMode: 0 }));
|
|
|
|
// threshold is 10
|
|
expect(mouse._accumulatedWheelDeltaX).to.be.equal(8);
|
|
|
|
this.clock.tick(10);
|
|
mouse._handleMouseWheel(mouseevent(
|
|
'mousewheel', { clientX: 18, clientY: 40,
|
|
deltaX: 4, deltaY: 0, deltaMode: 0 }));
|
|
|
|
expect(mouse.onmousebutton).to.have.callCount(2); // mouse down and up
|
|
|
|
this.clock.tick(10);
|
|
mouse._handleMouseWheel(mouseevent(
|
|
'mousewheel', { clientX: 18, clientY: 40,
|
|
deltaX: 4, deltaY: 9, deltaMode: 0 }));
|
|
|
|
expect(mouse._accumulatedWheelDeltaX).to.be.equal(4);
|
|
expect(mouse._accumulatedWheelDeltaY).to.be.equal(9);
|
|
|
|
expect(mouse.onmousebutton).to.have.callCount(2); // still
|
|
});
|
|
|
|
it('should not accumulate large wheel events', function () {
|
|
const mouse = new Mouse(target);
|
|
mouse.onmousebutton = sinon.spy();
|
|
|
|
mouse._handleMouseWheel(mouseevent(
|
|
'mousewheel', { clientX: 18, clientY: 40,
|
|
deltaX: 11, deltaY: 0, deltaMode: 0 }));
|
|
this.clock.tick(10);
|
|
mouse._handleMouseWheel(mouseevent(
|
|
'mousewheel', { clientX: 18, clientY: 40,
|
|
deltaX: 0, deltaY: 70, deltaMode: 0 }));
|
|
this.clock.tick(10);
|
|
mouse._handleMouseWheel(mouseevent(
|
|
'mousewheel', { clientX: 18, clientY: 40,
|
|
deltaX: 400, deltaY: 400, deltaMode: 0 }));
|
|
|
|
expect(mouse.onmousebutton).to.have.callCount(8); // mouse down and up
|
|
});
|
|
|
|
it('should send even small wheel events after a timeout', function () {
|
|
const mouse = new Mouse(target);
|
|
mouse.onmousebutton = sinon.spy();
|
|
|
|
mouse._handleMouseWheel(mouseevent(
|
|
'mousewheel', { clientX: 18, clientY: 40,
|
|
deltaX: 1, deltaY: 0, deltaMode: 0 }));
|
|
this.clock.tick(51); // timeout on 50 ms
|
|
|
|
expect(mouse.onmousebutton).to.have.callCount(2); // mouse down and up
|
|
});
|
|
|
|
it('should account for non-zero deltaMode', function () {
|
|
const mouse = new Mouse(target);
|
|
mouse.onmousebutton = sinon.spy();
|
|
|
|
mouse._handleMouseWheel(mouseevent(
|
|
'mousewheel', { clientX: 18, clientY: 40,
|
|
deltaX: 0, deltaY: 2, deltaMode: 1 }));
|
|
|
|
this.clock.tick(10);
|
|
|
|
mouse._handleMouseWheel(mouseevent(
|
|
'mousewheel', { clientX: 18, clientY: 40,
|
|
deltaX: 1, deltaY: 0, deltaMode: 2 }));
|
|
|
|
expect(mouse.onmousebutton).to.have.callCount(4); // mouse down and up
|
|
});
|
|
});
|
|
|
|
});
|