<h3 dir="auto">System info</h3>
<ul dir="auto">
<li>Playwright Version: [v1.35]</li>
<li>Operating System: [Windows]</li>
<li>Browser: [Edge]</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.<br>
The code of a simple page</li>
</ul>
<div class="highlight highlight-text-html-basic notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&lt;html&gt;
&lt;body&gt;
THING
&lt;img src=&quot;api/myImage.png&quot;/&gt;
&lt;/body&gt;
&lt;/html&gt;"><pre class="notranslate"><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">body</span><span class="pl-kos">&gt;</span>
THING
<span class="pl-kos">&lt;</span><span class="pl-ent">img</span> <span class="pl-c1">src</span>="<span class="pl-s">api/myImage.png</span>"/&gt;
<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">That end up with the following image in playwright because I try to mock my api and it's not up<br>
<a target="_blank" rel="noopener noreferrer" href="https://user-images.githubusercontent.com/3164314/252685402-3b7a41c0-9796-4ede-a811-fb979ea91f93.png"><img src="https://user-images.githubusercontent.com/3164314/252685402-3b7a41c0-9796-4ede-a811-fb979ea91f93.png" alt="image" style="max-width: 100%;"></a></p>
<p dir="auto">with my following test, only a 404 explaining my image can't be found (normal)</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="test(&quot;TEST&quot;, async ({ page }) =&gt; {
  await page.goto('index.html');
})"><pre class="notranslate"><span class="pl-en">test</span><span class="pl-kos">(</span><span class="pl-s">"TEST"</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">'index.html'</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>Link to the GitHub repository with the repro</strong></p>
<p dir="auto">[https://github.com/your_profile/playwright_issue_title]</p>
<p dir="auto">or</p>
<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: 'Microsoft Edge',
       use: { ...devices['Desktop Edge'], channel: 'msedge', baseURL: 'http://localhost:4200/' },
    }
});"><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">'Microsoft Edge'</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 Edge'</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-c1">channel</span>: <span class="pl-s">'msedge'</span><span class="pl-kos">,</span> <span class="pl-c1">baseURL</span>: <span class="pl-s">'http://localhost:4200/'</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 { test } from '@playwright/test';

test(&quot;TEST&quot;, async ({ page }) =&gt; {
  await page.route(`/api/myImage.png`, async route =&gt; {

    await route.fulfill({
      status: 200,
      path: &quot;screenshot.png&quot;,
    });
  });

  await page.goto('index.html');
})"><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-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">"TEST"</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">route</span><span class="pl-kos">(</span><span class="pl-s">`/api/myImage.png`</span><span class="pl-kos">,</span> <span class="pl-k">async</span> <span class="pl-s1">route</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>

    <span class="pl-k">await</span> <span class="pl-s1">route</span><span class="pl-kos">.</span><span class="pl-en">fulfill</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
      <span class="pl-c1">status</span>: <span class="pl-c1">200</span><span class="pl-kos">,</span>
      <span class="pl-c1">path</span>: <span class="pl-s">"screenshot.png"</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-s">'index.html'</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>[...]</li>
</ul>
<p dir="auto"><strong>Expected</strong><br>
The image is mocked and screenshot.png is displayed on the interface</p>
<p dir="auto"><strong>Actual</strong></p>
<p dir="auto">The image is not displayed on my interface, and the interface of my web app doesn't display anymore<br>
page.goto: Navigation failed because page was closed!</p>
<p dir="auto">navigating to "<a href="http://localhost:8080/index.html" rel="nofollow">http://localhost:8080/index.html</a>", waiting until "load"</p>
<p dir="auto">It would be great to be able to use pattern well adopted in React Testing Library tests - a custom render function which contains wrappers required by each component (ie. providers). Let's take a look at the example:</p>
<div class="highlight highlight-source-tsx notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// Button.test.tsx
import { test as base, expect } from '@playwright/experimental-ct-react';
import { CustomWrapper } from 'src/CustomWrapper';
import { Button } from './Button';

const test = base.extend({
  mount: async ({ mount: baseMount }, use) =&gt; {
    const mount: typeof baseMount = (component) =&gt; baseMount(&lt;CustomWrapper&gt;{component}&lt;/CustomWrapper&gt;);

    await use(mount);
  }
})

test('works', async ({ mount }) =&gt; {
  const component = await mount(&lt;Button&gt;a button&lt;/Button&gt;);

  await expect(await component.screenshot()).toMatchSnapshot();
})"><pre class="notranslate"><span class="pl-c">// Button.test.tsx</span>
<span class="pl-k">import</span> <span class="pl-kos">{</span> <span class="pl-s1">test</span> <span class="pl-k">as</span> <span class="pl-s1">base</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/experimental-ct-react'</span><span class="pl-kos">;</span>
<span class="pl-k">import</span> <span class="pl-kos">{</span> <span class="pl-smi">CustomWrapper</span> <span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">'src/CustomWrapper'</span><span class="pl-kos">;</span>
<span class="pl-k">import</span> <span class="pl-kos">{</span> <span class="pl-smi">Button</span> <span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">'./Button'</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-s1">test</span> <span class="pl-c1">=</span> <span class="pl-s1">base</span><span class="pl-kos">.</span><span class="pl-en">extend</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-en">mount</span>: <span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">mount</span>: <span class="pl-s1">baseMount</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-s1">use</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-en">mount</span>: <span class="pl-k">typeof</span> <span class="pl-s1">baseMount</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-s1">component</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-en">baseMount</span><span class="pl-kos">(</span><span class="pl-c1">&lt;</span><span class="pl-smi">CustomWrapper</span><span class="pl-c1">&gt;</span><span class="pl-kos">{</span><span class="pl-s1">component</span><span class="pl-kos">}</span><span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-smi">CustomWrapper</span><span class="pl-c1">&gt;</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-k">await</span> <span class="pl-en">use</span><span class="pl-kos">(</span><span class="pl-s1">mount</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">test</span><span class="pl-kos">(</span><span class="pl-s">'works'</span><span class="pl-kos">,</span> <span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-kos">{</span> mount <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">component</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-en">mount</span><span class="pl-kos">(</span><span class="pl-c1">&lt;</span><span class="pl-smi">Button</span><span class="pl-c1">&gt;</span>a button<span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-smi">Button</span><span class="pl-c1">&gt;</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-k">await</span> <span class="pl-s1">component</span><span class="pl-kos">.</span><span class="pl-en">screenshot</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">toMatchSnapshot</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">The above example works, because everything is implemented within the test module. This pattern, however, is not working when extracting extended <code class="notranslate">test</code> object to a separate module like so:</p>
<div class="highlight highlight-source-tsx notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// componentTest.tsx
import { test as base } from '@playwright/experimental-ct-react';
import { CustomWrapper } from 'src/CustomWrapper';

const test = base.extend({
  mount: async ({ mount: baseMount }, use) =&gt; {
    const mount: typeof baseMount = (component) =&gt; baseMount(&lt;CustomWrapper&gt;{component}&lt;/CustomWrapper&gt;);

    await use(mount);
  }
})

export * from '@playwright/experimental-ct-react';
export { test };"><pre class="notranslate"><span class="pl-c">// componentTest.tsx</span>
<span class="pl-k">import</span> <span class="pl-kos">{</span> <span class="pl-s1">test</span> <span class="pl-k">as</span> <span class="pl-s1">base</span> <span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">'@playwright/experimental-ct-react'</span><span class="pl-kos">;</span>
<span class="pl-k">import</span> <span class="pl-kos">{</span> <span class="pl-smi">CustomWrapper</span> <span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">'src/CustomWrapper'</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-s1">test</span> <span class="pl-c1">=</span> <span class="pl-s1">base</span><span class="pl-kos">.</span><span class="pl-en">extend</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-en">mount</span>: <span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">mount</span>: <span class="pl-s1">baseMount</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-s1">use</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-en">mount</span>: <span class="pl-k">typeof</span> <span class="pl-s1">baseMount</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-s1">component</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-en">baseMount</span><span class="pl-kos">(</span><span class="pl-c1">&lt;</span><span class="pl-smi">CustomWrapper</span><span class="pl-c1">&gt;</span><span class="pl-kos">{</span><span class="pl-s1">component</span><span class="pl-kos">}</span><span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-smi">CustomWrapper</span><span class="pl-c1">&gt;</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-k">await</span> <span class="pl-en">use</span><span class="pl-kos">(</span><span class="pl-s1">mount</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-c1">*</span> <span class="pl-k">from</span> <span class="pl-s">'@playwright/experimental-ct-react'</span><span class="pl-kos">;</span>
<span class="pl-k">export</span> <span class="pl-kos">{</span> <span class="pl-s1">test</span> <span class="pl-kos">}</span><span class="pl-kos">;</span></pre></div>
<div class="highlight highlight-source-tsx notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// Button.test.tsx
import { test, expect } from 'src/componentTest'; // &lt;----- this imports resolve to strings
import { Button } from './Button';

test('works', async ({ mount }) =&gt; {
  const component = await mount(&lt;Button&gt;a button&lt;/Button&gt;);

  await expect(await component.screenshot()).toMatchSnapshot();
})"><pre class="notranslate"><span class="pl-c">// Button.test.tsx</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">'src/componentTest'</span><span class="pl-kos">;</span> <span class="pl-c">// &lt;----- this imports resolve to strings</span>
<span class="pl-k">import</span> <span class="pl-kos">{</span> <span class="pl-smi">Button</span> <span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">'./Button'</span><span class="pl-kos">;</span>

<span class="pl-en">test</span><span class="pl-kos">(</span><span class="pl-s">'works'</span><span class="pl-kos">,</span> <span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-kos">{</span> mount <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">component</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-en">mount</span><span class="pl-kos">(</span><span class="pl-c1">&lt;</span><span class="pl-smi">Button</span><span class="pl-c1">&gt;</span>a button<span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-smi">Button</span><span class="pl-c1">&gt;</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-k">await</span> <span class="pl-s1">component</span><span class="pl-kos">.</span><span class="pl-en">screenshot</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">toMatchSnapshot</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">I assume this is due to custom <code class="notranslate">tsxTransform.ts</code> that keeps track of every component/jsx module that is imported within test module.</p>
<p dir="auto">SIDE NOTE: Even though I can't really figure out if it's possible to easily workaround this, in order to actually be able to test I found a hacky way to achieve this result by monkey-patching <code class="notranslate">react-dom</code> like so:</p>
<div class="highlight highlight-source-tsx notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// react-dom.patched.tsx
import _ReactDOM from '../node_modules/react-dom';
import { CustomWrapper } from './CustomWrapper';

const ReactDOM = Object.create(_ReactDOM);

ReactDOM.render = (children, el) =&gt; _ReactDOM.render(&lt;CustomWrapper&gt;{children}&lt;/CustomWrapper&gt;, el);

export default ReactDOM;"><pre class="notranslate"><span class="pl-c">// react-dom.patched.tsx</span>
<span class="pl-k">import</span> <span class="pl-s1">_ReactDOM</span> <span class="pl-k">from</span> <span class="pl-s">'../node_modules/react-dom'</span><span class="pl-kos">;</span>
<span class="pl-k">import</span> <span class="pl-kos">{</span> <span class="pl-smi">CustomWrapper</span> <span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">'./CustomWrapper'</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-smi">ReactDOM</span> <span class="pl-c1">=</span> <span class="pl-smi">Object</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-s1">_ReactDOM</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-smi">ReactDOM</span><span class="pl-kos">.</span><span class="pl-en">render</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-s1">children</span><span class="pl-kos">,</span> <span class="pl-s1">el</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-s1">_ReactDOM</span><span class="pl-kos">.</span><span class="pl-en">render</span><span class="pl-kos">(</span><span class="pl-c1">&lt;</span><span class="pl-smi">CustomWrapper</span><span class="pl-c1">&gt;</span><span class="pl-kos">{</span><span class="pl-s1">children</span><span class="pl-kos">}</span><span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-smi">CustomWrapper</span><span class="pl-c1">&gt;</span><span class="pl-kos">,</span> <span class="pl-s1">el</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-smi">ReactDOM</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">and then I alias <code class="notranslate">react-dom</code> in Vite configuration that is passed to Playwright.</p>
<p dir="auto">What do you guys think about it?</p>