Files
2026-07-13 13:39:12 +08:00

64 lines
2.0 KiB
TypeScript

/**
* Tests for src/shared/utils/clipboard.ts
* Runs under Vitest + jsdom (via vitest.config.ts — environment: "jsdom").
*/
import { describe, it, expect, vi, afterEach } from "vitest";
import { copyToClipboard } from "../../src/shared/utils/clipboard";
afterEach(() => {
vi.restoreAllMocks();
});
describe("copyToClipboard", () => {
it("exports copyToClipboard as a function", () => {
expect(typeof copyToClipboard).toBe("function");
});
it("returns a Promise", () => {
// Minimal smoke test: the function returns a thenable even when
// navigator.clipboard is undefined (HTTP context simulation).
const result = copyToClipboard("hello");
expect(result).toBeInstanceOf(Promise);
});
it("succeeds via Clipboard API when available", async () => {
const writeText = vi.fn().mockResolvedValue(undefined);
Object.defineProperty(navigator, "clipboard", {
value: { writeText },
configurable: true,
writable: true,
});
const ok = await copyToClipboard("test-text");
expect(writeText).toHaveBeenCalledWith("test-text");
expect(ok).toBe(true);
});
it("falls back to execCommand when Clipboard API throws", async () => {
const writeText = vi.fn().mockRejectedValue(new DOMException("NotAllowedError"));
Object.defineProperty(navigator, "clipboard", {
value: { writeText },
configurable: true,
writable: true,
});
// jsdom does not implement execCommand — it returns false.
// We just verify the function does not throw and returns a boolean.
const ok = await copyToClipboard("fallback-text");
expect(typeof ok).toBe("boolean");
});
it("falls back when navigator.clipboard is undefined (HTTP context)", async () => {
Object.defineProperty(navigator, "clipboard", {
value: undefined,
configurable: true,
writable: true,
});
// jsdom's execCommand returns false; that's acceptable in tests.
const ok = await copyToClipboard("http-context-text");
expect(typeof ok).toBe("boolean");
});
});