138 lines
7.2 KiB
TypeScript
138 lines
7.2 KiB
TypeScript
import { fireEvent, render, screen, waitFor, within } from '@testing-library/react';
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import { AdminAnalyticsPage } from './AdminAnalyticsPage';
|
|
|
|
const { api } = vi.hoisted(() => ({
|
|
api: { getSignatureQuality: vi.fn(), getSignatureRetirementHeatmap: vi.fn(), getUnreportedSignatures: vi.fn() },
|
|
}));
|
|
vi.mock('@/api/adminApi', () => ({ adminApi: api }));
|
|
|
|
describe('independent analytics tabs', () => {
|
|
it('combines separate activity search fields with AND and preserves them across tabs', async () => {
|
|
api.getSignatureRetirementHeatmap.mockResolvedValue({
|
|
items: [],
|
|
dimensions: [
|
|
{
|
|
dimensionType: 'channel',
|
|
signatureId: 'a',
|
|
signatureName: '签名甲',
|
|
tenantName: '企业甲',
|
|
applicationName: '应用甲',
|
|
channelName: '通道甲',
|
|
channelId: 'c',
|
|
carrier: 'mobile',
|
|
approvedAt: '2026-08-01',
|
|
},
|
|
{
|
|
dimensionType: 'channel',
|
|
signatureId: 'b',
|
|
signatureName: '签名乙',
|
|
tenantName: '企业甲',
|
|
applicationName: '应用乙',
|
|
channelName: '通道乙',
|
|
channelId: 'd',
|
|
carrier: 'unicom',
|
|
approvedAt: '2026-08-01',
|
|
},
|
|
],
|
|
});
|
|
render(<AdminAnalyticsPage />);
|
|
fireEvent.click(screen.getByRole('tab', { name: '通道签名活跃度' }));
|
|
const panel = screen.getByRole('region', { name: '通道签名活跃度' });
|
|
await within(panel).findByText('签名甲');
|
|
fireEvent.change(within(panel).getByLabelText('企业'), { target: { value: '企业甲' } });
|
|
fireEvent.change(within(panel).getByLabelText('企业应用'), { target: { value: '应用甲' } });
|
|
await waitFor(() => expect(within(panel).queryByText('签名乙')).not.toBeInTheDocument());
|
|
fireEvent.change(within(panel).getByLabelText('通道'), { target: { value: '通道乙' } });
|
|
await waitFor(() => expect(within(panel).queryByText('签名甲')).not.toBeInTheDocument());
|
|
fireEvent.click(screen.getByRole('tab', { name: '企业签名活跃度' }));
|
|
fireEvent.click(screen.getByRole('tab', { name: '通道签名活跃度' }));
|
|
expect(within(panel).getByLabelText('企业应用')).toHaveValue('应用甲');
|
|
});
|
|
beforeEach(() => {
|
|
vi.resetAllMocks();
|
|
api.getSignatureQuality.mockImplementation(async (query) => ({ ...query, total: 0, items: [] }));
|
|
api.getUnreportedSignatures.mockImplementation(async (query) => ({ ...query, total: 0, items: [] }));
|
|
api.getSignatureRetirementHeatmap.mockResolvedValue({ items: [], dimensions: [] });
|
|
});
|
|
it('loads only the visited tab and preserves independent dates when switching back', async () => {
|
|
render(<AdminAnalyticsPage />);
|
|
await waitFor(() =>
|
|
expect(api.getSignatureQuality).toHaveBeenCalledWith(expect.objectContaining({ pageSize: 25 })),
|
|
);
|
|
expect(api.getSignatureRetirementHeatmap).not.toHaveBeenCalled();
|
|
const quality = screen.getByRole('region', { name: '签名通道发送质量' });
|
|
fireEvent.change(within(quality).getByLabelText('统计日期'), { target: { value: '2026-08-20' } });
|
|
fireEvent.click(within(quality).getByRole('button', { name: '查询统计' }));
|
|
await waitFor(() =>
|
|
expect(api.getSignatureQuality).toHaveBeenLastCalledWith(expect.objectContaining({ date: '2026-08-20' })),
|
|
);
|
|
fireEvent.click(screen.getByRole('tab', { name: '未报备签名' }));
|
|
await waitFor(() => expect(api.getUnreportedSignatures).toHaveBeenCalledTimes(1));
|
|
const unreported = screen.getByRole('region', { name: '未报备签名' });
|
|
fireEvent.change(within(unreported).getByLabelText('统计日期'), { target: { value: '2026-08-25' } });
|
|
fireEvent.click(screen.getByRole('tab', { name: '签名通道发送质量' }));
|
|
expect(within(quality).getByLabelText('统计日期')).toHaveValue('2026-08-20');
|
|
fireEvent.click(screen.getByRole('tab', { name: '未报备签名' }));
|
|
expect(within(unreported).getByLabelText('统计日期')).toHaveValue('2026-08-25');
|
|
expect(api.getSignatureRetirementHeatmap).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it.each([
|
|
['签名通道发送质量', 'getSignatureQuality'],
|
|
['未报备签名', 'getUnreportedSignatures'],
|
|
] as const)('keeps %s page size in the footer and resets the page with applied filters', async (tab, method) => {
|
|
api[method].mockImplementation(async (query) => ({ ...query, total: 120, items: [] }));
|
|
render(<AdminAnalyticsPage />);
|
|
fireEvent.click(screen.getByRole('tab', { name: tab }));
|
|
const panel = screen.getByRole('region', { name: tab });
|
|
await waitFor(() => expect(within(panel).getByRole('button', { name: '下一页' })).toBeEnabled());
|
|
fireEvent.change(within(panel).getByLabelText('统计日期'), { target: { value: '2026-08-20' } });
|
|
fireEvent.click(within(panel).getByRole('button', { name: '查询统计' }));
|
|
await waitFor(() => expect(api[method]).toHaveBeenLastCalledWith(expect.objectContaining({ date: '2026-08-20' })));
|
|
fireEvent.click(within(panel).getByRole('button', { name: '下一页' }));
|
|
await waitFor(() => expect(api[method]).toHaveBeenLastCalledWith(expect.objectContaining({ page: 2 })));
|
|
// An unsubmitted date must not alter a pagination request.
|
|
fireEvent.change(within(panel).getByLabelText('统计日期'), { target: { value: '2026-08-21' } });
|
|
const size = within(panel).getByLabelText(/^每页数量/);
|
|
expect(size.closest('.ui-pagination')).not.toBeNull();
|
|
expect(size.closest('.page-actions')).toBeNull();
|
|
fireEvent.click(size);
|
|
expect(screen.getAllByRole('option').map((option) => option.textContent)).toEqual([
|
|
'10 条/页',
|
|
'25 条/页',
|
|
'50 条/页',
|
|
'100 条/页',
|
|
]);
|
|
fireEvent.click(screen.getByRole('option', { name: '100 条/页' }));
|
|
await waitFor(() =>
|
|
expect(api[method]).toHaveBeenLastCalledWith(
|
|
expect.objectContaining({ page: 1, pageSize: 100, date: '2026-08-20' }),
|
|
),
|
|
);
|
|
await waitFor(() => expect(within(panel).getByLabelText('跳转页码')).toHaveValue(1));
|
|
});
|
|
|
|
it.each(['企业签名活跃度', '通道签名活跃度'])(
|
|
'preserves %s footer size independently even with no rows',
|
|
async (tab) => {
|
|
render(<AdminAnalyticsPage />);
|
|
fireEvent.click(screen.getByRole('tab', { name: tab }));
|
|
await waitFor(() => expect(api.getSignatureRetirementHeatmap).toHaveBeenCalledTimes(1));
|
|
const panel = screen.getByRole('region', { name: tab });
|
|
const size = within(panel).getByLabelText(/^每页数量/);
|
|
expect(size.closest('.ui-pagination')).not.toBeNull();
|
|
expect(within(panel).getByRole('button', { name: '下一页' })).toBeDisabled();
|
|
fireEvent.click(size);
|
|
fireEvent.click(screen.getByRole('option', { name: '50 条/页' }));
|
|
fireEvent.click(screen.getByRole('tab', { name: '签名通道发送质量' }));
|
|
expect(
|
|
within(screen.getByRole('region', { name: '签名通道发送质量' })).getByLabelText(/^每页数量/),
|
|
).toHaveTextContent('25 条/页');
|
|
fireEvent.click(screen.getByRole('tab', { name: tab }));
|
|
expect(size).toHaveTextContent('50 条/页');
|
|
expect(api.getSignatureRetirementHeatmap).toHaveBeenCalledTimes(1);
|
|
},
|
|
);
|
|
});
|