Reputation: 241
I'm writing a test that uses puppeteer to test a component that copies something to the clipboard when it is interacted with. I want to test that the contents of the clipboard are correct after interacting. Other resources like this github issue mention using a tool like clipboardy to accomplish this. I tried using that and it works locally, but when run in my headless CI server, it complains about not having access to the X environment. Is there a way to access the clipboard without starting an X server?
I'm writing a test like this:
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://mypage.com');
await page.click('#my-component');
// This fails in a headless environment
expect(clipboardy.readSync()).toEqual("Some text");
Upvotes: 10
Views: 13979
Reputation: 11
An important point to note is that overridePermissions completely replaces the current set of permissions. So, something like:
await context.overridePermissions(/* browser origin */, ['clipboard-read']);
This would revoke all previous permissions and grant only clipboard read permission. You would need to provide additional permissions [clipboard-write, clipboard-sanitized-write] explicitly as follows:
await context.overridePermissions(/* web url */,['clipboard-read','clipboard-sanitized-write','clipboard-write']);
Upvotes: 0
Reputation: 71
In some cases:
await context.overridePermissions(/* web url */, ['clipboard-read']);
does not work instead give this:
await context.overridePermissions(/* web url */,['clipboard-read','clipboard-sanitized-write','clipboard-write']);
In my case the first code is not working, when I use this code it started to copy the data to clipboard.
Upvotes: 0
Reputation: 241
By adding the 'clipboard-read'
permission to puppeteer and using the
Clipboard API, you can run navigator.clipboard.readText()
to read from the
clipboard in a test. This will work even in a headless environment:
const browser = await puppeteer.launch();
const context = browser.defaultBrowserContext();
await context.overridePermissions(/* browser origin */, ['clipboard-read']);
const page = await browser.newPage();
await page.goto('https://mypage.com');
await page.click('#my-component');
expect(await page.evaluate(() => navigator.clipboard.readText()))
.toEqual("Some text");
Documentation of context.overridePermissions()
Upvotes: 14
Reputation: 872
In my chrome, navigator.clipboard = ...
did not work, because navigator
had getter and setter for clipboard
.
Mocking clipboard:
await page.evaluate(() => {
const clipboard = {
async writeText(text: string) {
this.text = text;
},
};
Object.defineProperty(navigator, 'clipboard', { value: clipboard });
});
Reading clipboard content:
page.evaluate(() => navigator.clipboard.text);
Upvotes: 1
Reputation: 411
In my case I couldn't override permissions, as Eduard suggested, because it requires to give origin as a parm. I'm injecting html content in my test to the page via setContent so the page address is about:blank
. Setting origin to "*"
doesn't work either, nor undefined
.
I have ended up mocking the clipboard api:
await page.evaluate((dataInternal) => {
// mock clipboard
let clipboardText = null;
window["navigator"]["clipboard"] = {
writeText: text => new Promise(resolve => clipboardText = text),
readText: () => new Promise(resolve => resolve(clipboardText)),
}
}
then you can just do the following assert:
expect(await page.evaluate(() => navigator.clipboard.readText())).toBe("your text in clipboard");
Upvotes: 2