From e25df5408fbd0520e77b92e8ff541f3c53e8e640 Mon Sep 17 00:00:00 2001 From: Obaydur Rahman Date: Tue, 30 Aug 2022 22:47:58 -0700 Subject: [PATCH] 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> --- .../__tests__/repeat-click.test.tsx | 50 +++++++------------ packages/directives/repeat-click/index.ts | 31 +++++++----- 2 files changed, 37 insertions(+), 44 deletions(-) diff --git a/packages/directives/__tests__/repeat-click.test.tsx b/packages/directives/__tests__/repeat-click.test.tsx index 299f6d5869..67c84c808d 100644 --- a/packages/directives/__tests__/repeat-click.test.tsx +++ b/packages/directives/__tests__/repeat-click.test.tsx @@ -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 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() }) }) diff --git a/packages/directives/repeat-click/index.ts b/packages/directives/repeat-click/index.ts index d37ede516d..bcfea54701 100644 --- a/packages/directives/repeat-click/index.ts +++ b/packages/directives/repeat-click/index.ts @@ -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 | null = null - let isHandlerCalled = false + let delay: ReturnType | 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) }) }, }