I'm trying to work with Selenium Webdriver with Python, automating the Chrome browser.
In re-optimising my code, I'm trying to get rid of any time.sleep()
commands and using implicit and explicit waits when possible.
The part I'm stuck on is an iframe / modal dialog - after switching to it I still need to wait for the modal dialog to load before I can interact with elements without errors.
Code that works:
driver.find_element(By.ID, "process").click() # Process form button - creates modal dialog
time.sleep(2) # Delay to wait for the frame to load
driver.switch_to.frame("acsframe") # acsframe is the ID of the modal dialog
driver.find_element(By.CSS_SELECTOR, r'input.btn.btn-warning').click() # Cancel button
Code that I'm trying to get to work:
driver.find_element(By.ID, "process").click() # Process form button
WebDriverWait(driver, 5).until(EC.frame_to_be_available_and_switch_to_it((By.ID, "acsframe")))
WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.CSS_SELECTOR, r'input.btn.btn-warning')))
driver.find_element(By.CSS_SELECTOR, r'input.btn.btn-warning').click() # Cancel button
Error Message:
NoSuchWindowException Traceback (most recent call last)
<ipython-input-24-acf8921ff08a> in <module>
2 WebDriverWait(driver, 5).until(EC.frame_to_be_available_and_switch_to_it((By.ID, "acsframe")))
----> 3 WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.CSS_SELECTOR, r'input.btn.btn-warning')))
4 driver.find_element(By.CSS_SELECTOR, r'input.btn.btn-warning').click()
I don't understand how/why I would be getting an error message here. I switch to the frame on line 2, and line 3 works about 1 time in 10, but otherwise throws an error. I know the element locator is right because it worked in the first example. If time.sleep()
worked, why wouldn't this work?
I've tried changing between XPATH and CSS Selector for locating the elements and it's the same result. There aren't any IDs for the buttons.
Update: This code also works:
driver.find_element(By.ID, "process").click() # Process form button
time.sleep(2)
WebDriverWait(driver, 5).until(EC.frame_to_be_available_and_switch_to_it((By.ID, "acsframe")))
WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.CSS_SELECTOR, r'input.btn.btn-warning')))
driver.find_element(By.CSS_SELECTOR, r'input.btn.btn-warning').click()
So it seems that a delay before waiting for the frame fixes it - but isn't that the entire purpose of the command to wait for the frame to be available? I still want a way to get this to work without time.sleep()
.
Screenshot of the relevant HTML
question from:
https://stackoverflow.com/questions/65626913/selenium-webdriver-with-python-nosuchwindowexception-after-using-frame-to-be-a