1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
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<typeof vi.fn>;
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(<CopyButton content="test content" />);
const button = screen.getByRole("button", { name: "Copy" });
expect(button).toBeTruthy();
});
it("renders with custom label", () => {
render(<CopyButton content="test" label="Copy code" />);
const button = screen.getByRole("button", { name: "Copy code" });
expect(button).toBeTruthy();
});
it("copies content to clipboard on click", async () => {
render(<CopyButton content="hello world" />);
const button = screen.getByRole("button");
fireEvent.click(button);
await waitFor(() => {
expect(mockWriteText).toHaveBeenCalledWith("hello world");
});
});
it("shows copied state after click", async () => {
render(<CopyButton content="test" />);
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(<CopyButton content="test" className="custom-class" />);
const button = screen.getByRole("button");
expect(button.classList.contains("custom-class")).toBe(true);
});
});
|