简体   繁体   中英

Using Python and Selenium WebDriver to wait and click on a visible button

I am having a torrid time trying to click on a button using Webdriver. The button is not visible until a value is entered in a prior field. I have tried adding sleeps and explicit waits but still no luck.

I am thinking it might have something to do with page javascript, but my skills don't quite extend that far. I am still learning so apoligies for my ugly code...

count=1
while count < 3:
time.sleep(2)
# Not the best way to select the button - but it works for now!
elem = driver.find_element_by_tag_name("button").click()
#Clear default amount
elem = driver.find_element_by_name("amount")
elem.send_keys(Keys.BACKSPACE)
elem.send_keys(Keys.BACKSPACE)
elem.send_keys(Keys.BACKSPACE)
elem.send_keys(Keys.BACKSPACE)
elem.send_keys(Keys.BACKSPACE)
elem.send_keys(Keys.BACKSPACE)
elem.send_keys("0.04")
print 'Entered Amount'
time.sleep(1)
elem.send_keys(Keys.TAB)

time.sleep(3)
elem.send_keys(Keys.TAB)

time.sleep(3)
elem.send_keys("\n")

# This finds the button - but it isn't visible
# elem = driver.find_element_by_tag_name("button").click()
time.sleep(6)
print 'Number of Payments = ', count
count = count + 1
print 'Finished!'

The website code looks like this:

<button type="button" class="btn alpha centred-form-button ng-binding" ng-click="accountsPayCtrl.submit()" ng-disabled="!accountsPayCtrl.paymentSubmitted &amp;&amp;
          (!paymentForm.$valid || !accountsPayCtrl.inAmount || !accountsPayCtrl.payToken)" tabindex="0" aria-disabled="false">
        Pay $0.04 now
      </button>

There are no doubt more elegant ways to get to the end result too!

Error I am getting is:

Traceback (most recent call last):
File "C:\MW_Test\energyaust_Explicit_Wait.py", line 43, in <module>
elem = driver.find_element_by_tag_name("button").click()
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webelement.py", line 75, in click
self._execute(Command.CLICK_ELEMENT)
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webelement.py", line 454, in _execute
return self._parent.execute(command, params)
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 201, in execute
self.error_handler.check_response(response)
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 181, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.ElementNotVisibleException: Message: Element is not currently visible and so may not be inter
acted with
Stacktrace:
at fxdriver.preconditions.visible (file:///c:/users/ozmatt/appdata/local/temp/tmpupncqr/extensions/fxdriver@googleco
de.com/components/command-processor.js:9981)
at DelayedCommand.prototype.checkPreconditions_ (file:///c:/users/ozmatt/appdata/local/temp/tmpupncqr/extensions/fxd
river@googlecode.com/components/command-processor.js:12517)
at DelayedCommand.prototype.executeInternal_/h (file:///c:/users/ozmatt/appdata/local/temp/tmpupncqr/extensions/fxdr
iver@googlecode.com/components/command-processor.js:12534)
at DelayedCommand.prototype.executeInternal_ (file:///c:/users/ozmatt/appdata/local/temp/tmpupncqr/extensions/fxdriv
er@googlecode.com/components/command-processor.js:12539)
at DelayedCommand.prototype.execute/< (file:///c:/users/ozmatt/appdata/local/temp/tmpupncqr/extensions/fxdriver@goog
lecode.com/components/command-processor.js:12481)

You should not use sleep under (almost) any circumstance. Instead, the Selenium API provides you with waits, Implicit and Explicit. From the Selenium documentation:

Implicit Waits An implicit wait is to tell WebDriver to poll the DOM for a certain amount of time when trying to find an element or elements if they are not immediately available. The default setting is 0. Once set, the implicit wait is set for the life of the WebDriver object instance.

And for Explicit waits:

Explicit Waits An explicit waits is code you define to wait for a certain condition to occur before proceeding further in the code. The worst case of this is Thread.sleep(), which sets the condition to an exact time period to wait. There are some convenience methods provided that help you write code that will wait only as long as required. WebDriverWait in combination with ExpectedCondition is one way this can be accomplished.

Now, in your case, what you need is to have the element visible, or since you need to click on it, have it clickable:

element = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "myDynamicElement")))

Refer to this for usages of Explicit waits.

Thanks for the suggestions guys. I had a colleague help me solve my issue and thought I would add it on here to perhaps help the next newbie like me.

Turns out that by not finding the detail to find the button, I was actually finding another, hidden button. I feel pretty silly but it is a good lesson!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM