<h3 dir="auto">System info</h3>
<ul dir="auto">
<li>Playwright Version: v1.31.0</li>
<li>Operating System: macOS 13.2.1 Chip Apple M2</li>
<li>Browser: Chromium</li>
<li>Other info:</li>
</ul>
<h3 dir="auto">Source code</h3>
<p dir="auto"><strong>Playwright Server:</strong></p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import * as playwright from &quot;playwright&quot;;

export type BrowserTypes = &quot;chromium&quot; | &quot;firefox&quot; | &quot;webkit&quot;;

export const launchOptions: playwright.LaunchOptions = {};
const chromiumDefaultArgs = [
  &quot;--disable-gpu&quot;,
  &quot;--disable-dev-shm-usage&quot;,
  &quot;--disable-setuid-sandbox&quot;,
  &quot;--no-sandbox&quot;,
  &quot;--no-zygote&quot;,
  &quot;--single-process&quot;,
];

const getLaunchOptions = (browser: BrowserTypes): playwright.LaunchOptions =&gt; {
  let newLaunchOptions = {
    ...launchOptions,
  };
  if (browser === &quot;chromium&quot;) {
    newLaunchOptions = {
      ...newLaunchOptions,
      args: [
        ...(launchOptions.args ? launchOptions.args : []),
        ...chromiumDefaultArgs,
      ],
    };
  }

  return newLaunchOptions;
};

interface BrowserInstance {
  [endPoint: string]: {
    server: playwright.BrowserServer;
    timer?: any;
    browser: string;
    guid: string;
  };
}

class BrowserServer {
  instances: BrowserInstance = {};

  async launchServer(
    browser: BrowserTypes,
    socket: net.Socket
  ): Promise&lt;playwright.BrowserServer&gt; {
    const server = await playwright[browser].launchServer(
      getLaunchOptions(browser)
    );

    if (!server) {
      return null;
    }

    const endPoint = server.wsEndpoint();

    const guid = /((\w{4,12}-?)){5}/.exec(endPoint)[0];

    this.instances[endPoint] = {
      server,
      browser,
      guid,
    };

    socket.on(&quot;error&quot;, (err: any) =&gt; {
      console.log(`ERROR: ${browser} - ${endPoint}`);
      console.error(err);
    });

    socket.on(&quot;end&quot;, () =&gt; {
      console.log(&quot;Socket ended successfully&quot;);
    });

    socket.on(&quot;close&quot;, async () =&gt; {
      await this.kill(server);
    });

    const timeout =
      process.env[BROWSER_SERVER_TIMEOUT] &amp;&amp;
      Number.parseInt(process.env[BROWSER_SERVER_TIMEOUT]);

    if (timeout) {
      console.log(`Browser will close in ${timeout} seconds`);
    }

    return server;
  }

  getWsEndPoint(server: playwright.BrowserServer): string {
    return server.wsEndpoint();
  }

  async killAll(): Promise&lt;void&gt; {
    const { instances } = this;

    for (const key in instances) {
      const info = instances[key];
      await this.kill(info.server);
    }
  }

  async kill(server: playwright.BrowserServer): Promise&lt;void&gt; {
    const endPoint = server.wsEndpoint();

    //   If instance is undefined then its already in the process of terminating.
    if (!this.instances[endPoint]) {
      return;
    }

    const { browser, guid } = this.instances[endPoint];
    clearTimeout(this.instances[endPoint].timer);
    console.log(`Terminating ${browser} (${guid})...`);
    delete this.instances[endPoint];
    await server.close();
    console.log(`${browser} terminiated (${guid}).`);
  }
}

export default BrowserServer;"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-c1">*</span> <span class="pl-k">as</span> <span class="pl-s1">playwright</span> <span class="pl-k">from</span> <span class="pl-s">"playwright"</span><span class="pl-kos">;</span>

<span class="pl-k">export</span> <span class="pl-s1">type</span> <span class="pl-v">BrowserTypes</span> <span class="pl-c1">=</span> <span class="pl-s">"chromium"</span> <span class="pl-c1">|</span> <span class="pl-s">"firefox"</span> <span class="pl-c1">|</span> <span class="pl-s">"webkit"</span><span class="pl-kos">;</span>

export <span class="pl-k">const</span> <span class="pl-s1">launchOptions</span>: <span class="pl-s1">playwright</span><span class="pl-kos">.</span><span class="pl-c1">LaunchOptions</span> <span class="pl-c1">=</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">chromiumDefaultArgs</span> <span class="pl-c1">=</span> <span class="pl-kos">[</span>
  <span class="pl-s">"--disable-gpu"</span><span class="pl-kos">,</span>
  <span class="pl-s">"--disable-dev-shm-usage"</span><span class="pl-kos">,</span>
  <span class="pl-s">"--disable-setuid-sandbox"</span><span class="pl-kos">,</span>
  <span class="pl-s">"--no-sandbox"</span><span class="pl-kos">,</span>
  <span class="pl-s">"--no-zygote"</span><span class="pl-kos">,</span>
  <span class="pl-s">"--single-process"</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">getLaunchOptions</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-s1">browser</span>: <span class="pl-v">BrowserTypes</span><span class="pl-kos">)</span>: <span class="pl-s1">playwright</span><span class="pl-kos">.</span><span class="pl-c1">LaunchOptions</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">let</span> <span class="pl-s1">newLaunchOptions</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
    ...<span class="pl-s1">launchOptions</span><span class="pl-kos">,</span>
  <span class="pl-kos">}</span><span class="pl-kos">;</span>
  <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">browser</span> <span class="pl-c1">===</span> <span class="pl-s">"chromium"</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-s1">newLaunchOptions</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
      ...<span class="pl-s1">newLaunchOptions</span><span class="pl-kos">,</span>
      <span class="pl-c1">args</span>: <span class="pl-kos">[</span>
        ...<span class="pl-kos">(</span><span class="pl-s1">launchOptions</span><span class="pl-kos">.</span><span class="pl-c1">args</span> ? <span class="pl-s1">launchOptions</span><span class="pl-kos">.</span><span class="pl-c1">args</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">chromiumDefaultArgs</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">return</span> <span class="pl-s1">newLaunchOptions</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-s1">interface</span> <span class="pl-v">BrowserInstance</span> <span class="pl-kos">{</span>
  <span class="pl-kos">[</span><span class="pl-s1">endPoint</span>: <span class="pl-s1">string</span><span class="pl-kos">]</span>: <span class="pl-kos">{</span>
    server: <span class="pl-s1">playwright</span><span class="pl-kos">.</span><span class="pl-c1">BrowserServer</span><span class="pl-kos">;</span>
    <span class="pl-s1">timer</span>?<span class="pl-s1"></span>: <span class="pl-s1">any</span><span class="pl-kos">;</span>
    browser: <span class="pl-s1">string</span><span class="pl-kos">;</span>
    guid: <span class="pl-s1">string</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">class</span> <span class="pl-v">BrowserServer</span> <span class="pl-kos">{</span>
  <span class="pl-c1">instances</span>: <span class="pl-c1">BrowserInstance</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

  <span class="pl-k">async</span> <span class="pl-en">launchServer</span><span class="pl-kos">(</span>
    <span class="pl-s1">browser</span>: <span class="pl-v">BrowserTypes</span><span class="pl-kos">,</span>
    <span class="pl-s1">socket</span>: <span class="pl-s1">net</span><span class="pl-kos">.</span><span class="pl-v">Socket</span>
  <span class="pl-kos">)</span>: <span class="pl-v">Promise</span><span class="pl-c1">&lt;</span><span class="pl-s1">playwright</span><span class="pl-kos">.</span><span class="pl-v">BrowserServer</span><span class="pl-c1">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">const</span> <span class="pl-s1">server</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">playwright</span><span class="pl-kos">[</span><span class="pl-s1">browser</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-en">launchServer</span><span class="pl-kos">(</span>
      <span class="pl-s1">getLaunchOptions</span><span class="pl-kos">(</span><span class="pl-s1">browser</span><span class="pl-kos">)</span>
    <span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-c1">!</span><span class="pl-s1">server</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">return</span> <span class="pl-c1">null</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>

    <span class="pl-k">const</span> <span class="pl-s1">endPoint</span> <span class="pl-c1">=</span> <span class="pl-s1">server</span><span class="pl-kos">.</span><span class="pl-en">wsEndpoint</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">guid</span> <span class="pl-c1">=</span> <span class="pl-pds"><span class="pl-c1">/</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-cce">\w</span><span class="pl-kos">{</span>4,12<span class="pl-kos">}</span>-?<span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">{</span>5<span class="pl-kos">}</span><span class="pl-c1">/</span></span><span class="pl-kos">.</span><span class="pl-en">exec</span><span class="pl-kos">(</span><span class="pl-s1">endPoint</span><span class="pl-kos">)</span><span class="pl-kos">[</span><span class="pl-c1">0</span><span class="pl-kos">]</span><span class="pl-kos">;</span>

    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">instances</span><span class="pl-kos">[</span><span class="pl-s1">endPoint</span><span class="pl-kos">]</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
      server<span class="pl-kos">,</span>
      browser<span class="pl-kos">,</span>
      guid<span class="pl-kos">,</span>
    <span class="pl-kos">}</span><span class="pl-kos">;</span>

    <span class="pl-s1">socket</span><span class="pl-kos">.</span><span class="pl-en">on</span><span class="pl-kos">(</span><span class="pl-s">"error"</span><span class="pl-kos">,</span> <span class="pl-kos">(</span><span class="pl-s1">err</span>: <span class="pl-s1">any</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</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">`ERROR: <span class="pl-s1"><span class="pl-kos">${</span><span class="pl-s1">browser</span><span class="pl-kos">}</span></span> - <span class="pl-s1"><span class="pl-kos">${</span><span class="pl-s1">endPoint</span><span class="pl-kos">}</span></span>`</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-s1">err</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">socket</span><span class="pl-kos">.</span><span class="pl-en">on</span><span class="pl-kos">(</span><span class="pl-s">"end"</span><span class="pl-kos">,</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</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">"Socket ended successfully"</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">socket</span><span class="pl-kos">.</span><span class="pl-en">on</span><span class="pl-kos">(</span><span class="pl-s">"close"</span><span class="pl-kos">,</span> <span class="pl-k">async</span> <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">await</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">kill</span><span class="pl-kos">(</span><span class="pl-s1">server</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">const</span> <span class="pl-s1">timeout</span> <span class="pl-c1">=</span>
      <span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">[</span><span class="pl-c1">BROWSER_SERVER_TIMEOUT</span><span class="pl-kos">]</span> <span class="pl-c1">&amp;&amp;</span>
      <span class="pl-v">Number</span><span class="pl-kos">.</span><span class="pl-en">parseInt</span><span class="pl-kos">(</span><span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">[</span><span class="pl-c1">BROWSER_SERVER_TIMEOUT</span><span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">timeout</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">`Browser will close in <span class="pl-s1"><span class="pl-kos">${</span><span class="pl-s1">timeout</span><span class="pl-kos">}</span></span> seconds`</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>

    <span class="pl-k">return</span> <span class="pl-s1">server</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>

  <span class="pl-en">getWsEndPoint</span><span class="pl-kos">(</span><span class="pl-s1">server</span>: <span class="pl-s1">playwright</span><span class="pl-kos">.</span><span class="pl-v">BrowserServer</span><span class="pl-kos">)</span>: <span class="pl-s1">string</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-s1">server</span><span class="pl-kos">.</span><span class="pl-en">wsEndpoint</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">async</span> <span class="pl-en">killAll</span><span class="pl-kos">(</span><span class="pl-kos">)</span>: <span class="pl-v">Promise</span><span class="pl-c1">&lt;</span><span class="pl-k">void</span><span class="pl-c1">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">const</span> <span class="pl-kos">{</span> instances <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">;</span>

    <span class="pl-k">for</span> <span class="pl-kos">(</span><span class="pl-k">const</span> <span class="pl-s1">key</span> <span class="pl-k">in</span> <span class="pl-s1">instances</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">const</span> <span class="pl-s1">info</span> <span class="pl-c1">=</span> <span class="pl-s1">instances</span><span class="pl-kos">[</span><span class="pl-s1">key</span><span class="pl-kos">]</span><span class="pl-kos">;</span>
      <span class="pl-k">await</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">kill</span><span class="pl-kos">(</span><span class="pl-s1">info</span><span class="pl-kos">.</span><span class="pl-c1">server</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">async</span> <span class="pl-en">kill</span><span class="pl-kos">(</span><span class="pl-s1">server</span>: <span class="pl-s1">playwright</span><span class="pl-kos">.</span><span class="pl-v">BrowserServer</span><span class="pl-kos">)</span>: <span class="pl-v">Promise</span><span class="pl-c1">&lt;</span><span class="pl-k">void</span><span class="pl-c1">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">const</span> <span class="pl-s1">endPoint</span> <span class="pl-c1">=</span> <span class="pl-s1">server</span><span class="pl-kos">.</span><span class="pl-en">wsEndpoint</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-c">//   If instance is undefined then its already in the process of terminating.</span>
    <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-c1">!</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">instances</span><span class="pl-kos">[</span><span class="pl-s1">endPoint</span><span class="pl-kos">]</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">return</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>

    <span class="pl-k">const</span> <span class="pl-kos">{</span> browser<span class="pl-kos">,</span> guid <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">instances</span><span class="pl-kos">[</span><span class="pl-s1">endPoint</span><span class="pl-kos">]</span><span class="pl-kos">;</span>
    <span class="pl-en">clearTimeout</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">instances</span><span class="pl-kos">[</span><span class="pl-s1">endPoint</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-c1">timer</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">`Terminating <span class="pl-s1"><span class="pl-kos">${</span><span class="pl-s1">browser</span><span class="pl-kos">}</span></span> (<span class="pl-s1"><span class="pl-kos">${</span><span class="pl-s1">guid</span><span class="pl-kos">}</span></span>)...`</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">delete</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">instances</span><span class="pl-kos">[</span><span class="pl-s1">endPoint</span><span class="pl-kos">]</span><span class="pl-kos">;</span>
    <span class="pl-k">await</span> <span class="pl-s1">server</span><span class="pl-kos">.</span><span class="pl-en">close</span><span class="pl-kos">(</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">`<span class="pl-s1"><span class="pl-kos">${</span><span class="pl-s1">browser</span><span class="pl-kos">}</span></span> terminiated (<span class="pl-s1"><span class="pl-kos">${</span><span class="pl-s1">guid</span><span class="pl-kos">}</span></span>).`</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">export</span> <span class="pl-k">default</span> <span class="pl-v">BrowserServer</span><span class="pl-kos">;</span></pre></div>
<hr>
<p dir="auto"><strong>Docker Server: some-registry/playwright-server:latest</strong></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="FROM mcr.microsoft.com/playwright:v1.31.0-focal

ENV NODE_ENV=production

# Run everything after as non-privileged user.
USER pwuser

ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1

ARG NPM_LOGLEVEL=info

# Create app directory
WORKDIR /home/pwuser

COPY package.json .

RUN npm install --loglevel ${NPM_LOGLEVEL} --force

COPY . .

CMD [&quot;node&quot;, &quot;build/src/main.js&quot;]

EXPOSE 3000/tcp
EXPOSE 5000/tcp"><pre class="notranslate"><code class="notranslate">FROM mcr.microsoft.com/playwright:v1.31.0-focal

ENV NODE_ENV=production

# Run everything after as non-privileged user.
USER pwuser

ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1

ARG NPM_LOGLEVEL=info

# Create app directory
WORKDIR /home/pwuser

COPY package.json .

RUN npm install --loglevel ${NPM_LOGLEVEL} --force

COPY . .

CMD ["node", "build/src/main.js"]

EXPOSE 3000/tcp
EXPOSE 5000/tcp
</code></pre></div>




<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 { Page } from &quot;playwright-core&quot;;
import { expect, PlaywrightTestConfig, devices } from &quot;@playwright/test&quot;;

const config: PlaywrightTestConfig = {
  globalSetup: require.resolve(&quot;./playwright.global-setup&quot;),
  forbidOnly: !!process.env.CI,
  timeout: 50000,
  testMatch: /.*\.spec\.ts/,
  testDir: &quot;../../packages&quot;,
  outputDir: &quot;./test-results&quot;,
  retries: process.env.CI ? 2 : 0,
  reporter: [[&quot;html&quot;, { open: &quot;never&quot; }], process.env.CI ? [&quot;dot&quot;] : [&quot;list&quot;]],
  webServer: [
    {
      command: &quot;npm run serve&quot;,
      port: 5000,
      timeout: 50000,
      reuseExistingServer: !process.env.CI
    },
    {
      command:
        &quot;podman run --rm -p 3000:3000 some-registry/playwright-server:latest&quot;,
      port: 3000,
      timeout: 50000,
      reuseExistingServer: !process.env.CI
    }
  ],
  use: {
    baseURL: process.env.IP_ADDRESS || &quot;http://localhost:5000/&quot;,
    locale: &quot;en-GB&quot;,
    trace: &quot;on-first-retry&quot;,
    screenshot: &quot;only-on-failure&quot;,
    connectOptions: {
      wsEndpoint: &quot;ws://127.0.0.1:3000/&quot;
    }
  },
  expect: {
    toHaveScreenshot: { maxDiffPixels: 10 }
  },
  projects: [
    {
       name: &quot;chromium&quot;,
       use: {
         ...devices[&quot;Desktop Chrome&quot;],
         viewport: { width: 1280, height: 1024 }
       }
    }
  ]
};

export default config;
"><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-v">Page</span> <span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">"playwright-core"</span><span class="pl-kos">;</span>
<span class="pl-k">import</span> <span class="pl-kos">{</span> <span class="pl-s1">expect</span><span class="pl-kos">,</span> <span class="pl-v">PlaywrightTestConfig</span><span class="pl-kos">,</span> <span class="pl-s1">devices</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">const</span> <span class="pl-s1">config</span>: <span class="pl-v">PlaywrightTestConfig</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
  <span class="pl-c1">globalSetup</span>: <span class="pl-en">require</span><span class="pl-kos">.</span><span class="pl-en">resolve</span><span class="pl-kos">(</span><span class="pl-s">"./playwright.global-setup"</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
  <span class="pl-c1">forbidOnly</span>: <span class="pl-c1">!</span><span class="pl-c1">!</span><span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">.</span><span class="pl-c1">CI</span><span class="pl-kos">,</span>
  <span class="pl-c1">timeout</span>: <span class="pl-c1">50000</span><span class="pl-kos">,</span>
  <span class="pl-c1">testMatch</span>: <span class="pl-pds"><span class="pl-c1">/</span>.<span class="pl-c1">*</span><span class="pl-cce">\.</span>spec<span class="pl-cce">\.</span>ts<span class="pl-c1">/</span></span><span class="pl-kos">,</span>
  <span class="pl-c1">testDir</span>: <span class="pl-s">"../../packages"</span><span class="pl-kos">,</span>
  <span class="pl-c1">outputDir</span>: <span class="pl-s">"./test-results"</span><span class="pl-kos">,</span>
  <span class="pl-c1">retries</span>: <span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">.</span><span class="pl-c1">CI</span> ? <span class="pl-c1">2</span> : <span class="pl-c1">0</span><span class="pl-kos">,</span>
  <span class="pl-c1">reporter</span>: <span class="pl-kos">[</span><span class="pl-kos">[</span><span class="pl-s">"html"</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">open</span>: <span class="pl-s">"never"</span> <span class="pl-kos">}</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">.</span><span class="pl-c1">CI</span> ? <span class="pl-kos">[</span><span class="pl-s">"dot"</span><span class="pl-kos">]</span> : <span class="pl-kos">[</span><span class="pl-s">"list"</span><span class="pl-kos">]</span><span class="pl-kos">]</span><span class="pl-kos">,</span>
  <span class="pl-c1">webServer</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span>
      <span class="pl-c1">command</span>: <span class="pl-s">"npm run serve"</span><span class="pl-kos">,</span>
      <span class="pl-c1">port</span>: <span class="pl-c1">5000</span><span class="pl-kos">,</span>
      <span class="pl-c1">timeout</span>: <span class="pl-c1">50000</span><span class="pl-kos">,</span>
      <span class="pl-c1">reuseExistingServer</span>: <span class="pl-c1">!</span><span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">.</span><span class="pl-c1">CI</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span>
      <span class="pl-c1">command</span>:
        <span class="pl-s">"podman run --rm -p 3000:3000 some-registry/playwright-server:latest"</span><span class="pl-kos">,</span>
      <span class="pl-c1">port</span>: <span class="pl-c1">3000</span><span class="pl-kos">,</span>
      <span class="pl-c1">timeout</span>: <span class="pl-c1">50000</span><span class="pl-kos">,</span>
      <span class="pl-c1">reuseExistingServer</span>: <span class="pl-c1">!</span><span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">.</span><span class="pl-c1">CI</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">]</span><span class="pl-kos">,</span>
  <span class="pl-c1">use</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">baseURL</span>: <span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">.</span><span class="pl-c1">IP_ADDRESS</span> <span class="pl-c1">||</span> <span class="pl-s">"http://localhost:5000/"</span><span class="pl-kos">,</span>
    <span class="pl-c1">locale</span>: <span class="pl-s">"en-GB"</span><span class="pl-kos">,</span>
    <span class="pl-c1">trace</span>: <span class="pl-s">"on-first-retry"</span><span class="pl-kos">,</span>
    <span class="pl-c1">screenshot</span>: <span class="pl-s">"only-on-failure"</span><span class="pl-kos">,</span>
    <span class="pl-c1">connectOptions</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">wsEndpoint</span>: <span class="pl-s">"ws://127.0.0.1:3000/"</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">expect</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">toHaveScreenshot</span>: <span class="pl-kos">{</span> <span class="pl-c1">maxDiffPixels</span>: <span class="pl-c1">10</span> <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">projects</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span>
       <span class="pl-c1">name</span>: <span class="pl-s">"chromium"</span><span class="pl-kos">,</span>
       <span class="pl-c1">use</span>: <span class="pl-kos">{</span>
         ...<span class="pl-s1">devices</span><span class="pl-kos">[</span><span class="pl-s">"Desktop Chrome"</span><span class="pl-kos">]</span><span class="pl-kos">,</span>
         <span class="pl-c1">viewport</span>: <span class="pl-kos">{</span> <span class="pl-c1">width</span>: <span class="pl-c1">1280</span><span class="pl-kos">,</span> <span class="pl-c1">height</span>: <span class="pl-c1">1024</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">export</span> <span class="pl-k">default</span> <span class="pl-s1">config</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="import { test, expect } from &quot;@playwright/test&quot;;

test.describe(&quot;@component&quot;, () =&gt; {
  test(&quot;should render my component correctly&quot;, async ({ page }) =&gt; {
    await page.goto(`/path/my-component/`);
    await page.waitForSelector(&quot;#test-container&quot;);
    await expect(page).toHaveScreenshot();
  });
});"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-kos">{</span> <span class="pl-s1">test</span><span class="pl-kos">,</span> <span class="pl-s1">expect</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-s1">test</span><span class="pl-kos">.</span><span class="pl-en">describe</span><span class="pl-kos">(</span><span class="pl-s">"@component"</span><span class="pl-kos">,</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-en">test</span><span class="pl-kos">(</span><span class="pl-s">"should render my component correctly"</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-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-s">`/path/my-component/`</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">waitForSelector</span><span class="pl-kos">(</span><span class="pl-s">"#test-container"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">await</span> <span class="pl-en">expect</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-en">toHaveScreenshot</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-kos">;</span></pre></div>
<p dir="auto"><strong>Steps</strong></p>
<ul dir="auto">
<li>Run the test <code class="notranslate">playwright test --update-snapshots --grep @component</code></li>
</ul>
<p dir="auto"><strong>Expected</strong><br>
No error while running chromium</p>
<p dir="auto"><strong>Actual</strong></p>
<p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/7147528/222090709-dcad7d9e-1c3e-4b3b-a01e-07b136f4319b.png"><img width="1421" alt="Screenshot 2023-03-01 at 09 54 21" src="https://user-images.githubusercontent.com/7147528/222090709-dcad7d9e-1c3e-4b3b-a01e-07b136f4319b.png" style="max-width: 100%;"></a></p>
<p dir="auto">I've been trying different chromium args but no luck. Before the Macbook M1 device, I was able to run the same setup with the following chromium args.</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="const chromiumDefaultArgs = [&quot;--disable-dev-shm-usage&quot;, &quot;--no-sandbox&quot;];"><pre class="notranslate"><span class="pl-k">const</span> <span class="pl-s1">chromiumDefaultArgs</span> <span class="pl-c1">=</span> <span class="pl-kos">[</span><span class="pl-s">"--disable-dev-shm-usage"</span><span class="pl-kos">,</span> <span class="pl-s">"--no-sandbox"</span><span class="pl-kos">]</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">After changing to Macbook M1 device, the same setup failed and I've tried different args (see below). I was able to run tests in Firefox successfully  but not in Chromium.</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="const chromiumDefaultArgs = [
  &quot;--disable-gpu&quot;,
  &quot;--disable-dev-shm-usage&quot;,
  &quot;--disable-setuid-sandbox&quot;,
  &quot;--no-sandbox&quot;,
  &quot;--no-zygote&quot;,
  &quot;--single-process&quot;,
];"><pre class="notranslate"><span class="pl-k">const</span> <span class="pl-s1">chromiumDefaultArgs</span> <span class="pl-c1">=</span> <span class="pl-kos">[</span>
  <span class="pl-s">"--disable-gpu"</span><span class="pl-kos">,</span>
  <span class="pl-s">"--disable-dev-shm-usage"</span><span class="pl-kos">,</span>
  <span class="pl-s">"--disable-setuid-sandbox"</span><span class="pl-kos">,</span>
  <span class="pl-s">"--no-sandbox"</span><span class="pl-kos">,</span>
  <span class="pl-s">"--no-zygote"</span><span class="pl-kos">,</span>
  <span class="pl-s">"--single-process"</span><span class="pl-kos">,</span>
<span class="pl-kos">]</span><span class="pl-kos">;</span></pre></div>
<h3 dir="auto">System info</h3>
<ul dir="auto">
<li>Playwright Version: [v1.32.2]</li>
<li>Operating System: [Windows 10]</li>
<li>Browser: [Firefox]</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, devices } from '@playwright/test';

export default defineConfig({
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'], },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
});"><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-s1">devices</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">projects</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span>
      <span class="pl-c1">name</span>: <span class="pl-s">'chromium'</span><span class="pl-kos">,</span>
      <span class="pl-c1">use</span>: <span class="pl-kos">{</span> ...<span class="pl-s1">devices</span><span class="pl-kos">[</span><span class="pl-s">'Desktop Chrome'</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-c1">name</span>: <span class="pl-s">'firefox'</span><span class="pl-kos">,</span>
      <span class="pl-c1">use</span>: <span class="pl-kos">{</span> ...<span class="pl-s1">devices</span><span class="pl-kos">[</span><span class="pl-s">'Desktop Firefox'</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-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="import * as sysPath from &quot;node:path&quot;;
import { test, expect } from &quot;@playwright/test&quot;;

test('should support exposeBinding/addInitScript/addScriptTag in dynamic iframes', async function({ page, browser }) {
    await page.exposeBinding(&quot;intercept&quot;, ({ page, frame }, value) =&gt; {
        console.log(&quot;intercepted&quot;, value);
    });

    await page.context().addInitScript(() =&gt; window['bar'] = 17);
    await page.addInitScript(() =&gt; window['foo'] = 42);
    await page.addInitScript(() =&gt; window['intercepted'] = typeof window.intercept === 'function');

    let ready = () =&gt; {};
    let iframes = 0;

    console.log(&quot;start&quot;);

    page.on(&quot;frameattached&quot;, frame =&gt; {
        // TEST : url is always empty
        console.log(&quot;frameattached %i, url [%s]&quot;, ++iframes, frame.url());

        frame.addScriptTag({ content: `window['baz'] = 54` }).then(async script =&gt; {
            // TEST : url is good on chromium
            // TEST : url is good on firefox when the page is a local server
            // TEST : url is empty on firefox when the page is a local file or a private website
            console.log(&quot;addScriptTag, url [%s]&quot;, frame.url());

            expect(await frame.evaluate(() =&gt; window['foo'])).toBe(42);
            expect(await frame.evaluate(() =&gt; window['bar'])).toBe(17);
            expect(await frame.evaluate(() =&gt; window['intercepted'])).toBe(true);
            expect(await frame.evaluate(() =&gt; window['baz'])).toBe(54);
        }, err =&gt; {
            // iframes are purposely detached
            // ignore detached frames
        });
    });

    page.on(&quot;framedetached&quot;, frame =&gt; {
        // TEST : url is always empty
        console.log(&quot;framedetached %i, url [%s]&quot;, --iframes, frame.url());
        if (iframes === 1) {
            ready();
        }
    });

    await page.goto(sysPath.join(__dirname, 'dynamic-oopif.html'));
    // await page.goto('http://127.0.0.1:3000/dynamic-oopif.html');

    console.log(&quot;wait for ready&quot;);

    await new Promise((resolve, reject) =&gt; {
        ready = resolve;
    });

    await page.waitForTimeout(1000);

    console.log(&quot;ready&quot;);

    expect(page.frames().length).toBe(2);

    // TEST : url is good on chromium
    // TEST : url is good on firefox when the page is a local server
    // TEST : url is empty on firefox when the page is a local file or a private website
    console.log(&quot;iframe, url [%s]&quot;, page.frames()[1].url());

    expect(await page.frames()[0].evaluate(() =&gt; window['foo'])).toBe(42);
    expect(await page.frames()[1].evaluate(() =&gt; window['foo'])).toBe(42);
    expect(await page.frames()[0].evaluate(() =&gt; window['bar'])).toBe(17);
    expect(await page.frames()[1].evaluate(() =&gt; window['bar'])).toBe(17);
    expect(await page.frames()[0].evaluate(() =&gt; window['intercepted'])).toBe(true);
    expect(await page.frames()[1].evaluate(() =&gt; window['intercepted'])).toBe(true);

    // TEST : pass on chromium
    // TEST : pass on firefox if the server is a local server
    // TEST : fail on firefox if the server is a local file or a private website
    expect(await page.frames()[1].evaluate(() =&gt; window['baz'])).toBe(54);
});"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-c1">*</span> <span class="pl-k">as</span> <span class="pl-s1">sysPath</span> <span class="pl-k">from</span> <span class="pl-s">"node:path"</span><span class="pl-kos">;</span>
<span class="pl-k">import</span> <span class="pl-kos">{</span> <span class="pl-s1">test</span><span class="pl-kos">,</span> <span class="pl-s1">expect</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-en">test</span><span class="pl-kos">(</span><span class="pl-s">'should support exposeBinding/addInitScript/addScriptTag in dynamic iframes'</span><span class="pl-kos">,</span> <span class="pl-k">async</span> <span class="pl-k">function</span><span class="pl-kos">(</span><span class="pl-kos">{</span> page<span class="pl-kos">,</span> browser <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">page</span><span class="pl-kos">.</span><span class="pl-en">exposeBinding</span><span class="pl-kos">(</span><span class="pl-s">"intercept"</span><span class="pl-kos">,</span> <span class="pl-kos">(</span><span class="pl-kos">{</span> page<span class="pl-kos">,</span> frame <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-s1">value</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</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">"intercepted"</span><span class="pl-kos">,</span> <span class="pl-s1">value</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">await</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-en">addInitScript</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">window</span><span class="pl-kos">[</span><span class="pl-s">'bar'</span><span class="pl-kos">]</span> <span class="pl-c1">=</span> <span class="pl-c1">17</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">addInitScript</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">window</span><span class="pl-kos">[</span><span class="pl-s">'foo'</span><span class="pl-kos">]</span> <span class="pl-c1">=</span> <span class="pl-c1">42</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">addInitScript</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">window</span><span class="pl-kos">[</span><span class="pl-s">'intercepted'</span><span class="pl-kos">]</span> <span class="pl-c1">=</span> <span class="pl-k">typeof</span> <span class="pl-smi">window</span><span class="pl-kos">.</span><span class="pl-c1">intercept</span> <span class="pl-c1">===</span> <span class="pl-s">'function'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-k">let</span> <span class="pl-en">ready</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</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">iframes</span> <span class="pl-c1">=</span> <span class="pl-c1">0</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">"start"</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">on</span><span class="pl-kos">(</span><span class="pl-s">"frameattached"</span><span class="pl-kos">,</span> <span class="pl-s1">frame</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
        <span class="pl-c">// TEST : url is always empty</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">"frameattached %i, url [%s]"</span><span class="pl-kos">,</span> <span class="pl-c1">++</span><span class="pl-s1">iframes</span><span class="pl-kos">,</span> <span class="pl-s1">frame</span><span class="pl-kos">.</span><span class="pl-en">url</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">frame</span><span class="pl-kos">.</span><span class="pl-en">addScriptTag</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">content</span>: <span class="pl-s">`window['baz'] = 54`</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">then</span><span class="pl-kos">(</span><span class="pl-k">async</span> <span class="pl-s1">script</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
            <span class="pl-c">// TEST : url is good on chromium</span>
            <span class="pl-c">// TEST : url is good on firefox when the page is a local server</span>
            <span class="pl-c">// TEST : url is empty on firefox when the page is a local file or a private website</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">"addScriptTag, url [%s]"</span><span class="pl-kos">,</span> <span class="pl-s1">frame</span><span class="pl-kos">.</span><span class="pl-en">url</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">expect</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">frame</span><span class="pl-kos">.</span><span class="pl-en">evaluate</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">window</span><span class="pl-kos">[</span><span class="pl-s">'foo'</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">toBe</span><span class="pl-kos">(</span><span class="pl-c1">42</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-en">expect</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">frame</span><span class="pl-kos">.</span><span class="pl-en">evaluate</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">window</span><span class="pl-kos">[</span><span class="pl-s">'bar'</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">toBe</span><span class="pl-kos">(</span><span class="pl-c1">17</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-en">expect</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">frame</span><span class="pl-kos">.</span><span class="pl-en">evaluate</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">window</span><span class="pl-kos">[</span><span class="pl-s">'intercepted'</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">toBe</span><span class="pl-kos">(</span><span class="pl-c1">true</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-en">expect</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">frame</span><span class="pl-kos">.</span><span class="pl-en">evaluate</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">window</span><span class="pl-kos">[</span><span class="pl-s">'baz'</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">toBe</span><span class="pl-kos">(</span><span class="pl-c1">54</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">err</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
            <span class="pl-c">// iframes are purposely detached</span>
            <span class="pl-c">// ignore detached frames</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-s1">page</span><span class="pl-kos">.</span><span class="pl-en">on</span><span class="pl-kos">(</span><span class="pl-s">"framedetached"</span><span class="pl-kos">,</span> <span class="pl-s1">frame</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
        <span class="pl-c">// TEST : url is always empty</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">"framedetached %i, url [%s]"</span><span class="pl-kos">,</span> <span class="pl-c1">--</span><span class="pl-s1">iframes</span><span class="pl-kos">,</span> <span class="pl-s1">frame</span><span class="pl-kos">.</span><span class="pl-en">url</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">if</span> <span class="pl-kos">(</span><span class="pl-s1">iframes</span> <span class="pl-c1">===</span> <span class="pl-c1">1</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-en">ready</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">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">sysPath</span><span class="pl-kos">.</span><span class="pl-en">join</span><span class="pl-kos">(</span><span class="pl-s1">__dirname</span><span class="pl-kos">,</span> <span class="pl-s">'dynamic-oopif.html'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-c">// await page.goto('http://127.0.0.1:3000/dynamic-oopif.html');</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">"wait for ready"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-k">await</span> <span class="pl-k">new</span> <span class="pl-v">Promise</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-s1">resolve</span><span class="pl-kos">,</span> <span class="pl-s1">reject</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
        <span class="pl-en">ready</span> <span class="pl-c1">=</span> <span class="pl-s1">resolve</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">await</span> <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">waitForTimeout</span><span class="pl-kos">(</span><span class="pl-c1">1000</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">"ready"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">expect</span><span class="pl-kos">(</span><span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">frames</span><span class="pl-kos">(</span><span class="pl-kos">)</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-en">toBe</span><span class="pl-kos">(</span><span class="pl-c1">2</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-c">// TEST : url is good on chromium</span>
    <span class="pl-c">// TEST : url is good on firefox when the page is a local server</span>
    <span class="pl-c">// TEST : url is empty on firefox when the page is a local file or a private website</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">"iframe, url [%s]"</span><span class="pl-kos">,</span> <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">frames</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">[</span><span class="pl-c1">1</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-en">url</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">expect</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">frames</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">[</span><span class="pl-c1">0</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-en">evaluate</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">window</span><span class="pl-kos">[</span><span class="pl-s">'foo'</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">toBe</span><span class="pl-kos">(</span><span class="pl-c1">42</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">expect</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">frames</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">[</span><span class="pl-c1">1</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-en">evaluate</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">window</span><span class="pl-kos">[</span><span class="pl-s">'foo'</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">toBe</span><span class="pl-kos">(</span><span class="pl-c1">42</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">expect</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">frames</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">[</span><span class="pl-c1">0</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-en">evaluate</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">window</span><span class="pl-kos">[</span><span class="pl-s">'bar'</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">toBe</span><span class="pl-kos">(</span><span class="pl-c1">17</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">expect</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">frames</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">[</span><span class="pl-c1">1</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-en">evaluate</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">window</span><span class="pl-kos">[</span><span class="pl-s">'bar'</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">toBe</span><span class="pl-kos">(</span><span class="pl-c1">17</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">expect</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">frames</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">[</span><span class="pl-c1">0</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-en">evaluate</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">window</span><span class="pl-kos">[</span><span class="pl-s">'intercepted'</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">toBe</span><span class="pl-kos">(</span><span class="pl-c1">true</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">expect</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">frames</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">[</span><span class="pl-c1">1</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-en">evaluate</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">window</span><span class="pl-kos">[</span><span class="pl-s">'intercepted'</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">toBe</span><span class="pl-kos">(</span><span class="pl-c1">true</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-c">// TEST : pass on chromium</span>
    <span class="pl-c">// TEST : pass on firefox if the server is a local server</span>
    <span class="pl-c">// TEST : fail on firefox if the server is a local file or a private website</span>
    <span class="pl-en">expect</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">frames</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">[</span><span class="pl-c1">1</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-en">evaluate</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">window</span><span class="pl-kos">[</span><span class="pl-s">'baz'</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">toBe</span><span class="pl-kos">(</span><span class="pl-c1">54</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></pre></div>
<p dir="auto">dynamic-oopif.html</p>
<div class="highlight highlight-text-html-basic notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&lt;script&gt;
const promiseTimeout = ms =&gt; {
  return new Promise((resolve, reject) =&gt; {
    setTimeout(resolve, ms);
  });
};

window.addEventListener('DOMContentLoaded', async () =&gt; {
  const iframes = [];

  function frameattach() {
    const iframe = document.createElement('iframe');
    iframe.src = &quot;https://fr.wikipedia.org/wiki/Main_Page&quot;;
    document.body.appendChild(iframe);
    iframes.push(iframe);
  }

  function framedetach() {
    const iframe = iframes.pop();
    document.body.removeChild(iframe);
  }

  await promiseTimeout(2000);

  frameattach();

  await promiseTimeout(1000);

  frameattach();
  framedetach();
}, false);
&lt;/script&gt;"><pre class="notranslate"><span class="pl-kos">&lt;</span><span class="pl-ent">script</span><span class="pl-kos">&gt;</span>
<span class="pl-k">const</span> <span class="pl-en">promiseTimeout</span> <span class="pl-c1">=</span> <span class="pl-s1">ms</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">return</span> <span class="pl-k">new</span> <span class="pl-v">Promise</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-s1">resolve</span><span class="pl-kos">,</span> <span class="pl-s1">reject</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-en">setTimeout</span><span class="pl-kos">(</span><span class="pl-s1">resolve</span><span class="pl-kos">,</span> <span class="pl-s1">ms</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-smi">window</span><span class="pl-kos">.</span><span class="pl-en">addEventListener</span><span class="pl-kos">(</span><span class="pl-s">'DOMContentLoaded'</span><span class="pl-kos">,</span> <span class="pl-k">async</span> <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-s1">iframes</span> <span class="pl-c1">=</span> <span class="pl-kos">[</span><span class="pl-kos">]</span><span class="pl-kos">;</span>

  <span class="pl-k">function</span> <span class="pl-en">frameattach</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">iframe</span> <span class="pl-c1">=</span> <span class="pl-smi">document</span><span class="pl-kos">.</span><span class="pl-en">createElement</span><span class="pl-kos">(</span><span class="pl-s">'iframe'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-s1">iframe</span><span class="pl-kos">.</span><span class="pl-c1">src</span> <span class="pl-c1">=</span> <span class="pl-s">"https://fr.wikipedia.org/wiki/Main_Page"</span><span class="pl-kos">;</span>
    <span class="pl-smi">document</span><span class="pl-kos">.</span><span class="pl-c1">body</span><span class="pl-kos">.</span><span class="pl-en">appendChild</span><span class="pl-kos">(</span><span class="pl-s1">iframe</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-s1">iframes</span><span class="pl-kos">.</span><span class="pl-en">push</span><span class="pl-kos">(</span><span class="pl-s1">iframe</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>

  <span class="pl-k">function</span> <span class="pl-en">framedetach</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">iframe</span> <span class="pl-c1">=</span> <span class="pl-s1">iframes</span><span class="pl-kos">.</span><span class="pl-en">pop</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-smi">document</span><span class="pl-kos">.</span><span class="pl-c1">body</span><span class="pl-kos">.</span><span class="pl-en">removeChild</span><span class="pl-kos">(</span><span class="pl-s1">iframe</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">promiseTimeout</span><span class="pl-kos">(</span><span class="pl-c1">2000</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-en">frameattach</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">promiseTimeout</span><span class="pl-kos">(</span><span class="pl-c1">1000</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-en">frameattach</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-en">framedetach</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-c1">false</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></pre></div>
<p dir="auto"><strong>Steps</strong></p>
<ul dir="auto">
<li>[Run the test]</li>
<li><code class="notranslate">node node_modules/playwright/cli.js test --project=firefox --headed oopif.spec.ts</code></li>
</ul>
<p dir="auto"><strong>Expected</strong></p>
<p dir="auto">frame.evaluate to return the correct value</p>
<p dir="auto"><strong>Actual</strong></p>
<p dir="auto">Error: frame.evaluate: Execution context was destroyed, most likely because of a navigation</p>
<div class="highlight highlight-text-adblock notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="Running 1 test using 1 worker
[firefox] › oopif.spec.ts:4:5 › should support exposeBinding/addInitScript/addScriptTag in dynamic iframes
start
wait for ready
frameattached 1, url []
addScriptTag, url []
frameattached 2, url []
framedetached 1, url []
ready
iframe, url []
  1) [firefox] › oopif.spec.ts:4:5 › should support exposeBinding/addInitScript/addScriptTag in dynamic iframes

    Error: frame.evaluate: Execution context was destroyed, most likely because of a navigation.

      65 |
      66 |     expect(await page.frames()[0].evaluate(() =&gt; window['foo'])).toBe(42);
    &gt; 67 |     expect(await page.frames()[1].evaluate(() =&gt; window['foo'])).toBe(42);
         |                                   ^
      68 |     expect(await page.frames()[0].evaluate(() =&gt; window['bar'])).toBe(17);
      69 |     expect(await page.frames()[1].evaluate(() =&gt; window['bar'])).toBe(17);
      70 |     expect(await page.frames()[0].evaluate(() =&gt; window['intercepted'])).toBe(true);"><pre class="notranslate">Running 1 test using 1 worker
[firefox] › oopif.spec.ts:4:5 › should support exposeBinding/addInitScript/addScriptTag in dynamic iframes
start
wait for ready
frameattached 1, url []
addScriptTag, url []
frameattached 2, url []
framedetached 1, url []
ready
iframe, url []
  1) [firefox] › oopif.spec.ts:4:5 › should support exposeBinding/addInitScript/addScriptTag in dynamic iframes

    Error: frame.evaluate: Execution context was destroyed, most likely because of a navigation.

      65 <span class="pl-k">|</span>
      66 |     expect(await page.frames()[0].evaluate(() =&gt; window['foo'])).toBe(42);
    &gt; 67 |     expect(await page.frames()[1].evaluate(() =&gt; window['foo'])).toBe(42);
         |                                   <span class="pl-k">^</span>
      68 |     expect(await page.frames()[0].evaluate(() =&gt; window['bar'])).toBe(17);
      69 |     expect(await page.frames()[1].evaluate(() =&gt; window['bar'])).toBe(17);
      70 |     expect(await page.frames()[0].evaluate(() =&gt; window['intercepted'])).toBe(true);</pre></div>
<div class="highlight highlight-text-adblock notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="Running 1 test using 1 worker
[chromium] › oopif.spec.ts:4:5 › should support exposeBinding/addInitScript/addScriptTag in dynamic iframes
start
wait for ready
frameattached 1, url []
addScriptTag, url [https://fr.wikipedia.org/wiki/Main_Page]
frameattached 2, url []
framedetached 1, url []
ready
iframe, url [https://fr.wikipedia.org/wiki/Wikip%C3%A9dia:Accueil_principal]
  1 passed (7.3s)"><pre class="notranslate">Running 1 test using 1 worker
[chromium] › oopif.spec.ts:4:5 › should support exposeBinding/addInitScript/addScriptTag in dynamic iframes
start
wait for ready
frameattached 1, url []
addScriptTag, url [https://fr.wikipedia.org/wiki/Main_Page]
frameattached 2, url []
framedetached 1, url []
ready
iframe, url [https://fr.wikipedia.org/wiki/Wikip%C3%A9dia:Accueil_principal]
  1 passed (7.3s)</pre></div>