<h3 dir="auto">System info</h3>
<ul dir="auto">
<li>Playwright Version: [v1.35.1]</li>
<li>Operating System: [Ubuntu 20]</li>
<li>Browser: [WebKit]</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"> I provided exact source code that allows reproducing the issue locally.</li>
</ul>




<p dir="auto">I have not provided a sample repro for this as it's not something I can reproduce easily. It would probably be harder for me to try to create a smaller version of the code where I'm having this problem and then still be able to replicate it.<br>
The app I'm working on is small and although I'm not comfortable exposing it as a public repo I would be open to creating a private repo and give access to the required people that would investigate this.</p>
<p dir="auto">Alternatively, I'm open to getting on a discord call and demo the problem and provide any further information.</p>
<h3 dir="auto">Problem description</h3>
<p dir="auto">When I run the tests I get a similar problem to what is reported in <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1548116810" data-permission-text="Title is private" data-url="https://github.com/microsoft/playwright/issues/20203" data-hovercard-type="issue" data-hovercard-url="/microsoft/playwright/issues/20203/hovercard" href="https://github.com/microsoft/playwright/issues/20203">#20203</a>. See the images below where the spacing between <code class="notranslate">m</code> and <code class="notranslate">i</code> in the word  <code class="notranslate">academic</code> is not deterministic will sometimes make tests fail.</p>
<p dir="auto">Diff:<br>
<a target="_blank" rel="noopener noreferrer" href="https://user-images.githubusercontent.com/15857357/246894964-d21fa0f2-45c2-4aba-8c3b-80e7d4c15ebf.png"><img src="https://user-images.githubusercontent.com/15857357/246894964-d21fa0f2-45c2-4aba-8c3b-80e7d4c15ebf.png" alt="image" style="max-width: 100%;"></a></p>
<p dir="auto">Actual:<br>
<a target="_blank" rel="noopener noreferrer" href="https://user-images.githubusercontent.com/15857357/246895037-89c4de18-4f76-4357-855a-3580fb4764d2.png"><img src="https://user-images.githubusercontent.com/15857357/246895037-89c4de18-4f76-4357-855a-3580fb4764d2.png" alt="image" style="max-width: 100%;"></a></p>
<p dir="auto">Expected:<br>
<a target="_blank" rel="noopener noreferrer" href="https://user-images.githubusercontent.com/15857357/246895074-707eaa28-d959-49cd-ace4-918d7af96667.png"><img src="https://user-images.githubusercontent.com/15857357/246895074-707eaa28-d959-49cd-ace4-918d7af96667.png" alt="image" style="max-width: 100%;"></a></p>
<p dir="auto">I've tried the workaround proposed in <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1548116810" data-permission-text="Title is private" data-url="https://github.com/microsoft/playwright/issues/20203" data-hovercard-type="issue" data-hovercard-url="/microsoft/playwright/issues/20203/hovercard" href="https://github.com/microsoft/playwright/issues/20203">#20203</a> but it didn't work for my case.<br>
So far, the only workaround I found that seems reliably work is to do <code class="notranslate">await page.waitForTimeout(1500);</code> before I do <code class="notranslate">await expect(page).toHaveScreenshot();</code>. On my PC, I've tried 500ms and 1s and those always fail but the 1.5s seems to always be successful so far.</p>
<p dir="auto">Any suggestions?</p>
<h3 dir="auto">Notes</h3>
<ul dir="auto">
<li>Initially this test would sometimes pass and sometimes fail. The way I got it to always fail when running locally was to run with <code class="notranslate">workers: 1</code> instead of <code class="notranslate">workers: undefined</code>.</li>
<li>When running locally, I'm on a <code class="notranslate">Windows 10</code> OS and I run the test via the docker image <code class="notranslate">mcr.microsoft.com/playwright:v1.35.1-jammy</code>.</li>
<li>When running this test on the CI server, the CI server uses an Ubuntu distro and it almost never fails. In the times where it fails, the fact that I have <code class="notranslate">retries</code> set to <code class="notranslate">2</code> in the playwright config when it's running on CI was enough to avoid a flaky pipeline.</li>
</ul>
<h3 dir="auto">System info</h3>
<ul dir="auto">
<li>Playwright Version: 1.32.3-beta-1681174265000</li>
<li>Operating System:  Windows 11</li>
<li>Browser: [All, Chromium, Firefox, WebKit]</li>
<li>Other info:</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({
{
      name: 'android.chrome',
      use: {
        ...devices['Pixel 5'],    
      },
    }, 

 {
      name: 'ipad.safari',
      use: {
         ...devices['iPad (gen 6)'],
      },
   }
});
```mdc.login.page.ts
import { expect, Locator, Page } from '@playwright/test';

const baseURL =  String(process.env.URL);
const username = String(process.env.userid);
console.log(username);
const password = String(process.env.password);
const Title = String(process.env.Title);


export  class mdcloginPage {
 
    readonly page: Page;
    readonly username_field : Locator;
    readonly password_field : Locator;
    readonly login_button : Locator;
    
    // Locators

    constructor(page: Page) {
        this.page = page;
        this.username_field = page.locator('input[name=&quot;username&quot;]');
        this.password_field = page.locator('input[name=&quot;password&quot;]');
         this.login_button = page.getByRole('button', { name: 'Login' });
    }
       
    //Actions
    public async logintomdc() {
        await this.page.goto(baseURL);
        
       await expect((this.page),'checking page title').toHaveTitle(Title);
        await this.page.screenshot({path: 'screenshot/title.png'});
        /*await this.username_field.waitFor({state: &quot;visible&quot;});*/
        await this.username_field.type(username);
        await this.password_field.fill(password);
        await this.login_button.click();   

    }
**Test file (self-contained)**

```MDC.spec.ts
import { test, expect } from &quot;@playwright/test&quot;;
import {mdcloginPage} from &quot;./mdc/mdc.login.page&quot;;



test.describe('MDC Regression', async() =&gt; {  
    
    
  test('mdc tc1', async ({ page }) =&gt; {    
    const mdclogin = new mdcloginPage(page);
    mdclogin.logintomdc();  
  });
})"><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-kos">{</span>
      <span class="pl-c1">name</span>: <span class="pl-s">'android.chrome'</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">'Pixel 5'</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">'ipad.safari'</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">'iPad (gen 6)'</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-s">``</span><span class="pl-s">`mdc.login.page.ts</span>
<span class="pl-s">import { expect, Locator, Page } from '@playwright/test';</span>
<span class="pl-s"></span>
<span class="pl-s">const baseURL =  String(process.env.URL);</span>
<span class="pl-s">const username = String(process.env.userid);</span>
<span class="pl-s">console.log(username);</span>
<span class="pl-s">const password = String(process.env.password);</span>
<span class="pl-s">const Title = String(process.env.Title);</span>
<span class="pl-s"></span>
<span class="pl-s"></span>
<span class="pl-s">export  class mdcloginPage {</span>
<span class="pl-s"> </span>
<span class="pl-s">    readonly page: Page;</span>
<span class="pl-s">    readonly username_field : Locator;</span>
<span class="pl-s">    readonly password_field : Locator;</span>
<span class="pl-s">    readonly login_button : Locator;</span>
<span class="pl-s">    </span>
<span class="pl-s">    // Locators</span>
<span class="pl-s"></span>
<span class="pl-s">    constructor(page: Page) {</span>
<span class="pl-s">        this.page = page;</span>
<span class="pl-s">        this.username_field = page.locator('input[name="username"]');</span>
<span class="pl-s">        this.password_field = page.locator('input[name="password"]');</span>
<span class="pl-s">         this.login_button = page.getByRole('button', { name: 'Login' });</span>
<span class="pl-s">    }</span>
<span class="pl-s">       </span>
<span class="pl-s">    //Actions</span>
<span class="pl-s">    public async logintomdc() {</span>
<span class="pl-s">        await this.page.goto(baseURL);</span>
<span class="pl-s">        </span>
<span class="pl-s">       await expect((this.page),'checking page title').toHaveTitle(Title);</span>
<span class="pl-s">        await this.page.screenshot({path: 'screenshot/title.png'});</span>
<span class="pl-s">        /*await this.username_field.waitFor({state: "visible"});*/</span>
<span class="pl-s">        await this.username_field.type(username);</span>
<span class="pl-s">        await this.password_field.fill(password);</span>
<span class="pl-s">        await this.login_button.click();   </span>
<span class="pl-s"></span>
<span class="pl-s">    }</span>
<span class="pl-s">**Test file (self-contained)**</span>
<span class="pl-s"></span>
<span class="pl-s">`</span><span class="pl-s">``</span><span class="pl-c1">MDC</span><span class="pl-kos">.</span><span class="pl-c1">spec</span><span class="pl-kos">.</span><span class="pl-c1">ts</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-k">import</span> <span class="pl-kos">{</span><span class="pl-s1">mdcloginPage</span><span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">"./mdc/mdc.login.page"</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">'MDC Regression'</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-en">test</span><span class="pl-kos">(</span><span class="pl-s">'mdc tc1'</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">const</span> <span class="pl-s1">mdclogin</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-s1">mdcloginPage</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-s1">mdclogin</span><span class="pl-kos">.</span><span class="pl-en">logintomdc</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>
<p dir="auto"><strong>Expected</strong></p>
<p dir="auto">Navigate to url and fill username, password<br>
click on login button.</p>
<p dir="auto"><strong>Actual</strong></p>
<p dir="auto">it's closing the browser before it's loaded properly with below error</p>
<p dir="auto">before hooks<br>
page goto(url)<br>
after hooks<br>
Test finished within timeout of 30000ms, but tearing down "context" ran out of time.<br>
Please allow more time for the test, since teardown is attributed towards the test timeout budget.</p>
<p dir="auto"><strong>But when not following pom and I write the script in main test it's working fine</strong><br>
MDC.spec.ts<br>
import { test, expect } from "@playwright/test";<br>
import {mdcloginPage} from "./mdc/mdc.login.page";</p>
<p dir="auto">test.describe('MDC Regression', async() =&gt; {</p>
<p dir="auto">test('mdc tc1', async ({ page }) =&gt; {</p>
<p dir="auto">const baseURL = String(process.env.URL);<br>
const username1 = String(process.env.userid);<br>
const password = String(process.env.password);<br>
const Title = String(process.env.Title);</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="    await page.goto(baseURL) ;     
 
// Expect a title &quot;to contain&quot; a substring.
     await expect((page),'checking page title').toHaveTitle(Title);
    await page.screenshot({path: 'screenshot/title.png'})

   
    await page.locator('input[name=&quot;username&quot;]').fill(username1);
    await page.locator('input[name=&quot;username&quot;]').press('Tab');
    await page.locator('input[name=&quot;password&quot;]').fill(password);
    await page.getByRole('button', { name: 'Login' }).click();"><pre class="notranslate"><code class="notranslate">    await page.goto(baseURL) ;     
 
// Expect a title "to contain" a substring.
     await expect((page),'checking page title').toHaveTitle(Title);
    await page.screenshot({path: 'screenshot/title.png'})

   
    await page.locator('input[name="username"]').fill(username1);
    await page.locator('input[name="username"]').press('Tab');
    await page.locator('input[name="password"]').fill(password);
    await page.getByRole('button', { name: 'Login' }).click();
</code></pre></div>
<p dir="auto">});<br>
})</p>
<p dir="auto">Above case it's working as expected</p>
<p dir="auto">before Hooks<br>
login to page<br>
after Hooks</p>