maplibre-gl
Version:
BSD licensed community fork of mapbox-gl, a WebGL interactive maps library
340 lines (253 loc) • 12.5 kB
text/typescript
import {describe, beforeEach, test, expect, vi} from 'vitest';
import {browser} from '../../util/browser';
import {Map} from '../map';
import {DOM} from '../../util/dom';
import simulate from '../../../test/unit/lib/simulate_interaction';
import {beforeMapTest, sleep} from '../../util/test/util';
function createMap(cooperativeGestures) {
return new Map({
container: DOM.create('div', '', window.document.body),
style: {
'version': 8,
'sources': {},
'layers': []
},
cooperativeGestures
});
}
beforeEach(() => {
beforeMapTest();
});
describe('CoopGesturesHandler', () => {
test('Does not zoom on wheel if no key is down', async () => {
const browserNow = vi.spyOn(browser, 'now');
let now = 1555555555555;
browserNow.mockReturnValue(now);
const map = createMap(true);
map._renderTaskQueue.run();
const cooperativegestureprevented = vi.fn();
map.on('cooperativegestureprevented', cooperativegestureprevented);
const startZoom = map.getZoom();
// simulate a single 'wheel' event
const wheelEvent = {type: 'wheel', deltaY: -simulate.magicWheelZoomDelta};
simulate.wheel(map.getCanvas(), wheelEvent);
map._renderTaskQueue.run();
expect(map.getContainer().querySelector('.maplibregl-cooperative-gesture-screen.maplibregl-show')).toBeInstanceOf(HTMLDivElement);
// ensure events are emitted when cooperative gesture is prevented
expect(cooperativegestureprevented).toHaveBeenCalledTimes(1);
expect(cooperativegestureprevented).toHaveBeenCalledWith(expect.objectContaining({
type: 'cooperativegestureprevented',
gestureType: 'wheel_zoom',
}));
expect(cooperativegestureprevented.mock.calls[0][0].originalEvent).toMatchObject(wheelEvent);
now += 400;
browserNow.mockReturnValue(now);
map._renderTaskQueue.run();
const endZoom = map.getZoom();
expect(endZoom).toBeCloseTo(startZoom);
await sleep(200);
expect(map.getContainer().querySelector('.maplibregl-cooperative-gesture-screen.maplibregl-show')).toBeNull();
map.remove();
});
test('Zooms on wheel if no key is down after disabling cooperative gestures', () => {
const browserNow = vi.spyOn(browser, 'now');
let now = 1555555555555;
browserNow.mockReturnValue(now);
const map = createMap(true);
map.cooperativeGestures.disable();
map._renderTaskQueue.run();
const startZoom = map.getZoom();
// simulate a single 'wheel' event
simulate.wheel(map.getCanvas(), {type: 'wheel', deltaY: -simulate.magicWheelZoomDelta});
map._renderTaskQueue.run();
now += 400;
browserNow.mockReturnValue(now);
map._renderTaskQueue.run();
const endZoom = map.getZoom();
expect(endZoom - startZoom).toBeCloseTo(0.0285, 3);
map.remove();
});
test('Zooms on wheel if control key is down', () => {
// NOTE: This should pass regardless of whether cooperativeGestures is enabled or not
const browserNow = vi.spyOn(browser, 'now');
let now = 1555555555555;
browserNow.mockReturnValue(now);
const map = createMap(true);
map._renderTaskQueue.run();
const startZoom = map.getZoom();
// simulate a single 'wheel' event
simulate.wheel(map.getCanvas(), {type: 'wheel', deltaY: -simulate.magicWheelZoomDelta, ctrlKey: true});
map._renderTaskQueue.run();
now += 400;
browserNow.mockReturnValue(now);
map._renderTaskQueue.run();
const endZoom = map.getZoom();
expect(endZoom - startZoom).toBeCloseTo(0.0285, 3);
map.remove();
});
test('Zooms on trackpad pinch when metaKey is the bypass key', () => {
// NOTE: This should pass regardless of whether cooperativeGestures is enabled or not
const browserNow = vi.spyOn(browser, 'now');
let now = 1555555555555;
browserNow.mockReturnValue(now);
const map = createMap(true);
// pretend we're on a Mac, where the ctrlKey isn't the bypassKey
map.cooperativeGestures._bypassKey = 'metaKey';
map._renderTaskQueue.run();
const startZoom = map.getZoom();
// simulate a single 'wheel' trackpad pinch event
simulate.wheel(map.getCanvas(), {
type: 'wheel',
deltaY: -simulate.magicWheelZoomDelta,
// this is how a browser identifies a trackpad pinch
ctrlKey: true
});
map._renderTaskQueue.run();
now += 400;
browserNow.mockReturnValue(now);
map._renderTaskQueue.run();
const endZoom = map.getZoom();
expect(endZoom - startZoom).toBeCloseTo(0.0285, 3);
map.remove();
});
test('Does not show message if scrollZoom is disabled', () => {
// NOTE: This should pass regardless of whether cooperativeGestures is enabled or not
const browserNow = vi.spyOn(browser, 'now');
const now = 1555555555555;
browserNow.mockReturnValue(now);
const map = createMap(true);
const cooperativegestureprevented = vi.fn();
map.on('cooperativegestureprevented', cooperativegestureprevented);
map.scrollZoom.disable();
map._renderTaskQueue.run();
// simulate a single 'wheel' event
simulate.wheel(map.getCanvas(), {type: 'wheel', deltaY: -simulate.magicWheelZoomDelta});
map._renderTaskQueue.run();
expect(map.getContainer().querySelector('.maplibregl-cooperative-gesture-screen.maplibregl-show')).toBeNull();
// ensure events are not emitted when cooperative gesture is prevented
expect(cooperativegestureprevented).toHaveBeenCalledTimes(0);
map.remove();
});
test('Does not pan on touchmove with a single touch', () => {
const map = createMap(true);
const target = map.getCanvas();
const startCenter = map.getCenter();
map._renderTaskQueue.run();
const dragstart = vi.fn();
const drag = vi.fn();
const dragend = vi.fn();
const cooperativegestureprevented = vi.fn();
map.on('dragstart', dragstart);
map.on('drag', drag);
map.on('dragend', dragend);
map.on('cooperativegestureprevented', cooperativegestureprevented);
simulate.touchstart(target, {touches: [{target, clientX: 0, clientY: 0}]});
map._renderTaskQueue.run();
simulate.touchmove(target, {touches: [{target, clientX: 10, clientY: 10}]});
map._renderTaskQueue.run();
expect(map.getContainer().querySelector('.maplibregl-cooperative-gesture-screen.maplibregl-show')).toBeInstanceOf(HTMLDivElement);
// ensure events are emitted when cooperative gesture is prevented
expect(cooperativegestureprevented).toHaveBeenCalledTimes(1);
expect(cooperativegestureprevented).toHaveBeenCalledWith(expect.objectContaining({
type: 'cooperativegestureprevented',
gestureType: 'touch_pan',
}));
expect(cooperativegestureprevented.mock.calls[0][0].originalEvent.touches[0].clientX).toBe(10);
simulate.touchend(target);
map._renderTaskQueue.run();
const endCenter = map.getCenter();
expect(endCenter.lng).toEqual(startCenter.lng);
expect(endCenter.lat).toEqual(startCenter.lat);
map.remove();
});
test('Pans on touchmove with a single touch after disabling cooperative gestures', () => {
const map = createMap(true);
const cooperativegestureprevented = vi.fn();
map.on('cooperativegestureprevented', cooperativegestureprevented);
map.cooperativeGestures.disable();
const target = map.getCanvasContainer();
const startCenter = map.getCenter();
map._renderTaskQueue.run();
simulate.touchstart(target, {touches: [{target, clientX: 0, clientY: 0}, {target, clientX: 1, clientY: 1}]});
map._renderTaskQueue.run();
simulate.touchmove(target, {touches: [{target, clientX: 10, clientY: 10}, {target, clientX: 11, clientY: 11}]});
map._renderTaskQueue.run();
expect(map.getContainer().querySelector('.maplibregl-cooperative-gesture-screen.maplibregl-show')).toBeNull();
expect(cooperativegestureprevented).toHaveBeenCalledTimes(0);
simulate.touchend(target);
map._renderTaskQueue.run();
const endCenter = map.getCenter();
expect(endCenter.lng).toBeGreaterThan(startCenter.lng);
expect(endCenter.lat).toBeGreaterThan(startCenter.lat);
map.remove();
});
test('Does pan on touchmove with a double touch but does not change pitch', () => {
const map = createMap(true);
const cooperativegestureprevented = vi.fn();
map.on('cooperativegestureprevented', cooperativegestureprevented);
const target = map.getCanvas();
const startCenter = map.getCenter();
const startPitch = map.getPitch();
map._renderTaskQueue.run();
simulate.touchstart(target, {touches: [{target, clientX: 0, clientY: 0}, {target, clientX: 1, clientY: 1}]});
map._renderTaskQueue.run();
simulate.touchmove(target, {touches: [{target, clientX: 10, clientY: 10}, {target, clientX: 11, clientY: 11}]});
map._renderTaskQueue.run();
expect(map.getContainer().querySelector('.maplibregl-cooperative-gesture-screen.maplibregl-show')).toBeNull();
expect(cooperativegestureprevented).toHaveBeenCalledTimes(0);
simulate.touchend(target);
map._renderTaskQueue.run();
const endCenter = map.getCenter();
expect(endCenter.lng).toBeGreaterThan(startCenter.lng);
expect(endCenter.lat).toBeGreaterThan(startCenter.lat);
expect(startPitch).toBe(map.getPitch());
map.remove();
});
test('Drag pitch works with 3 fingers', () => {
// NOTE: This should pass regardless of whether cooperativeGestures is enabled or not
const map = createMap(true);
const cooperativegestureprevented = vi.fn();
map.on('cooperativegestureprevented', cooperativegestureprevented);
const target = map.getCanvas();
const startPitch = map.getPitch();
map._renderTaskQueue.run();
simulate.touchstart(target, {touches: [{target, clientX: 0, clientY: 0}, {target, clientX: 1, clientY: 1}, {target, clientX: 2, clientY: 2}]});
map._renderTaskQueue.run();
simulate.touchmove(target, {touches: [{target, clientX: 0, clientY: -10}, {target, clientX: 1, clientY: -11}, {target, clientX: 2, clientY: -12}]});
map._renderTaskQueue.run();
expect(map.getContainer().querySelector('.maplibregl-cooperative-gesture-screen.maplibregl-show')).toBeNull();
expect(cooperativegestureprevented).toHaveBeenCalledTimes(0);
simulate.touchend(target);
map._renderTaskQueue.run();
const endPitch = map.getPitch();
expect(endPitch).toBeGreaterThan(startPitch);
map.remove();
});
test('Initially disabled cooperative gestures can be later enabled', () => {
const browserNow = vi.spyOn(browser, 'now');
let now = 1555555555555;
browserNow.mockReturnValue(now);
const map = createMap(false);
map._renderTaskQueue.run();
const startZoom = map.getZoom();
// simulate a single 'wheel' event
simulate.wheel(map.getCanvas(), {type: 'wheel', deltaY: -simulate.magicWheelZoomDelta});
map._renderTaskQueue.run();
now += 400;
browserNow.mockReturnValue(now);
map._renderTaskQueue.run();
const midZoom = map.getZoom();
expect(midZoom - startZoom).toBeCloseTo(0.0285, 3);
// Enable cooperative gestures
map.cooperativeGestures.enable();
// This 'wheel' event should not zoom
simulate.wheel(map.getCanvas(), {type: 'wheel', deltaY: -simulate.magicWheelZoomDelta});
map._renderTaskQueue.run();
now += 400;
browserNow.mockReturnValue(now);
map._renderTaskQueue.run();
const endZoom = map.getZoom();
expect(endZoom).toBeCloseTo(midZoom);
map.remove();
});
});