- React 适配器子包:@metona-team/metona-toast/react — useToast() hook + 声明式 <Toast /> 组件,组件卸载自动清理;react 为 optional peerDependency,主包保持零依赖 - loading 链式转换改原地 update:id 稳定不重建 DOM,转换后 duration 恢复默认自动关闭;update() 支持 duration 变更动态重启计时器 - _emit 幽灵实例修复:beforeShow 拦截后的 toast 不再注册进 _toasts - dragThreshold 配置项(默认 120px,原硬编码);RTL 容器 dir 属性 + 进度条/side 条/色条镜像 - dedupe 预设插件:相同 type+message 自动去重,支持 uninstall - jest 环境隔离测试独立成 tests/ssr.test.ts(resetModules 不再污染共享模块状态);新增 tests/setup.ts 补 TextEncoder - 文档:README/docs.html 补 React 适配器、dedupe、dragThreshold;CHANGELOG 更新;328 测试全过
91 lines
3.0 KiB
TypeScript
91 lines
3.0 KiB
TypeScript
/**
|
|
* MetonaToast React 适配器测试
|
|
* @module tests
|
|
* @version 0.4.0
|
|
*/
|
|
|
|
import React from 'react';
|
|
import { renderToString } from 'react-dom/server';
|
|
import MeToast, { Toast } from '../src/index';
|
|
import { createBoundApi, Toast as ToastComponent } from '../src/react';
|
|
import type { ToastInstance } from '../src/types';
|
|
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
MeToast._toasts.clear();
|
|
MeToast.resetConfig();
|
|
(MeToast as unknown as { _destroyed?: boolean })._destroyed = false;
|
|
Toast._hooks.clear();
|
|
Toast._registry.clear();
|
|
const { _containerCache } = require('../src/toast.js');
|
|
_containerCache.clear();
|
|
MeToast.animations.reset();
|
|
});
|
|
|
|
describe('React 适配器 — createBoundApi', () => {
|
|
test('跟踪创建的 toast id', () => {
|
|
const cleanup = new Set<string>();
|
|
const api = createBoundApi(cleanup);
|
|
(api.info as (m: string) => ToastInstance)('hello');
|
|
expect(cleanup.size).toBe(1);
|
|
});
|
|
|
|
test('success/error/warning/show 均被跟踪', () => {
|
|
const cleanup = new Set<string>();
|
|
const api = createBoundApi(cleanup);
|
|
(api.success as (m: string) => ToastInstance)('a');
|
|
(api.error as (m: string) => ToastInstance)('b');
|
|
(api.warning as (m: string) => ToastInstance)('c');
|
|
(api.show as (m: string) => ToastInstance)('d');
|
|
expect(cleanup.size).toBe(4);
|
|
});
|
|
|
|
test('loading 控制对象也被跟踪', () => {
|
|
const cleanup = new Set<string>();
|
|
const api = createBoundApi(cleanup);
|
|
(api.loading as (m: string) => { id: string })('loading...');
|
|
expect(cleanup.size).toBe(1);
|
|
});
|
|
|
|
test('dismiss 同步清理集合', () => {
|
|
const cleanup = new Set<string>();
|
|
const api = createBoundApi(cleanup);
|
|
const t = (api.success as (m: string) => ToastInstance)('hi');
|
|
expect(cleanup.has(t.id)).toBe(true);
|
|
(api.dismiss as (id?: string) => void)(t.id);
|
|
expect(cleanup.has(t.id)).toBe(false);
|
|
});
|
|
|
|
test('removeToast 同步清理集合', () => {
|
|
const cleanup = new Set<string>();
|
|
const api = createBoundApi(cleanup);
|
|
const t = (api.info as (m: string) => ToastInstance)('hi');
|
|
(api.removeToast as (id: string) => void)(t.id);
|
|
expect(cleanup.size).toBe(0);
|
|
});
|
|
|
|
test('未跟踪的方法直接透传', () => {
|
|
const cleanup = new Set<string>();
|
|
const api = createBoundApi(cleanup);
|
|
expect(typeof (api as Record<string, unknown>).count).toBe('function');
|
|
expect((api as { count(): number }).count()).toBe(0);
|
|
});
|
|
});
|
|
|
|
describe('React 适配器 — Toast 组件', () => {
|
|
test('SSR 渲染为空(effect 不执行)', () => {
|
|
const html = renderToString(React.createElement(ToastComponent, { message: 'ssr message' }));
|
|
expect(html).toBe('');
|
|
});
|
|
|
|
test('SSR 带 type 不抛异常', () => {
|
|
const html = renderToString(React.createElement(ToastComponent, { message: 'x', type: 'success' }));
|
|
expect(html).toBe('');
|
|
});
|
|
|
|
test('SSR 未知 type fallback 到 show 不抛异常', () => {
|
|
const html = renderToString(React.createElement(ToastComponent, { message: 'y', type: 'custom-type' }));
|
|
expect(html).toBe('');
|
|
});
|
|
});
|