first commit
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
# mock-clipboard
|
||||
|
||||
## Purpose
|
||||
|
||||
`mockClipboard` installs a deterministic, in-memory clipboard implementation on the navigator object for a Playwright page. The default clipboard shipped by Chromium headless requires explicit user-gesture permissions and does not work at all in some CI environments; this helper replaces it with a programmatic pair of `writeText` / `readText` that behaves identically in every environment.
|
||||
|
||||
## Features
|
||||
|
||||
- Installs via `page.addInitScript` so the mock is active before any app code runs
|
||||
- In-memory state is per-page — different pages don't share clipboard state
|
||||
- Matches the real `navigator.clipboard` API surface for `writeText` and `readText`
|
||||
- Idempotent — calling twice on the same page just re-installs the same script
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { mockClipboard } from "@suaveplan/testing-e2e/helpers";
|
||||
|
||||
await mockClipboard(page);
|
||||
await page.goto("/settings");
|
||||
await page.click("text=Copy API key");
|
||||
const copied = await page.evaluate(() => navigator.clipboard.readText());
|
||||
expect(copied).toMatch(/^sk_/);
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { mockClipboard } from "@suaveplan/testing-e2e/helpers";
|
||||
import { expect } from "@playwright/test";
|
||||
|
||||
test("copy + paste round trip", async ({ page }) => {
|
||||
await mockClipboard(page);
|
||||
await page.goto("/notes/123");
|
||||
|
||||
await page.getByRole("button", { name: /copy link/i }).click();
|
||||
const copied = await page.evaluate(() => navigator.clipboard.readText());
|
||||
expect(copied).toBe("https://notes.example/123");
|
||||
|
||||
// Paste somewhere:
|
||||
await page.goto("/notes/new");
|
||||
await page.evaluate(async () => {
|
||||
const text = await navigator.clipboard.readText();
|
||||
(document.querySelector("textarea") as HTMLTextAreaElement).value = text;
|
||||
});
|
||||
await expect(page.locator("textarea")).toHaveValue("https://notes.example/123");
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `mockClipboard(page): Promise<void>`
|
||||
|
||||
- `page: Page` — Playwright page (must be called before any navigation for the init script to take effect)
|
||||
- Returns `Promise<void>` that resolves after the init script is registered
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The init script defines `navigator.clipboard` using `Object.defineProperty` with `writable: true` so a test that wants to swap in a further spy can still do so. Because the mock is installed via `addInitScript`, it's reinstalled automatically on every navigation within the same page — tests don't need to reinstall after `page.goto`.
|
||||
|
||||
### Behaviour
|
||||
|
||||
`mockClipboard(page)` installs an `addInitScript` that replaces `navigator.clipboard.readText` / `writeText` with in-memory stubs whose state survives page navigations inside the same context. A companion `getClipboardValue(page)` reads the current mock value synchronously from the page's JS context so assertions do not need to await a clipboard-permissions prompt.
|
||||
Reference in New Issue
Block a user