2020-08-18 00:25:10 +08:00
|
|
|
import { mount } from '@vue/test-utils'
|
|
|
|
import * as Vue from 'vue'
|
|
|
|
import * as popperExports from '@popperjs/core'
|
|
|
|
import ElPopper from '../src/index.vue'
|
|
|
|
|
|
|
|
import type { VueWrapper } from '@vue/test-utils'
|
|
|
|
|
2020-08-18 11:58:34 +08:00
|
|
|
type UnKnownProps = Record<string, unknown>
|
2020-08-18 00:25:10 +08:00
|
|
|
|
2020-08-18 11:58:34 +08:00
|
|
|
jest.mock('lodash')
|
2020-08-18 00:25:10 +08:00
|
|
|
|
2020-08-18 18:02:28 +08:00
|
|
|
jest.useFakeTimers()
|
|
|
|
|
2020-08-18 20:23:39 +08:00
|
|
|
const { h, nextTick } = Vue
|
2020-08-18 11:58:34 +08:00
|
|
|
const AXIOM = 'Rem is the best girl'
|
2020-08-18 18:02:28 +08:00
|
|
|
const selector = '[role="tooltip"]'
|
|
|
|
const TEST_TRIGGER = 'test-trigger'
|
|
|
|
const MOUSE_ENTER_EVENT = 'mouseenter'
|
|
|
|
const MOUSE_LEAVE_EVENT = 'mouseleave'
|
2020-08-28 10:47:02 +08:00
|
|
|
const CLICK_EVENT = 'click'
|
|
|
|
const FOCUS_EVENT = 'focus'
|
|
|
|
const BLUR_EVENT = 'blur'
|
2020-08-18 18:02:28 +08:00
|
|
|
const DISPLAY_NONE = 'display: none'
|
2020-08-18 00:25:10 +08:00
|
|
|
|
2020-08-18 18:02:28 +08:00
|
|
|
const Wrapped = (props: UnKnownProps, { slots }) => h('div', h(ElPopper, props, slots))
|
2020-08-18 11:58:34 +08:00
|
|
|
const Transition = (_: UnKnownProps, { attrs, slots }) => h('div', attrs, slots)
|
2020-08-18 00:25:10 +08:00
|
|
|
Transition.displayName = 'Transition'
|
|
|
|
// eslint-disable-next-line
|
|
|
|
const _mount = (props: Record<string, unknown> = {}, slots = {}): VueWrapper<any> =>
|
|
|
|
mount(Wrapped, {
|
|
|
|
props,
|
2020-08-18 18:02:28 +08:00
|
|
|
slots: {
|
|
|
|
trigger: () => h('div', {
|
|
|
|
class: TEST_TRIGGER,
|
|
|
|
}),
|
|
|
|
...slots,
|
|
|
|
},
|
2020-08-18 00:25:10 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
|
2020-08-18 11:58:34 +08:00
|
|
|
const popperMock = jest.spyOn(popperExports, 'createPopper').mockImplementation(() => ({
|
|
|
|
update: jest.fn(),
|
|
|
|
forceUpdate: jest.fn(),
|
|
|
|
setOptions: jest.fn(),
|
|
|
|
destroy: jest.fn(),
|
|
|
|
state: null,
|
|
|
|
}))
|
|
|
|
|
2020-08-18 00:25:10 +08:00
|
|
|
describe('Popper.vue', () => {
|
2020-08-18 11:58:34 +08:00
|
|
|
// eslint-disable-next-line
|
|
|
|
// eslint-disable-next-line
|
2020-08-18 00:25:10 +08:00
|
|
|
const oldTransition = Vue.Transition
|
|
|
|
beforeAll(() => {
|
|
|
|
// eslint-disable-next-line
|
|
|
|
;(Vue as any).Transition = Transition
|
|
|
|
})
|
2020-08-18 11:58:34 +08:00
|
|
|
|
2020-08-18 00:25:10 +08:00
|
|
|
afterAll(() => {
|
|
|
|
popperMock.mockReset()
|
|
|
|
// eslint-disable-next-line
|
|
|
|
;(Vue as any).Transition = oldTransition
|
|
|
|
})
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
popperMock.mockClear()
|
|
|
|
})
|
|
|
|
|
|
|
|
test('render test', () => {
|
|
|
|
let wrapper = _mount({
|
|
|
|
appendToBody: false,
|
|
|
|
}, {
|
|
|
|
default: () => AXIOM,
|
|
|
|
})
|
|
|
|
|
|
|
|
expect(wrapper.text()).toEqual(AXIOM)
|
|
|
|
|
|
|
|
wrapper = _mount({
|
|
|
|
appendToBody: false,
|
|
|
|
content: AXIOM,
|
|
|
|
})
|
|
|
|
|
|
|
|
expect(wrapper.text()).toEqual(AXIOM)
|
|
|
|
})
|
|
|
|
|
|
|
|
test('append to body', () => {
|
|
|
|
let wrapper = _mount()
|
2020-08-24 00:00:20 +08:00
|
|
|
expect(wrapper.find(selector).exists()).toBe(false)
|
2020-08-25 22:25:46 +08:00
|
|
|
/**
|
|
|
|
* Current layout of `ElPopper`
|
|
|
|
* --> Teleport
|
|
|
|
* --> mask
|
|
|
|
* --> transition
|
|
|
|
* --> popper
|
|
|
|
*/
|
|
|
|
|
2020-08-18 00:25:10 +08:00
|
|
|
wrapper = _mount({
|
|
|
|
appendToBody: false,
|
|
|
|
})
|
|
|
|
|
|
|
|
expect(wrapper.find('[role="tooltip"]').exists()).toBe(true)
|
|
|
|
})
|
|
|
|
|
|
|
|
test('should show popper when mouse entered and hide when popper left', async () => {
|
|
|
|
const wrapper = _mount({
|
|
|
|
appendToBody: false,
|
|
|
|
})
|
|
|
|
|
2020-08-18 18:02:28 +08:00
|
|
|
expect(wrapper.find(selector).attributes('style')).toContain(DISPLAY_NONE)
|
|
|
|
await wrapper.find(selector).trigger(MOUSE_ENTER_EVENT)
|
2020-08-18 00:25:10 +08:00
|
|
|
|
2020-08-18 18:02:28 +08:00
|
|
|
expect(wrapper.find(selector).attributes('style')).not.toContain(DISPLAY_NONE)
|
2020-08-18 00:25:10 +08:00
|
|
|
|
2020-08-18 18:02:28 +08:00
|
|
|
await wrapper.find(selector).trigger(MOUSE_LEAVE_EVENT)
|
2020-08-18 00:25:10 +08:00
|
|
|
|
2020-08-18 18:02:28 +08:00
|
|
|
expect(wrapper.find(selector).attributes('style')).toContain(DISPLAY_NONE)
|
2020-08-18 00:25:10 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
test('should be able to manual open', async () => {
|
|
|
|
const wrapper = _mount({
|
|
|
|
manualMode: true,
|
|
|
|
appendToBody: false,
|
|
|
|
value: false,
|
|
|
|
})
|
2020-08-18 18:02:28 +08:00
|
|
|
expect(wrapper.find(selector).attributes('style')).toContain(DISPLAY_NONE)
|
|
|
|
await wrapper.find(selector).trigger(MOUSE_ENTER_EVENT)
|
2020-08-18 11:58:34 +08:00
|
|
|
|
2020-08-18 18:02:28 +08:00
|
|
|
expect(wrapper.find(selector).attributes('style')).toContain(DISPLAY_NONE)
|
2020-08-18 00:25:10 +08:00
|
|
|
await wrapper.setProps({
|
|
|
|
value: true,
|
|
|
|
})
|
|
|
|
|
2020-08-18 18:02:28 +08:00
|
|
|
expect(wrapper.find(selector).attributes('style')).not.toContain(DISPLAY_NONE)
|
2020-08-18 00:25:10 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
test('should disable popper to popup', async () => {
|
|
|
|
const wrapper = _mount({
|
|
|
|
disabled: true,
|
|
|
|
appendToBody: false,
|
|
|
|
})
|
|
|
|
|
2020-08-18 18:02:28 +08:00
|
|
|
expect(wrapper.find(selector).attributes('style')).toContain(DISPLAY_NONE)
|
|
|
|
await wrapper.find(selector).trigger(MOUSE_ENTER_EVENT)
|
2020-08-18 00:25:10 +08:00
|
|
|
|
2020-08-18 18:02:28 +08:00
|
|
|
expect(wrapper.find(selector).attributes('style')).toContain(DISPLAY_NONE)
|
2020-08-18 00:25:10 +08:00
|
|
|
|
|
|
|
await wrapper.setProps({
|
|
|
|
disabled: false,
|
|
|
|
})
|
2020-08-18 18:02:28 +08:00
|
|
|
await wrapper.find(selector).trigger(MOUSE_ENTER_EVENT)
|
2020-08-18 11:58:34 +08:00
|
|
|
|
2020-08-18 18:02:28 +08:00
|
|
|
expect(wrapper.find(selector).attributes('style')).not.toContain(DISPLAY_NONE)
|
2020-08-18 00:25:10 +08:00
|
|
|
})
|
|
|
|
|
2020-08-18 18:02:28 +08:00
|
|
|
test('should add tab index to referrer', async () => {
|
2020-08-18 00:25:10 +08:00
|
|
|
const wrapper = _mount({
|
|
|
|
appendToBody: false,
|
|
|
|
})
|
2020-08-18 18:02:28 +08:00
|
|
|
expect(wrapper.find(`.${TEST_TRIGGER}`).attributes('tabindex')).toBe('0')
|
|
|
|
})
|
2020-08-18 00:25:10 +08:00
|
|
|
|
2020-08-18 18:02:28 +08:00
|
|
|
test('should initialize a new popper when component mounted', async () => {
|
|
|
|
_mount({
|
|
|
|
appendToBody: false,
|
2020-08-18 00:25:10 +08:00
|
|
|
})
|
|
|
|
|
2020-08-18 18:02:28 +08:00
|
|
|
expect(popperExports.createPopper).toHaveBeenCalledTimes(1)
|
|
|
|
|
2020-08-18 00:25:10 +08:00
|
|
|
})
|
|
|
|
|
2020-08-18 18:02:28 +08:00
|
|
|
test('should hide after hide after is given', async () => {
|
|
|
|
|
2020-08-18 00:25:10 +08:00
|
|
|
const wrapper = _mount({
|
2020-08-18 18:02:28 +08:00
|
|
|
hideAfter: 200,
|
2020-08-18 00:25:10 +08:00
|
|
|
appendToBody: false,
|
|
|
|
})
|
2020-08-18 18:02:28 +08:00
|
|
|
await wrapper.find(selector).trigger(MOUSE_ENTER_EVENT)
|
|
|
|
expect(wrapper.find(selector).attributes('style')).not.toContain(DISPLAY_NONE)
|
2020-08-18 20:23:39 +08:00
|
|
|
jest.runOnlyPendingTimers()
|
|
|
|
await nextTick()
|
|
|
|
expect(wrapper.find(selector).attributes('style')).toContain(DISPLAY_NONE)
|
2020-08-18 18:02:28 +08:00
|
|
|
})
|
2020-08-18 00:25:10 +08:00
|
|
|
|
2020-08-18 18:02:28 +08:00
|
|
|
test('should throw error when there is no trigger', () => {
|
2020-08-18 20:23:39 +08:00
|
|
|
const errorHandler = jest.fn()
|
|
|
|
mount(Wrapped, {
|
|
|
|
slots: {
|
|
|
|
trigger: undefined,
|
|
|
|
},
|
|
|
|
global: {
|
|
|
|
config: {
|
|
|
|
errorHandler(err: Error) {
|
|
|
|
errorHandler(err)
|
|
|
|
},
|
|
|
|
warnHandler() {
|
|
|
|
// suppress warning
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2020-08-18 00:25:10 +08:00
|
|
|
})
|
2020-08-18 20:23:39 +08:00
|
|
|
// due to vue catches the error during rendering, and throws it asynchronously
|
|
|
|
// the only way to test this is by providing an error handler to catch it
|
2020-08-18 18:02:28 +08:00
|
|
|
expect(errorHandler).toHaveBeenCalledTimes(1)
|
2020-08-18 00:25:10 +08:00
|
|
|
})
|
2020-08-28 10:47:02 +08:00
|
|
|
describe('trigger', () => {
|
|
|
|
|
|
|
|
test('should work with click trigger', async () => {
|
|
|
|
const wrapper = _mount({
|
|
|
|
trigger: ['click'],
|
|
|
|
appendToBody: false,
|
|
|
|
})
|
|
|
|
await nextTick()
|
|
|
|
|
|
|
|
const trigger = wrapper.find(`.${TEST_TRIGGER}`)
|
|
|
|
const popper = wrapper.findComponent(ElPopper)
|
|
|
|
expect(popper.vm.visible).toBe(false)
|
|
|
|
// for now triggering event on element via DOMWrapper is not available so we need to apply
|
|
|
|
// old way
|
|
|
|
await trigger.trigger(CLICK_EVENT)
|
|
|
|
|
|
|
|
expect(popper.vm.visible).toBe(true)
|
|
|
|
|
|
|
|
await trigger.trigger(MOUSE_ENTER_EVENT)
|
|
|
|
expect(popper.vm.visible).toBe(true)
|
|
|
|
await trigger.trigger(FOCUS_EVENT)
|
|
|
|
expect(popper.vm.visible).toBe(true)
|
|
|
|
})
|
|
|
|
|
|
|
|
test('should work with hover trigger', async () => {
|
|
|
|
const wrapper = _mount({
|
|
|
|
trigger: ['hover'],
|
|
|
|
appendToBody: false,
|
|
|
|
})
|
|
|
|
await nextTick()
|
|
|
|
|
|
|
|
const trigger = wrapper.find(`.${TEST_TRIGGER}`)
|
|
|
|
const popper = wrapper.findComponent(ElPopper)
|
|
|
|
expect(popper.vm.visible).toBe(false)
|
|
|
|
// for now triggering event on element via DOMWrapper is not available so we need to apply
|
|
|
|
// old way
|
|
|
|
await trigger.trigger(MOUSE_ENTER_EVENT)
|
|
|
|
|
|
|
|
expect(popper.vm.visible).toBe(true)
|
|
|
|
|
|
|
|
await trigger.trigger(MOUSE_LEAVE_EVENT)
|
|
|
|
expect(popper.vm.visible).toBe(false)
|
|
|
|
|
|
|
|
await trigger.trigger(FOCUS_EVENT)
|
|
|
|
expect(popper.vm.visible).toBe(false)
|
|
|
|
|
|
|
|
await trigger.trigger(CLICK_EVENT)
|
|
|
|
expect(popper.vm.visible).toBe(false)
|
|
|
|
})
|
|
|
|
|
|
|
|
test('should work with focus trigger', async () => {
|
|
|
|
const wrapper = _mount({
|
|
|
|
trigger: [FOCUS_EVENT],
|
|
|
|
appendToBody: false,
|
|
|
|
})
|
|
|
|
await nextTick()
|
|
|
|
|
|
|
|
|
|
|
|
const trigger = wrapper.find(`.${TEST_TRIGGER}`)
|
|
|
|
const popper = wrapper.findComponent(ElPopper)
|
|
|
|
expect(popper.vm.visible).toBe(false)
|
|
|
|
// for now triggering event on element via DOMWrapper is not available so we need to apply
|
|
|
|
// old way
|
|
|
|
await trigger.trigger(FOCUS_EVENT)
|
|
|
|
|
|
|
|
expect(popper.vm.visible).toBe(true)
|
|
|
|
|
|
|
|
await trigger.trigger(BLUR_EVENT)
|
|
|
|
expect(popper.vm.visible).toBe(false)
|
|
|
|
|
|
|
|
await trigger.trigger(MOUSE_ENTER_EVENT)
|
|
|
|
expect(popper.vm.visible).toBe(false)
|
|
|
|
|
|
|
|
await trigger.trigger(CLICK_EVENT)
|
|
|
|
expect(popper.vm.visible).toBe(false)
|
|
|
|
})
|
|
|
|
|
|
|
|
test('combined trigger', async () => {
|
|
|
|
const wrapper = _mount({
|
|
|
|
trigger: [FOCUS_EVENT, CLICK_EVENT, 'hover'],
|
|
|
|
appendToBody: false,
|
|
|
|
})
|
|
|
|
await nextTick()
|
|
|
|
|
|
|
|
const trigger = wrapper.find(`.${TEST_TRIGGER}`)
|
|
|
|
const popper = wrapper.findComponent(ElPopper)
|
|
|
|
expect(popper.vm.visible).toBe(false)
|
|
|
|
// for now triggering event on element via DOMWrapper is not available so we need to apply
|
|
|
|
// old way
|
|
|
|
await trigger.trigger(CLICK_EVENT)
|
|
|
|
|
|
|
|
expect(popper.vm.visible).toBe(true)
|
|
|
|
|
|
|
|
await trigger.trigger(BLUR_EVENT)
|
|
|
|
expect(popper.vm.visible).toBe(false)
|
|
|
|
|
|
|
|
await trigger.trigger(MOUSE_ENTER_EVENT)
|
|
|
|
expect(popper.vm.visible).toBe(true)
|
|
|
|
|
|
|
|
await trigger.trigger(CLICK_EVENT)
|
|
|
|
expect(popper.vm.visible).toBe(false)
|
|
|
|
|
|
|
|
await trigger.trigger(FOCUS_EVENT)
|
|
|
|
expect(popper.vm.visible).toBe(true)
|
|
|
|
|
|
|
|
await trigger.trigger(CLICK_EVENT)
|
|
|
|
expect(popper.vm.visible).toBe(false)
|
|
|
|
})
|
|
|
|
})
|
2020-08-18 00:25:10 +08:00
|
|
|
})
|