Testing clipboard interactions in End-to-End/Integration Playwright tests often comes with a few hidden challenges:
-
Permissions: Browsers require explicit permissions (
clipboard-read,clipboard-write) to allow clipboard access in automated environments. - Flakiness: Asynchronous copy-paste operations can lead to flaky assertions if the clipboard state hasn't updated in time.
-
JSON Handling: Parsing complex objects copied to the clipboard usually involves writing repetitive
JSON.parse()wrapper functions.
To solve this cleanly, I built a lightweight open-source helper package: playwright-clipboard-testing.
Here is a quick guide on how to use it in your Playwright test suite.
Installation
Install the package as a development dependency:
npm install --save-dev playwright-clipboard-testing
Direct Usage
If you don't use custom test fixtures, you can import test and expect directly from playwright-clipboard-testing. The package automatically grants Chromium permissions and manages the clipboard state.
import { test, expect } from 'playwright-clipboard-testing';
test('should copy text to clipboard', async ({ page, clipboard }) => {
await page.goto('https://example.com');
await page.locator('#copy-button').click();
// Uses Playwright's built-in polling to wait for the expected content
await expect(clipboard).toHaveData('Hello, World!');
});
Testing JSON Data
If your web application serializes structured data (like table rows or state objects) into the clipboard, you can assert JSON directly:
test('should copy object as JSON', async ({ page, clipboard }) => {
await page.goto('https://example.com');
await page.locator('#copy-json-button').click();
// Asserts deep object equality automatically
await expect(clipboard).toHaveData({ id: 101, status: 'active' });
});
You can also read parsed JSON directly into your test using clipboard.readJSON():
const data = await clipboard.readJSON<{ id: number }>();
console.log(data.id);
Extending Existing Custom Fixtures
If your project already defines custom Playwright fixtures, you don't need to change your imports. You can extend your base fixtures using clipboardFixture and clipboardMatchers:
import { expect as baseExpect, test as baseTest } from '@playwright/test';
import {
type ClipboardHandler,
clipboardFixture,
clipboardMatchers
} from 'playwright-clipboard-testing';
export const test = baseTest.extend<{ clipboard: ClipboardHandler }>({
clipboard: clipboardFixture,
});
export const expect = baseExpect.extend(clipboardMatchers);
Browser Support Note
⚠️ Note: The Web Clipboard Permissions API is currently supported in Chromium-based browsers. If your setup runs tests across multiple browser engines, simply skip non-Chromium runs:
test('clipboard test', async ({ page, clipboard, browserName }) => {
test.skip(browserName !== 'chromium', 'Clipboard API is Chromium-only');
// test logic...
});
Summary & Links
📦 NPM Package: playwright-clipboard-testing
💻 GitHub Repository: playwright-clipboard-testing
If you find this fixture useful, feel free to drop a ⭐️ on GitHub! Feedback and suggestions are always welcome in the issues.
Top comments (0)