import { act, render, screen } from '@testing-library/react';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { I18nProvider } from '../lib/i18n';
import { Toast } from './ui';
describe('Toast', () => {
afterEach(() => {
vi.useRealTimers();
});
it('renders in the shared browser viewport with a countdown and dismisses automatically', () => {
vi.useFakeTimers();
const onClose = vi.fn();
const { container } = render(
<I18nProvider><Toast title="保存成功" message="触发器已经立即生效" duration={3_000} onClose={onClose} /></I18nProvider>,
);
const notification = screen.getByRole('status');
expect(container).toBeEmptyDOMElement();
expect(notification.closest('#xfesm-toast-viewport')).toBe(document.body.querySelector('#xfesm-toast-viewport'));
expect(notification).toHaveTextContent('保存成功');
expect(notification).toHaveTextContent('触发器已经立即生效');
expect(notification.querySelector('.toast__countdown')).toBeInTheDocument();
expect(notification).toHaveStyle('--toast-duration: 3000ms');
act(() => vi.advanceTimersByTime(3_000));
expect(onClose).toHaveBeenCalledOnce();
expect(screen.queryByRole('status')).not.toBeInTheDocument();
});
it('stacks simultaneous notifications in one viewport', () => {
render(<I18nProvider><><Toast message="第一条" duration={0} /><Toast message="第二条" tone="warn" duration={0} /></></I18nProvider>);
const viewport = document.body.querySelector('#xfesm-toast-viewport');
expect(viewport?.querySelectorAll('.toast')).toHaveLength(2);
expect(screen.getAllByRole('status')).toHaveLength(2);
});
});
import { act, render, screen } from '@testing-library/react';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { I18nProvider } from '../lib/i18n';
import { Toast } from './ui';
describe('Toast', () => {
afterEach(() => {
vi.useRealTimers();
});
it('renders in the shared browser viewport with a countdown and dismisses automatically', () => {
vi.useFakeTimers();
const onClose = vi.fn();
const { container } = render(
<I18nProvider><Toast title="保存成功" message="触发器已经立即生效" duration={3_000} onClose={onClose} /></I18nProvider>,
);
const notification = screen.getByRole('status');
expect(container).toBeEmptyDOMElement();
expect(notification.closest('#xfesm-toast-viewport')).toBe(document.body.querySelector('#xfesm-toast-viewport'));
expect(notification).toHaveTextContent('保存成功');
expect(notification).toHaveTextContent('触发器已经立即生效');
expect(notification.querySelector('.toast__countdown')).toBeInTheDocument();
expect(notification).toHaveStyle('--toast-duration: 3000ms');
act(() => vi.advanceTimersByTime(3_000));
expect(onClose).toHaveBeenCalledOnce();
expect(screen.queryByRole('status')).not.toBeInTheDocument();
});
it('stacks simultaneous notifications in one viewport', () => {
render(<I18nProvider><><Toast message="第一条" duration={0} /><Toast message="第二条" tone="warn" duration={0} /></></I18nProvider>);
const viewport = document.body.querySelector('#xfesm-toast-viewport');
expect(viewport?.querySelectorAll('.toast')).toHaveLength(2);
expect(screen.getAllByRole('status')).toHaveLength(2);
});
});