playwright icon indicating copy to clipboard operation
playwright copied to clipboard

[BUG] ClickAsync() on popup window that closes itself causes exception

Open coderb opened this issue 2 years ago • 8 comments
trafficstars

System info

  • Playwright Version: v1.36
  • Operating System: All
  • Browser: All
  • Other info:

A popup window that includes a button which closes the window sometimes causes an Exception in playwright.

It happens about half the time (probably a race condition that depends on how fast the browser window is closed).

Source code

            var popup = await page.RunAndWaitForPopupAsync(async () => { 
                await buttonThatOpensPopupWindow.ClickAsync();
            });
            await popup.WaitForLoadStateAsync();
            await popup.ClickAsync("#btnOk");

Expected

no exception

Actual

============================================================
Exception: PlaywrightException: Target closed
=========================== logs ===========================
waiting for Locator("#btnOk")
  locator resolved to <a class="button-primary" onclick="Foo…>…</a>
attempting click action
  waiting for element to be visible, enabled and stable
  element is visible, enabled and stable
  scrolling into view if needed
  done scrolling
  performing click action
============================================================
   at Microsoft.Playwright.Transport.Connection.InnerSendMessageToServerAsync[T](String guid, String method, Dictionary`2 dictionary, Boolean keepNulls) in /_/src/Playwright/Transport/Connection.cs:line 192
   at Microsoft.Playwright.Transport.Connection.WrapApiCallAsync[T](Func`1 action, Boolean isInternal)
   at Test.Do(IPage page) in c:\source\Test.cs:line 163

coderb avatar Aug 29 '23 20:08 coderb

Can you share a reproducible which demonstrates the issue with actual and expected behavior?

mxschmitt avatar Aug 31 '23 15:08 mxschmitt

unfortunately it's with a financial website that requires an account and login.

my code is very basic and the relevant part is above. is there some other way to provide you with any additional info you need to address the issue?

btw- thanks for your hard work, the project is fantastic.

coderb avatar Aug 31 '23 15:08 coderb

additional info: also present in 1.37.1 seems to only happen w/firefox

coderb avatar Sep 06 '23 13:09 coderb

Thanks for filing! I can reproduce actually with this code which passes in CR and WK but fails in FF:

using Microsoft.Playwright;

using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Webkit.LaunchAsync(new BrowserTypeLaunchOptions() { Headless = false });
var context = await browser.NewContextAsync();
var page = await context.NewPageAsync();
await page.GotoAsync("https://example.com");

await context.RouteAsync("**/popup.html", async (route) =>
{
    await route.FulfillAsync(new()
    {
        Status = 200,
        ContentType = "text/html",
        Body = "<button id=btnOk onclick=\"window.close();\">Close Me</button>"
    });
});

await page.SetContentAsync(@"
    <button onclick=""window.open('https://example.com/popup.html')"" id=button>Button</button>
    <script>
        button.addEventListener('click', () => {
            const popup = window.open('https://example.com/popup.html');
            popup.onload = () => {
                popup.document.querySelector('button').click();
            };
        });
    </script>
");

var popup = await page.RunAndWaitForPopupAsync(async () => { 
    await page.GetByRole(AriaRole.Button, new() { Name = "Button" }).ClickAsync();
});
await popup.GetByRole(AriaRole.Button, new() { Name = "Close Me" }).ClickAsync();

No action needed from your side anymore.

mxschmitt avatar Sep 06 '23 13:09 mxschmitt

Can also reproduce it in Node.js, moving over to the main repo:

import playwright from 'playwright';

(async () => {
  const browser = await playwright.firefox.launch({ headless: false });
  const context = await browser.newContext();
  const page = await context.newPage();
  await page.goto('https://example.com');

  await context.route('**/popup.html', async route => {
    await route.fulfill({
      status: 200,
      contentType: 'text/html',
      body: `<button id="btnOk" onclick="window.close();">Close Me</button>`
    });
  });

  const popupPromise = page.waitForEvent('popup');
  await page.evaluate(() => {
    window.open('https://example.com/popup.html');
  });
  const popup = await popupPromise;
  await popup.getByRole('button', { name: 'Close Me' }).click();
  await browser.close();
})();

Expected: Passes Actual: Last click() throws locator.click: Target closed

mxschmitt avatar Sep 06 '23 13:09 mxschmitt

Investigation notes:

  • When hitting the "close" button in pop-up, Juggler sends a sequence of events: mousemove, mousedown and mouseup
  • These events are dispatched to the pop-up renderer process
  • By the time the mouseup event is dispatched in the renderer, the popup is getting closed; the ACK from the mouseup renderer process is not dispatched to the browser process since the communication channel between the 2 is already terminated.
  • Once the page is closed, the mouseup ack is not received (and will never be received), so juggler in the browser process sends an error to the client

So far there's no easy way to fix this on the Juggler side other than add a hack (i.e. ignore missing ACK from the mouseup event in the browser process). We decided to hold this fix until there are more reports.

As a workaround, folks should try-catch the click method that closes the page.

aslushnikov avatar Sep 27 '23 17:09 aslushnikov

I understand you are frustrated with a significant bug in Playwright that has been unresolved for an extended period. Please allow me to express your concerns in a polite and constructive manner:

While I appreciate the diligence of the Playwright team, I am concerned about the prolonged existence of a major bug related to closing popup windows. Despite an issue having been filed over six months ago, this bug remains unresolved. As a newcomer to Playwright, I spent an entire day troubleshooting this issue, assuming the problem lay in my code, as a humble programmer should. It is highly unusual for such a common operation to be affected by a bug, and one would typically consider this as a last resort.

The lack of a timely resolution to this issue is frustrating, especially given the significant impact it can have on productivity. I understand that the team may be waiting for more reports, but such a severe bug deserves prompt attention. A more proactive approach to addressing critical issues could prevent some engineers from abandoning Playwright altogether.

I kindly request that the Playwright team prioritize the resolution of this bug to improve the overall user experience and maintain the project's reputation for reliability and efficiency. A more responsive approach to addressing major bugs would be greatly appreciated by the Playwright community.

hoge20240619 avatar Jun 19 '24 05:06 hoge20240619

Yup, I am proficient having used robotframework with selenium and other automation tools ... switched to playwright a couple weeks ago - the recorder provided the steps and on re-executing, failed so many times ... I do see the blank new tab opened in --ui mode (all browsers) it seems that the original page is closed and the new tab is opened ... but because page "closes" (there is no action on the tested site that closes the page, it simply opens another tab) it cannot seem to find the new tab ... I have included multiple waitfornetwork idles in case this was the issue ... please fix soon?

matthew-starling avatar Jun 20 '24 21:06 matthew-starling

got the same kind of issue using Firefox

 Error: locator.click: Target page, context or browser has been closed
    Call log:
      - waiting for getByRole('button', { name: 'OK' })
      -   locator resolved to <input value="OK" type="button" id="ChampionCommentOK" class="btn bg-purple btn-flat btn-sm"/>
      - attempting click action
      -   waiting for element to be visible, enabled and stable
      -   element is visible, enabled and stable
      -   scrolling into view if needed
      -   done scrolling
      -   performing click action

iansinaga avatar Oct 25 '24 05:10 iansinaga