8

I have an internal web application that has a modal dialog. Unfortunately I cannot post the actual web application location here, but let me describe this as best as possible.

  • When the application starts, you get a box on the screen that tells you a bunch of text. You can press "next" to get the next page of text.
  • On the final page, the "next" button is disabled, and the rest of the UI of the web application is enabled.
  • There are a variable number of pages, so I don't know how many times I have to click "next".

I'm able to click through a fixed number of times (ex: if I know there's two pages I can click twice) but I am unsure how to vary this so that it'll run no matter what number of pages I have. I would like a general solution; presumably this uses a loop of some sort that would check if the button is enabled. If it is, then click it. If it's disabled, then exit the loop.

The question is: How can I set up a loop in Selenium that clicks a button repeatedly until it is disabled?

Here's the code I've tried:

from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC # available since 2.26.0

# Create a new instance of the Firefox driver
driver = webdriver.Firefox()

driver.get("http://localhost/myapp")

try:
    wait = WebDriverWait(driver, 100)    
    wait.until(EC.element_to_be_clickable((By.ID,'menuIntroBox_buttonNext')))    
    driver.find_element_by_id("menuIntroBox_buttonNext").click()

    # Click through the introduction text... this is the problematic code.
    # Here I tried to wait for the element to be clickable, then tried to do a while 
    # loop so I can click on it as long as it's clickable, but it never seems to do the
    # break.
    wait.until(EC.element_to_be_clickable((By.ID,'main_buttonMissionTextNext')))
    while EC.element_to_be_clickable((By.ID,'main_buttonMissionTextNext')):
        element = driver.find_element_by_id("main_buttonMissionTextNext")
        element.click()
        print "Waiting until it's clickable."

        if not element.is_enabled():
            break

    print "Here is where I'd do other stuff.... the stuff I want to actually do in the test case."
finally:
    driver.quit()
Irwin
  • 422
  • 5
  • 13
  • Why are you checking the same condition in the `while` and in an `if not… break` inside the `while`? – abarnert Apr 05 '13 at 00:49
  • Meanwhile, are you sure the "Next" button is actually disabled? If it's, say, enabled but just does nothing, `element_to_be_clickable` will be true. – abarnert Apr 05 '13 at 00:51
  • This isn't just one question. It is a whole bunch of questions. Can you please edit your question and narrow it down to something we can specifically help you with? – djangofan Apr 05 '13 at 02:05
  • @abarnert: The button does become disabled, I've checked the DOM. The "if not ..." was just an idea, since the button is disabled only after you click on it. I can edit this, but the code still doesn't work as intended. – Irwin Apr 05 '13 at 02:32

2 Answers2

2

Figured it out. Here's the relevant code block:

wait.until(EC.element_to_be_clickable((By.ID, 'main_buttonMissionTextNext')))
while EC.element_to_be_clickable((By.ID,'main_buttonMissionTextNext')):
    driver.find_element_by_id("main_buttonMissionTextNext").click()
    if not driver.find_element_by_id("main_buttonMissionTextNext").click().is_enabled():
        break
    wait.until(EC.element_to_be_clickable((By.ID, 'main_buttonMissionTextNext')))

Two things I found out:

  1. You can check if an element is enabled using is_enabled().
  2. You have to re-search the DOM for the element after clicking on it. I'm guessing that the dialog redraws itself, so you need to find it again.

I can likely refactor this to look nicer but the basic idea is here now.

Irwin
  • 422
  • 5
  • 13
0
While driver.find_element_by_id("main_buttonMissionTextNext").isEnabled() {
  driver.find_element_by_id("main_buttonMissionTextNext").click();
  sleep(1);
}

//sleep function is in java, so you can "translate" it in python 
void sleep(int i){
  driver.manage().timeouts().implicitlyWait(i, TimeUnit.SECONDS);
}

try it and tell me what's up.

e1che
  • 1,241
  • 1
  • 17
  • 34