收口前端平台组件库能力
新增 PlatformUiKit 通用弹窗、按钮、状态、空态、媒体、表单和标签等公共组件 迁移结果页、创作工作台、认证入口、RPG 暗色面板和运行态弹窗的重复 UI chrome 补充组件测试、页面回归测试、技术文档和 Hermes 共享决策记录
This commit is contained in:
85
src/components/common/useCopyFeedback.test.tsx
Normal file
85
src/components/common/useCopyFeedback.test.tsx
Normal file
@@ -0,0 +1,85 @@
|
||||
/* @vitest-environment jsdom */
|
||||
|
||||
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import { afterEach, describe, expect, test, vi } from 'vitest';
|
||||
|
||||
import * as clipboardService from '../../services/clipboard';
|
||||
import { useCopyFeedback } from './useCopyFeedback';
|
||||
|
||||
vi.mock('../../services/clipboard', () => ({
|
||||
copyTextToClipboard: vi.fn(),
|
||||
}));
|
||||
|
||||
function CopyFeedbackHarness({
|
||||
value,
|
||||
resetDelayMs = 1400,
|
||||
}: {
|
||||
value: string;
|
||||
resetDelayMs?: number;
|
||||
}) {
|
||||
const { copyState, copyText, resetCopyState } = useCopyFeedback({
|
||||
resetDelayMs,
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div data-testid="copy-state">{copyState}</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
void copyText(value);
|
||||
}}
|
||||
>
|
||||
复制
|
||||
</button>
|
||||
<button type="button" onClick={resetCopyState}>
|
||||
重置
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
describe('useCopyFeedback', () => {
|
||||
test('copies text and resets after the feedback delay', async () => {
|
||||
vi.useFakeTimers();
|
||||
vi.mocked(clipboardService.copyTextToClipboard).mockResolvedValue(true);
|
||||
|
||||
render(<CopyFeedbackHarness value="作品号:PZ-1" resetDelayMs={10} />);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '复制' }));
|
||||
|
||||
await act(async () => {
|
||||
await Promise.resolve();
|
||||
});
|
||||
expect(screen.getByTestId('copy-state').textContent).toBe('copied');
|
||||
expect(clipboardService.copyTextToClipboard).toHaveBeenCalledWith(
|
||||
'作品号:PZ-1',
|
||||
);
|
||||
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(10);
|
||||
});
|
||||
expect(screen.getByTestId('copy-state').textContent).toBe('idle');
|
||||
});
|
||||
|
||||
test('keeps failure state until reset or timeout', async () => {
|
||||
vi.mocked(clipboardService.copyTextToClipboard).mockResolvedValue(false);
|
||||
|
||||
render(<CopyFeedbackHarness value="" />);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '复制' }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('copy-state').textContent).toBe('failed');
|
||||
});
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '重置' }));
|
||||
|
||||
expect(screen.getByTestId('copy-state').textContent).toBe('idle');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user