This error message...
<class 'selenium.common.exceptions.WebDriverException'>
Message: The command 'GET /session/.../displayed' was not found.
...implies that the GET request to /session/{session id}/element/{element id}/displayed
failed.
element displayed
As per the WebDriver W3C Editor's Draft the element displayed algorithm is a boolean state where true
signifies that the element is displayed and false
signifies that the element is not displayed. To compute the state on element, invoke the Call(bot.dom.isShown, null, element)
. If doing so does not produce an error, return the return value from this function call. Otherwise return an error with error code unknown error.
This function is typically exposed to GET requests with a URI Template of
/session/{session id}/element/{element id}/displayed
Analysis
You have invoked:
WebDriverWait(driver, 30).until(expected_conditions.element_to_be_clickable((By.CSS_SELECTOR, "#search")))
element_to_be_clickable()
class internally invokes visibility_of_element_located()
and is defined as:
class element_to_be_clickable(object):
""" An Expectation for checking an element is visible and enabled such that you can click it."""
def __init__(self, locator):
self.locator = locator
def __call__(self, driver):
element = visibility_of_element_located(self.locator)(driver)
if element and element.is_enabled():
return element
else:
return False
Now, visibility_of_element_located()
class returns _element_if_visible(_find_element(driver, self.locator))
which is defined as:
class visibility_of_element_located(object):
""" An expectation for checking that an element is present on the DOM of a
page and visible. Visibility means that the element is not only displayed
but also has a height and width that is greater than 0.
locator - used to find the element
returns the WebElement once it is located and visible
"""
def __init__(self, locator):
self.locator = locator
def __call__(self, driver):
try:
return _element_if_visible(_find_element(driver, self.locator))
except StaleElementReferenceException:
return False
Again, _element_if_visible()
returns element if element.is_displayed() == visibility else False
which is defined as:
def _element_if_visible(element, visibility=True):
return element if element.is_displayed() == visibility else False
So, as the if()
condition of element.is_displayed() == visibility
failed hence you see the error as GET
request to the /session/{session id}/element/{element id}/displayed
endpoint failed.
Without the relevant HTML and previous steps it is tough to guess the exact reason but possibly can be either of the following:
Reason
The reason for NoSuchElementException can be either of the following :
- The Locator Strategy you have adopted doesn't identifies any element in the HTML DOM.
- The Locator Strategy you have adopted is unable to identify the element as it is not within the browser's Viewport.
- The Locator Strategy you have adopted identifies the element but is invisible due to presence of the attribute style="display: none;".
- The Locator Strategy you have adopted doesn't uniquely identifies the desired element in the HTML DOM and currently finds some other hidden / invisible element.
- The WebElement you are trying to locate is within an
<iframe>
tag.
Solution
The solution to address NoSuchElementException can be either of the following :
Adopt a Locator Strategy which uniquely identifies the desired WebElement. You can take help of the Developer Tools (Ctrl+Shift+I or F12) and use Element Inspector.
Here you will find a detailed discussion on how to inspect element in selenium3.6 as firebug is not an option any more for FF 56?
Use execute_script()
method to scroll the element in to view as follows :
elem = driver.find_element_by_xpath("element_xpath")
driver.execute_script("arguments[0].scrollIntoView();", elem)
Here you will find a detailed discussion on Scrolling to top of the page in Python using Selenium
Incase element is having the attribute style="display: none;", remove the attribute through executeScript()
method as follows :
elem = driver.find_element_by_xpath("element_xpath")
driver.execute_script("arguments[0].removeAttribute('style')", elem)
elem.send_keys("text_to_send")
To check if the element is within an <iframe>
traverse up the HTML to locate the respective <iframe>
tag and switchTo()
the desired iframe through either of the following methods :
driver.switch_to.frame("iframe_name")
driver.switch_to.frame("iframe_id")
driver.switch_to.frame(1) // 1 represents frame index
Here you can find a detailed discussion on How can I select a html element no matter what frame it is in in selenium?.