swipe.spec.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. import EventHandler from '../../../src/dom/event-handler.js'
  2. import { noop } from '../../../src/util/index.js'
  3. import Swipe from '../../../src/util/swipe.js'
  4. import { clearFixture, getFixture } from '../../helpers/fixture.js'
  5. describe('Swipe', () => {
  6. const { Simulator, PointerEvent } = window
  7. const originWinPointerEvent = PointerEvent
  8. const supportPointerEvent = Boolean(PointerEvent)
  9. let fixtureEl
  10. let swipeEl
  11. const clearPointerEvents = () => {
  12. window.PointerEvent = null
  13. }
  14. const restorePointerEvents = () => {
  15. window.PointerEvent = originWinPointerEvent
  16. }
  17. // The headless browser does not support touch events, so we need to fake it
  18. // in order to test that touch events are added properly
  19. const defineDocumentElementOntouchstart = () => {
  20. document.documentElement.ontouchstart = noop
  21. }
  22. const deleteDocumentElementOntouchstart = () => {
  23. delete document.documentElement.ontouchstart
  24. }
  25. const mockSwipeGesture = (element, options = {}, type = 'touch') => {
  26. Simulator.setType(type)
  27. const _options = { deltaX: 0, deltaY: 0, ...options }
  28. Simulator.gestures.swipe(element, _options)
  29. }
  30. beforeEach(() => {
  31. fixtureEl = getFixture()
  32. const cssStyle = [
  33. '<style>',
  34. ' #fixture .pointer-event {',
  35. ' touch-action: pan-y;',
  36. ' }',
  37. ' #fixture div {',
  38. ' width: 300px;',
  39. ' height: 300px;',
  40. ' }',
  41. '</style>'
  42. ].join('')
  43. fixtureEl.innerHTML = `<div id="swipeEl"></div>${cssStyle}`
  44. swipeEl = fixtureEl.querySelector('div')
  45. })
  46. afterEach(() => {
  47. clearFixture()
  48. deleteDocumentElementOntouchstart()
  49. })
  50. describe('constructor', () => {
  51. it('should add touch event listeners by default', () => {
  52. defineDocumentElementOntouchstart()
  53. spyOn(Swipe.prototype, '_initEvents').and.callThrough()
  54. const swipe = new Swipe(swipeEl)
  55. expect(swipe._initEvents).toHaveBeenCalled()
  56. })
  57. it('should not add touch event listeners if touch is not supported', () => {
  58. spyOn(Swipe, 'isSupported').and.returnValue(false)
  59. spyOn(Swipe.prototype, '_initEvents').and.callThrough()
  60. const swipe = new Swipe(swipeEl)
  61. expect(swipe._initEvents).not.toHaveBeenCalled()
  62. })
  63. })
  64. describe('Config', () => {
  65. it('Test leftCallback', () => {
  66. return new Promise(resolve => {
  67. const spyRight = jasmine.createSpy('spy')
  68. clearPointerEvents()
  69. defineDocumentElementOntouchstart()
  70. // eslint-disable-next-line no-new
  71. new Swipe(swipeEl, {
  72. leftCallback() {
  73. expect(spyRight).not.toHaveBeenCalled()
  74. restorePointerEvents()
  75. resolve()
  76. },
  77. rightCallback: spyRight
  78. })
  79. mockSwipeGesture(swipeEl, {
  80. pos: [300, 10],
  81. deltaX: -300
  82. })
  83. })
  84. })
  85. it('Test rightCallback', () => {
  86. return new Promise(resolve => {
  87. const spyLeft = jasmine.createSpy('spy')
  88. clearPointerEvents()
  89. defineDocumentElementOntouchstart()
  90. // eslint-disable-next-line no-new
  91. new Swipe(swipeEl, {
  92. rightCallback() {
  93. expect(spyLeft).not.toHaveBeenCalled()
  94. restorePointerEvents()
  95. resolve()
  96. },
  97. leftCallback: spyLeft
  98. })
  99. mockSwipeGesture(swipeEl, {
  100. pos: [10, 10],
  101. deltaX: 300
  102. })
  103. })
  104. })
  105. it('Test endCallback', () => {
  106. return new Promise(resolve => {
  107. clearPointerEvents()
  108. defineDocumentElementOntouchstart()
  109. let isFirstTime = true
  110. const callback = () => {
  111. if (isFirstTime) {
  112. isFirstTime = false
  113. return
  114. }
  115. expect().nothing()
  116. restorePointerEvents()
  117. resolve()
  118. }
  119. // eslint-disable-next-line no-new
  120. new Swipe(swipeEl, {
  121. endCallback: callback
  122. })
  123. mockSwipeGesture(swipeEl, {
  124. pos: [10, 10],
  125. deltaX: 300
  126. })
  127. mockSwipeGesture(swipeEl, {
  128. pos: [300, 10],
  129. deltaX: -300
  130. })
  131. })
  132. })
  133. })
  134. describe('Functionality on PointerEvents', () => {
  135. it('should not allow pinch with touch events', () => {
  136. Simulator.setType('touch')
  137. clearPointerEvents()
  138. deleteDocumentElementOntouchstart()
  139. const swipe = new Swipe(swipeEl)
  140. const spy = spyOn(swipe, '_handleSwipe')
  141. mockSwipeGesture(swipeEl, {
  142. pos: [300, 10],
  143. deltaX: -300,
  144. deltaY: 0,
  145. touches: 2
  146. })
  147. restorePointerEvents()
  148. expect(spy).not.toHaveBeenCalled()
  149. })
  150. it('should allow swipeRight and call "rightCallback" with pointer events', () => {
  151. return new Promise(resolve => {
  152. if (!supportPointerEvent) {
  153. expect().nothing()
  154. resolve()
  155. return
  156. }
  157. const style = '#fixture .pointer-event { touch-action: none !important; }'
  158. fixtureEl.innerHTML += style
  159. defineDocumentElementOntouchstart()
  160. // eslint-disable-next-line no-new
  161. new Swipe(swipeEl, {
  162. rightCallback() {
  163. deleteDocumentElementOntouchstart()
  164. expect().nothing()
  165. resolve()
  166. }
  167. })
  168. mockSwipeGesture(swipeEl, { deltaX: 300 }, 'pointer')
  169. })
  170. })
  171. it('should allow swipeLeft and call "leftCallback" with pointer events', () => {
  172. return new Promise(resolve => {
  173. if (!supportPointerEvent) {
  174. expect().nothing()
  175. resolve()
  176. return
  177. }
  178. const style = '#fixture .pointer-event { touch-action: none !important; }'
  179. fixtureEl.innerHTML += style
  180. defineDocumentElementOntouchstart()
  181. // eslint-disable-next-line no-new
  182. new Swipe(swipeEl, {
  183. leftCallback() {
  184. expect().nothing()
  185. deleteDocumentElementOntouchstart()
  186. resolve()
  187. }
  188. })
  189. mockSwipeGesture(swipeEl, {
  190. pos: [300, 10],
  191. deltaX: -300
  192. }, 'pointer')
  193. })
  194. })
  195. })
  196. describe('Dispose', () => {
  197. it('should call EventHandler.off', () => {
  198. defineDocumentElementOntouchstart()
  199. spyOn(EventHandler, 'off').and.callThrough()
  200. const swipe = new Swipe(swipeEl)
  201. swipe.dispose()
  202. expect(EventHandler.off).toHaveBeenCalledWith(swipeEl, '.bs.swipe')
  203. })
  204. it('should destroy', () => {
  205. const addEventSpy = spyOn(fixtureEl, 'addEventListener').and.callThrough()
  206. const removeEventSpy = spyOn(EventHandler, 'off').and.callThrough()
  207. defineDocumentElementOntouchstart()
  208. const swipe = new Swipe(fixtureEl)
  209. const expectedArgs =
  210. swipe._supportPointerEvents ?
  211. [
  212. ['pointerdown', jasmine.any(Function), jasmine.any(Boolean)],
  213. ['pointerup', jasmine.any(Function), jasmine.any(Boolean)]
  214. ] :
  215. [
  216. ['touchstart', jasmine.any(Function), jasmine.any(Boolean)],
  217. ['touchmove', jasmine.any(Function), jasmine.any(Boolean)],
  218. ['touchend', jasmine.any(Function), jasmine.any(Boolean)]
  219. ]
  220. expect(addEventSpy.calls.allArgs()).toEqual(expectedArgs)
  221. swipe.dispose()
  222. expect(removeEventSpy).toHaveBeenCalledWith(fixtureEl, '.bs.swipe')
  223. deleteDocumentElementOntouchstart()
  224. })
  225. })
  226. describe('"isSupported" static', () => {
  227. it('should return "true" if "touchstart" exists in document element)', () => {
  228. Object.defineProperty(window.navigator, 'maxTouchPoints', () => 0)
  229. defineDocumentElementOntouchstart()
  230. expect(Swipe.isSupported()).toBeTrue()
  231. })
  232. it('should return "false" if "touchstart" not exists in document element and "navigator.maxTouchPoints" are zero (0)', () => {
  233. Object.defineProperty(window.navigator, 'maxTouchPoints', () => 0)
  234. deleteDocumentElementOntouchstart()
  235. if ('ontouchstart' in document.documentElement) {
  236. expect().nothing()
  237. return
  238. }
  239. expect(Swipe.isSupported()).toBeFalse()
  240. })
  241. })
  242. })