7becd38117
桌面端泥点详情支持从按钮移动到浮层并取消点击保持 统一弹窗仅在完整遮罩指针序列后关闭 补充泥点悬浮与登录遮罩拖出回归测试 记录遮罩关闭交互约束
167 lines
4.6 KiB
TypeScript
167 lines
4.6 KiB
TypeScript
/* @vitest-environment jsdom */
|
|
|
|
import { fireEvent, render, screen } from '@testing-library/react';
|
|
import { expect, test, vi } from 'vitest';
|
|
|
|
import { UnifiedModal } from './UnifiedModal';
|
|
|
|
test('renders an accessible platform modal', () => {
|
|
render(
|
|
<UnifiedModal open title="统一弹窗" onClose={() => {}} portal={false}>
|
|
<div>窗口内容</div>
|
|
</UnifiedModal>,
|
|
);
|
|
|
|
expect(screen.getByRole('dialog', { name: '统一弹窗' })).toBeTruthy();
|
|
expect(screen.getByText('窗口内容')).toBeTruthy();
|
|
expect(screen.getByRole('button', { name: '关闭' }).className).toContain(
|
|
'platform-icon-button',
|
|
);
|
|
});
|
|
|
|
test('closes through backdrop and escape', () => {
|
|
const onClose = vi.fn();
|
|
const { rerender } = render(
|
|
<UnifiedModal open title="统一弹窗" onClose={onClose} portal={false}>
|
|
<div>窗口内容</div>
|
|
</UnifiedModal>,
|
|
);
|
|
|
|
fireEvent.click(screen.getByRole('dialog').parentElement as HTMLElement);
|
|
expect(onClose).toHaveBeenCalledTimes(1);
|
|
|
|
rerender(
|
|
<UnifiedModal open title="统一弹窗" onClose={onClose} portal={false}>
|
|
<div>窗口内容</div>
|
|
</UnifiedModal>,
|
|
);
|
|
fireEvent.keyDown(window, { key: 'Escape' });
|
|
expect(onClose).toHaveBeenCalledTimes(2);
|
|
});
|
|
|
|
test('keeps the modal open when a pointer press starts inside and releases over the backdrop', () => {
|
|
const onClose = vi.fn();
|
|
render(
|
|
<UnifiedModal open title="统一弹窗" onClose={onClose} portal={false}>
|
|
<button type="button">窗口内容</button>
|
|
</UnifiedModal>,
|
|
);
|
|
|
|
const dialog = screen.getByRole('dialog');
|
|
const backdrop = dialog.parentElement as HTMLElement;
|
|
|
|
fireEvent.pointerDown(screen.getByRole('button', { name: '窗口内容' }));
|
|
fireEvent.pointerUp(backdrop);
|
|
fireEvent.click(backdrop);
|
|
|
|
expect(onClose).not.toHaveBeenCalled();
|
|
});
|
|
|
|
test('supports disabling escape close while keeping the custom close button chrome', () => {
|
|
const onClose = vi.fn();
|
|
render(
|
|
<UnifiedModal
|
|
open
|
|
title="个人中心弹窗"
|
|
onClose={onClose}
|
|
closeOnEscape={false}
|
|
closeVariant="profileCompact"
|
|
titleClassName="font-black"
|
|
portal={false}
|
|
>
|
|
<div>窗口内容</div>
|
|
</UnifiedModal>,
|
|
);
|
|
|
|
fireEvent.keyDown(window, { key: 'Escape' });
|
|
expect(onClose).not.toHaveBeenCalled();
|
|
|
|
const closeButton = screen.getByRole('button', { name: '关闭' });
|
|
expect(closeButton.className).toContain('platform-profile-icon-button');
|
|
expect(screen.getByRole('dialog', { name: '个人中心弹窗' })).toBeTruthy();
|
|
});
|
|
|
|
test('supports headerless dialogs while preserving the accessible name', () => {
|
|
render(
|
|
<UnifiedModal
|
|
open
|
|
title="支付成功"
|
|
description="账户状态已刷新"
|
|
onClose={() => {}}
|
|
showHeader={false}
|
|
showCloseButton={false}
|
|
portal={false}
|
|
>
|
|
<div>窗口内容</div>
|
|
</UnifiedModal>,
|
|
);
|
|
|
|
const dialog = screen.getByRole('dialog', { name: '支付成功' });
|
|
|
|
expect(dialog).toBeTruthy();
|
|
expect(screen.queryByRole('button', { name: '关闭' })).toBeNull();
|
|
expect(screen.getByText('窗口内容')).toBeTruthy();
|
|
});
|
|
|
|
test('supports a stable aria label while keeping the visible title', () => {
|
|
render(
|
|
<UnifiedModal
|
|
open
|
|
title="雨夜猫街"
|
|
ariaLabel="关卡详情"
|
|
onClose={() => {}}
|
|
portal={false}
|
|
>
|
|
<div>窗口内容</div>
|
|
</UnifiedModal>,
|
|
);
|
|
|
|
const dialog = screen.getByRole('dialog', { name: '关卡详情' });
|
|
|
|
expect(dialog).toBeTruthy();
|
|
expect(screen.getByText('雨夜猫街')).toBeTruthy();
|
|
});
|
|
|
|
test('respects closeDisabled for every default close path', () => {
|
|
const onClose = vi.fn();
|
|
render(
|
|
<UnifiedModal
|
|
open
|
|
title="生成中"
|
|
onClose={onClose}
|
|
closeDisabled
|
|
portal={false}
|
|
>
|
|
<div>窗口内容</div>
|
|
</UnifiedModal>,
|
|
);
|
|
|
|
fireEvent.click(screen.getByRole('dialog').parentElement as HTMLElement);
|
|
fireEvent.keyDown(window, { key: 'Escape' });
|
|
fireEvent.click(screen.getByRole('button', { name: '关闭' }));
|
|
|
|
expect(onClose).not.toHaveBeenCalled();
|
|
});
|
|
|
|
test('uses shared pixel close button chrome', () => {
|
|
render(
|
|
<UnifiedModal
|
|
open
|
|
title="像素弹窗"
|
|
onClose={() => {}}
|
|
variant="pixel"
|
|
portal={false}
|
|
>
|
|
<div>窗口内容</div>
|
|
</UnifiedModal>,
|
|
);
|
|
|
|
const closeButton = screen.getByRole('button', { name: '关闭' });
|
|
|
|
expect(screen.getByRole('dialog', { name: '像素弹窗' }).className).toContain(
|
|
'pixel-modal-shell',
|
|
);
|
|
expect(closeButton.className).toContain('bg-black/30');
|
|
expect(closeButton.className).toContain('text-zinc-400');
|
|
});
|