microsoft / playwright

Playwright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API.
https://playwright.dev
Apache License 2.0
64.18k stars 3.49k forks source link

[BUG] browser.newContext: Unknown permission: clipboard-read for webkit #13037

Open amrsa1 opened 2 years ago

amrsa1 commented 2 years ago

Context:

Code Snippet

const config: PlaywrightTestConfig = {
    globalTeardown: require.resolve('../src/utils/teardown'),
    workers: configList.workers,
    use: {
        contextOptions: {
            userAgent: configList.userAgent,
            permissions: ['clipboard-read', 'clipboard-write']
        },
    test('test', async ({ browserName, page }) => {
        expect(await page.screenshot({ fullPage: true, timeout: 4000 })).toMatchSnapshot(`${browserName}-EN.png`);
    });

Describe the bug

Test is failing for webkit browser, if config file contains permissions: ['clipboard-read', 'clipboard-write'] however there is not any clipboard event is being used in this test

error :

  3) [Desktop Firefox] › search/.test.ts:38:5 › Landing page Test Suite › test

    browser.newContext: Unknown permission: clipboard-read
dgozman commented 2 years ago

Indeed, clipboard-read and clipboard-write are only supported in Chromium.

amrsa1 commented 2 years ago

@dgozman Could it be enhanced, so that if its included in the config file it will has no effect on webkit rather than make it fail, as the same config ia running agaisnt chrome and firefox in the same instance as well

mirao commented 2 years ago

I had the same issue in Firefox, CodeceptJS + Playwright. In Firefox no permission is needed to have working "copy of text to clipboard" (note it works in secure sites only).

It would be great if Playwright was able to suppress the error browser.newContext: Unknown permission: clipboard-write if given browser doesn't provide that feature. Currently I must allow such setting in test for Chromium and not for Firefox which makes tests more complex.

amrsa1 commented 2 years ago

Any update regarding this topic

rahulvramesh commented 2 years ago

any update ?

dgozman commented 2 years ago

We suggest to set permission per browser. Most likely, you already have test projects with different browsers configured, so just move permission to the respective project.

// playwright.config.ts

export default {
  projects: [
    {
      name: 'chromium',
      browserName: 'chromium',
      use: {
        contextOptions: {
          // chromium-specific permissions
          permissions: ['clipboard-read', 'clipboard-write'],
        },
      },
    },
    {
      name: 'firefox',
      browserName: 'firefox',
      use: {
        contextOptions: {
          // firefox-specific permissions
          permissions: ['geolocation'],
        },
      },
    },
  ],
};
rahulvramesh commented 2 years ago

thanks, @dgozman , will try it out though somehow, the below code worked for me, which is similar to something I tried first.

const browser = await chromium.launch({headless: false});
  const context = await browser.newContext({
    permissions: ['geolocation', 'microphone', 'camera'],
    colorScheme: 'dark',
    recordVideo: {
      dir: 'videos/',
      size: { width: 1920, height: 1080 },
    }
  });
dimitur2204 commented 1 year ago

How can I even test copying and pasting from Firefox or Webkit then? Is it impossible currently?

IgorKoryapin commented 1 year ago

faced the same problem, did not find a solution

gselsidi commented 1 year ago

@dgozman does safari support read write permissions? how do we set them? as it fails with the above chromium settings

aalayoubi commented 1 year ago

@dimitur2204 I'm having the same issue, did you figure it out?

dimitur2204 commented 1 year ago

@dimitur2204 I'm having the same issue, did you figure it out?

No I did not

aalayoubi commented 1 year ago

@dimitur2204 I had to skip the test being run on firefox because I couldn't find a way around it

Palak-Jethwani commented 1 year ago

This is indeed an issue which must be fixed in Playwright. I am using Cucumber as my test runner so I can't use projects as well in config. And my tests fail in firefox and webkit because of unknown permission error. Please fix asap or provide at least a workaround.

moshikd commented 1 year ago

any update on this issue?? i'm facing it on webkit and firefox ? @dgozman @mxschmitt

erickbelfy commented 1 year ago

im also facing the same issue.

yakovkurochkin commented 11 months ago

Workaround for Firefox:

test('Firefox clipboard', async ({}) => {
  const browser = await firefox.launch({
    firefoxUserPrefs: {
      'dom.events.asyncClipboard.readText': true,
      'dom.events.testing.asyncClipboard': true,
    },
  });

  const page = await browser.newPage();

  await page.goto('https://copy-current-url-button.webflow.io/');
  await page.locator('#copy-status').click();

  const clipboardContents = await page.evaluate('navigator.clipboard.readText()');

  console.log(clipboardContents);
});
porleaaron commented 9 months ago

This approach should work

projects: [{
  name: "chromium",
  use: {
    ...devices["Desktop Chrome"],
    contextOptions: {
      // chromium-specific permissions
      permissions: ['clipboard-read', 'clipboard-write'],
    },
  },
},

{
  name: "firefox",
  use: {
    ...devices["Desktop Firefox"],
    launchOptions: {
      firefoxUserPrefs: {
        'dom.events.asyncClipboard.readText': true,
        'dom.events.testing.asyncClipboard': true,
      },
    }
  },
},

{
  name: "webkit",
  use: { ...devices["Desktop Safari"] },
}]
krachtstefan commented 9 months ago

This worked for me, except in Safari. If anyone can give me a hint on how to setup the proper permissions for safari, I would be very happy.

In the meantime I solved it by mocking the clipborad API and find it might be worth sharing:

e2e/utils/index.ts

import { Page } from "@playwright/test";

/**
 * this will mock the browsers clipboard API, since it might not be available in the test environment
 * due to invalid permissions. It's recommended to use this function in the beforeAll or beforeEach hook
 * of the test to inject the mock into the page very early. It will e.g. not work if it's called after
 * page.goto() has been called.
 */
export const mockClipboardAPI = async (page: Page) =>
  await page.addInitScript(() => {
    // create a mock of the clipboard API
    const mockClipboard = {
      clipboardData: "",
      writeText: async (text: string) => {
        mockClipboard.clipboardData = text;
      },
      readText: async () => mockClipboard.clipboardData,
    };

    // override the native clipboard API
    Object.defineProperty(navigator, "clipboard", {
      value: mockClipboard,
      writable: false,
      enumerable: true,
      configurable: true,
    });
  });

e2e/mytest.ts

import { mockClipboardAPI } from "e2e/utils/testutils";

test.beforeEach(async ({ page }) => {
  await mockClipboardAPI(page);
});

test("I am a test that needs to validate that some text was copied into the clipboard", async ({
  page,
}) => {
  /**
   * this might be replaces by an interaction with the UI,
   * in which the user copies something into the clipboard
   */
  await page.evaluate(() =>
    navigator.clipboard.writeText("I was copied into the clipboard")
  );

  const clipboardText = await page.evaluate(() =>
    /**
     * this will call the mock instead of the real clipboard API. To make
     * sure the mock was actually used, go to the mockClipboardAPI function
     * and change the return value of the readText function to some test
     * data and see if will end up here.
     */
    navigator.clipboard.readText()
  );

  expect(clipboardText).toBe("I was copied into the clipboard");
});
agusmakmun commented 8 months ago

I have the same issue, and using selector for safari:

try {
  email = await page.evaluate("navigator.clipboard.readText()");
} catch (e) {
  // this case is to handle the safari browser where having the clipboard permission
  // https://github.com/microsoft/playwright/issues/13037
  let emailLocator = await page.locator('//div[contains(@class, "cursor-pointer")]/p');
  email = await emailLocator.innerText();
}

Above case will need to wait until few times, to make it fast we can use the browserName fixture as a conditional:

test("something", async ({ page, browserName }) => {
  ...

  if (['webkit', 'Desktop Safari', 'Mobile Safari'].includes(browserName)) {
    let emailLocator = await page.locator('//div[contains(@class, "cursor-pointer")]/p');
    email = await emailLocator.innerText();
  } else {
    email = await page.evaluate("navigator.clipboard.readText()");
  }
})
marcin-bojar commented 4 months ago

same issue here, Safari does not allow to test copy-to-clipboard functionality, any timelines for the fix?

RuanAlesi commented 3 months ago

Same thing here

Microsoft.Playwright.PlaywrightException : Unknown permission: clipboard-write

Any news?

amrsa1 commented 3 months ago

I have found that we dont need to have this permission with webkit.

So simply this issue can be resolved as a work around by adding to projects one with chrome and relative permission and another project with webkit without permission

RuanAlesi commented 3 months ago

What do you mean don't need to have this permission @amrsa1 ? Copying content into the application is one of my tests and using Webkit ends up with the error message: The request is not allowed by the user or the platform in the current context, possibly because the user denied permission

amrsa1 commented 3 months ago

You dont need to have this permission with webkit.

So simply this issue can be resolved as a work around by adding to projects one with chrome and relative permission and another project with webkit without permission

I mean you can copy without permission as far as i remeber for webkit.

RuanAlesi commented 3 months ago

It's not what I see. I have that error message when using clipboard functions with Webkit.

amrsa1 commented 3 months ago

It's not what I see. I have that error message when using clipboard functions with Webkit.

The issue is that this permissions are dedicated for chrome.

If this test is running against multiple browser, maybe you can disable it for safari.

This ticket is there since long ago and i cant remeber how i over come this

StevenBoutcher commented 1 week ago

launchOptions: { firefoxUserPrefs: { 'dom.events.asyncClipboard.readText': true, 'dom.events.testing.asyncClipboard': true, }, }

This worked for me. I'll cite this in my blog post, thank you!