/* @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 (
{copyState}
);
}
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();
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();
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');
});
});