Files
OpenFlare/frontend/tests/cloudflare/member-add-dialog.test.tsx
T
Deqiying 9a51a68206 feat(domain): 支持通配符域名及关联功能适配 (#63)
* feat(domain): 支持通配符域名及关联功能适配

* fix(domain): preserve legacy Unicode imports and address review findings

* fix(domain): canonicalize legacy IDNs and exclude empty host labels

* fix(domain): normalize equivalent Unicode IDN spellings

---------

Co-authored-by: Ryan <63696351+Rain-kl@users.noreply.github.com>
Co-authored-by: ryan <ryan@arctel.net>
2026-11-09 10:31:03 +08:00

188 lines
5.5 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);
});
it('searches and selects a wildcard domain without treating it as a URL', () => {
const onSubmit = vi.fn();
render(
<NextIntlClientProvider
locale='zh-CN'
messages={zhCN}
timeZone='Asia/Shanghai'
>
<MemberAddDialog
open
onOpenChange={vi.fn()}
domains={[
...domains,
{ ...domains[0], id: 5, domain: '*.s3.example.com' },
]}
defaultProxied={false}
pending={false}
onSubmit={onSubmit}
/>
</NextIntlClientProvider>,
);
fireEvent.change(screen.getByPlaceholderText('搜索域名或顶级域…'), {
target: { value: '*.s3' },
});
expect(screen.queryByText('www.example.com')).not.toBeInTheDocument();
const label = screen.getByText('*.s3.example.com').closest('label');
expect(label).toBeTruthy();
fireEvent.click(within(label as HTMLElement).getByRole('checkbox'));
fireEvent.click(screen.getByRole('button', { name: '添加并同步' }));
expect(onSubmit).toHaveBeenCalledWith([5], false);
expect(screen.queryByRole('link')).not.toBeInTheDocument();
});
});