mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-23 05:58:26 +08:00
test(gestures): adds unit tests for pan recognizer
This commit is contained in:
163
src/gestures/simulator.ts
Normal file
163
src/gestures/simulator.ts
Normal file
@ -0,0 +1,163 @@
|
||||
import { pointerCoord, Coordinates } from '../util/dom';
|
||||
|
||||
interface Point {
|
||||
coord: Coordinates;
|
||||
duration: number;
|
||||
}
|
||||
|
||||
export class Simulate {
|
||||
private index: number = 0;
|
||||
private points: Point[] = [];
|
||||
public timedelta: number = 1 / 60;
|
||||
|
||||
public static from(x: any, y?: number): Simulate {
|
||||
let s = new Simulate();
|
||||
return s.start(x, y);
|
||||
}
|
||||
|
||||
reset(): Simulate {
|
||||
this.index = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
start(x: any, y?: number): Simulate {
|
||||
this.points = [];
|
||||
return this.to(x, y);
|
||||
}
|
||||
|
||||
to(x: any, y?: number): Simulate {
|
||||
this.newPoint(parseCoordinates(x, y), 1);
|
||||
return this;
|
||||
}
|
||||
|
||||
delta(x: any, y?: number): Simulate {
|
||||
let newPoint = parseCoordinates(x, y);
|
||||
let prevCoord = this.getLastPoint().coord;
|
||||
newPoint.x += prevCoord.x;
|
||||
newPoint.y += prevCoord.y;
|
||||
|
||||
this.newPoint(newPoint, 1);
|
||||
return this;
|
||||
}
|
||||
|
||||
deltaPolar(angle: number, distance: number): Simulate {
|
||||
angle *= Math.PI / 180;
|
||||
let prevCoord = this.getLastPoint().coord;
|
||||
let coord = {
|
||||
x: prevCoord.x + (Math.cos(angle) * distance),
|
||||
y: prevCoord.y + (Math.sin(angle) * distance)
|
||||
};
|
||||
this.newPoint(coord, 1);
|
||||
return this;
|
||||
}
|
||||
|
||||
toPolar(angle: number, distance: number): Simulate {
|
||||
angle *= Math.PI / 180;
|
||||
let coord = {
|
||||
x: Math.cos(angle) * distance,
|
||||
y: Math.sin(angle) * distance
|
||||
};
|
||||
this.newPoint(coord, 1);
|
||||
return this;
|
||||
}
|
||||
|
||||
duration(duration: number): Simulate {
|
||||
this.getLastPoint().duration = duration;
|
||||
return this;
|
||||
}
|
||||
|
||||
velocity(vel: number): Simulate {
|
||||
let p1 = this.getLastPoint();
|
||||
let p2 = this.getPreviousPoint();
|
||||
let d = distance(p1, p2);
|
||||
return this.duration(d / vel);
|
||||
}
|
||||
|
||||
swipeRight(maxAngle: number, distance: number): Simulate {
|
||||
// x------>
|
||||
let angle = randomAngle(maxAngle);
|
||||
return this.deltaPolar(angle, distance);
|
||||
}
|
||||
|
||||
swipeLeft(maxAngle: number, distance: number): Simulate {
|
||||
// <------x
|
||||
let angle = randomAngle(maxAngle) + 180;
|
||||
return this.deltaPolar(angle, distance);
|
||||
}
|
||||
|
||||
swipeTop(maxAngle: number, distance: number): Simulate {
|
||||
let angle = randomAngle(maxAngle) + 90;
|
||||
return this.deltaPolar(angle, distance);
|
||||
}
|
||||
|
||||
swipeBottom(maxAngle: number, distance: number): Simulate {
|
||||
let angle = randomAngle(maxAngle) - 90;
|
||||
return this.deltaPolar(angle, distance);
|
||||
}
|
||||
|
||||
run(callback: Function) {
|
||||
let points = this.points;
|
||||
let len = points.length - 1;
|
||||
let i = 0;
|
||||
for (; i < len; i++) {
|
||||
var p1 = points[i].coord;
|
||||
var p2 = points[i + 1].coord;
|
||||
var duration = points[i + 1].duration;
|
||||
var vectorX = p2.x - p1.x;
|
||||
var vectorY = p2.y - p1.y;
|
||||
var nuSteps = Math.ceil(duration / this.timedelta);
|
||||
vectorX /= nuSteps;
|
||||
vectorY /= nuSteps;
|
||||
for (let j = 0; j < nuSteps; j++) {
|
||||
callback({
|
||||
x: p1.x + vectorX * j,
|
||||
y: p1.y + vectorY * j
|
||||
});
|
||||
}
|
||||
}
|
||||
this.index = i;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
private newPoint(coord: Coordinates, duration: number) {
|
||||
this.points.push({
|
||||
coord: coord,
|
||||
duration: duration,
|
||||
});
|
||||
}
|
||||
|
||||
private getLastPoint(): Point {
|
||||
let len = this.points.length;
|
||||
if (len > 0) {
|
||||
return this.points[len - 1];
|
||||
}
|
||||
throw new Error('can not call point');
|
||||
}
|
||||
|
||||
private getPreviousPoint(): Point {
|
||||
let len = this.points.length;
|
||||
if (len > 1) {
|
||||
return this.points[len - 2];
|
||||
}
|
||||
throw new Error('can not call point');
|
||||
}
|
||||
}
|
||||
|
||||
function randomAngle(maxAngle: number): number {
|
||||
return (Math.random() * maxAngle * 2) - maxAngle;
|
||||
}
|
||||
|
||||
function distance(a: Coordinates, b: Coordinates): number {
|
||||
let deltaX = a.x - b.x;
|
||||
let deltaY = a.y - a.y;
|
||||
return Math.hypot(deltaX, deltaY);
|
||||
}
|
||||
|
||||
function parseCoordinates(coord: Coordinates | number, y?: number): Coordinates {
|
||||
if (typeof coord === 'number') {
|
||||
return { x: coord, y: y };
|
||||
}
|
||||
return coord;
|
||||
}
|
@ -3,13 +3,13 @@ import { GestureController, DisableScroll } from '../../../src';
|
||||
export function run() {
|
||||
|
||||
it('should create an instance of GestureController', () => {
|
||||
let c = new GestureController();
|
||||
let c = new GestureController(null);
|
||||
expect(c.isCaptured()).toEqual(false);
|
||||
expect(c.isScrollDisabled()).toEqual(false);
|
||||
});
|
||||
|
||||
it('should test scrolling enable/disable stack', () => {
|
||||
let c = new GestureController();
|
||||
let c = new GestureController(null);
|
||||
c.enableScroll(1);
|
||||
expect(c.isScrollDisabled()).toEqual(false);
|
||||
|
||||
@ -37,7 +37,7 @@ export function run() {
|
||||
});
|
||||
|
||||
it('should test gesture enable/disable stack', () => {
|
||||
let c = new GestureController();
|
||||
let c = new GestureController(null);
|
||||
c.enableGesture('swipe', 1);
|
||||
expect(c.isDisabled('swipe')).toEqual(false);
|
||||
|
||||
@ -71,7 +71,7 @@ export function run() {
|
||||
|
||||
|
||||
it('should test if canStart', () => {
|
||||
let c = new GestureController();
|
||||
let c = new GestureController(null);
|
||||
expect(c.canStart('event')).toEqual(true);
|
||||
expect(c.canStart('event1')).toEqual(true);
|
||||
expect(c.canStart('event')).toEqual(true);
|
||||
@ -82,7 +82,7 @@ export function run() {
|
||||
|
||||
|
||||
it('should initialize a delegate without options', () => {
|
||||
let c = new GestureController();
|
||||
let c = new GestureController(null);
|
||||
let g = c.create('event');
|
||||
expect(g['name']).toEqual('event');
|
||||
expect(g.priority).toEqual(0);
|
||||
@ -97,7 +97,7 @@ export function run() {
|
||||
|
||||
|
||||
it('should initialize a delegate with options', () => {
|
||||
let c = new GestureController();
|
||||
let c = new GestureController(null);
|
||||
let g = c.create('swipe', {
|
||||
priority: -123,
|
||||
disableScroll: DisableScroll.DuringCapture,
|
||||
@ -112,7 +112,7 @@ export function run() {
|
||||
});
|
||||
|
||||
it('should test if several gestures can be started', () => {
|
||||
let c = new GestureController();
|
||||
let c = new GestureController(null);
|
||||
let g1 = c.create('swipe');
|
||||
let g2 = c.create('swipe1', {priority: 3});
|
||||
let g3 = c.create('swipe2', {priority: 4});
|
||||
@ -147,7 +147,7 @@ export function run() {
|
||||
|
||||
|
||||
it('should test if several gestures try to capture at the same time', () => {
|
||||
let c = new GestureController();
|
||||
let c = new GestureController(null);
|
||||
let g1 = c.create('swipe1');
|
||||
let g2 = c.create('swipe2', { priority: 2 });
|
||||
let g3 = c.create('swipe3', { priority: 3 });
|
||||
@ -199,7 +199,7 @@ export function run() {
|
||||
|
||||
|
||||
it('should destroy correctly', () => {
|
||||
let c = new GestureController();
|
||||
let c = new GestureController(null);
|
||||
let g = c.create('swipe', {
|
||||
priority: 123,
|
||||
disableScroll: DisableScroll.Always,
|
||||
@ -233,7 +233,7 @@ export function run() {
|
||||
|
||||
|
||||
it('should disable some events', () => {
|
||||
let c = new GestureController();
|
||||
let c = new GestureController(null);
|
||||
|
||||
let goback = c.create('goback');
|
||||
expect(goback.canStart()).toEqual(true);
|
||||
@ -276,7 +276,7 @@ export function run() {
|
||||
});
|
||||
|
||||
it('should disable scrolling on capture', () => {
|
||||
let c = new GestureController();
|
||||
let c = new GestureController(null);
|
||||
let g = c.create('goback', {
|
||||
disableScroll: DisableScroll.DuringCapture,
|
||||
});
|
||||
|
206
src/gestures/test/recognizers.spec.ts
Normal file
206
src/gestures/test/recognizers.spec.ts
Normal file
@ -0,0 +1,206 @@
|
||||
|
||||
import { PanRecognizer } from '../../../src/gestures/recognizers';
|
||||
import { Simulate } from '../../../src/gestures/simulator';
|
||||
|
||||
export function run() {
|
||||
|
||||
it('should not fire if it did not start', () => {
|
||||
let p = new PanRecognizer('x', 2, 2);
|
||||
expect(p.pan()).toEqual(0);
|
||||
|
||||
Simulate.from(0, 0).to(99, 0).run((coord: Coordinates) => {
|
||||
expect(p.detect(coord)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('should reset', () => {
|
||||
let p = new PanRecognizer('x', 2, 2);
|
||||
|
||||
p.start({ x: 0, y: 0 });
|
||||
expect(p.pan()).toEqual(0);
|
||||
|
||||
Simulate.from(0, 0).to(10, 0).run((coord: Coordinates) => {
|
||||
p.detect(coord);
|
||||
});
|
||||
expect(p.pan()).toEqual(1);
|
||||
|
||||
p.start({ x: 0, y: 0 });
|
||||
expect(p.pan()).toEqual(0);
|
||||
|
||||
Simulate.from(0, 0).to(-10, 0).run((coord: Coordinates) => {
|
||||
p.detect(coord);
|
||||
});
|
||||
expect(p.pan()).toEqual(-1);
|
||||
});
|
||||
|
||||
it('should fire with large threshold', () => {
|
||||
let detected = false;
|
||||
let p = new PanRecognizer('x', 100, 40);
|
||||
p.start({ x: 0, y: 0 });
|
||||
|
||||
Simulate
|
||||
.from(0, 0).to(99, 0)
|
||||
// Since threshold is 100, it should not fire yet
|
||||
.run((coord: Coordinates) => expect(p.detect(coord)).toEqual(false))
|
||||
|
||||
// Now it should fire
|
||||
.delta(2, 0)
|
||||
.run((coord: Coordinates) => {
|
||||
if (p.detect(coord)) {
|
||||
// it should detect a horizontal pan
|
||||
expect(p.pan()).toEqual(1);
|
||||
detected = true;
|
||||
}
|
||||
})
|
||||
|
||||
// It should not detect again
|
||||
.delta(20, 0)
|
||||
.to(0, 0)
|
||||
.to(102, 0)
|
||||
.run((coord: Coordinates) => expect(p.detect(coord)).toEqual(false));
|
||||
|
||||
expect(detected).toEqual(true);
|
||||
});
|
||||
|
||||
it('should detect swipe left', () => {
|
||||
let p = new PanRecognizer('x', 20, 20);
|
||||
p.start({ x: 0, y: 0 });
|
||||
Simulate
|
||||
.from(0, 0).deltaPolar(19, 21).delta(-30, 0)
|
||||
.run((coord: Coordinates) => p.detect(coord));
|
||||
expect(p.pan()).toEqual(1);
|
||||
|
||||
p.start({ x: 0, y: 0 });
|
||||
Simulate
|
||||
.from(0, 0).deltaPolar(-19, 21).delta(-30, 0)
|
||||
.run((coord: Coordinates) => p.detect(coord));
|
||||
expect(p.pan()).toEqual(1);
|
||||
});
|
||||
|
||||
it('should detect swipe right', () => {
|
||||
let p = new PanRecognizer('x', 20, 20);
|
||||
p.start({ x: 0, y: 0 });
|
||||
Simulate
|
||||
.from(0, 0).deltaPolar(180 - 19, 21).delta(30, 0)
|
||||
.run((coord: Coordinates) => p.detect(coord));
|
||||
expect(p.pan()).toEqual(-1);
|
||||
|
||||
p.start({ x: 0, y: 0 });
|
||||
Simulate
|
||||
.from(0, 0).deltaPolar(180 + 19, 21).delta(30, 0)
|
||||
.run((coord: Coordinates) => p.detect(coord));
|
||||
expect(p.pan()).toEqual(-1);
|
||||
});
|
||||
|
||||
it('should NOT detect swipe left', () => {
|
||||
let p = new PanRecognizer('x', 20, 20);
|
||||
p.start({ x: 0, y: 0 });
|
||||
Simulate
|
||||
.from(0, 0).deltaPolar(21, 21).delta(-30, 0)
|
||||
.run((coord: Coordinates) => p.detect(coord));
|
||||
expect(p.pan()).toEqual(0);
|
||||
|
||||
p.start({ x: 0, y: 0 });
|
||||
Simulate
|
||||
.from(0, 0).deltaPolar(-21, 21).delta(-30, 0)
|
||||
.run((coord: Coordinates) => p.detect(coord));
|
||||
expect(p.pan()).toEqual(0);
|
||||
});
|
||||
|
||||
it('should NOT detect swipe right', () => {
|
||||
let p = new PanRecognizer('x', 20, 20);
|
||||
p.start({ x: 0, y: 0 });
|
||||
Simulate
|
||||
.from(0, 0).deltaPolar(180 - 21, 21).delta(30, 0)
|
||||
.run((coord: Coordinates) => p.detect(coord));
|
||||
expect(p.pan()).toEqual(0);
|
||||
|
||||
p.start({ x: 0, y: 0 });
|
||||
Simulate
|
||||
.from(0, 0).deltaPolar(180 + 21, 21).delta(30, 0)
|
||||
.run((coord: Coordinates) => p.detect(coord));
|
||||
expect(p.pan()).toEqual(0);
|
||||
});
|
||||
|
||||
|
||||
|
||||
it('should detect swipe top', () => {
|
||||
let p = new PanRecognizer('y', 20, 20);
|
||||
p.start({ x: 0, y: 0 });
|
||||
Simulate
|
||||
.from(0, 0).deltaPolar(90 - 19, 21).delta(-30, 0)
|
||||
.run((coord: Coordinates) => p.detect(coord));
|
||||
expect(p.pan()).toEqual(1);
|
||||
|
||||
p.start({ x: 0, y: 0 });
|
||||
Simulate
|
||||
.from(0, 0).deltaPolar(90 + 19, 21).delta(-30, 0)
|
||||
.run((coord: Coordinates) => p.detect(coord));
|
||||
expect(p.pan()).toEqual(1);
|
||||
});
|
||||
|
||||
it('should detect swipe bottom', () => {
|
||||
let p = new PanRecognizer('y', 20, 20);
|
||||
p.start({ x: 0, y: 0 });
|
||||
Simulate
|
||||
.from(0, 0).deltaPolar(-90 + 19, 21).delta(30, 0)
|
||||
.run((coord: Coordinates) => p.detect(coord));
|
||||
expect(p.pan()).toEqual(-1);
|
||||
|
||||
p.start({ x: 0, y: 0 });
|
||||
Simulate
|
||||
.from(0, 0).deltaPolar(-90 - 19, 21).delta(30, 0)
|
||||
.run((coord: Coordinates) => p.detect(coord));
|
||||
expect(p.pan()).toEqual(-1);
|
||||
});
|
||||
|
||||
it('should NOT detect swipe top', () => {
|
||||
let p = new PanRecognizer('y', 20, 20);
|
||||
p.start({ x: 0, y: 0 });
|
||||
Simulate
|
||||
.from(0, 0).deltaPolar(90 - 21, 21).delta(-30, 0)
|
||||
.run((coord: Coordinates) => p.detect(coord));
|
||||
expect(p.pan()).toEqual(0);
|
||||
|
||||
p.start({ x: 0, y: 0 });
|
||||
Simulate
|
||||
.from(0, 0).deltaPolar(90 + 21, 21).delta(-30, 0)
|
||||
.run((coord: Coordinates) => p.detect(coord));
|
||||
expect(p.pan()).toEqual(0);
|
||||
});
|
||||
|
||||
it('should NOT detect swipe bottom', () => {
|
||||
let p = new PanRecognizer('y', 20, 20);
|
||||
p.start({ x: 0, y: 0 });
|
||||
Simulate
|
||||
.from(0, 0).deltaPolar(-90 + 21, 21).delta(30, 0)
|
||||
.run((coord: Coordinates) => p.detect(coord));
|
||||
expect(p.pan()).toEqual(0);
|
||||
|
||||
p.start({ x: 0, y: 0 });
|
||||
Simulate
|
||||
.from(0, 0).deltaPolar(-90 - 21, 21).delta(30, 0)
|
||||
.run((coord: Coordinates) => p.detect(coord));
|
||||
expect(p.pan()).toEqual(0);
|
||||
});
|
||||
|
||||
it('should NOT confuse between pan Y and X', () => {
|
||||
let p = new PanRecognizer('x', 20, 20);
|
||||
p.start({ x: 0, y: 0 });
|
||||
Simulate
|
||||
.from(0, 0).deltaPolar(90, 21).delta(30, 0)
|
||||
.run((coord: Coordinates) => p.detect(coord));
|
||||
|
||||
expect(p.pan()).toEqual(0);
|
||||
});
|
||||
|
||||
it('should NOT confuse between pan X and Y', () => {
|
||||
let p = new PanRecognizer('y', 20, 20);
|
||||
p.start({ x: 0, y: 0 });
|
||||
Simulate
|
||||
.from(0, 0).delta(30, 0)
|
||||
.run((coord: Coordinates) => p.detect(coord));
|
||||
|
||||
expect(p.pan()).toEqual(0);
|
||||
});
|
||||
}
|
Reference in New Issue
Block a user