diff --git a/docs/api/puppeteer.page.isserviceworkerbypassed.md b/docs/api/puppeteer.page.isserviceworkerbypassed.md
new file mode 100644
index 00000000000..78f9d0fe6d0
--- /dev/null
+++ b/docs/api/puppeteer.page.isserviceworkerbypassed.md
@@ -0,0 +1,19 @@
+---
+sidebar_label: Page.isServiceWorkerBypassed
+---
+
+# Page.isServiceWorkerBypassed() method
+
+`true` if the service worker are being bypassed, `false` otherwise.
+
+#### Signature:
+
+```typescript
+class Page {
+ isServiceWorkerBypassed(): boolean;
+}
+```
+
+**Returns:**
+
+boolean
diff --git a/docs/api/puppeteer.page.md b/docs/api/puppeteer.page.md
index d84f8090bd0..55bc3f3b90c 100644
--- a/docs/api/puppeteer.page.md
+++ b/docs/api/puppeteer.page.md
@@ -117,6 +117,7 @@ page.off('request', logRequest);
| [isClosed()](./puppeteer.page.isclosed.md) | | Indicates that the page has been closed. |
| [isDragInterceptionEnabled()](./puppeteer.page.isdraginterceptionenabled.md) | | true
if drag events are being intercepted, false
otherwise. |
| [isJavaScriptEnabled()](./puppeteer.page.isjavascriptenabled.md) | | true
if the page has JavaScript enabled, false
otherwise. |
+| [isServiceWorkerBypassed()](./puppeteer.page.isserviceworkerbypassed.md) | | true
if the service worker are being bypassed, false
otherwise. |
| [mainFrame()](./puppeteer.page.mainframe.md) | | The page's main frame. |
| [metrics()](./puppeteer.page.metrics.md) | | Object containing metrics as key/value pairs. |
| [off(eventName, handler)](./puppeteer.page.off.md) | | |
@@ -130,6 +131,7 @@ page.off('request', logRequest);
| [screenshot(options)](./puppeteer.page.screenshot_2.md) | | |
| [select(selector, values)](./puppeteer.page.select.md) | | Triggers a change
and input
event once all the provided options have been selected. If there's no <select>
element matching selector
, the method throws an error. |
| [setBypassCSP(enabled)](./puppeteer.page.setbypasscsp.md) | | Toggles bypassing page's Content-Security-Policy. |
+| [setBypassServiceWorker(bypass)](./puppeteer.page.setbypassserviceworker.md) | | Toggles ignoring of service worker for each request. |
| [setCacheEnabled(enabled)](./puppeteer.page.setcacheenabled.md) | | Toggles ignoring cache for each request based on the enabled state. By default, caching is enabled. |
| [setContent(html, options)](./puppeteer.page.setcontent.md) | | Set the content of the page. |
| [setCookie(cookies)](./puppeteer.page.setcookie.md) | | |
diff --git a/docs/api/puppeteer.page.setbypassserviceworker.md b/docs/api/puppeteer.page.setbypassserviceworker.md
new file mode 100644
index 00000000000..34fbd40ce30
--- /dev/null
+++ b/docs/api/puppeteer.page.setbypassserviceworker.md
@@ -0,0 +1,25 @@
+---
+sidebar_label: Page.setBypassServiceWorker
+---
+
+# Page.setBypassServiceWorker() method
+
+Toggles ignoring of service worker for each request.
+
+#### Signature:
+
+```typescript
+class Page {
+ setBypassServiceWorker(bypass: boolean): Promise;
+}
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --------- | ------- | ------------------------------------------------------- |
+| bypass | boolean | Whether to bypass service worker and load from network. |
+
+**Returns:**
+
+Promise<void>
diff --git a/packages/puppeteer-core/src/api/Page.ts b/packages/puppeteer-core/src/api/Page.ts
index f18a25d767f..f60b2da0044 100644
--- a/packages/puppeteer-core/src/api/Page.ts
+++ b/packages/puppeteer-core/src/api/Page.ts
@@ -445,6 +445,13 @@ export class Page extends EventEmitter {
super();
}
+ /**
+ * `true` if the service worker are being bypassed, `false` otherwise.
+ */
+ isServiceWorkerBypassed(): boolean {
+ throw new Error('Not implemented');
+ }
+
/**
* `true` if drag events are being intercepted, `false` otherwise.
*/
@@ -687,6 +694,16 @@ export class Page extends EventEmitter {
throw new Error('Not implemented');
}
+ /**
+ * Toggles ignoring of service worker for each request.
+ *
+ * @param bypass - Whether to bypass service worker and load from network.
+ */
+ async setBypassServiceWorker(bypass: boolean): Promise;
+ async setBypassServiceWorker(): Promise {
+ throw new Error('Not implemented');
+ }
+
/**
* @param enabled - Whether to enable drag interception.
*
diff --git a/packages/puppeteer-core/src/common/Page.ts b/packages/puppeteer-core/src/common/Page.ts
index 31157b0f69e..193133dba15 100644
--- a/packages/puppeteer-core/src/common/Page.ts
+++ b/packages/puppeteer-core/src/common/Page.ts
@@ -157,6 +157,7 @@ export class CDPPage extends Page {
#fileChooserPromises = new Set>();
#disconnectPromise?: Promise;
+ #serviceWorkerBypassed = false;
#userDragInterceptionEnabled = false;
/**
@@ -347,6 +348,10 @@ export class CDPPage extends Page {
return this.#client;
}
+ override isServiceWorkerBypassed(): boolean {
+ return this.#serviceWorkerBypassed;
+ }
+
override isDragInterceptionEnabled(): boolean {
return this.#userDragInterceptionEnabled;
}
@@ -472,6 +477,11 @@ export class CDPPage extends Page {
return this.#frameManager.networkManager.setRequestInterception(value);
}
+ override async setBypassServiceWorker(bypass: boolean): Promise {
+ this.#serviceWorkerBypassed = bypass;
+ return this.#client.send('Network.setBypassServiceWorker', {bypass});
+ }
+
override async setDragInterception(enabled: boolean): Promise {
this.#userDragInterceptionEnabled = enabled;
return this.#client.send('Input.setInterceptDrags', {enabled});
diff --git a/test/TestExpectations.json b/test/TestExpectations.json
index 8dd05fe0787..9f802997124 100644
--- a/test/TestExpectations.json
+++ b/test/TestExpectations.json
@@ -521,6 +521,18 @@
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
},
+ {
+ "testIdPattern": "[network.spec] network Page.setBypassServiceWorker *",
+ "platforms": ["darwin", "linux", "win32"],
+ "parameters": ["webDriverBiDi"],
+ "expectations": ["FAIL"]
+ },
+ {
+ "testIdPattern": "[network.spec] network Page.setBypassServiceWorker *",
+ "platforms": ["darwin", "linux", "win32"],
+ "parameters": ["firefox"],
+ "expectations": ["FAIL", "TIMEOUT"]
+ },
{
"testIdPattern": "[oopif.spec] *",
"platforms": ["darwin", "linux", "win32"],
diff --git a/test/src/network.spec.ts b/test/src/network.spec.ts
index b195f33bd8a..a6d5c817d54 100644
--- a/test/src/network.spec.ts
+++ b/test/src/network.spec.ts
@@ -855,4 +855,44 @@ describe('network', function () {
}
});
});
+
+ describe('Page.setBypassServiceWorker', async () => {
+ it('bypass for network', async () => {
+ const {page, server} = getTestState();
+
+ const responses = new Map();
+ page.on('response', r => {
+ return !isFavicon(r) && responses.set(r.url().split('/').pop(), r);
+ });
+
+ // Load and re-load to make sure serviceworker is installed and running.
+ await page.goto(server.PREFIX + '/serviceworkers/fetch/sw.html', {
+ waitUntil: 'networkidle2',
+ });
+ await page.evaluate(async () => {
+ return await (globalThis as any).activationPromise;
+ });
+ await page.reload({
+ waitUntil: 'networkidle2',
+ });
+
+ expect(page.isServiceWorkerBypassed()).toBe(false);
+ expect(responses.size).toBe(2);
+ expect(responses.get('sw.html').status()).toBe(200);
+ expect(responses.get('sw.html').fromServiceWorker()).toBe(true);
+ expect(responses.get('style.css').status()).toBe(200);
+ expect(responses.get('style.css').fromServiceWorker()).toBe(true);
+
+ await page.setBypassServiceWorker(true);
+ await page.reload({
+ waitUntil: 'networkidle2',
+ });
+
+ expect(page.isServiceWorkerBypassed()).toBe(true);
+ expect(responses.get('sw.html').status()).toBe(200);
+ expect(responses.get('sw.html').fromServiceWorker()).toBe(false);
+ expect(responses.get('style.css').status()).toBe(200);
+ expect(responses.get('style.css').fromServiceWorker()).toBe(false);
+ });
+ });
});