patchEvents.spec.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import { patchProp } from '../src/patchProp'
  2. const timeout = () => new Promise(r => setTimeout(r))
  3. describe(`runtime-dom: events patching`, () => {
  4. it('should assign event handler', async () => {
  5. const el = document.createElement('div')
  6. const event = new Event('click')
  7. const fn = jest.fn()
  8. patchProp(el, 'onClick', null, fn)
  9. el.dispatchEvent(event)
  10. await timeout()
  11. el.dispatchEvent(event)
  12. await timeout()
  13. el.dispatchEvent(event)
  14. await timeout()
  15. expect(fn).toHaveBeenCalledTimes(3)
  16. })
  17. it('should update event handler', async () => {
  18. const el = document.createElement('div')
  19. const event = new Event('click')
  20. const prevFn = jest.fn()
  21. const nextFn = jest.fn()
  22. patchProp(el, 'onClick', null, prevFn)
  23. el.dispatchEvent(event)
  24. patchProp(el, 'onClick', prevFn, nextFn)
  25. await timeout()
  26. el.dispatchEvent(event)
  27. await timeout()
  28. el.dispatchEvent(event)
  29. await timeout()
  30. expect(prevFn).toHaveBeenCalledTimes(1)
  31. expect(nextFn).toHaveBeenCalledTimes(2)
  32. })
  33. it('should support multiple event handlers', async () => {
  34. const el = document.createElement('div')
  35. const event = new Event('click')
  36. const fn1 = jest.fn()
  37. const fn2 = jest.fn()
  38. patchProp(el, 'onClick', null, [fn1, fn2])
  39. el.dispatchEvent(event)
  40. await timeout()
  41. expect(fn1).toHaveBeenCalledTimes(1)
  42. expect(fn2).toHaveBeenCalledTimes(1)
  43. })
  44. it('should unassign event handler', async () => {
  45. const el = document.createElement('div')
  46. const event = new Event('click')
  47. const fn = jest.fn()
  48. patchProp(el, 'onClick', null, fn)
  49. patchProp(el, 'onClick', fn, null)
  50. el.dispatchEvent(event)
  51. await timeout()
  52. expect(fn).not.toHaveBeenCalled()
  53. })
  54. it('should support event option modifiers', async () => {
  55. const el = document.createElement('div')
  56. const event = new Event('click')
  57. const fn = jest.fn()
  58. patchProp(el, 'onClickOnceCapture', null, fn)
  59. el.dispatchEvent(event)
  60. await timeout()
  61. el.dispatchEvent(event)
  62. await timeout()
  63. expect(fn).toHaveBeenCalledTimes(1)
  64. })
  65. it('should unassign event handler with options', async () => {
  66. const el = document.createElement('div')
  67. const event = new Event('click')
  68. const fn = jest.fn()
  69. patchProp(el, 'onClickCapture', null, fn)
  70. el.dispatchEvent(event)
  71. await timeout()
  72. expect(fn).toHaveBeenCalledTimes(1)
  73. patchProp(el, 'onClickCapture', fn, null)
  74. el.dispatchEvent(event)
  75. await timeout()
  76. el.dispatchEvent(event)
  77. await timeout()
  78. expect(fn).toHaveBeenCalledTimes(1)
  79. })
  80. it('should support native onclick', async () => {
  81. const el = document.createElement('div')
  82. const event = new Event('click')
  83. // string should be set as attribute
  84. const fn = ((window as any).__globalSpy = jest.fn())
  85. patchProp(el, 'onclick', null, '__globalSpy(1)')
  86. el.dispatchEvent(event)
  87. await timeout()
  88. delete (window as any).__globalSpy
  89. expect(fn).toHaveBeenCalledWith(1)
  90. const fn2 = jest.fn()
  91. patchProp(el, 'onclick', '__globalSpy(1)', fn2)
  92. el.dispatchEvent(event)
  93. await timeout()
  94. expect(fn).toHaveBeenCalledTimes(1)
  95. expect(fn2).toHaveBeenCalledWith(event)
  96. })
  97. it('should support stopImmediatePropagation on multiple listeners', async () => {
  98. const el = document.createElement('div')
  99. const event = new Event('click')
  100. const fn1 = jest.fn((e: Event) => {
  101. e.stopImmediatePropagation()
  102. })
  103. const fn2 = jest.fn()
  104. patchProp(el, 'onClick', null, [fn1, fn2])
  105. el.dispatchEvent(event)
  106. await timeout()
  107. expect(fn1).toHaveBeenCalledTimes(1)
  108. expect(fn2).toHaveBeenCalledTimes(0)
  109. })
  110. })