diff --git a/package.json b/package.json index 73b2a65916..d5866a37f3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@nutui/nutui", - "version": "4.3.15", + "version": "4.3.16", "description": "京东风格的轻量级移动端 Vue2、Vue3 组件库(支持小程序开发)", "main": "dist/nutui.umd.js", "module": "dist/nutui.es.js", diff --git a/publish/nutui-taro/package.json b/publish/nutui-taro/package.json index 24a571a67d..f86c415af6 100644 --- a/publish/nutui-taro/package.json +++ b/publish/nutui-taro/package.json @@ -1,6 +1,6 @@ { "name": "@nutui/nutui-taro", - "version": "4.3.15", + "version": "4.3.16", "description": "京东风格的轻量级移动端 Vue2、Vue3 组件库(支持小程序开发)", "main": "dist/nutui.umd.js", "module": "dist/nutui.es.js", diff --git a/publish/nutui/package.json b/publish/nutui/package.json index 6a1f8e368f..ac985dc3f7 100644 --- a/publish/nutui/package.json +++ b/publish/nutui/package.json @@ -1,6 +1,6 @@ { "name": "@nutui/nutui", - "version": "4.3.15", + "version": "4.3.16", "description": "京东风格的轻量级移动端 Vue2、Vue3 组件库(支持小程序开发)", "main": "dist/nutui.umd.js", "module": "dist/nutui.es.js", diff --git a/src/packages/__VUE/toast/__tests__/index.spec.ts b/src/packages/__VUE/toast/__tests__/index.spec.ts index d367fe8954..5ad6cbdf11 100644 --- a/src/packages/__VUE/toast/__tests__/index.spec.ts +++ b/src/packages/__VUE/toast/__tests__/index.spec.ts @@ -1,4 +1,5 @@ import { mount } from '@vue/test-utils' +import { vi } from 'vitest' import { nextTick } from 'vue' import { Toast } from '@nutui/nutui' @@ -40,6 +41,7 @@ describe('component toast', () => { const toastCover: any = wrapper.find('.nut-toast-cover') expect(toastCover.element.style.backgroundColor).toEqual('black') }) + test('should close Toast when using closeOnClickOverlay prop and clicked', async () => { const wrapper = mount(Toast, { props: { @@ -54,14 +56,94 @@ describe('component toast', () => { await nextTick() expect(toast.element.style.display).toEqual('none') }) - test('should render customClass when using customClass prop ', async () => { + test('should not close Toast when closeOnClickOverlay is false and clicked', async () => { const wrapper = mount(Toast, { props: { - customClass: 'custom' + cover: true, + closeOnClickOverlay: false, + duration: 0 } }) await nextTick() - const toast: any = wrapper.find('.custom') - expect(toast.exists()).toBe(true) + const toast: any = wrapper.find('.nut-toast') + await toast.trigger('click') + await nextTick() + expect(toast.element.style.display).not.toEqual('none') + }) + + test('should auto-hide after duration', async () => { + vi.useFakeTimers() + const wrapper = mount(Toast, { + props: { msg: 'msg', duration: 100 } + }) + await nextTick() + const toast: any = wrapper.find('.nut-toast') + expect(toast.element.style.display).not.toEqual('none') + + vi.advanceTimersByTime(100) + await nextTick() + expect(toast.element.style.display).toEqual('none') + vi.useRealTimers() + }) + + test('should not auto-hide when duration is 0', async () => { + vi.useFakeTimers() + const wrapper = mount(Toast, { + props: { msg: 'msg', duration: 0 } + }) + await nextTick() + const toast: any = wrapper.find('.nut-toast') + vi.advanceTimersByTime(5000) + await nextTick() + expect(toast.element.style.display).not.toEqual('none') + vi.useRealTimers() + }) + test('should set state.closing to true after clicking overlay', async () => { + const wrapper = mount(Toast, { + props: { cover: true, closeOnClickOverlay: true, duration: 0 } + }) + await nextTick() + const toast = wrapper.find('.nut-toast') + await toast.trigger('click') + await nextTick() + expect((wrapper.vm as any).state.closing).toBe(true) + expect(toast.element.style.display).toEqual('none') + }) + + test('should not re-trigger hide when clicking overlay during closing animation', async () => { + const wrapper = mount(Toast, { + props: { cover: true, closeOnClickOverlay: true, duration: 0 } + }) + await nextTick() + const toast = wrapper.find('.nut-toast') + + // 第一次点击:state.mounted = false,state.closing = true + await toast.trigger('click') + await nextTick() + expect((wrapper.vm as any).state.closing).toBe(true) + expect(toast.element.style.display).toEqual('none') + + // 第二次点击:closing = true,clickCover 提前 return,state 保持不变 + await toast.trigger('click') + await nextTick() + expect((wrapper.vm as any).state.closing).toBe(true) + expect((wrapper.vm as any).state.mounted).toBe(false) + }) + + test('should reset closing state when show() is called again', async () => { + const wrapper = mount(Toast, { + props: { cover: true, closeOnClickOverlay: true, duration: 0 } + }) + await nextTick() + const toast = wrapper.find('.nut-toast') + + await toast.trigger('click') + await nextTick() + expect((wrapper.vm as any).state.closing).toBe(true) + + // 更新 duration 触发 watch → show() → closing 重置 + await wrapper.setProps({ duration: 100 }) + await nextTick() + expect((wrapper.vm as any).state.closing).toBe(false) }) }) diff --git a/src/packages/__VUE/toast/index.taro.vue b/src/packages/__VUE/toast/index.taro.vue index 084d3e99fa..88f2b4af67 100644 --- a/src/packages/__VUE/toast/index.taro.vue +++ b/src/packages/__VUE/toast/index.taro.vue @@ -33,7 +33,7 @@