playwright
playwright copied to clipboard
[Feature] a dedicated clipboard API
It might be nice to have a dedicated clipboard API scoped to page.
Some ideas:
await page.pasteText(text);
await page.keyboard.press('Ctrl + V');
await page.copySelection();
await context.clipboard.setContent(mimeType, content);
Would be great.
Would really help us out as well!
+1
My current workaround is this (C#)
public async Task<string> GetClipboardAsync()
{
IPage page = await Context.Context.NewPageAsync();
await Context.CurrentPage.SetContentAsync("<textarea id='target'></textarea>");
ILocator target = page.Locator("xpath=//textarea[@id='target']");
await target.FocusAsync();
string controlKey = page.Context.Browser!.BrowserType.Name is "webkit" ? "Meta" : "Control";
await target.PressAsync($"{controlKey}+v");
string text = await target.InputValueAsync();
await page.CloseAsync();
return text;
}
public async Task SetClipboardAsync(string value)
{
IPage page = await Context.Context.NewPageAsync();
await page.SetContentAsync($"<textarea id='target'>{value}</textarea>");
ILocator target = page.Locator("xpath=//textarea[@id='target']");
await target .SelectTextAsync(); // Focus & Ctrl+a
string controlKey = page.Context.Browser!.BrowserType.Name is "webkit" ? "Meta" : "Control";
await target.PressAsync($"{controlKey}+c");
await page.CloseAsync();
}
Note the control key won't work if you're using non-safari on macOS. Getting the operating system can be a bit of a hassle (you need javascript, navigator.userAgentData is experimental, parsing navigator.userAgent isn't trivial, etc). So this solution will need tweaking if (unlike me) you test that browser-OS permutation.
Wrote the following to simulate copy and paste events for testing a component that handles them:
import type { JSHandle, Locator } from '@playwright/test';
/**
* Copy the selection to the clipboard and return a `JSHandle` to the data.
*/
export async function copy(locator: Locator): Promise<JSHandle<DataTransfer>> {
return locator.evaluateHandle(() => {
const event = new ClipboardEvent('copy', { bubbles: true, cancelable: true, clipboardData: new DataTransfer() });
window.getSelection()?.anchorNode?.dispatchEvent(event);
return event.clipboardData;
});
}
/**
* Paste the given data at the selection.
*/
export async function paste(locator: Locator, clipboardData: JSHandle<DataTransfer>): Promise<void> {
await locator.evaluate((element, clipboardData) => {
const event = new ClipboardEvent('paste', { bubbles: true, cancelable: true, clipboardData });
window.getSelection()?.anchorNode?.dispatchEvent(event);
}, clipboardData);
}
Wrote the following to simulate copy and paste events for testing a component that handles them:
import type { JSHandle, Locator } from '@playwright/test'; /** * Copy the selection to the clipboard and return a `JSHandle` to the data. */ export async function copy(locator: Locator): Promise<JSHandle<DataTransfer>> { return locator.evaluateHandle(() => { const event = new ClipboardEvent('copy', { bubbles: true, cancelable: true, clipboardData: new DataTransfer() }); window.getSelection()?.anchorNode?.dispatchEvent(event); return event.clipboardData; }); } /** * Paste the given data at the selection. */ export async function paste(locator: Locator, clipboardData: JSHandle<DataTransfer>): Promise<void> { await locator.evaluate((element, clipboardData) => { const event = new ClipboardEvent('paste', { bubbles: true, cancelable: true, clipboardData }); window.getSelection()?.anchorNode?.dispatchEvent(event); }, clipboardData); }
Work like a charm!
It might also be useful to be able to read the current values of the clipboard, rather than e.g. using
await component.evaluate( 'navigator.clipboard.readText()',)