0

In this scenario, I am trying to click on the submit button with Selenium webdriver but so far have been unable to click the element.

<button type="submit" class="pcty-button pcty-size-medium pcty-button-full-width pcty-button-full-width-mobile pcty-size-responsive submit-button login-button">Login</button>

The code that I have to locate the button as it is now reads as:

WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[@type='submit' and normalize-space()='Login']"))).click()

I thought that this code was covering all of the bases and expected it to click the button, but have had no luck so far. Every error I have seen with other code has raised that no element existed or it was unable to locate.

The error that I get is:

raise TimeoutException(message, screen, stacktrace) selenium.common.exceptions.TimeoutException

I've used some answers to try and find a solution from these threads: 1 and 2 but as of right now I have no clue what I am doing wrong.

I have been asked for a larger part of the HTML of this webpage for context.

If I need to expand even more of it, I am happy to do so. The answers provided have been tested and come up with the same timeout errors.

      <div class="pcty-col pcty-padding-top pcty-large-padding-horizontal">
        <div class="pcty-input pcty-input-checkbox">
          <label class="pcty-checkbox-label pcty-input-label" for="IsRememberingUser">
            <input type="checkbox" checked="checked" data-val="true" data-val-required="The IsRememberingUser field is required." id="IsRememberingUser" name="IsRememberingUser" value="true">Remember My Username
          </label>
        </div>
      </div>
    </div>

  <div class="pcty-row-flex">
    <div class="pcty-col pcty-padding-top pcty-large-padding-horizontal">
      <button type="submit" class="pcty-button pcty-size-medium pcty-button-full-width pcty-button-full-width-mobile pcty-size-responsive submit-button login-button">Login</button>
    </div>
  </div>```

2 Answers2

0

Instead of normalize-space(), I would try using just contains(text(), 'Login'):

WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Login')]"))).click()

Since the above solution doesn't seem to be working for you, I also wrote up a fully-working code sample that successfully runs against the page link you provided. I was able to successfully send credentials and click the login button using the following:

from selenium import webdriver
from time import sleep
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC


driver=webdriver.Chrome()
driver.get("https://access.paylocity.com/")

# company id - send keys
WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "CompanyId"))).send_keys("test_company_id")

# username - send keys
WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "Username"))).send_keys("test_username")


# password - send keys
WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "Password"))).send_keys("test_PASSWORD")

# login - click button
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Login')]"))).click()

# result: "The credentials provided are incorrect", meaning login button click succeeded

sleep(10) # explicit sleep here so i can visually observe the results on browser
driver.close()
driver.quit()

My code snippet uses the exact line of code I provided at the top of this answer, so I'm not sure why it wouldn't work for you. If the full sample in this answer works for you, but the single line of code does not work in the context of your own code, then something else must be interfering that is causing this issue.

If the full sample in this answer does not work for you, then the issue may be outside of Selenium.

CEH
  • 5,701
  • 2
  • 16
  • 40
  • Hi, I added more of the HTML from the page I have working with. Will you take a look and tell me if there is something present that would explain the errors currently? Thank you. – Taylor Dean Nov 20 '19 at 16:08
  • Based on the sample, I don't see anything that could be wrong. We will probably need to see the full page HTML or a link to the page you are automating -- my guess, like another user has suggested, could be hidden `iframe`. – CEH Nov 20 '19 at 16:19
  • Interesting, I was able to navigate to the website and send test credentials and successfully click the login button using the code sample I provided. Not sure what the issue is here -- I provided my full, working code sample that may hopefully give some insight. I ran this against the URL you provided with success. – CEH Nov 20 '19 at 18:41
  • it is the only `button` on the starting page, can you not find it by tag name rather than XPATH? – A_Patterson Nov 20 '19 at 18:49
  • It's better practice in general to use more specific XPaths like the one from my sample. If the website develop ever adds another button on the page, the`find_by_tag_name` code will not work anymore. Why bother with refactoring when you can just write a specific XPath to begin with? – CEH Nov 20 '19 at 18:51
  • If you are just going to reference IDs in your locators, it's better if you just use By.ID instead of XPath. It's better supported, clearer to read (more clearly indicates intent, etc.) – JeffC Nov 20 '19 at 22:27
  • I originally went with XPath because Login button did not have an ID, but `By.ID` for the other fields (company, username, password) is better practice. – CEH Nov 20 '19 at 23:04
0

To click() on the element you have to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following Locator Strategies:

  • Using CSS_SELECTOR:

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.pcty-button.pcty-size-medium.pcty-button-full-width.pcty-button-full-width-mobile.pcty-size-responsive.submit-button.login-button[type='submit']"))).click()
    
  • Using XPATH:

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[@class='pcty-button pcty-size-medium pcty-button-full-width pcty-button-full-width-mobile pcty-size-responsive submit-button login-button' and text()='Login']"))).click()
    
  • Note : You have to add the following imports :

    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352