<h3 dir="auto">System info</h3>
<ul dir="auto">
<li>Playwright Version: 1.31.2</li>
<li>Operating System: MacOS 13.2.1</li>
<li>Browser: Chromium</li>
<li>Other info:</li>
</ul>
<h3 dir="auto">Source code</h3>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I provided exact source code that allows reproducing the issue locally.</li>
</ul>
<p dir="auto"><strong>Config file</strong></p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// playwright.config.ts
import { defineConfig } from &quot;@playwright/test&quot;;

export default defineConfig({
  timeout: 15 * 60 * 1000, // 15 minutes
  use: {
    acceptDownloads: true,
    actionTimeout: 5 * 1000, // 5 seconds
    trace: &quot;retain-on-failure&quot;,
  },
  workers: 5,
  fullyParallel: true,
});
"><pre class="notranslate"><span class="pl-c">// playwright.config.ts</span>
<span class="pl-k">import</span> <span class="pl-kos">{</span> <span class="pl-s1">defineConfig</span> <span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">"@playwright/test"</span><span class="pl-kos">;</span>

<span class="pl-k">export</span> <span class="pl-k">default</span> <span class="pl-en">defineConfig</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">timeout</span>: <span class="pl-c1">15</span> <span class="pl-c1">*</span> <span class="pl-c1">60</span> <span class="pl-c1">*</span> <span class="pl-c1">1000</span><span class="pl-kos">,</span> <span class="pl-c">// 15 minutes</span>
  <span class="pl-c1">use</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">acceptDownloads</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
    <span class="pl-c1">actionTimeout</span>: <span class="pl-c1">5</span> <span class="pl-c1">*</span> <span class="pl-c1">1000</span><span class="pl-kos">,</span> <span class="pl-c">// 5 seconds</span>
    <span class="pl-c1">trace</span>: <span class="pl-s">"retain-on-failure"</span><span class="pl-kos">,</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">workers</span>: <span class="pl-c1">5</span><span class="pl-kos">,</span>
  <span class="pl-c1">fullyParallel</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto"><strong>Test file (self-contained)</strong></p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="it('should timeout after 3 seconds', async ({ page }) =&gt; {
  page.goto(&quot;http://localhost:3000/&quot;);
  page.setDefaultTimeout(3 * 1000); // 3 seconds
  await page.waitForSelector('text=&quot;something not in the dom&quot;')
});"><pre class="notranslate"><span class="pl-en">it</span><span class="pl-kos">(</span><span class="pl-s">'should timeout after 3 seconds'</span><span class="pl-kos">,</span> <span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-kos">{</span> page <span class="pl-kos">}</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">goto</span><span class="pl-kos">(</span><span class="pl-s">"http://localhost:3000/"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">setDefaultTimeout</span><span class="pl-kos">(</span><span class="pl-c1">3</span> <span class="pl-c1">*</span> <span class="pl-c1">1000</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 3 seconds</span>
  <span class="pl-k">await</span> <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">waitForSelector</span><span class="pl-kos">(</span><span class="pl-s">'text="something not in the dom"'</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto"><strong>Steps</strong></p>
<ul dir="auto">
<li>Run the test</li>
<li>Observe that it waits until the global test timeout of 15 minutes elapses</li>
</ul>
<p dir="auto"><strong>Expected</strong><br>
According to the docs, the <code class="notranslate">page.setDefaultTimeout</code> value of 3 seconds should kick in here.<br>
Also, according to this issue: <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1214178547" data-permission-text="Title is private" data-url="https://github.com/microsoft/playwright/issues/13723" data-hovercard-type="issue" data-hovercard-url="/microsoft/playwright/issues/13723/hovercard" href="https://github.com/microsoft/playwright/issues/13723">#13723</a>, the actionTimeout of 5 seconds should also apply.</p>
<p dir="auto"><strong>Actual</strong></p>
<p dir="auto">The only way I've been able to get this to timeout as expected is by passing the option directly to <code class="notranslate">waitForSelector</code>.</p>
<h3 dir="auto">System info</h3>
<ul dir="auto">
<li>Playwright Version: playwright-chromium@1.31.2</li>
<li>Operating System: macOS 13.1</li>
<li>Browser: Chrome 110.0.5481.77 (Official Build) (arm64)</li>
<li>Other info:</li>
</ul>
<h3 dir="auto">Source code</h3>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I provided exact source code that allows reproducing the issue locally.</li>
</ul>




<p dir="auto"><code class="notranslate">script.ts</code>:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import { Browser, BrowserContext, chromium, Page } from &quot;playwright-chromium&quot;;
import * as path from &quot;path&quot;;
import * as url from &quot;url&quot;;

async function intercept(page: Page) {
	const context = page.context();

	const client = await context.newCDPSession(page);

	await client.send(&quot;Fetch.enable&quot;, {
		&quot;patterns&quot;: [
			{
				&quot;requestStage&quot;: &quot;Response&quot;,
				&quot;urlPattern&quot;: &quot;*&quot;
			}
		]
	});

	client.on(&quot;Fetch.requestPaused&quot;, async ({ requestId, request }) =&gt; {
		const { hostname, pathname } = new URL(request.url);

		try {
			const { body } = await client.send(&quot;Fetch.getResponseBody&quot;, {
				&quot;requestId&quot;: requestId
			});

			let baseName = path.basename(pathname);
			const pathName = path.join(pathname.slice(0, -baseName.length));
			const fileName = path.join(hostname, pathName, baseName || &quot;index.html&quot;);
			baseName ||= path.basename(fileName);

			console.log(&quot;Saving &quot; + request.url + &quot; as &quot; + baseName);
		} catch (error) {
			console.error(&quot;Failed to get &quot; + request.url);
		} finally {
			await client.send(&quot;Fetch.continueRequest&quot;, {
				&quot;requestId&quot;: requestId
			});
		}
	});
}

let browser: Browser;

let context: BrowserContext;

export async function init() {
	browser ??= await chromium.launch({
		&quot;args&quot;: [&quot;--disable-web-security&quot;],
		&quot;devtools&quot;: true,
		&quot;headless&quot;: false //!(Boolean(process.env[&quot;CI&quot;]) || process.platform === &quot;win32&quot; || Boolean(process.env[&quot;DISPLAY&quot;]))
	});

	context ??= await browser.newContext();

	const page = await context.newPage();

	await intercept(page);

	await page.goto(url.pathToFileURL(path.resolve(&quot;./index.html&quot;)).toString());
}

init();"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-kos">{</span> <span class="pl-v">Browser</span><span class="pl-kos">,</span> <span class="pl-v">BrowserContext</span><span class="pl-kos">,</span> <span class="pl-s1">chromium</span><span class="pl-kos">,</span> <span class="pl-v">Page</span> <span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">"playwright-chromium"</span><span class="pl-kos">;</span>
<span class="pl-k">import</span> <span class="pl-c1">*</span> <span class="pl-k">as</span> <span class="pl-s1">path</span> <span class="pl-k">from</span> <span class="pl-s">"path"</span><span class="pl-kos">;</span>
<span class="pl-k">import</span> <span class="pl-c1">*</span> <span class="pl-k">as</span> <span class="pl-s1">url</span> <span class="pl-k">from</span> <span class="pl-s">"url"</span><span class="pl-kos">;</span>

<span class="pl-k">async</span> <span class="pl-k">function</span> <span class="pl-en">intercept</span><span class="pl-kos">(</span><span class="pl-s1">page</span>: <span class="pl-v">Page</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
	<span class="pl-k">const</span> <span class="pl-s1">context</span> <span class="pl-c1">=</span> <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">context</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

	<span class="pl-k">const</span> <span class="pl-s1">client</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-en">newCDPSession</span><span class="pl-kos">(</span><span class="pl-s1">page</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

	<span class="pl-k">await</span> <span class="pl-s1">client</span><span class="pl-kos">.</span><span class="pl-en">send</span><span class="pl-kos">(</span><span class="pl-s">"Fetch.enable"</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
		<span class="pl-s">"patterns"</span>: <span class="pl-kos">[</span>
			<span class="pl-kos">{</span>
				<span class="pl-s">"requestStage"</span>: <span class="pl-s">"Response"</span><span class="pl-kos">,</span>
				<span class="pl-s">"urlPattern"</span>: <span class="pl-s">"*"</span>
			<span class="pl-kos">}</span>
		<span class="pl-kos">]</span>
	<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

	<span class="pl-s1">client</span><span class="pl-kos">.</span><span class="pl-en">on</span><span class="pl-kos">(</span><span class="pl-s">"Fetch.requestPaused"</span><span class="pl-kos">,</span> <span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-kos">{</span> requestId<span class="pl-kos">,</span> request <span class="pl-kos">}</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
		<span class="pl-k">const</span> <span class="pl-kos">{</span> hostname<span class="pl-kos">,</span> pathname <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-c1">URL</span><span class="pl-kos">(</span><span class="pl-s1">request</span><span class="pl-kos">.</span><span class="pl-c1">url</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

		<span class="pl-k">try</span> <span class="pl-kos">{</span>
			<span class="pl-k">const</span> <span class="pl-kos">{</span> body <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">client</span><span class="pl-kos">.</span><span class="pl-en">send</span><span class="pl-kos">(</span><span class="pl-s">"Fetch.getResponseBody"</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
				<span class="pl-s">"requestId"</span>: <span class="pl-s1">requestId</span>
			<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

			<span class="pl-k">let</span> <span class="pl-s1">baseName</span> <span class="pl-c1">=</span> <span class="pl-s1">path</span><span class="pl-kos">.</span><span class="pl-en">basename</span><span class="pl-kos">(</span><span class="pl-s1">pathname</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
			<span class="pl-k">const</span> <span class="pl-s1">pathName</span> <span class="pl-c1">=</span> <span class="pl-s1">path</span><span class="pl-kos">.</span><span class="pl-en">join</span><span class="pl-kos">(</span><span class="pl-s1">pathname</span><span class="pl-kos">.</span><span class="pl-en">slice</span><span class="pl-kos">(</span><span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">-</span><span class="pl-s1">baseName</span><span class="pl-kos">.</span><span class="pl-c1">length</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
			<span class="pl-k">const</span> <span class="pl-s1">fileName</span> <span class="pl-c1">=</span> <span class="pl-s1">path</span><span class="pl-kos">.</span><span class="pl-en">join</span><span class="pl-kos">(</span><span class="pl-s1">hostname</span><span class="pl-kos">,</span> <span class="pl-s1">pathName</span><span class="pl-kos">,</span> <span class="pl-s1">baseName</span> <span class="pl-c1">||</span> <span class="pl-s">"index.html"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
			<span class="pl-s1">baseName</span> <span class="pl-c1">||=</span> <span class="pl-s1">path</span><span class="pl-kos">.</span><span class="pl-en">basename</span><span class="pl-kos">(</span><span class="pl-s1">fileName</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

			<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">"Saving "</span> <span class="pl-c1">+</span> <span class="pl-s1">request</span><span class="pl-kos">.</span><span class="pl-c1">url</span> <span class="pl-c1">+</span> <span class="pl-s">" as "</span> <span class="pl-c1">+</span> <span class="pl-s1">baseName</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
		<span class="pl-kos">}</span> <span class="pl-k">catch</span> <span class="pl-kos">(</span><span class="pl-s1">error</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
			<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">error</span><span class="pl-kos">(</span><span class="pl-s">"Failed to get "</span> <span class="pl-c1">+</span> <span class="pl-s1">request</span><span class="pl-kos">.</span><span class="pl-c1">url</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
		<span class="pl-kos">}</span> <span class="pl-k">finally</span> <span class="pl-kos">{</span>
			<span class="pl-k">await</span> <span class="pl-s1">client</span><span class="pl-kos">.</span><span class="pl-en">send</span><span class="pl-kos">(</span><span class="pl-s">"Fetch.continueRequest"</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
				<span class="pl-s">"requestId"</span>: <span class="pl-s1">requestId</span>
			<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
		<span class="pl-kos">}</span>
	<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">let</span> <span class="pl-s1">browser</span>: <span class="pl-v">Browser</span><span class="pl-kos">;</span>

<span class="pl-k">let</span> <span class="pl-s1">context</span>: <span class="pl-v">BrowserContext</span><span class="pl-kos">;</span>

<span class="pl-k">export</span> <span class="pl-k">async</span> <span class="pl-k">function</span> <span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
	<span class="pl-s1">browser</span> <span class="pl-c1">??=</span> <span class="pl-k">await</span> <span class="pl-s1">chromium</span><span class="pl-kos">.</span><span class="pl-en">launch</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
		<span class="pl-s">"args"</span>: <span class="pl-kos">[</span><span class="pl-s">"--disable-web-security"</span><span class="pl-kos">]</span><span class="pl-kos">,</span>
		<span class="pl-s">"devtools"</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
		<span class="pl-s">"headless"</span>: <span class="pl-c1">false</span> <span class="pl-c">//!(Boolean(process.env["CI"]) || process.platform === "win32" || Boolean(process.env["DISPLAY"]))</span>
	<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

	<span class="pl-s1">context</span> <span class="pl-c1">??=</span> <span class="pl-k">await</span> <span class="pl-s1">browser</span><span class="pl-kos">.</span><span class="pl-en">newContext</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

	<span class="pl-k">const</span> <span class="pl-s1">page</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-en">newPage</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

	<span class="pl-k">await</span> <span class="pl-en">intercept</span><span class="pl-kos">(</span><span class="pl-s1">page</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

	<span class="pl-k">await</span> <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">goto</span><span class="pl-kos">(</span><span class="pl-s1">url</span><span class="pl-kos">.</span><span class="pl-en">pathToFileURL</span><span class="pl-kos">(</span><span class="pl-s1">path</span><span class="pl-kos">.</span><span class="pl-en">resolve</span><span class="pl-kos">(</span><span class="pl-s">"./index.html"</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toString</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto"><code class="notranslate">index.html</code>:</p>
<div class="highlight highlight-text-html-basic notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta name=&quot;description&quot; content=&quot;&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;iframe id=&quot;nodebox-iframe&quot;&gt;&lt;/iframe&gt;
    &lt;iframe id=&quot;preview-iframe&quot;&gt;&lt;/iframe&gt;
    &lt;script type=&quot;module&quot;&gt;
        import { Nodebox } from &quot;https://cdn.jsdelivr.net/npm/@codesandbox/nodebox/build/index.min.mjs&quot;;

        const nodeboxIframe = document.getElementById(&quot;nodebox-iframe&quot;);
        const previewIframe = document.getElementById(&quot;preview-iframe&quot;);

        const nodebox = new Nodebox({
            &quot;iframe&quot;: nodeboxIframe
        });

        await nodebox.connect();

        await nodebox.fs.init({
            &quot;index.js&quot;: `
// server.ts
import * as http from &quot;http&quot;;

// server.ts
var BASE_URL = &quot;http://localhost:8000&quot;;
var router = {
  &quot;/&quot;: function(request, response) {
    response.writeHead(200, { &quot;Content-Type&quot;: &quot;text/html&quot; });
    response.end(&quot;OK&quot;);
  }
};
var server = http.createServer(function(request, response) {
  const startTime = performance.now();
  let status = 200;
  try {
    if (request.method === &quot;GET&quot; &amp;&amp; router[request.url] !== void 0) {
      router[request.url](request, response);
    } else {
      status = 404;
      response.writeHead(status, { &quot;Content-Type&quot;: &quot;text/plain&quot; });
      response.end(&quot;File not found&quot;);
    }
  } catch (error) {
    status = 500;
    response.writeHead(status, { &quot;Content-Type&quot;: &quot;text/plain&quot; });
    response.end(&quot;Internal server error&quot;);
  }
  response.on(&quot;finish&quot;, function() {
    console.log(request.method, request.url, status, (performance.now() - startTime).toFixed(3), &quot;ms&quot;);
  });
});
server.listen(new URL(BASE_URL).port, function() {
  console.log(&quot;&gt; Ready on &quot; + BASE_URL);
});
    `
        });

        const shell = nodebox.shell.create();

        const { id } = await shell.runCommand(&quot;node&quot;, [&quot;index.js&quot;]);

        const { url } = await nodebox.preview.getByShellId(id);
        previewIframe.setAttribute(&quot;src&quot;, url);
    &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;"><pre class="notranslate"><span class="pl-c1">&lt;!DOCTYPE html<span class="pl-kos">&gt;</span></span>
<span class="pl-kos">&lt;</span><span class="pl-ent">html</span><span class="pl-kos">&gt;</span>
<span class="pl-kos">&lt;</span><span class="pl-ent">head</span><span class="pl-kos">&gt;</span>
    <span class="pl-kos">&lt;</span><span class="pl-ent">meta</span> <span class="pl-c1">name</span>="<span class="pl-s">description</span>" <span class="pl-c1">content</span>="" /&gt;
    <span class="pl-kos">&lt;</span><span class="pl-ent">meta</span> <span class="pl-c1">name</span>="<span class="pl-s">viewport</span>" <span class="pl-c1">content</span>="<span class="pl-s">width=device-width, initial-scale=1</span>" /&gt;
<span class="pl-kos">&lt;/</span><span class="pl-ent">head</span><span class="pl-kos">&gt;</span>
<span class="pl-kos">&lt;</span><span class="pl-ent">body</span><span class="pl-kos">&gt;</span>
    <span class="pl-kos">&lt;</span><span class="pl-ent">iframe</span> <span class="pl-c1">id</span>="<span class="pl-s">nodebox-iframe</span>"<span class="pl-kos">&gt;</span><span class="pl-kos">&lt;/</span><span class="pl-ent">iframe</span><span class="pl-kos">&gt;</span>
    <span class="pl-kos">&lt;</span><span class="pl-ent">iframe</span> <span class="pl-c1">id</span>="<span class="pl-s">preview-iframe</span>"<span class="pl-kos">&gt;</span><span class="pl-kos">&lt;/</span><span class="pl-ent">iframe</span><span class="pl-kos">&gt;</span>
    <span class="pl-kos">&lt;</span><span class="pl-ent">script</span> <span class="pl-c1">type</span>="<span class="pl-s">module</span>"<span class="pl-kos">&gt;</span>
        <span class="pl-k">import</span> <span class="pl-kos">{</span> <span class="pl-v">Nodebox</span> <span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">"https://cdn.jsdelivr.net/npm/@codesandbox/nodebox/build/index.min.mjs"</span><span class="pl-kos">;</span>

        <span class="pl-k">const</span> <span class="pl-s1">nodeboxIframe</span> <span class="pl-c1">=</span> <span class="pl-smi">document</span><span class="pl-kos">.</span><span class="pl-en">getElementById</span><span class="pl-kos">(</span><span class="pl-s">"nodebox-iframe"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">previewIframe</span> <span class="pl-c1">=</span> <span class="pl-smi">document</span><span class="pl-kos">.</span><span class="pl-en">getElementById</span><span class="pl-kos">(</span><span class="pl-s">"preview-iframe"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-k">const</span> <span class="pl-s1">nodebox</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Nodebox</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
            <span class="pl-s">"iframe"</span>: <span class="pl-s1">nodeboxIframe</span>
        <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-k">await</span> <span class="pl-s1">nodebox</span><span class="pl-kos">.</span><span class="pl-en">connect</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-k">await</span> <span class="pl-s1">nodebox</span><span class="pl-kos">.</span><span class="pl-c1">fs</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
            <span class="pl-s">"index.js"</span>: <span class="pl-s">`</span>
<span class="pl-s">// server.ts</span>
<span class="pl-s">import * as http from "http";</span>
<span class="pl-s"></span>
<span class="pl-s">// server.ts</span>
<span class="pl-s">var BASE_URL = "http://localhost:8000";</span>
<span class="pl-s">var router = {</span>
<span class="pl-s">  "/": function(request, response) {</span>
<span class="pl-s">    response.writeHead(200, { "Content-Type": "text/html" });</span>
<span class="pl-s">    response.end("OK");</span>
<span class="pl-s">  }</span>
<span class="pl-s">};</span>
<span class="pl-s">var server = http.createServer(function(request, response) {</span>
<span class="pl-s">  const startTime = performance.now();</span>
<span class="pl-s">  let status = 200;</span>
<span class="pl-s">  try {</span>
<span class="pl-s">    if (request.method === "GET" &amp;&amp; router[request.url] !== void 0) {</span>
<span class="pl-s">      router[request.url](request, response);</span>
<span class="pl-s">    } else {</span>
<span class="pl-s">      status = 404;</span>
<span class="pl-s">      response.writeHead(status, { "Content-Type": "text/plain" });</span>
<span class="pl-s">      response.end("File not found");</span>
<span class="pl-s">    }</span>
<span class="pl-s">  } catch (error) {</span>
<span class="pl-s">    status = 500;</span>
<span class="pl-s">    response.writeHead(status, { "Content-Type": "text/plain" });</span>
<span class="pl-s">    response.end("Internal server error");</span>
<span class="pl-s">  }</span>
<span class="pl-s">  response.on("finish", function() {</span>
<span class="pl-s">    console.log(request.method, request.url, status, (performance.now() - startTime).toFixed(3), "ms");</span>
<span class="pl-s">  });</span>
<span class="pl-s">});</span>
<span class="pl-s">server.listen(new URL(BASE_URL).port, function() {</span>
<span class="pl-s">  console.log("&gt; Ready on " + BASE_URL);</span>
<span class="pl-s">});</span>
<span class="pl-s">    `</span>
        <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-k">const</span> <span class="pl-s1">shell</span> <span class="pl-c1">=</span> <span class="pl-s1">nodebox</span><span class="pl-kos">.</span><span class="pl-c1">shell</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-k">const</span> <span class="pl-kos">{</span> id <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">shell</span><span class="pl-kos">.</span><span class="pl-en">runCommand</span><span class="pl-kos">(</span><span class="pl-s">"node"</span><span class="pl-kos">,</span> <span class="pl-kos">[</span><span class="pl-s">"index.js"</span><span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-k">const</span> <span class="pl-kos">{</span> url <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">nodebox</span><span class="pl-kos">.</span><span class="pl-c1">preview</span><span class="pl-kos">.</span><span class="pl-en">getByShellId</span><span class="pl-kos">(</span><span class="pl-s1">id</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">previewIframe</span><span class="pl-kos">.</span><span class="pl-en">setAttribute</span><span class="pl-kos">(</span><span class="pl-s">"src"</span><span class="pl-kos">,</span> <span class="pl-s1">url</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">&lt;/</span><span class="pl-ent">script</span><span class="pl-kos">&gt;</span>
<span class="pl-kos">&lt;/</span><span class="pl-ent">body</span><span class="pl-kos">&gt;</span>
<span class="pl-kos">&lt;/</span><span class="pl-ent">html</span><span class="pl-kos">&gt;</span></pre></div>
<p dir="auto"><code class="notranslate">package.json</code>:</p>
<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="{
  &quot;dependencies&quot;: {
    &quot;playwright-chromium&quot;: &quot;latest&quot;,
    &quot;ts-node&quot;: &quot;latest&quot;,
    &quot;typescript&quot;: &quot;latest&quot;
  },
  &quot;scripts&quot;: {
    &quot;start&quot;: &quot;node --experimental-specifier-resolution=node --loader=ts-node/esm script.ts&quot;
  }
}"><pre class="notranslate">{
  <span class="pl-ent">"dependencies"</span>: {
    <span class="pl-ent">"playwright-chromium"</span>: <span class="pl-s"><span class="pl-pds">"</span>latest<span class="pl-pds">"</span></span>,
    <span class="pl-ent">"ts-node"</span>: <span class="pl-s"><span class="pl-pds">"</span>latest<span class="pl-pds">"</span></span>,
    <span class="pl-ent">"typescript"</span>: <span class="pl-s"><span class="pl-pds">"</span>latest<span class="pl-pds">"</span></span>
  },
  <span class="pl-ent">"scripts"</span>: {
    <span class="pl-ent">"start"</span>: <span class="pl-s"><span class="pl-pds">"</span>node --experimental-specifier-resolution=node --loader=ts-node/esm script.ts<span class="pl-pds">"</span></span>
  }
}</pre></div>
<p dir="auto"><strong>Expected</strong></p>
<p dir="auto">Capture all network traffic, including:</p>
<ul dir="auto">
<li>requests originating from iframes,</li>
<li>nested iframes,</li>
<li>service workers</li>
</ul>
<p dir="auto"><strong>Actual</strong></p>
<p dir="auto">Output:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Saving ./playwright-issue/index.html as index.html
Saving https://cdn.jsdelivr.net/npm/@codesandbox/nodebox/build/index.min.mjs as index.min.mjs
Saving ./playwright-issue/index.html as index.html
Saving https://nodebox-runtime.codesandbox.io/ as index.html"><pre class="notranslate"><code class="notranslate">Saving ./playwright-issue/index.html as index.html
Saving https://cdn.jsdelivr.net/npm/@codesandbox/nodebox/build/index.min.mjs as index.min.mjs
Saving ./playwright-issue/index.html as index.html
Saving https://nodebox-runtime.codesandbox.io/ as index.html
</code></pre></div>
<p dir="auto">Less than what you would expect given a look at the network panel in the Chrome DevTools.</p>
<hr>
<p dir="auto">I'm going to compile some more of what I came across while researching this issue and what I tried below, but it seemed like this has been asked frequently enough with no particularly clear, working solution that I hope to at least document it better.</p>
<ul dir="auto">
<li>
<p dir="auto"><a href="https://stackoverflow.com/questions/70645680/does-chromium-support-intercept-webworker-requests-via-cdp" rel="nofollow">https://stackoverflow.com/questions/70645680/does-chromium-support-intercept-webworker-requests-via-cdp</a></p>
<blockquote>
<p dir="auto">After digging in puppeteer source code and tracing raw protocol messages, it seems that calling <code class="notranslate">page.setRequestInterception(true)</code> also intercepts WebWorker requests, but <strong>these requests never issue any <code class="notranslate">Network.requestWillBeSent</code> events</strong>, which is known as <code class="notranslate">page.request</code> events in puppeteer, then WebWorker requests hang for waiting for a <code class="notranslate">request.continue()</code> which is usually called in the <code class="notranslate">page.request</code> event handler.</p>
</blockquote>
</li>
</ul>
<p dir="auto">Mentions using <a href="https://chromedevtools.github.io/devtools-protocol/tot/Target/#event-attachedToTarget" rel="nofollow"><code class="notranslate">Target.attachedToTarget</code></a>.</p>
<ul dir="auto">
<li><a href="https://groups.google.com/a/chromium.org/g/chromium-extensions/c/3AnHiXwNO4o?pli=1" rel="nofollow">https://groups.google.com/a/chromium.org/g/chromium-extensions/c/3AnHiXwNO4o?pli=1</a></li>
</ul>
<p dir="auto">Someone experiencing the same issue. Notes that they tried sending <a href="https://chromedevtools.github.io/devtools-protocol/tot/Target/#method-setAutoAttach" rel="nofollow"><code class="notranslate">Target.setAutoAttach</code></a>, which didn't appear to change anything for me. Also notes that they couldn't get <a href="https://chromedevtools.github.io/devtools-protocol/tot/Target/#event-targetCreated" rel="nofollow"><code class="notranslate">Target.targetCreated</code></a> to fire, which I also encountered.</p>
<ul dir="auto">
<li><a href="https://stackoverflow.com/questions/63357370/capture-requests-xhr-js-css-from-embedded-iframes-using-devtool-protocol" rel="nofollow">https://stackoverflow.com/questions/63357370/capture-requests-xhr-js-css-from-embedded-iframes-using-devtool-protocol</a></li>
</ul>
<p dir="auto">Issue could be worked around by using the <code class="notranslate">--disable-features</code> flag. Linked resources also talks about how <a href="https://groups.google.com/g/chrome-debugging-protocol/c/n1FQ4Ypww6w" rel="nofollow"><code class="notranslate">setAutoAttach</code> shouldn't be relied on</a>.</p>
<ul dir="auto">
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="334252168" data-permission-text="Title is private" data-url="https://github.com/puppeteer/puppeteer/issues/2781" data-hovercard-type="issue" data-hovercard-url="/puppeteer/puppeteer/issues/2781/hovercard?comment_id=513045753&amp;comment_type=issue_comment" href="https://github.com/puppeteer/puppeteer/issues/2781#issuecomment-513045753">puppeteer/puppeteer#2781 (comment)</a></li>
</ul>
<p dir="auto">This is what my current code is based on, although I couldn't get <code class="notranslate">browser.on('targetcreated')</code> to fire. <a href="https://github.com/puppeteer/puppeteer/issues/2781#issuecomment-942001514" data-hovercard-type="issue" data-hovercard-url="/puppeteer/puppeteer/issues/2781/hovercard">Someone towards the bottom mentions <code class="notranslate">serviceWorkerTarget.setRequestInterception</code></a>.</p>
<ul dir="auto">
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1305349954" data-permission-text="Title is private" data-url="https://github.com/microsoft/playwright/issues/15684" data-hovercard-type="issue" data-hovercard-url="/microsoft/playwright/issues/15684/hovercard" href="https://github.com/microsoft/playwright/issues/15684">#15684</a></li>
</ul>
<blockquote>
<p dir="auto">Currently, Playwright supports an experimental feature to inspect and route Network traffic made by Service Workers (in Chrome / Chromium). To learn more and enable, please read: <a href="https://playwright.dev/docs/service-workers-experimental" rel="nofollow">https://playwright.dev/docs/service-workers-experimental</a>.</p>
</blockquote>
<p dir="auto">Looks like there is some <a href="https://playwright.dev/docs/service-workers-experimental" rel="nofollow">experimental Service Worker</a>-specific network events that I could enable.</p>
<ul dir="auto">
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="570117009" data-permission-text="Title is private" data-url="https://github.com/microsoft/playwright/issues/1090" data-hovercard-type="issue" data-hovercard-url="/microsoft/playwright/issues/1090/hovercard?comment_id=1192893661&amp;comment_type=issue_comment" href="https://github.com/microsoft/playwright/issues/1090#issuecomment-1192893661">#1090 (comment)</a></li>
</ul>
<p dir="auto">Further confirmation that I should be using the <a href="https://playwright.dev/docs/service-workers-experimental" rel="nofollow">experimental Service Worker</a>-specific network events (<a href="https://playwright.dev/docs/network#missing-network-events-and-service-workers" rel="nofollow">this section in particular</a>).</p>
<ul dir="auto">
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="390860655" data-permission-text="Title is private" data-url="https://github.com/puppeteer/puppeteer/issues/3667" data-hovercard-type="issue" data-hovercard-url="/puppeteer/puppeteer/issues/3667/hovercard?comment_id=611477600&amp;comment_type=issue_comment" href="https://github.com/puppeteer/puppeteer/issues/3667#issuecomment-611477600">puppeteer/puppeteer#3667 (comment)</a></li>
</ul>
<blockquote>
<p dir="auto">Playwright seems to have worked around this/provided a fix: <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="575927512" data-permission-text="Title is private" data-url="https://github.com/microsoft/playwright/issues/1226" data-hovercard-type="pull_request" data-hovercard-url="/microsoft/playwright/pull/1226/hovercard" href="https://github.com/microsoft/playwright/pull/1226">#1226</a></p>
</blockquote>
<p dir="auto">Something about iframes and auto-attaching? It sounds like with this PR, frames should auto-attach. The PR talks about frames as being popups, but surely it should apply to anything that creates a new frame.</p>
<ul dir="auto">
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1380203602" data-permission-text="Title is private" data-url="https://github.com/puppeteer/puppeteer/issues/8991" data-hovercard-type="issue" data-hovercard-url="/puppeteer/puppeteer/issues/8991/hovercard" href="https://github.com/puppeteer/puppeteer/issues/8991">puppeteer/puppeteer#8991</a></li>
</ul>
<p dir="auto">Another suggestion to use <code class="notranslate">setRequestInterception</code>, which is deprecated and suggests you use <code class="notranslate">Fetch.enable</code> instead. I don't fully understand how I would programmatically attach to all of the frames.</p>
<p dir="auto">That's everything that seems relevant.</p>