import { App as AntApp, ConfigProvider } from 'antd';
import { act, render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { createMemoryRouter, RouterProvider } from 'react-router-dom';
import { describe, expect, it, vi } from 'vitest';
import { I18nProvider } from '../../src/frontend/i18n/react';
import { api } from '../../src/frontend/services/api';
import { mailhubTheme } from '../../src/frontend/theme';
import type { SendEvent } from '../../src/frontend/types';
import SendingLogs from '../../src/pages/SendingLogs';
describe('Activity direct detail navigation', () => {
it('restores direct-link tabs with history and closes past them to the filtered list', async () => {
const user = userEvent.setup();
mockActivityApis();
const router = renderPage({
initialEntries: ['/overview', '/activity/11?page=2&pageSize=25&status=failed&tab=raw'],
initialIndex: 1
});
expect(await screen.findByRole('tab', { name: '原始日志', selected: true })).not.toBeNull();
await user.click(screen.getByRole('tab', { name: 'Webhook' }));
await waitFor(() => expect(currentTab(router)).toBe('webhooks'));
await user.click(screen.getByRole('tab', { name: '互动跟踪' }));
await waitFor(() => expect(currentTab(router)).toBe('tracking'));
await act(async () => {
await router.navigate(-1);
});
expect(currentTab(router)).toBe('webhooks');
expect(screen.getByRole('tab', { name: 'Webhook', selected: true })).not.toBeNull();
await act(async () => {
await router.navigate(-1);
});
expect(currentTab(router)).toBe('raw');
expect(screen.getByRole('tab', { name: '原始日志', selected: true })).not.toBeNull();
await act(async () => {
await router.navigate(1);
});
expect(currentTab(router)).toBe('webhooks');
await act(async () => {
await router.navigate(1);
});
expect(currentTab(router)).toBe('tracking');
await user.click(screen.getByRole('button', { name: 'Close' }));
await waitFor(() => expect(router.state.location.pathname).toBe('/activity'));
const listParams = new URLSearchParams(router.state.location.search);
expect(listParams.get('page')).toBe('2');
expect(listParams.get('pageSize')).toBe('25');
expect(listParams.get('status')).toBe('failed');
expect(listParams.has('tab')).toBe(false);
await act(async () => {
await router.navigate(-1);
});
expect(router.state.location.pathname).toBe('/overview');
});
it('replaces an untouched direct detail with its list even without prior history', async () => {
const user = userEvent.setup();
mockActivityApis();
const router = renderPage({
initialEntries: ['/activity/11?page=1&pageSize=25'],
initialIndex: 0
});
await screen.findByRole('dialog', { name: '发送详情' });
await user.click(screen.getByRole('button', { name: 'Close' }));
await waitFor(() => expect(router.state.location.pathname).toBe('/activity'));
await act(async () => {
await router.navigate(-1);
});
expect(router.state.location.pathname).toBe('/activity');
});
});
function mockActivityApis() {
vi.spyOn(api, 'events').mockResolvedValue({ events: [sendEvent], total: 1, page: 2, pageSize: 25 });
vi.spyOn(api, 'domains').mockResolvedValue({ domains: [] });
vi.spyOn(api, 'event').mockResolvedValue({ event: sendEvent });
}
function renderPage({ initialEntries, initialIndex }: { initialEntries: string[]; initialIndex: number }) {
const router = createMemoryRouter([
{ path: '/activity', element: