コンテンツにスキップ

クリップボード操作をテストする

ユースケース: 「リンクをコピー」ボタン、セルのペーストを受け付けるスプレッドシートグリッド、Wordのマークアップを整形してくれるエディタ。コピー&ペーストは中核的なインタラクションでありながら、自動化できるものの中で最もブラウザ間の差異が大きい部類です。

クリップボードはシステムリソースで、ブラウザごとに異なるパーミッションとユーザーアクティベーションのルールに守られています。Playwrightにはクリップボードの第一級APIがなく、Chromiumで動くコードがWebKitでは静かに失敗します。

Chromium: パーミッションを付与して非同期APIを使う

Section titled “Chromium: パーミッションを付与して非同期APIを使う”
import { test, expect } from '@playwright/test';
test.use({ permissions: ['clipboard-read', 'clipboard-write'] });
test('copy button puts the share URL on the clipboard', async ({ page }) => {
await page.goto('/document/42');
await page.getByRole('button', { name: 'Copy link' }).click();
const text = await page.evaluate(() => navigator.clipboard.readText());
expect(text).toBe('https://example.com/s/abc123');
});

本物のペースト=クリップボードの内容+pasteイベントです。クリップボードに書き込んでから、実際のキーボードショートカットを送ってアプリの paste リスナーを発火させます:

test('pasting cells fills the grid', async ({ page }) => {
await page.goto('/sheet');
await page.evaluate(() =>
navigator.clipboard.writeText('1\t2\n3\t4'), // スプレッドシートのコピーと同じTSV形式
);
await page.locator('.cell-a1').click();
await page.keyboard.press(process.platform === 'darwin' ? 'Meta+v' : 'Control+v');
await expect(page.locator('.cell-b2')).toHaveText('4');
});

リッチ形式(WordからのHTMLペースト、画像)は DataTransfer を自分で組み立ててイベントをディスパッチします。この方法ならパーミッションプロンプトも完全に回避できます:

await page.locator('#editor').evaluate((el) => {
const dt = new DataTransfer();
dt.setData('text/html', '<b>bold</b> from Word<o:p></o:p>');
dt.setData('text/plain', 'bold from Word');
el.dispatchEvent(new ClipboardEvent('paste', { clipboardData: dt, bubbles: true, cancelable: true }));
});
await expect(page.locator('#editor strong')).toHaveText('bold');

permissions: [...] によるクリップボード付与はChromium限定です。移植可能な選択肢は:

  • ClipboardEvent をディスパッチする(上記) — すべてのブラウザでアプリのハンドラをテストできます。実クリップボードは経由しません。
  • Firefox: テスト用プリファレンスを有効化 — firefoxUserPrefs: { 'dom.events.testing.asyncClipboard': true }
  • WebKit: 読み取りにはユーザーアクティベーションが必要です。イベントディスパッチ方式が現実的な選択肢です。

よくあるパターンは、Chromiumで実クリップボードの完全なカバレッジを取り、同じ機能をブラウザ横断ではイベントレベルでカバーする構成です。

  • クリップボードの状態は同一コンテキスト内のテスト間でリークします。beforeEach で既知の値を書き込むか、新しいコンテキストを使ってください。
  • ユーザーアクティベーションの判定はヘッドありとヘッドレスで挙動が異なります。グリーンにすべき環境はCIのヘッドレスです。
  • ホストマシンのクリップボード(OSユーティリティ経由)に対するアサートは絶対に避けてください。並列ワーカーが取り合いになります。