chore: update chrome extensions doc and tests (#34236)
This commit is contained in:
parent
d6d5944797
commit
7ee7e018fa
|
@ -9,7 +9,9 @@ title: "Chrome extensions"
|
|||
Extensions only work in Chrome / Chromium launched with a persistent context. Use custom browser args at your own risk, as some of them may break Playwright functionality.
|
||||
:::
|
||||
|
||||
The following is code for getting a handle to the [background page](https://developer.chrome.com/extensions/background_pages) of a [Manifest v2](https://developer.chrome.com/docs/extensions/mv2/) extension whose source is located in `./my-extension`:
|
||||
The snippet below retrieves the [background page](https://developer.chrome.com/extensions/background_pages) of a [Manifest v2](https://developer.chrome.com/docs/extensions/mv2/) extension whose source is located in `./my-extension`.
|
||||
|
||||
Note the use of the `chromium` channel that allows to run extensions in headless mode. Alternatively, you can launch the browser in headed mode.
|
||||
|
||||
```js
|
||||
const { chromium } = require('playwright');
|
||||
|
@ -18,7 +20,7 @@ const { chromium } = require('playwright');
|
|||
const pathToExtension = require('path').join(__dirname, 'my-extension');
|
||||
const userDataDir = '/tmp/test-user-data-dir';
|
||||
const browserContext = await chromium.launchPersistentContext(userDataDir, {
|
||||
headless: false,
|
||||
channel: 'chromium',
|
||||
args: [
|
||||
`--disable-extensions-except=${pathToExtension}`,
|
||||
`--load-extension=${pathToExtension}`
|
||||
|
@ -44,7 +46,7 @@ user_data_dir = "/tmp/test-user-data-dir"
|
|||
async def run(playwright: Playwright):
|
||||
context = await playwright.chromium.launch_persistent_context(
|
||||
user_data_dir,
|
||||
headless=False,
|
||||
channel="chromium",
|
||||
args=[
|
||||
f"--disable-extensions-except={path_to_extension}",
|
||||
f"--load-extension={path_to_extension}",
|
||||
|
@ -78,7 +80,7 @@ user_data_dir = "/tmp/test-user-data-dir"
|
|||
def run(playwright: Playwright):
|
||||
context = playwright.chromium.launch_persistent_context(
|
||||
user_data_dir,
|
||||
headless=False,
|
||||
channel="chromium",
|
||||
args=[
|
||||
f"--disable-extensions-except={path_to_extension}",
|
||||
f"--load-extension={path_to_extension}",
|
||||
|
@ -101,6 +103,8 @@ with sync_playwright() as playwright:
|
|||
|
||||
To have the extension loaded when running tests you can use a test fixture to set the context. You can also dynamically retrieve the extension id and use it to load and test the popup page for example.
|
||||
|
||||
Note the use of the `chromium` channel that allows to run extensions in headless mode. Alternatively, you can launch the browser in headed mode.
|
||||
|
||||
First, add fixtures that will load the extension:
|
||||
|
||||
```js title="fixtures.ts"
|
||||
|
@ -114,7 +118,7 @@ export const test = base.extend<{
|
|||
context: async ({ }, use) => {
|
||||
const pathToExtension = path.join(__dirname, 'my-extension');
|
||||
const context = await chromium.launchPersistentContext('', {
|
||||
headless: false,
|
||||
channel: 'chromium',
|
||||
args: [
|
||||
`--disable-extensions-except=${pathToExtension}`,
|
||||
`--load-extension=${pathToExtension}`,
|
||||
|
@ -155,7 +159,7 @@ def context(playwright: Playwright) -> Generator[BrowserContext, None, None]:
|
|||
path_to_extension = Path(__file__).parent.joinpath("my-extension")
|
||||
context = playwright.chromium.launch_persistent_context(
|
||||
"",
|
||||
headless=False,
|
||||
channel="chromium",
|
||||
args=[
|
||||
f"--disable-extensions-except={path_to_extension}",
|
||||
f"--load-extension={path_to_extension}",
|
||||
|
@ -211,33 +215,3 @@ def test_popup_page(page: Page, extension_id: str) -> None:
|
|||
page.goto(f"chrome-extension://{extension_id}/popup.html")
|
||||
expect(page.locator("body")).to_have_text("my-extension popup")
|
||||
```
|
||||
|
||||
## Headless mode
|
||||
|
||||
By default, Chrome's headless mode in Playwright does not support Chrome extensions. To overcome this limitation, you can run Chrome's persistent context with a new headless mode by using [channel `chromium`](./browsers.md#chromium-new-headless-mode):
|
||||
|
||||
```js title="fixtures.ts"
|
||||
// ...
|
||||
|
||||
const pathToExtension = path.join(__dirname, 'my-extension');
|
||||
const context = await chromium.launchPersistentContext('', {
|
||||
channel: 'chromium',
|
||||
args: [
|
||||
`--disable-extensions-except=${pathToExtension}`,
|
||||
`--load-extension=${pathToExtension}`,
|
||||
],
|
||||
});
|
||||
// ...
|
||||
```
|
||||
|
||||
```python title="conftest.py"
|
||||
path_to_extension = Path(__file__).parent.joinpath("my-extension")
|
||||
context = playwright.chromium.launch_persistent_context(
|
||||
"",
|
||||
channel="chromium",
|
||||
args=[
|
||||
f"--disable-extensions-except={path_to_extension}",
|
||||
f"--load-extension={path_to_extension}",
|
||||
],
|
||||
)
|
||||
```
|
||||
|
|
|
@ -52,19 +52,17 @@ it('should open devtools when "devtools: true" option is given', async ({ browse
|
|||
await browser.close();
|
||||
});
|
||||
|
||||
it('should return background pages', async ({ browserType, createUserDataDir, asset, isHeadlessShell }) => {
|
||||
it('should return background pages', async ({ browserType, asset, isHeadlessShell }) => {
|
||||
it.skip(isHeadlessShell, 'Headless Shell has no support for extensions');
|
||||
|
||||
const userDataDir = await createUserDataDir();
|
||||
const extensionPath = asset('simple-extension');
|
||||
const extensionOptions = {
|
||||
headless: false,
|
||||
args: [
|
||||
`--disable-extensions-except=${extensionPath}`,
|
||||
`--load-extension=${extensionPath}`,
|
||||
],
|
||||
};
|
||||
const context = await browserType.launchPersistentContext(userDataDir, extensionOptions);
|
||||
const context = await browserType.launchPersistentContext('', extensionOptions);
|
||||
const backgroundPages = context.backgroundPages();
|
||||
const backgroundPage = backgroundPages.length
|
||||
? backgroundPages[0]
|
||||
|
@ -77,13 +75,11 @@ it('should return background pages', async ({ browserType, createUserDataDir, as
|
|||
expect(context.backgroundPages().length).toBe(0);
|
||||
});
|
||||
|
||||
it('should return background pages when recording video', async ({ browserType, createUserDataDir, asset, isHeadlessShell }, testInfo) => {
|
||||
it('should return background pages when recording video', async ({ browserType, asset, isHeadlessShell }, testInfo) => {
|
||||
it.skip(isHeadlessShell, 'Headless Shell has no support for extensions');
|
||||
|
||||
const userDataDir = await createUserDataDir();
|
||||
const extensionPath = asset('simple-extension');
|
||||
const extensionOptions = {
|
||||
headless: false,
|
||||
args: [
|
||||
`--disable-extensions-except=${extensionPath}`,
|
||||
`--load-extension=${extensionPath}`,
|
||||
|
@ -92,7 +88,7 @@ it('should return background pages when recording video', async ({ browserType,
|
|||
dir: testInfo.outputPath(''),
|
||||
},
|
||||
};
|
||||
const context = await browserType.launchPersistentContext(userDataDir, extensionOptions);
|
||||
const context = await browserType.launchPersistentContext('', extensionOptions);
|
||||
const backgroundPages = context.backgroundPages();
|
||||
const backgroundPage = backgroundPages.length
|
||||
? backgroundPages[0]
|
||||
|
@ -103,23 +99,21 @@ it('should return background pages when recording video', async ({ browserType,
|
|||
await context.close();
|
||||
});
|
||||
|
||||
it('should support request/response events when using backgroundPage()', async ({ browserType, createUserDataDir, asset, server, isHeadlessShell }) => {
|
||||
it('should support request/response events when using backgroundPage()', async ({ browserType, asset, server, isHeadlessShell }) => {
|
||||
it.skip(isHeadlessShell, 'Headless Shell has no support for extensions');
|
||||
|
||||
server.setRoute('/empty.html', (req, res) => {
|
||||
res.writeHead(200, { 'Content-Type': 'text/html', 'x-response-foobar': 'BarFoo' });
|
||||
res.end(`<span>hello world!</span>`);
|
||||
});
|
||||
const userDataDir = await createUserDataDir();
|
||||
const extensionPath = asset('simple-extension');
|
||||
const extensionOptions = {
|
||||
headless: false,
|
||||
args: [
|
||||
`--disable-extensions-except=${extensionPath}`,
|
||||
`--load-extension=${extensionPath}`,
|
||||
],
|
||||
};
|
||||
const context = await browserType.launchPersistentContext(userDataDir, extensionOptions);
|
||||
const context = await browserType.launchPersistentContext('', extensionOptions);
|
||||
const backgroundPages = context.backgroundPages();
|
||||
const backgroundPage = backgroundPages.length
|
||||
? backgroundPages[0]
|
||||
|
@ -154,19 +148,17 @@ it('should support request/response events when using backgroundPage()', async (
|
|||
|
||||
it('should report console messages from content script', {
|
||||
annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32762' }
|
||||
}, async ({ browserType, createUserDataDir, asset, server, isHeadlessShell }) => {
|
||||
}, async ({ browserType, asset, server, isHeadlessShell }) => {
|
||||
it.skip(isHeadlessShell, 'Headless Shell has no support for extensions');
|
||||
|
||||
const userDataDir = await createUserDataDir();
|
||||
const extensionPath = asset('extension-with-logging');
|
||||
const extensionOptions = {
|
||||
headless: false,
|
||||
args: [
|
||||
`--disable-extensions-except=${extensionPath}`,
|
||||
`--load-extension=${extensionPath}`,
|
||||
],
|
||||
};
|
||||
const context = await browserType.launchPersistentContext(userDataDir, extensionOptions);
|
||||
const context = await browserType.launchPersistentContext('', extensionOptions);
|
||||
const page = await context.newPage();
|
||||
const consolePromise = page.waitForEvent('console', e => e.text().includes('Test console log from a third-party execution context'));
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
|
|
Loading…
Reference in New Issue