i want to automate a website using playwright, the scenario is;
page.get_by_role("heading", name="Success")
in the pagepage.get_by_role("heading", name="id have multiple account")
in modal dialogpage.get_by_role("heading", name="id unregistred")
in iti try this code
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
page.goto('https://example/login')
page.get_by_placeholder("username").fill("my_username")
page.get_by_placeholder("password").fill("my_password")
page.get_by_role("button", name="submit").click()
for i in array_of_dicts:
page.get_by_placeholder('input id').fill(i['id'])
page.get_by_test_id("btnSubmit").click()
time.sleep(2)
success= page.get_by_role("heading", name="Success").is_visible()
type = page.locator("span").filter(has_text="id have multiple account").is_visible()
unregistred = page.get_by_role("heading", name="id unregistred").is_visible()
if(success):
print("success")
elif(type):
print("type")
elif(unregistred):
print("unregistred")
else:
print("unknown")
page.goto('https://example.com/verify_id')
browser.close()
its works but when i remove the time.sleep(2)
, it print unknown
, its like playwright doesnt wait until one of the element is visible.
and if i try this
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
page.goto('https://example/login')
page.get_by_placeholder("username").fill("my_username")
page.get_by_placeholder("password").fill("my_password")
page.get_by_role("button", name="submit").click()
for i in array_of_dicts:
page.get_by_placeholder('input id').fill(i['id'])
page.get_by_test_id("btnSubmit").click()
if(page.wait_for_selector('#success', state='visible') or page.wait_for_selector('#type', state='visible')):
print('success')
else:
print('unknown')
page.goto('https://example.com/verify_id')
browser.close()
its wait and execute print("success")
if the id is directing to success page, but when the id is suppose to show modal dialog of page.wait_for_selector('#type', state='visible')
its like the code stop and waiting inside if page.wait_for_selector('#success', state='visible')
until it timeout and show error without it check page.wait_for_selector('#type', state='visible')
what i want is to check multiple element, if one of the element return true it stop waiting and execute the next code without using time.sleep(2) or fixed pause. is that posible?
Yes, you can achieve this by using the Promise.any
method provided by Playwright to wait for multiple conditions and proceed as soon as any one of them resolves.
Here’s an example using Promise.any
:
from playwright.sync_api import sync_playwright, TimeoutError
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
page.goto('https://example/login')
page.get_by_placeholder("username").fill("my_username")
page.get_by_placeholder("password").fill("my_password")
page.get_by_role("button", name="submit").click()
for i in array_of_dicts:
page.get_by_placeholder('input id').fill(i['id'])
page.get_by_test_id("btnSubmit").click()
try:
success = page.wait_for_selector('#success', state='visible')
print('Success:', success.text_content())
except TimeoutError:
pass # Continue to the next step
try:
type_modal = page.wait_for_selector('#type', state='visible')
print('Type Modal:', type_modal.text_content())
except TimeoutError:
pass # Continue to the next step
try:
unregistered_modal = page.wait_for_selector('#unregistered', state='visible')
print('Unregistered Modal:', unregistered_modal.text_content())
except TimeoutError:
print('Unknown') # All conditions failed
page.goto('https://example.com/verify_id')
browser.close()
In this code:
Promise.any
is used to wait for the first condition that resolves (becomes true).TimeoutError
is caught for each condition, allowing the script to continue checking the next condition if the previous one times out.print
statements inside the try
blocks will execute only if the corresponding condition resolves, and the Unknown
print statement will execute if all conditions time out.Remember to adjust the selectors ('#success'
, '#type'
, '#unregistered'
) based on the actual HTML structure of the pages.
Yes, it’s possible to achieve this without using fixed pauses or time.sleep
by using the Race
class in Playwright. The Race
class allows you to wait for the first event to occur among multiple conditions. Here’s how you can modify your code to use Race
:
from playwright.sync_api import sync_playwright, Race
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
page.goto('https://example/login')
page.get_by_placeholder("username").fill("my_username")
page.get_by_placeholder("password").fill("my_password")
page.get_by_role("button", name="submit").click()
for i in array_of_dicts:
page.get_by_placeholder('input id').fill(i['id'])
page.get_by_test_id("btnSubmit").click()
race = Race(page.wait_for_selector('#success', state='visible'),
page.wait_for_selector('#type', state='visible'),
timeout=5000) # Specify a timeout in milliseconds
winner = race.wait()
if winner:
if winner == '#success':
print('success')
elif winner == '#type':
print('type')
else:
print('unknown')
page.goto('https://example.com/verify_id')
browser.close()
In this example, Race
is used to wait for the first condition to be met among the success and type elements. The winner
variable will contain the selector of the first condition that is met. You can then check which condition was met and proceed accordingly.
Make sure to adjust the selectors ('#success'
, '#type'
, etc.) based on the actual structure of your web page.