2022-01-04 09:15:15 +08:00
|
|
|
import { nextTick } from 'vue'
|
2022-01-11 10:24:48 +08:00
|
|
|
import { mount } from '@vue/test-utils'
|
2022-04-19 12:46:57 +08:00
|
|
|
import {
|
|
|
|
afterAll,
|
|
|
|
afterEach,
|
|
|
|
beforeAll,
|
|
|
|
beforeEach,
|
|
|
|
describe,
|
|
|
|
expect,
|
|
|
|
it,
|
|
|
|
} from 'vitest'
|
2022-01-11 10:24:48 +08:00
|
|
|
import { usePopperContainer } from '@element-plus/hooks'
|
2022-01-04 09:15:15 +08:00
|
|
|
import { genTooltipProvides } from '../test-helper/provides'
|
|
|
|
import ElTooltipContent from '../src/content.vue'
|
|
|
|
import { TOOLTIP_INJECTION_KEY } from '../src/tokens'
|
|
|
|
|
|
|
|
const AXIOM = 'rem is the best girl'
|
|
|
|
|
|
|
|
describe('<ElTooltipContent />', () => {
|
|
|
|
const {
|
|
|
|
controlled,
|
|
|
|
id,
|
|
|
|
open,
|
|
|
|
trigger,
|
|
|
|
onOpen,
|
|
|
|
onClose,
|
|
|
|
onToggle,
|
|
|
|
onShow,
|
|
|
|
onHide,
|
2022-02-21 17:08:21 +08:00
|
|
|
onBeforeShow,
|
|
|
|
onBeforeHide,
|
2022-01-04 09:15:15 +08:00
|
|
|
} = genTooltipProvides()
|
|
|
|
|
|
|
|
const defaultProvide = {
|
|
|
|
[TOOLTIP_INJECTION_KEY as symbol]: {
|
|
|
|
controlled,
|
|
|
|
id,
|
|
|
|
open,
|
|
|
|
trigger,
|
|
|
|
onOpen,
|
|
|
|
onClose,
|
|
|
|
onToggle,
|
|
|
|
onShow,
|
|
|
|
onHide,
|
2022-02-21 17:08:21 +08:00
|
|
|
onBeforeShow,
|
|
|
|
onBeforeHide,
|
2022-01-04 09:15:15 +08:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2022-01-11 10:24:48 +08:00
|
|
|
let unmount
|
|
|
|
const createComponent = (props = {}, provides = {}) => {
|
|
|
|
const wrapper = mount(
|
|
|
|
{
|
|
|
|
components: {
|
|
|
|
ElTooltipContent,
|
|
|
|
},
|
|
|
|
template: `<el-tooltip-content><slot /></el-tooltip-content>`,
|
|
|
|
setup() {
|
|
|
|
usePopperContainer()
|
2022-01-04 09:15:15 +08:00
|
|
|
},
|
|
|
|
},
|
2022-01-11 10:24:48 +08:00
|
|
|
{
|
|
|
|
props,
|
|
|
|
global: {
|
|
|
|
provide: {
|
|
|
|
...defaultProvide,
|
|
|
|
...provides,
|
|
|
|
},
|
|
|
|
stubs: ['ElPopperContent'],
|
|
|
|
},
|
|
|
|
slots: {
|
|
|
|
default: () => [AXIOM],
|
|
|
|
},
|
2022-01-04 09:15:15 +08:00
|
|
|
|
2022-01-11 10:24:48 +08:00
|
|
|
attachTo: document.body,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
unmount = () => wrapper.unmount()
|
|
|
|
return wrapper.findComponent(ElTooltipContent)
|
|
|
|
}
|
2022-01-04 09:15:15 +08:00
|
|
|
|
|
|
|
let wrapper: ReturnType<typeof createComponent>
|
|
|
|
const OLD_ENV = process.env.NODE_ENV
|
|
|
|
beforeAll(() => {
|
2022-01-11 10:24:48 +08:00
|
|
|
process.env.NODE_ENV = 'test'
|
2022-01-04 09:15:15 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
afterAll(() => {
|
|
|
|
process.env.NODE_ENV = OLD_ENV
|
|
|
|
})
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
open.value = false
|
|
|
|
controlled.value = false
|
2022-01-11 10:24:48 +08:00
|
|
|
trigger.value = 'hover'
|
|
|
|
unmount?.()
|
2022-01-04 09:15:15 +08:00
|
|
|
document.body.innerHTML = ''
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('rendering', () => {
|
|
|
|
it('should render nothing initially when not controlled', async () => {
|
|
|
|
wrapper = createComponent()
|
|
|
|
await nextTick()
|
|
|
|
|
|
|
|
expect(wrapper.text()).toBe('')
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('persistent content', () => {
|
|
|
|
it('should be able to inherit style', async () => {
|
|
|
|
const customStyle = {
|
|
|
|
position: 'absolute',
|
|
|
|
}
|
|
|
|
|
|
|
|
wrapper = createComponent({
|
|
|
|
style: customStyle,
|
|
|
|
})
|
|
|
|
await nextTick()
|
|
|
|
|
|
|
|
expect(wrapper.vm.contentStyle).toEqual(customStyle)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2022-01-11 10:24:48 +08:00
|
|
|
describe('content rendering', () => {
|
|
|
|
it('should not show the content when disabled', async () => {
|
|
|
|
wrapper = createComponent({
|
|
|
|
disabled: true,
|
|
|
|
})
|
2022-01-04 09:15:15 +08:00
|
|
|
|
|
|
|
await nextTick()
|
|
|
|
|
2022-01-11 10:24:48 +08:00
|
|
|
expect(wrapper.vm.shouldShow).toBe(false)
|
2022-01-04 09:15:15 +08:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('events', () => {
|
|
|
|
beforeEach(async () => {
|
|
|
|
wrapper = createComponent()
|
|
|
|
await nextTick()
|
|
|
|
open.value = true
|
|
|
|
await nextTick()
|
|
|
|
await nextTick()
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should be able to enter trigger', async () => {
|
|
|
|
const { vm } = wrapper
|
|
|
|
expect(onOpen).not.toHaveBeenCalled()
|
|
|
|
const enterEvent = new MouseEvent('mouseenter')
|
|
|
|
vm.onContentEnter(enterEvent)
|
|
|
|
expect(onOpen).toHaveBeenCalled()
|
|
|
|
const leaveEvent = new MouseEvent('mouseleave')
|
|
|
|
expect(onClose).not.toHaveBeenCalled()
|
|
|
|
vm.onContentLeave(leaveEvent)
|
|
|
|
expect(onClose).toHaveBeenCalled()
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should not trigger close event when the trigger is not hover', async () => {
|
|
|
|
const { vm } = wrapper
|
|
|
|
|
|
|
|
trigger.value = 'click'
|
|
|
|
await nextTick()
|
|
|
|
const leaveEvent = new MouseEvent('mouseleave')
|
|
|
|
expect(onClose).not.toHaveBeenCalled()
|
|
|
|
vm.onContentLeave(leaveEvent)
|
|
|
|
expect(onClose).not.toHaveBeenCalled()
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should be able to stop triggering when controlled', async () => {
|
|
|
|
controlled.value = true
|
|
|
|
await nextTick()
|
|
|
|
const { vm } = wrapper
|
|
|
|
|
|
|
|
expect(onOpen).not.toHaveBeenCalled()
|
|
|
|
const enterEvent = new MouseEvent('mouseenter')
|
|
|
|
vm.onContentEnter(enterEvent)
|
|
|
|
expect(onOpen).not.toHaveBeenCalled()
|
|
|
|
const leaveEvent = new MouseEvent('mouseleave')
|
|
|
|
expect(onClose).not.toHaveBeenCalled()
|
|
|
|
vm.onContentLeave(leaveEvent)
|
|
|
|
expect(onClose).not.toHaveBeenCalled()
|
|
|
|
})
|
2022-01-11 10:24:48 +08:00
|
|
|
|
|
|
|
describe('onCloseOutside', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
// Have to mock this ref because we are not going to render the content in this component
|
|
|
|
wrapper.vm.contentRef = {
|
|
|
|
popperContentRef: document.createElement('div'),
|
|
|
|
} as any
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should not close the content after click outside when trigger is hover', async () => {
|
|
|
|
document.body.click()
|
|
|
|
await nextTick()
|
|
|
|
expect(onClose).not.toHaveBeenCalled()
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should not close the content after click outside when controlled', async () => {
|
|
|
|
controlled.value = true
|
|
|
|
trigger.value = 'click'
|
|
|
|
await nextTick()
|
|
|
|
|
|
|
|
document.body.click()
|
|
|
|
await nextTick()
|
|
|
|
expect(onClose).not.toHaveBeenCalled()
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should close component after click outside', async () => {
|
|
|
|
trigger.value = 'click'
|
|
|
|
|
|
|
|
document.body.click()
|
|
|
|
await nextTick()
|
|
|
|
|
|
|
|
expect(onClose).toHaveBeenCalled()
|
|
|
|
})
|
|
|
|
})
|
2022-01-04 09:15:15 +08:00
|
|
|
})
|
2022-01-11 11:02:32 +08:00
|
|
|
|
|
|
|
it('should append to', async () => {
|
|
|
|
const el = document.createElement('div')
|
|
|
|
const id = 'test_id'
|
|
|
|
el.id = id
|
|
|
|
document.body.appendChild(el)
|
|
|
|
|
|
|
|
wrapper = createComponent({
|
|
|
|
appendTo: `#${id}`,
|
|
|
|
})
|
|
|
|
|
|
|
|
await nextTick()
|
|
|
|
|
|
|
|
expect(el.children).toHaveLength(1)
|
|
|
|
expect(el.querySelector('[aria-hidden="true"]')).not.toBeNull()
|
|
|
|
})
|
2022-01-04 09:15:15 +08:00
|
|
|
})
|
|
|
|
})
|