Reputation: 767
I am trying to do logout on a web page by selenium and python, and currently no luck. In order to do a logout, I need to click the link at the upper right corner of the web page, and it will have a small drop-down window open, and then I can click the "logout" icon inside this drop-down window. Here is the picture of this drop down window.
And the inspect code for this logout icon in the dropdown window.
Now in my python code, I was able to have the drop-down window open, but if I was to click the logout icon, I keep getting exception of "selenium.common.exceptions.ElementNotVisibleException".
Here is my code:
try:
# to click the link so that the drop-down window opens
action = ActionChains(self.driver)
dropdownwindow= self.driver.find_element_by_xpath("//span[@class='ssobanner_logged']/img")
action.move_to_element(dropdownwindow).perform()
dropdownwindow.click()
# try to click the logout icon in the drop-down so that user may logout
logoutLink = self.driver.find_element_by_xpath(
"//*[@id='ctl00_HeaderAfterLogin1_DL_Portals1']/tbody/tr/td[4]/a/img")
action.move_to_element(logoutLink).perform()
logoutLink.click()
return True
except Exception as e:
self.logger.info(e)
raise
return False
And I have got such exceptions during the run time.
selenium.common.exceptions.NoSuchElementException:
Message: no such element: Unable to locate element:
{"method":"xpath","selector":"//*[@id='ctl00_HeaderAfterLogin1_DL_Portals1']/tbody/tr/td[4]/a/img"}
Does anyone know a better way to handle that, other than the xpath I was using ?
Upvotes: 0
Views: 2995
Reputation: 193098
Once the drop-down window opens up to click on the icon with text as Logout you need 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, "span.portals-separator +table td>a[title='Log out'][data-mkey='Logout']>img"))).click()
Using XPATH
:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Support and Settings']//following-sibling::table[1]//td/a[@title='Log out' and @data-mkey='Logout']/img"))).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
Upvotes: 1
Reputation: 798
The problem is most likely that the dropdown menu has not fully been expanded/rendered after it is clicked. While a time.sleep(1)
command could be a potential fix, a more appropriate fix is a dynamic wait using WebDriverWait
:
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.ui import WebDriverWait
by = By.XPATH # This could also be By.CSS_SELECTOR, By.Name, etc.
hook = "//*[@id='ctl00_HeaderAfterLogin1_DL_Portals1']/tbody/tr/td[4]/a/img"
max_time_to_wait = 10 # Maximum time to wait for the element to be present
WebDriverWait(driver, max_time_to_wait).until(expected_conditions.element_to_be_clickable((by, hook)))
expected_conditions
can also wait using visibility_of_element_located
or presence_of_element_located
Upvotes: 1