element-plus/packages/hooks/__tests__/use-popper.test.tsx
Jeremy ec161eaef5
feat(hooks): [use-popper] (#10983)
* feat(hooks): [use-popper]

* Implement use-popper

* chore: code adjustment

* test: add test for use popper

* test: finish test for use popper

* fix: popper API

* chore: remove unused imports

* chore: refine code

* feat: export popper from hooks package

* chore: enhanced how to process default value

Co-authored-by: JeremyWuuuuu <15975785+JeremyWuuuuu@users.noreply.github.com>
2022-12-19 21:46:16 +08:00

123 lines
3.4 KiB
TypeScript

import { defineComponent, nextTick, ref } from 'vue'
import { mount } from '@vue/test-utils'
import { afterEach, beforeEach, describe, expect, it, vitest } from 'vitest'
import { usePopper } from '../use-popper'
import type { State } from '@popperjs/core'
import type { PartialOptions } from '../use-popper'
describe('usePopper', () => {
const optionsRef = ref<PartialOptions>({} as PartialOptions)
const popperRef = ref()
const referenceRef = ref()
const TestComponent = defineComponent({
setup() {
const usePopperReturns = usePopper(referenceRef, popperRef, optionsRef)
return usePopperReturns
},
render() {
return <div />
},
})
let wrapper: ReturnType<typeof mount>
const createComponent = async () => {
wrapper = mount(TestComponent)
await nextTick()
referenceRef.value = document.createElement('div')
popperRef.value = document.createElement('div')
}
const getExposed = (key: string) => wrapper.vm[key] as any
beforeEach(async () => {
await createComponent()
})
afterEach(() => {
wrapper.unmount()
referenceRef.value = undefined
popperRef.value = undefined
optionsRef.value = {} as PartialOptions
})
it('should render well', async () => {
await createComponent()
expect(getExposed('state')).toBeDefined()
})
describe('updates', () => {
it('should not render popper instance when elements have not changed', async () => {
const preservedInstance = getExposed('instanceRef')
await wrapper.setProps({})
expect(preservedInstance).toStrictEqual(getExposed('instanceRef'))
})
it('should render again after reference/popper element changed', async () => {
let prevInstance = getExposed('instanceRef')
referenceRef.value = document.createElement('div')
await nextTick()
expect(prevInstance).not.toStrictEqual(getExposed('instanceRef'))
prevInstance = getExposed('instanceRef')
popperRef.value = document.createElement('div')
await nextTick()
expect(prevInstance).not.toStrictEqual(getExposed('instanceRef'))
})
it('should not render twice if only options changed', async () => {
const instance = getExposed('instanceRef')
optionsRef.value = { placement: 'bottom' } as PartialOptions
await nextTick()
expect(getExposed('instanceRef')).toStrictEqual(instance)
})
it('update options', async () => {
const instance = getExposed('instanceRef') as any
const setOptionSpy = vitest.spyOn(instance, 'setOptions')
optionsRef.value = { placement: 'bottom' } as PartialOptions
await nextTick()
expect(setOptionSpy).toHaveBeenCalled()
})
it('destroys popper instance when unmounted', async () => {
const instance = getExposed('instanceRef') as any
const destroySpy = vitest.spyOn(instance, 'destroy')
wrapper.unmount()
expect(destroySpy).toHaveBeenCalled()
})
it('with arrow element', async () => {
const arrowEl = document.createElement('div')
popperRef.value.appendChild(arrowEl)
optionsRef.value = {
modifiers: [{ name: 'arrow', options: { element: arrowEl } }],
} as PartialOptions
await nextTick()
expect((getExposed('state').styles as State['styles']).arrow).toEqual(
expect.objectContaining({
position: 'absolute',
transform: 'translate(0px, 0px)',
})
)
})
})
})