/
message.test.ts
184 lines (158 loc) Β· 5.35 KB
/
message.test.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
import { h, nextTick } from 'vue'
import { describe, expect, test, vi } from 'vitest'
import makeMount from '@element-plus/test-utils/make-mount'
import { rAF } from '@element-plus/test-utils/tick'
import { TypeComponentsMap } from '@element-plus/utils'
import { EVENT_CODE } from '@element-plus/constants'
import Message from '../src/message.vue'
import type { CSSProperties, Component, ComponentPublicInstance } from 'vue'
const AXIOM = 'Rem is the best girl'
type MessageInstance = ComponentPublicInstance<{
visible: boolean
iconComponent: string | Component
customStyle: CSSProperties
}>
const onClose = vi.fn()
const _mount = makeMount(Message, {
props: {
onClose,
},
})
describe('Message.vue', () => {
describe('render', () => {
test('basic render test', () => {
const wrapper = _mount({
slots: {
default: AXIOM,
},
})
const vm = wrapper.vm as MessageInstance
expect(wrapper.text()).toEqual(AXIOM)
expect(vm.visible).toBe(true)
expect(vm.iconComponent).toBe(TypeComponentsMap['info'])
expect(vm.customStyle).toEqual({ top: '16px', zIndex: 0 })
})
test('should be able to render VNode', () => {
const wrapper = _mount({
slots: {
default: h('span', { class: 'text-node' }, AXIOM),
},
})
expect(wrapper.find('.text-node').exists()).toBe(true)
})
test('should be able to render raw HTML with dangerouslyUseHTMLString prop', () => {
const tagClass = 'test-class'
const wrapper = _mount({
props: {
dangerouslyUseHTMLString: true,
message: `<string class="${tagClass}"'>${AXIOM}</strong>`,
},
})
expect(wrapper.find(`.${tagClass}`).exists()).toBe(true)
})
test('should not be able to render raw HTML without dangerouslyUseHTMLString prop', () => {
const tagClass = 'test-class'
const wrapper = _mount({
props: {
dangerouslyUseHTMLString: false,
message: `<string class="${tagClass}"'>${AXIOM}</strong>`,
},
})
expect(wrapper.find(`.${tagClass}`).exists()).toBe(false)
})
})
describe('Message.type', () => {
test('should be able to render typed messages', () => {
for (const type of ['success', 'warning', 'info', 'error'] as const) {
const wrapper = _mount({ props: { type } })
expect(wrapper.findComponent(TypeComponentsMap[type]).exists()).toBe(
true
)
}
})
test('should not be able to render invalid type icon', () => {
const consoleWarn = console.warn
console.warn = vi.fn()
const type = 'some-type'
const wrapper = _mount({ props: { type } })
for (const component of Object.values(TypeComponentsMap)) {
expect(wrapper.findComponent(component).exists()).toBe(false)
}
console.warn = consoleWarn
})
})
describe('event handlers', () => {
test('it should be able to close the message by clicking close button', async () => {
const onClose = vi.fn()
const wrapper = _mount({
slots: { default: AXIOM },
props: {
onClose,
showClose: true,
},
})
const closeBtn = wrapper.find('.el-message__closeBtn')
expect(closeBtn.exists()).toBe(true)
await closeBtn.trigger('click')
expect((wrapper.vm as MessageInstance).visible).toBe(false)
})
test('it should close after duration', async () => {
vi.useFakeTimers()
const duration = 1000
const wrapper = _mount({ props: { duration } })
const vm = wrapper.vm as MessageInstance
await nextTick()
expect(vm.visible).toBe(true)
vi.runAllTimers()
await nextTick()
expect(vm.visible).toBe(false)
vi.useRealTimers()
})
test('it should prevent close when hovered', async () => {
vi.useFakeTimers()
const duration = 1000
const wrapper = _mount({ props: { duration } })
const vm = wrapper.vm as MessageInstance
vi.advanceTimersByTime(50)
expect(vm.visible).toBe(true)
await wrapper.find('[role="alert"]').trigger('mouseenter')
vi.runAllTimers()
expect(vm.visible).toBe(true)
await wrapper.find('[role="alert"]').trigger('mouseleave')
expect(vm.visible).toBe(true)
vi.runAllTimers()
expect(vm.visible).toBe(false)
vi.useRealTimers()
})
test('it should not close when duration is set to 0', () => {
vi.useFakeTimers()
const duration = 0
const wrapper = _mount({ props: { duration } })
const vm = wrapper.vm as MessageInstance
expect(vm.visible).toBe(true)
vi.runAllTimers()
expect(vm.visible).toBe(true)
vi.useRealTimers()
})
test('it should close when esc is pressed', async () => {
const wrapper = _mount({ slots: { default: AXIOM } })
const event = new KeyboardEvent('keydown', {
code: EVENT_CODE.esc,
})
document.dispatchEvent(event)
expect((wrapper.vm as MessageInstance).visible).toBe(false)
})
test('it should call close after transition ends', async () => {
const onClose = vi.fn()
const wrapper = _mount({
slots: { default: AXIOM },
props: { onClose },
})
await rAF()
const vm = wrapper.vm as MessageInstance
vm.visible = false
await rAF()
expect(onClose).toHaveBeenCalledTimes(1)
})
})
})