click-outside.test.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import { mount } from '@vue/test-utils'
  2. import { beforeEach, describe, expect, it, vi } from 'vitest'
  3. import ClickOutside from '../click-outside'
  4. const AXIOM = 'Rem is the best girl'
  5. const TRIGGER = 'trigger'
  6. const OTHER_CLASS = 'other-class'
  7. // init some local variables
  8. let mousedownObject: MouseEvent | null
  9. let mouseupObject: MouseEvent | null
  10. // mock handler with implementations which makes assignment to the local variable that we registered above.
  11. const handler = vi.fn((eMouseup, eMousedown) => {
  12. mouseupObject = eMouseup
  13. mousedownObject = eMousedown
  14. })
  15. const _mount = () =>
  16. mount(
  17. {
  18. setup() {
  19. return () => (
  20. <div>
  21. <div class={OTHER_CLASS}>Hello</div>
  22. <div class={TRIGGER} v-click-outside={handler}>
  23. {AXIOM}
  24. </div>
  25. </div>
  26. )
  27. },
  28. },
  29. {
  30. global: {
  31. directives: {
  32. ClickOutside,
  33. },
  34. },
  35. }
  36. )
  37. const triggerDocumentClickEvent = () => {
  38. const mousedown = new MouseEvent('mousedown', {
  39. screenX: 0,
  40. screenY: 0,
  41. clientX: 0,
  42. clientY: 0,
  43. })
  44. document.dispatchEvent(mousedown)
  45. const mouseup = new MouseEvent('mouseup', {
  46. screenX: 0,
  47. screenY: 0,
  48. clientX: 0,
  49. clientY: 0,
  50. })
  51. document.dispatchEvent(mouseup)
  52. }
  53. describe('Directives.vue', () => {
  54. beforeEach(() => {
  55. // clear the previously assigned event object
  56. mousedownObject = null
  57. mouseupObject = null
  58. })
  59. it('render test', () => {
  60. const wrapper = _mount()
  61. expect(wrapper.text()).toContain(AXIOM)
  62. expect(handler).toHaveBeenCalledTimes(0)
  63. wrapper.unmount()
  64. })
  65. it('should trigger handler', async () => {
  66. const wrapper = _mount()
  67. await wrapper.find(`.${TRIGGER}`).trigger('mousedown')
  68. await wrapper.find(`.${TRIGGER}`).trigger('mouseup')
  69. expect(handler).toHaveBeenCalledTimes(0)
  70. triggerDocumentClickEvent()
  71. // here is the different part
  72. // we test the existence of the local variable.
  73. expect(mousedownObject).toBeDefined()
  74. expect(mouseupObject).toBeDefined()
  75. })
  76. })
  77. describe('Multiple click-outside directives', () => {
  78. const firstHandler = vi.fn()
  79. const secondHandler = vi.fn()
  80. it('should support for multiple directives', async () => {
  81. const wrapper = mount(
  82. {
  83. setup() {
  84. return () => (
  85. <div class={OTHER_CLASS} v-click-outside={secondHandler}>
  86. <div class={TRIGGER} v-click-outside={firstHandler}>
  87. {AXIOM}
  88. </div>
  89. </div>
  90. )
  91. },
  92. },
  93. {
  94. global: {
  95. directives: {
  96. ClickOutside,
  97. },
  98. },
  99. }
  100. )
  101. // click inside trigger element
  102. await wrapper.find(`.${TRIGGER}`).trigger('mousedown')
  103. await wrapper.find(`.${TRIGGER}`).trigger('mouseup')
  104. expect(firstHandler).toHaveBeenCalledTimes(0)
  105. expect(secondHandler).toHaveBeenCalledTimes(0)
  106. // click outside trigger element
  107. triggerDocumentClickEvent()
  108. expect(firstHandler).toHaveBeenCalledTimes(1)
  109. expect(secondHandler).toHaveBeenCalledTimes(1)
  110. // update the component instance
  111. wrapper.vm.$forceUpdate()
  112. triggerDocumentClickEvent()
  113. expect(firstHandler).toHaveBeenCalledTimes(2)
  114. expect(secondHandler).toHaveBeenCalledTimes(2)
  115. })
  116. })