import { describe, it, expect, beforeEach, vi } from "vitest"; import { render, screen, fireEvent, waitFor } from "@testing-library/react"; import { CopyButton } from "./CopyButton"; describe("CopyButton", () => { let mockWriteText: ReturnType; beforeEach(() => { mockWriteText = vi.fn(() => Promise.resolve()); // Mock clipboard API with secure context Object.assign(navigator, { clipboard: { writeText: mockWriteText, }, }); // Mock secure context Object.defineProperty(window, "isSecureContext", { value: true, writable: true, }); // Mock execCommand as fallback document.execCommand = vi.fn(() => true); }); it("renders with default label", () => { render(); const button = screen.getByRole("button", { name: "Copy" }); expect(button).toBeTruthy(); }); it("renders with custom label", () => { render(); const button = screen.getByRole("button", { name: "Copy code" }); expect(button).toBeTruthy(); }); it("copies content to clipboard on click", async () => { render(); const button = screen.getByRole("button"); fireEvent.click(button); await waitFor(() => { expect(mockWriteText).toHaveBeenCalledWith("hello world"); }); }); it("shows copied state after click", async () => { render(); const button = screen.getByRole("button"); fireEvent.click(button); // Button should show "Copied!" label after async operation await waitFor(() => { expect(button.getAttribute("aria-label")).toBe("Copied!"); expect(button.classList.contains("copy-btn-copied")).toBe(true); }); }); it("applies custom className", () => { render(); const button = screen.getByRole("button"); expect(button.classList.contains("custom-class")).toBe(true); }); });