From 900e965ae60c6db3a9455f47dcd4e53aee760ada Mon Sep 17 00:00:00 2001 From: tianhao Date: Tue, 16 Jun 2026 13:09:50 +0800 Subject: [PATCH] =?UTF-8?q?fix(#24,#25,#26,#27,#30):=20action=E6=8C=89?= =?UTF-8?q?=E9=92=AE=E9=A1=BA=E5=BA=8F;=20group=E8=BE=B9=E7=95=8C;=20Notif?= =?UTF-8?q?ication=E6=9D=83=E9=99=90;=20queue=20catch;=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=8A=9F=E8=83=BD=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core.js | 19 +++++++++++--- src/index.js | 12 +++++++-- tests/index.test.js | 64 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 6 deletions(-) diff --git a/src/core.js b/src/core.js index c85083c..988ae73 100644 --- a/src/core.js +++ b/src/core.js @@ -1018,7 +1018,7 @@ const meToast = { const t = this._emit({ ...normalized, - html: _actionHTML(actions) + (normalized.html || ''), + html: (normalized.html || '') + _actionHTML(actions), }); if (Array.isArray(actions)) { @@ -1090,6 +1090,7 @@ const meToast = { }); return { then: (fn, rj) => promise.then(fn, rj), + catch: (rj) => promise.catch(rj), cancel: () => { cancelled = true; }, }; }, @@ -1167,9 +1168,19 @@ const meToast = { const g = { _group: name }; methods.forEach(m => { g[m] = (...args) => { - const last = typeof args[args.length - 1] === 'object' && args[args.length - 1] !== null && !Array.isArray(args[args.length - 1]) - ? args.pop() : {}; - return self[m](...args, { ...last, group: name }); + const lastArg = args[args.length - 1]; + const isObj = typeof lastArg === 'object' && lastArg !== null && !Array.isArray(lastArg); + // 单对象参数:直接合并group + if (isObj && args.length === 1) { + return self[m]({ ...lastArg, group: name }); + } + // 末尾是配置对象:pop后合并 + if (isObj) { + args.pop(); + return self[m](...args, { ...lastArg, group: name }); + } + // 无配置对象 + return self[m](...args, { group: name }); }; }); g.dismiss = () => self.dismissGroup(name); diff --git a/src/index.js b/src/index.js index 71b4824..8030f4b 100644 --- a/src/index.js +++ b/src/index.js @@ -260,10 +260,18 @@ if (typeof window !== 'undefined') { // Notification API — 页面不可见时自动发送系统通知 enhancedMeToast._notify = (toast) => { - if (typeof Notification === 'undefined' || Notification.permission !== 'granted') return; + if (typeof Notification === 'undefined') return; + if (Notification.permission === 'denied') return; if (!document.hidden) return; + if (Notification.permission === 'default') { + Notification.requestPermission().then(p => { if (p === 'granted') sendNotification(toast); }); + return; + } + sendNotification(toast); + }; + const sendNotification = (toast) => { try { - new Notification(toast.title || toast.type, { body: toast.message, icon: '/favicon.ico' }); + new Notification(toast.title || toast.type, { body: toast.message }); } catch (_) {} }; Toast.on('afterShow', (toast) => { diff --git a/tests/index.test.js b/tests/index.test.js index 136d66d..7632874 100644 --- a/tests/index.test.js +++ b/tests/index.test.js @@ -1931,3 +1931,67 @@ describe('边界情况', () => { expect(MeToast.getToast()).toBeNull(); }); }); + +// ========== 新增功能测试 ========== + +describe('新增功能', () => { + beforeEach(() => { + MeToast._toasts.clear(); + }); + + test('resetTimerOnUpdate — update后重置计时器', () => { + const t = MeToast.info('test', { duration: 5000, resetTimerOnUpdate: true }); + const oldRemaining = t.remaining; + t.update({ message: 'updated' }); + expect(t.remaining).toBe(5000); + expect(t.paused).toBe(false); + }); + + test('onUpdate 回调触发', () => { + const fn = jest.fn(); + const t = MeToast.success('test', { onUpdate: fn }); + t.update({ message: 'changed' }); + expect(fn).toHaveBeenCalledWith(t); + }); + + test('action 返回控制对象', () => { + const a = MeToast.action('test', [{ text: 'OK', onClick: () => {} }]); + expect(a).toBeDefined(); + expect(a.id).toBeDefined(); + expect(a.toast).toBeDefined(); + expect(a.dismiss).toBeInstanceOf(Function); + }); + + test('queue 返回可取消对象', () => { + const q = MeToast.queue(['a', 'b'], { delay: 10, duration: 10 }); + expect(q.then).toBeInstanceOf(Function); + expect(q.catch).toBeInstanceOf(Function); + expect(q.cancel).toBeInstanceOf(Function); + q.cancel(); + }); + + test('group 创建分组并正常工作', () => { + const g = MeToast.group('test-group'); + expect(g._group).toBe('test-group'); + expect(g.dismiss).toBeInstanceOf(Function); + expect(g.count).toBeInstanceOf(Function); + const t = g.info('grouped message'); + expect(t.group).toBe('test-group'); + }); + + test('dismissGroup 按组关闭', () => { + const g = MeToast.group('batch'); + g.success('m1'); + g.error('m2'); + expect(MeToast._groupCount('batch')).toBe(2); + MeToast.dismissGroup('batch'); + }); + + test('自定义渲染函数', () => { + const t = MeToast.show({ + render: (toast) => `${toast.message}`, + message: 'rendered', + }); + expect(t.config.render).toBeInstanceOf(Function); + }); +});