Files
OpenFlare/frontend/tests/cloudflare/member-add-dialog.test.tsx
T
ryan f5c9da03f4 前端测试套件 44 失败→全绿:10 个测试文件补 NextIntlClientProvider 包装(含 React19 createElement 类型修复、.ts→.tsx 重命名);修复真实 i18n ICU bug(githubUrlInvalid 的 {owner}/{repo} 未转义导致生产渲染成 key,zh/en + fragment 4 文件同步转义);更新 2 处过期测试期望。vitest 116/116 + tsc + eslint 全绿,checks.sh 增加前端测试门禁。
Result: {"status":"keep","total_issues":8,"golint_canonicalheader":0,"golint_errname":0,"golint_errorlint":1,"golint_exhaustive":0,"golint_forcetypeassert":0,"golint_gosec":0,"golint_intrange":0,"golint_modernize":3,"golint_nilnil":3,"golint_perfsprint":0,"golint_prealloc":0,"golint_recvcheck":1,"golint_usestdlibvars":0,"golint_wastedassign":0,"golint_total":8,"golint_test_testifylint":0,"golint_test_thelper":0,"golint_test_usetesting":0,"golint_test_total":0,"golint_vetx_total":0,"eslint_problems":0,"eslint_errors":0,"eslint_warnings":0,"tsc_errors":0,"measure_s":39}
2026-08-16 19:08:21 +08:00

138 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { fireEvent, render, screen, within } from '@testing-library/react';
import { describe, expect, it, vi } from 'vitest';
import { MemberAddDialog } from '@/app/(main)/cloudflare/components/member-add-dialog';
import { NextIntlClientProvider } from 'next-intl';
import zhCN from '@/messages/zh-CN.json';
import type { CloudflareAvailableDomain } from '@/lib/services/openflare';
const domains: CloudflareAvailableDomain[] = [
{
id: 1,
zone_id: 10,
domain: 'example.com',
zone_domain: 'example.com',
},
{
id: 2,
zone_id: 10,
domain: 'www.example.com',
zone_domain: 'example.com',
},
{
id: 3,
zone_id: 10,
domain: 'api.example.com',
zone_domain: 'example.com',
},
{
id: 4,
zone_id: 20,
domain: 'app.other.io',
zone_domain: 'other.io',
},
];
describe('MemberAddDialog advanced domain picker', () => {
it('groups domains under top-level zone roots and supports batch select', () => {
const onSubmit = vi.fn();
render(
<NextIntlClientProvider locale='zh-CN' messages={zhCN} timeZone='Asia/Shanghai'>
<MemberAddDialog
open
onOpenChange={vi.fn()}
domains={domains}
defaultProxied
pending={false}
onSubmit={onSubmit}
/>
</NextIntlClientProvider>,
);
expect(screen.getAllByText('example.com').length).toBeGreaterThan(0);
expect(screen.getAllByText('other.io').length).toBeGreaterThan(0);
expect(screen.getByText('www.example.com')).toBeVisible();
expect(screen.getByText('api.example.com')).toBeVisible();
fireEvent.click(screen.getByRole('button', { name: '全选可见' }));
fireEvent.click(screen.getByRole('button', { name: '添加并同步(4)' }));
expect(onSubmit).toHaveBeenCalledTimes(1);
const [ids, proxied] = onSubmit.mock.calls[0] as [number[], boolean];
expect([...ids].sort((a, b) => a - b)).toEqual([1, 2, 3, 4]);
expect(proxied).toBe(true);
});
it('filters by keyword across domain and zone root', () => {
render(
<NextIntlClientProvider locale='zh-CN' messages={zhCN} timeZone='Asia/Shanghai'>
<MemberAddDialog
open
onOpenChange={vi.fn()}
domains={domains}
defaultProxied={false}
pending={false}
onSubmit={vi.fn()}
/>
</NextIntlClientProvider>,
);
fireEvent.change(screen.getByPlaceholderText('搜索域名或顶级域…'), {
target: { value: 'other' },
});
expect(screen.queryByText('www.example.com')).not.toBeInTheDocument();
expect(screen.getByText('app.other.io')).toBeVisible();
expect(screen.getByText('other.io')).toBeVisible();
});
it('selects an entire top-level domain group', () => {
const onSubmit = vi.fn();
render(
<NextIntlClientProvider locale='zh-CN' messages={zhCN} timeZone='Asia/Shanghai'>
<MemberAddDialog
open
onOpenChange={vi.fn()}
domains={domains}
defaultProxied
pending={false}
onSubmit={onSubmit}
/>
</NextIntlClientProvider>,
);
fireEvent.click(
screen.getByRole('checkbox', { name: '选择顶级域 example.com' }),
);
fireEvent.click(screen.getByRole('button', { name: '添加并同步(3)' }));
expect(onSubmit).toHaveBeenCalledTimes(1);
const [ids, proxied] = onSubmit.mock.calls[0] as [number[], boolean];
expect([...ids].sort((a, b) => a - b)).toEqual([1, 2, 3]);
expect(proxied).toBe(true);
});
it('toggles individual domains within a group', () => {
const onSubmit = vi.fn();
render(
<NextIntlClientProvider locale='zh-CN' messages={zhCN} timeZone='Asia/Shanghai'>
<MemberAddDialog
open
onOpenChange={vi.fn()}
domains={domains}
defaultProxied={false}
pending={false}
onSubmit={onSubmit}
/>
</NextIntlClientProvider>,
);
const wwwLabel = screen.getByText('www.example.com').closest('label');
expect(wwwLabel).toBeTruthy();
fireEvent.click(within(wwwLabel as HTMLElement).getByRole('checkbox'));
fireEvent.click(screen.getByRole('button', { name: '添加并同步' }));
expect(onSubmit).toHaveBeenCalledWith([2], false);
});
});