From 1073a23fb24f74f4586963b2aae393a9d2868210 Mon Sep 17 00:00:00 2001 From: lejunyang Date: Sat, 2 Nov 2024 18:47:05 +0800 Subject: [PATCH] test: add auto close test for Message --- .../__test__/components/Message.test.tsx | 67 +++++++++++++++++++ .../src/components/message/Message.tsx | 3 +- .../components/src/components/message/type.ts | 2 +- utils/testSetup.ts | 7 +- 4 files changed, 73 insertions(+), 6 deletions(-) diff --git a/packages/components/__test__/components/Message.test.tsx b/packages/components/__test__/components/Message.test.tsx index 067ca874..0f3676c4 100644 --- a/packages/components/__test__/components/Message.test.tsx +++ b/packages/components/__test__/components/Message.test.tsx @@ -1,6 +1,73 @@ import { Message } from '@lun-web/components'; +import { userEvent } from '@vitest/browser/context'; import { nextTick } from 'vue'; + describe('Message', () => { + it('auto close, hover to reset auto close', async () => { + vi.useFakeTimers(); + const onOpen = vi.fn(), + onAfterOpen = vi.fn(), + onClose = vi.fn(), + onAfterClose = vi.fn(), + onAllClosed = vi.fn(); + const handlers = { + onOpen, + onAfterOpen, + onClose, + onAfterClose, + onAllClosed, + }; + const message = Message.open({ + message: 'first', + key: 'first', // must set key, or Message will use Date.now() (we're using fake timers, Date.now() will always return same result if we don't advance it) + duration: 5000, + ...handlers, + }); + message.open({ + message: 'second', + key: 'second', + duration: 10000, + ...handlers, + }); + message.open({ + message: 'third', + key: 'third', + duration: 'none', + ...handlers, + }); + await vi.waitFor(() => expect(onOpen).toBeCalledTimes(3)); + await vi.waitFor(() => expect(onAfterOpen).toBeCalledTimes(3)); + + await vi.advanceTimersByTimeAsync(3000); + expect(onClose).not.toBeCalled(); + expect(onAfterClose).not.toBeCalled(); + + await vi.advanceTimersByTimeAsync(2000); + expect(onClose).toBeCalledTimes(1); + await vi.waitFor(() => expect(onAfterClose).toBeCalledTimes(1)); + expect(onAllClosed).not.toBeCalled(); + + const second = (message.shadowRoot as HTMLElement).querySelector(`[data-key='second']`)!; + expect(second).not.toBeNull(); + await userEvent.hover(second); // hover to pause and reset auto close + await vi.advanceTimersByTimeAsync(5000); + expect(onClose).toBeCalledTimes(1); + expect(onAfterClose).toBeCalledTimes(1); + expect(onAllClosed).not.toBeCalled(); + + await userEvent.unhover(second); + await vi.advanceTimersByTimeAsync(10000); + expect(onClose).toBeCalledTimes(2); + await vi.waitFor(() => expect(onAfterClose).toBeCalledTimes(2)); + expect(onAllClosed).not.toBeCalled(); + + message.close('third'); + await nextTick(); + expect(onClose).toBeCalledTimes(3); + await vi.waitFor(() => expect(onAfterClose).toBeCalledTimes(3)); + expect(onAllClosed).toBeCalledTimes(1); + }); + it('static methods container', async () => { let message = Message.open('hello') as HTMLElement; expect(message.parentElement!.tagName).toBe('BODY'); diff --git a/packages/components/src/components/message/Message.tsx b/packages/components/src/components/message/Message.tsx index 04b47e74..88f27d9c 100644 --- a/packages/components/src/components/message/Message.tsx +++ b/packages/components/src/components/message/Message.tsx @@ -95,7 +95,7 @@ export const Message = Object.assign( class: ns.e('callout'), }; const key = (config.key ||= Date.now()); - (config as any)['data-key'] = key; + (config as any)['data-key'] = '' + key; Object.assign(config, getCalloutHandlers(config)); if (config.duration === undefined) config.duration = 3000; const { duration } = config; @@ -104,6 +104,7 @@ export const Message = Object.assign( calloutMap[key] = { ...calloutMap[key], ...config }; } else calloutMap[key] = config; startTimer(key, duration); + return key; }, close(key) { if ((tempCalloutMap[key] = calloutMap[key])) { diff --git a/packages/components/src/components/message/type.ts b/packages/components/src/components/message/type.ts index 17f393ca..44e3cd2f 100644 --- a/packages/components/src/components/message/type.ts +++ b/packages/components/src/components/message/type.ts @@ -51,7 +51,7 @@ export type MessageEvents = GetEventPropsFromEmits; export type MessageProps = Partial & MessageEvents; export type MessageMethods = { - open(config?: MessageOpenConfig): void; + open(config?: MessageOpenConfig): string; close(key: string | number): void; closeAll(): void; }; diff --git a/utils/testSetup.ts b/utils/testSetup.ts index d63c7b7a..f4ad12c3 100644 --- a/utils/testSetup.ts +++ b/utils/testSetup.ts @@ -29,12 +29,11 @@ defineAllComponents(); const persistCount = new WeakMap(); afterEach(() => { + const specialToRemove = ['l-message', 'l-dialog', 'l-theme-provider', 'l-teleport-holder']; const testEls = document.querySelectorAll(`[${testAttr}]`), - themeProviders = document.querySelectorAll('l-theme-provider'), - teleportHolders = document.querySelectorAll('l-teleport-holder'); + specials = specialToRemove.map((name) => Array.from(document.querySelectorAll(name))).flat(); Array.from(testEls) - .concat(Array.from(themeProviders)) - .concat(Array.from(teleportHolders)) + .concat(specials) .forEach((el) => { if (el.getAttribute(persistAttr) != null) { const count = persistCount.get(el) || 0;