mirror of
https://github.com/twbs/bootstrap.git
synced 2024-12-14 02:24:00 +01:00
42da2b9556
* Update devDependencies * @babel/core ^7.17.0 → ^7.17.2 * @rollup/plugin-replace ^3.0.1 → ^3.1.0 * eslint ^8.8.0 → ^8.9.0 * eslint-config-xo ^0.39.0 → ^0.40.0 * hugo-bin ^0.80.1 → ^0.80.2 * karma ^6.3.15 → ^6.3.16 * rollup ^2.67.1 → ^2.67.2 * Fix new ESLint errors
292 lines
7.9 KiB
JavaScript
292 lines
7.9 KiB
JavaScript
import { clearFixture, getFixture } from '../../helpers/fixture'
|
|
import EventHandler from '../../../src/dom/event-handler'
|
|
import Swipe from '../../../src/util/swipe'
|
|
import { noop } from '../../../src/util'
|
|
|
|
describe('Swipe', () => {
|
|
const { Simulator, PointerEvent } = window
|
|
const originWinPointerEvent = PointerEvent
|
|
const supportPointerEvent = Boolean(PointerEvent)
|
|
|
|
let fixtureEl
|
|
let swipeEl
|
|
const clearPointerEvents = () => {
|
|
window.PointerEvent = null
|
|
}
|
|
|
|
const restorePointerEvents = () => {
|
|
window.PointerEvent = originWinPointerEvent
|
|
}
|
|
|
|
// The headless browser does not support touch events, so we need to fake it
|
|
// in order to test that touch events are added properly
|
|
const defineDocumentElementOntouchstart = () => {
|
|
document.documentElement.ontouchstart = noop
|
|
}
|
|
|
|
const deleteDocumentElementOntouchstart = () => {
|
|
delete document.documentElement.ontouchstart
|
|
}
|
|
|
|
const mockSwipeGesture = (element, options = {}, type = 'touch') => {
|
|
Simulator.setType(type)
|
|
const _options = { deltaX: 0, deltaY: 0, ...options }
|
|
|
|
Simulator.gestures.swipe(element, _options)
|
|
}
|
|
|
|
beforeEach(() => {
|
|
fixtureEl = getFixture()
|
|
const cssStyle = [
|
|
'<style>',
|
|
' #fixture .pointer-event {',
|
|
' touch-action: pan-y;',
|
|
' }',
|
|
' #fixture div {',
|
|
' width: 300px;',
|
|
' height: 300px;',
|
|
' }',
|
|
'</style>'
|
|
].join('')
|
|
|
|
fixtureEl.innerHTML = `<div id="swipeEl"></div>${cssStyle}`
|
|
swipeEl = fixtureEl.querySelector('div')
|
|
})
|
|
|
|
afterEach(() => {
|
|
clearFixture()
|
|
deleteDocumentElementOntouchstart()
|
|
})
|
|
|
|
describe('constructor', () => {
|
|
it('should add touch event listeners by default', () => {
|
|
defineDocumentElementOntouchstart()
|
|
|
|
spyOn(Swipe.prototype, '_initEvents').and.callThrough()
|
|
const swipe = new Swipe(swipeEl)
|
|
expect(swipe._initEvents).toHaveBeenCalled()
|
|
})
|
|
|
|
it('should not add touch event listeners if touch is not supported', () => {
|
|
spyOn(Swipe, 'isSupported').and.returnValue(false)
|
|
|
|
spyOn(Swipe.prototype, '_initEvents').and.callThrough()
|
|
const swipe = new Swipe(swipeEl)
|
|
|
|
expect(swipe._initEvents).not.toHaveBeenCalled()
|
|
})
|
|
})
|
|
|
|
describe('Config', () => {
|
|
it('Test leftCallback', () => {
|
|
return new Promise(resolve => {
|
|
const spyRight = jasmine.createSpy('spy')
|
|
clearPointerEvents()
|
|
defineDocumentElementOntouchstart()
|
|
// eslint-disable-next-line no-new
|
|
new Swipe(swipeEl, {
|
|
leftCallback() {
|
|
expect(spyRight).not.toHaveBeenCalled()
|
|
restorePointerEvents()
|
|
resolve()
|
|
},
|
|
rightCallback: spyRight
|
|
})
|
|
|
|
mockSwipeGesture(swipeEl, {
|
|
pos: [300, 10],
|
|
deltaX: -300
|
|
})
|
|
})
|
|
})
|
|
|
|
it('Test rightCallback', () => {
|
|
return new Promise(resolve => {
|
|
const spyLeft = jasmine.createSpy('spy')
|
|
clearPointerEvents()
|
|
defineDocumentElementOntouchstart()
|
|
// eslint-disable-next-line no-new
|
|
new Swipe(swipeEl, {
|
|
rightCallback() {
|
|
expect(spyLeft).not.toHaveBeenCalled()
|
|
restorePointerEvents()
|
|
resolve()
|
|
},
|
|
leftCallback: spyLeft
|
|
})
|
|
|
|
mockSwipeGesture(swipeEl, {
|
|
pos: [10, 10],
|
|
deltaX: 300
|
|
})
|
|
})
|
|
})
|
|
|
|
it('Test endCallback', () => {
|
|
return new Promise(resolve => {
|
|
clearPointerEvents()
|
|
defineDocumentElementOntouchstart()
|
|
let isFirstTime = true
|
|
|
|
const callback = () => {
|
|
if (isFirstTime) {
|
|
isFirstTime = false
|
|
return
|
|
}
|
|
|
|
expect().nothing()
|
|
restorePointerEvents()
|
|
resolve()
|
|
}
|
|
|
|
// eslint-disable-next-line no-new
|
|
new Swipe(swipeEl, {
|
|
endCallback: callback
|
|
})
|
|
mockSwipeGesture(swipeEl, {
|
|
pos: [10, 10],
|
|
deltaX: 300
|
|
})
|
|
|
|
mockSwipeGesture(swipeEl, {
|
|
pos: [300, 10],
|
|
deltaX: -300
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('Functionality on PointerEvents', () => {
|
|
it('should not allow pinch with touch events', () => {
|
|
Simulator.setType('touch')
|
|
clearPointerEvents()
|
|
deleteDocumentElementOntouchstart()
|
|
|
|
const swipe = new Swipe(swipeEl)
|
|
spyOn(swipe, '_handleSwipe')
|
|
|
|
mockSwipeGesture(swipeEl, {
|
|
pos: [300, 10],
|
|
deltaX: -300,
|
|
deltaY: 0,
|
|
touches: 2
|
|
})
|
|
|
|
restorePointerEvents()
|
|
expect(swipe._handleSwipe).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('should allow swipeRight and call "rightCallback" with pointer events', () => {
|
|
return new Promise(resolve => {
|
|
if (!supportPointerEvent) {
|
|
expect().nothing()
|
|
resolve()
|
|
return
|
|
}
|
|
|
|
const style = '#fixture .pointer-event { touch-action: none !important; }'
|
|
fixtureEl.innerHTML += style
|
|
|
|
defineDocumentElementOntouchstart()
|
|
// eslint-disable-next-line no-new
|
|
new Swipe(swipeEl, {
|
|
rightCallback() {
|
|
deleteDocumentElementOntouchstart()
|
|
expect().nothing()
|
|
resolve()
|
|
}
|
|
})
|
|
|
|
mockSwipeGesture(swipeEl, { deltaX: 300 }, 'pointer')
|
|
})
|
|
})
|
|
|
|
it('should allow swipeLeft and call "leftCallback" with pointer events', () => {
|
|
return new Promise(resolve => {
|
|
if (!supportPointerEvent) {
|
|
expect().nothing()
|
|
resolve()
|
|
return
|
|
}
|
|
|
|
const style = '#fixture .pointer-event { touch-action: none !important; }'
|
|
fixtureEl.innerHTML += style
|
|
|
|
defineDocumentElementOntouchstart()
|
|
// eslint-disable-next-line no-new
|
|
new Swipe(swipeEl, {
|
|
leftCallback() {
|
|
expect().nothing()
|
|
deleteDocumentElementOntouchstart()
|
|
resolve()
|
|
}
|
|
})
|
|
|
|
mockSwipeGesture(swipeEl, {
|
|
pos: [300, 10],
|
|
deltaX: -300
|
|
}, 'pointer')
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('Dispose', () => {
|
|
it('should call EventHandler.off', () => {
|
|
defineDocumentElementOntouchstart()
|
|
spyOn(EventHandler, 'off').and.callThrough()
|
|
const swipe = new Swipe(swipeEl)
|
|
|
|
swipe.dispose()
|
|
expect(EventHandler.off).toHaveBeenCalledWith(swipeEl, '.bs.swipe')
|
|
})
|
|
|
|
it('should destroy', () => {
|
|
const addEventSpy = spyOn(fixtureEl, 'addEventListener').and.callThrough()
|
|
const removeEventSpy = spyOn(EventHandler, 'off').and.callThrough()
|
|
defineDocumentElementOntouchstart()
|
|
|
|
const swipe = new Swipe(fixtureEl)
|
|
|
|
const expectedArgs =
|
|
swipe._supportPointerEvents ?
|
|
[
|
|
['pointerdown', jasmine.any(Function), jasmine.any(Boolean)],
|
|
['pointerup', jasmine.any(Function), jasmine.any(Boolean)]
|
|
] :
|
|
[
|
|
['touchstart', jasmine.any(Function), jasmine.any(Boolean)],
|
|
['touchmove', jasmine.any(Function), jasmine.any(Boolean)],
|
|
['touchend', jasmine.any(Function), jasmine.any(Boolean)]
|
|
]
|
|
|
|
expect(addEventSpy.calls.allArgs()).toEqual(expectedArgs)
|
|
|
|
swipe.dispose()
|
|
|
|
expect(removeEventSpy).toHaveBeenCalledWith(fixtureEl, '.bs.swipe')
|
|
deleteDocumentElementOntouchstart()
|
|
})
|
|
})
|
|
|
|
describe('"isSupported" static', () => {
|
|
it('should return "true" if "touchstart" exists in document element)', () => {
|
|
Object.defineProperty(window.navigator, 'maxTouchPoints', () => 0)
|
|
defineDocumentElementOntouchstart()
|
|
|
|
expect(Swipe.isSupported()).toBeTrue()
|
|
})
|
|
|
|
it('should return "false" if "touchstart" not exists in document element and "navigator.maxTouchPoints" are zero (0)', () => {
|
|
Object.defineProperty(window.navigator, 'maxTouchPoints', () => 0)
|
|
deleteDocumentElementOntouchstart()
|
|
|
|
if ('ontouchstart' in document.documentElement) {
|
|
expect().nothing()
|
|
return
|
|
}
|
|
|
|
expect(Swipe.isSupported()).toBeFalse()
|
|
})
|
|
})
|
|
})
|