Files
lislgosms/src/apps/admin/AdminAnalyticsPage.test.tsx
T

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);
},
);
});