fix(directives): [repeat-click] Interval time is too short for single clicks (#9466)

* fix(directives): [repeat-click] time is too short for single clicks

* fix(test-utils): [repeat-click] increase sleep time

Updated times according to PR #9466

* fix(test-utils): [repeat-click] increase test time

Updated times according to PR #9466

* chore: update

* chore: improve test case

Co-authored-by: holazz <2418184580@qq.com>
This commit is contained in:
Obaydur Rahman
2022-08-30 22:47:58 -07:00
committed by GitHub
parent fa312f0b85
commit e25df5408f
2 changed files with 37 additions and 44 deletions

View File

@@ -1,8 +1,8 @@
import { mount } from '@vue/test-utils'
import { describe, expect, it, vi } from 'vitest'
import sleep from '@element-plus/test-utils/sleep'
import RepeatClick from '../repeat-click'
import RepeatClick, { REPEAT_DELAY, REPEAT_INTERVAL } from '../repeat-click'
const PRESS_TIME = REPEAT_DELAY + REPEAT_INTERVAL
let handler: ReturnType<typeof vi.fn>
const _mount = () =>
@@ -27,40 +27,28 @@ const _mount = () =>
)
describe('Directives.vue', () => {
it('click test', async () => {
it('single click', async () => {
const wrapper = _mount()
const block = wrapper.find('#block')
vi.useFakeTimers()
block.trigger('mousedown')
await sleep(330)
vi.advanceTimersByTime(PRESS_TIME - 1)
document.dispatchEvent(new MouseEvent('mouseup'))
expect(handler).toHaveBeenCalledTimes(1)
vi.useRealTimers()
})
it('click and hold on', async () => {
const wrapper = _mount()
const block = wrapper.find('#block')
vi.useFakeTimers()
block.trigger('mousedown')
vi.advanceTimersByTime(PRESS_TIME)
document.dispatchEvent(new MouseEvent('mouseup'))
expect(handler).toHaveBeenCalledTimes(3)
})
it('time interval between mousedown and mouseup is slightly less than 100ms', async () => {
const wrapper = _mount()
const block = wrapper.find('#block')
for (let i = 0; i < 10; i++) {
block.trigger('mousedown')
await sleep(99)
document.dispatchEvent(new MouseEvent('mouseup'))
}
expect(handler).toHaveBeenCalledTimes(10)
})
it('time interval between mousedown and mouseup is slightly more than 100ms', async () => {
const wrapper = _mount()
const block = wrapper.find('#block')
for (let i = 0; i < 10; i++) {
block.trigger('mousedown')
await sleep(101)
document.dispatchEvent(new MouseEvent('mouseup'))
}
expect(handler).toHaveBeenCalledTimes(10)
expect(handler).toHaveBeenCalledTimes(2)
vi.useRealTimers()
})
})

View File

@@ -1,32 +1,37 @@
import type { DirectiveBinding, ObjectDirective } from 'vue'
export const REPEAT_INTERVAL = 100
export const REPEAT_DELAY = 600
const RepeatClick: ObjectDirective = {
beforeMount(el: HTMLElement, binding: DirectiveBinding) {
let interval: ReturnType<typeof setInterval> | null = null
let isHandlerCalled = false
let delay: ReturnType<typeof setTimeout> | null = null
const handler = () => binding.value && binding.value()
const clear = () => {
clearInterval(interval!)
interval = null
if (!isHandlerCalled) {
handler()
if (delay) {
clearTimeout(delay)
delay = null
}
if (interval) {
clearInterval(interval)
interval = null
}
isHandlerCalled = false
}
el.addEventListener('mousedown', (e: MouseEvent) => {
if (e.button !== 0) return
handler()
document.addEventListener('mouseup', clear, { once: true })
clearInterval(interval!)
interval = setInterval(() => {
isHandlerCalled = true
handler()
}, 100)
clear()
delay = setTimeout(() => {
interval = setInterval(() => {
handler()
}, REPEAT_INTERVAL)
}, REPEAT_DELAY)
})
},
}