[Question] : the "on" function of Page object works for some events but not for others
I was trying to perform 3 things using Playwright with python.
- Handle a Dialog
- Handle File Download / Upload
- Handle a new Window
For Handling a Dialog I can across the following Page Event Dialog
Dialog Opening App The following was my code and it worked well
TestBase.get_page().goto("https://the-internet.herokuapp.com/context_menu")
box = TestBase.get_page().locator("#hot-spot")
def handle_alert_custom(dialog: Dialog):
print("Your Alert Message is : ", dialog.message)
# waiting for 2 seconds so you can see the Alert on UI
time.sleep(2)
# now you can accept or reject the dialog
dialog.accept()
# dialog.dismiss()
TestBase.get_page().on("dialog", handle_alert_custom)
box.click(button='right')
time.sleep(2)
TestBase.get_page().close()
I tried to do something similar for File Download / Upload assuming that will work File Download & File Upload
and also similar for Handling a New Window New Window
for each of the above things i added something like Page.on("download", handle_download) #where handle_download is a valid function Page.on("popup", handle_popup) # where handle_popup is a valid function
but some how i did not work the way I handled the Dialog.
I did found a work around using the following
with TestBase.get_page().expect_download() as download_info:
download_link.click()
download_info.value.save_as("theFileYouWant.json")
&
with TestBase.get_page().expect_event("popup") as pop:
click_here.click()
new_page = pop.value
print(new_page.locator("h3").text_content())
new_page.close()
but why does it not work when i try to put up with the "on" and use appropriate event ?
for my examples i used Multi window & File download
Can someone please tell me what is going on with Page."on" function and Page."expect_event" function
Thanks
For the cases that aren't working, can you include a minimal script that we can run cleanly/directly. Please explain/paste the output/error you see as well as what you expect to happen.
I'm mostly following your above description, but want to make sure we're working through the same code/issue. Thanks!
Sure @rwoll
the lib.test_base.py module
from playwright.sync_api import Browser, Page, sync_playwright
class TestBase:
__browser: Browser = None
__page: Page = None
@staticmethod
def get_browser():
if TestBase.__browser is None or not(TestBase.__browser.is_connected()):
TestBase.__browser = sync_playwright().start().chromium.launch(headless=False, channel='chrome', slow_mo=100)
return TestBase.__browser
@staticmethod
def get_page():
if TestBase.__page is None or (TestBase.__page.is_closed()):
TestBase.__page = TestBase.get_browser().new_page()
return TestBase.__page
the downloading_file.py module
import time
from playwright.sync_api import Download
from lib.test_base import TestBase
url = "https://the-internet.herokuapp.com/download"
def handle_download(download: Download):
time.sleep(1)
print(f"The file was downloaded at : {download.path()}")
download.save_as("your_text_file.txt")
time.sleep(1)
TestBase.get_page().goto(url)
TestBase.get_page().on("download", handle_download)
download_link = TestBase.get_page().locator("xpath=//a[text()='text.txt']")
time.sleep(1)
download_link.click()
time.sleep(1)
the multi_window.py module
import time
from lib.test_base import TestBase
url = "https://the-internet.herokuapp.com/windows"
def handle_pop(pop):
print(f"New Page Title {pop.title()}")
TestBase.get_page().on("popup", handle_pop)
TestBase.get_page().goto(url)
click_here = TestBase.get_page().locator("a", has_text="Click Here")
click_here.click()
The following example shows the popup handler firing:
import sys
from playwright.sync_api import Playwright, sync_playwright, expect
def run(playwright: Playwright) -> None:
browser = playwright.chromium.launch()
context = browser.new_context()
page = context.new_page()
page.goto("https://the-internet.herokuapp.com/windows")
page.locator("text=Click Here").click()
waiting_for_popup = True
def exit_on_popup():
print("found a popup!")
nonlocal waiting_for_popup
waiting_for_popup = False
page.on("popup", exit_on_popup)
while waiting_for_popup:
page.wait_for_timeout(100)
context.close()
browser.close()
with sync_playwright() as playwright:
run(playwright)
and here's it using Playwright's actual expect APIs:
from playwright.sync_api import Playwright, sync_playwright, expect
def run(playwright: Playwright) -> None:
browser = playwright.chromium.launch()
context = browser.new_context()
page = context.new_page()
page.goto("https://the-internet.herokuapp.com/windows")
with page.expect_popup() as popup_info:
page.locator("text=Click Here").click()
popup = popup_info.value
expect(popup).to_have_url('https://the-internet.herokuapp.com/windows/new')
context.close()
browser.close()
with sync_playwright() as playwright:
run(playwright)
I suggest you change your code so you remove all uses of sleeps (or if you must have them as a last resort, use page.wait_for_timeout instead), and instead use the expect event pattern from the second script above:
with page.expect_popup() as popup_info:
page.locator("text=Click Here").click()
popup = popup_info.value
Your use of sleeps is likely causing you issues in either exiting too soon or otherwise interrupting the flow.