Initial commit
This commit is contained in:
304
kasmweb/tests/test.mouse.js
Normal file
304
kasmweb/tests/test.mouse.js
Normal file
@@ -0,0 +1,304 @@
|
||||
const expect = chai.expect;
|
||||
|
||||
import Mouse from '../core/input/mouse.js';
|
||||
|
||||
describe('Mouse Event Handling', function () {
|
||||
"use strict";
|
||||
|
||||
let target;
|
||||
|
||||
beforeEach(function () {
|
||||
// For these tests we can assume that the canvas is 100x100
|
||||
// located at coordinates 10x10
|
||||
target = document.createElement('canvas');
|
||||
target.style.position = "absolute";
|
||||
target.style.top = "10px";
|
||||
target.style.left = "10px";
|
||||
target.style.width = "100px";
|
||||
target.style.height = "100px";
|
||||
document.body.appendChild(target);
|
||||
});
|
||||
afterEach(function () {
|
||||
document.body.removeChild(target);
|
||||
target = null;
|
||||
});
|
||||
|
||||
// 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
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user