popover.test.tsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. import { nextTick, ref } from 'vue'
  2. import { mount } from '@vue/test-utils'
  3. import { afterEach, describe, expect, it, vi } from 'vitest'
  4. import { usePopperContainerId, useZIndex } from '@element-plus/hooks'
  5. import { rAF } from '@element-plus/test-utils/tick'
  6. import { ElPopperTrigger } from '@element-plus/components/popper'
  7. import Popover from '../src/popover.vue'
  8. import type { VueWrapper } from '@vue/test-utils'
  9. import type { PopoverProps } from '../src/popover'
  10. const AXIOM = 'Rem is the best girl'
  11. const _mount = (props?: Partial<PopoverProps>) =>
  12. mount(
  13. {
  14. setup() {
  15. const slots = {
  16. default: () => AXIOM,
  17. reference: () => <button>click me</button>,
  18. }
  19. return () => <Popover {...props} v-slots={slots} />
  20. },
  21. },
  22. {
  23. attachTo: document.body,
  24. }
  25. )
  26. describe('Popover.vue', () => {
  27. let wrapper: VueWrapper<any>
  28. const findContentComp = () =>
  29. wrapper.findComponent({
  30. name: 'ElPopperContent',
  31. })
  32. afterEach(() => {
  33. wrapper?.unmount()
  34. document.body.innerHTML = ''
  35. })
  36. it('render test', () => {
  37. wrapper = _mount()
  38. expect(findContentComp().text()).toEqual(AXIOM)
  39. })
  40. it('should render with title', () => {
  41. const title = 'test title'
  42. wrapper = _mount({ title })
  43. expect(findContentComp().text()).toContain(title)
  44. })
  45. it(`should modify popover's style with width`, async () => {
  46. wrapper = _mount({ width: 200 })
  47. const popperContent = findContentComp()
  48. expect(getComputedStyle(popperContent.element).width).toBe('200px')
  49. await wrapper.setProps({ width: '100vw' })
  50. expect(getComputedStyle(popperContent.element).width).toBe('100vw')
  51. })
  52. it('the content should be overrode by slots', () => {
  53. const content = 'test content'
  54. wrapper = _mount({ content })
  55. expect(findContentComp().text()).toContain(AXIOM)
  56. })
  57. it('should render content when no slots were passed', () => {
  58. const content = 'test content'
  59. const virtualRef = document.createElement('button')
  60. wrapper = mount(() => (
  61. <Popover
  62. content={content}
  63. teleported={false}
  64. virtualRef={virtualRef}
  65. virtualTriggering
  66. />
  67. ))
  68. expect(findContentComp().text()).toBe(content)
  69. })
  70. it('popper z-index should be dynamical', () => {
  71. wrapper = _mount()
  72. const { currentZIndex } = useZIndex()
  73. expect(
  74. Number.parseInt(window.getComputedStyle(findContentComp().element).zIndex)
  75. ).toBeLessThanOrEqual(currentZIndex.value)
  76. })
  77. it('defind hide method', async () => {
  78. wrapper = _mount()
  79. const vm = wrapper.findComponent(Popover).vm
  80. expect(vm.hide).toBeDefined()
  81. })
  82. it('should be able to emit after-enter and after-leave', async () => {
  83. const wrapper = _mount({ trigger: 'click' })
  84. await nextTick()
  85. const trigger$ = wrapper.findComponent(ElPopperTrigger)
  86. const triggerEl = trigger$.find('.el-tooltip__trigger')
  87. vi.useFakeTimers()
  88. await triggerEl.trigger('click')
  89. vi.runAllTimers()
  90. vi.useRealTimers()
  91. await rAF()
  92. expect(wrapper.findComponent(Popover).emitted()).toHaveProperty(
  93. 'after-enter'
  94. )
  95. vi.useFakeTimers()
  96. await triggerEl.trigger('click')
  97. vi.runAllTimers()
  98. vi.useRealTimers()
  99. await rAF()
  100. expect(wrapper.findComponent(Popover).emitted()).toHaveProperty(
  101. 'after-leave'
  102. )
  103. })
  104. it('test visible controlled mode trigger invalid', async () => {
  105. const wrapper = _mount({ visible: false, trigger: 'click' })
  106. await nextTick()
  107. const trigger$ = wrapper.findComponent(ElPopperTrigger)
  108. const triggerEl = trigger$.find('.el-tooltip__trigger')
  109. const popoverDom: HTMLElement = document.querySelector('.el-popper')!
  110. vi.useFakeTimers()
  111. await triggerEl.trigger('click')
  112. vi.runAllTimers()
  113. vi.useRealTimers()
  114. await rAF()
  115. expect(popoverDom.style.display).toBe('none')
  116. vi.useFakeTimers()
  117. await wrapper.setProps({ visible: true })
  118. vi.runAllTimers()
  119. vi.useRealTimers()
  120. await rAF()
  121. expect(popoverDom.style.display).not.toBe('none')
  122. vi.useFakeTimers()
  123. await wrapper.setProps({ visible: false })
  124. vi.runAllTimers()
  125. vi.useRealTimers()
  126. await rAF()
  127. expect(popoverDom.style.display).toBe('none')
  128. })
  129. it('test v-model:visible', async () => {
  130. const wrapper = mount(
  131. {
  132. setup() {
  133. const visible = ref(false)
  134. return () => (
  135. <Popover v-model={[visible.value, 'visible']} trigger="click">
  136. {{
  137. default: () => AXIOM,
  138. reference: () => <button>click me</button>,
  139. }}
  140. </Popover>
  141. )
  142. },
  143. },
  144. {
  145. attachTo: document.body,
  146. }
  147. )
  148. await nextTick()
  149. const trigger$ = wrapper.findComponent(ElPopperTrigger)
  150. const triggerEl = trigger$.find('.el-tooltip__trigger')
  151. const popoverDom: HTMLElement = document.querySelector('.el-popper')!
  152. vi.useFakeTimers()
  153. await triggerEl.trigger('click')
  154. vi.runAllTimers()
  155. vi.useRealTimers()
  156. await rAF()
  157. expect(popoverDom.style.display).not.toBe('none')
  158. vi.useFakeTimers()
  159. await triggerEl.trigger('click')
  160. vi.runAllTimers()
  161. vi.useRealTimers()
  162. await rAF()
  163. expect(popoverDom.style.display).toBe('none')
  164. })
  165. describe('teleported API', () => {
  166. it('should mount on popper container', async () => {
  167. expect(document.body.innerHTML).toBe('')
  168. _mount()
  169. await nextTick()
  170. const { selector } = usePopperContainerId()
  171. expect(document.body.querySelector(selector.value)?.innerHTML).not.toBe(
  172. ''
  173. )
  174. })
  175. it('should not mount on the popper container', async () => {
  176. expect(document.body.innerHTML).toBe('')
  177. _mount({ teleported: false })
  178. await nextTick()
  179. const { selector } = usePopperContainerId()
  180. expect(document.body.querySelector(selector.value)?.innerHTML).toBe('')
  181. })
  182. })
  183. })