Official Locator Strategies For the Webdriver

Official locator strategies for the webdriver

Yes, you saw it right.

As per the current WebDriver - W3C Candidate Recommendation the Locator Strategies enlisted are as follows:

  • "css selector": CSS selector
  • "link text": Link text selector
  • "partial link text": Partial link text selector
  • "tag name": Tag name
  • "xpath": XPath selector

Snapshot:

Locator Strategies

However, the JsonWireProtocol was once used to support the Locator Strategies enlisted below, but currently the documentation clearly states its Status as obsolete:

  • class name: Returns an element whose class name contains the search value; compound class names are not permitted.
  • css selector: Returns an element matching a CSS selector.
  • id: Returns an element whose ID attribute matches the search value.
  • name: Returns an element whose NAME attribute matches the search value.
  • link text: Returns an anchor element whose visible text matches the search value.
  • partial link text: Returns an anchor element whose visible text partially matches the search value.
  • tag name: Returns an element whose tag name matches the search value.
  • xpath: Returns an element matching an XPath expression. The provided XPath expression must be applied to the server "as is"; if the expression is not relative to the element root, the server should not modify it. Consequently, an XPath query may return elements not contained in the root element's subtree.

Snapshot:

Locator Strategies

The change was propagated through the respective client-specific bindings. For the Selenium-Java clients here is the client code where we have the switch case working for the users:

        switch (using) {
case "class name":
toReturn.put("using", "css selector");
toReturn.put("value", "." + cssEscape(value));
break;

case "id":
toReturn.put("using", "css selector");
toReturn.put("value", "#" + cssEscape(value));
break;

case "link text":
// Do nothing
break;

case "name":
toReturn.put("using", "css selector");
toReturn.put("value", "*[name='" + value + "']");
break;

case "partial link text":
// Do nothing
break;

case "tag name":
toReturn.put("using", "css selector");
toReturn.put("value", cssEscape(value));
break;

case "xpath":
// Do nothing
break;
}
return toReturn;

Which locator strategies can be used to find the element in selenium for the below code

As per the HTML you can use only the following Locator Strategies:

  • LinkText:

    Yearbooks   
  • Xpath:

    "//a[@class='collapsed noRewrite' and contains(@data-target, 'menu-yearbooks')]"

Viable locator strategies for partial link text in webdriver

Your question

Is visibility of element located a sub-par choice for partial link
text?

No, absolutely no.

See what is underneath of visibility_of_element_located Method :-

""" 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
"""
class visibility_of_element_located(object):
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

so basically it calls,

_element_if_visible

and this is what we have

def _element_if_visible(element, visibility=True):
return element if element.is_displayed() == visibility else False

So, direct answer to your question is No. But it depends, how you have defined EC, in your case, Are you sure if that is the unique link_text or partial_link_text,
did you try changing that to css or xpath and verified like below ?

//*[contains(text(),'Hello')]

in code :

msg_receive_1 = WebDriverWait(driver1, 15).until(
EC.visibility_of_element_located((By.XPATH, "//*[contains(text(),'Hello')]"))
)

as an xpath ?

How to find elements on gipfy.com using Selenium Webdriver

The locator strategy you have used:

/html/body/div[4]/div[1]/div/div[6]/div[2]/div[1]

identifies only one element within the HTML DOM, hence you see only a single element.

To extract the value of the href attributes you have to induce WebDriverWait for visibility_of_all_elements_located() and you can use either of the following locator strategies:

  • Using XPATH:

    driver.get("https://giphy.com/search/pixelart")
    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Agree and close']"))).click()
    print([my_elem.get_attribute("href") for my_elem in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//picture//ancestor::a[1][@href]")))])
  • Console Output:

    ['https://giphy.com/gifs/party-epic-fest-26AHzeyITON4vzMM8', 'https://giphy.com/gifs/2tTh7wB6DtL1QQvAF5', 'https://giphy.com/gifs/perfect-loops-pVGsAWjzvXcZW4ZBTE', 'https://giphy.com/gifs/bw-pixelart-minimalism-3oEdvc7q2VwJFEQDGU', 'https://giphy.com/gifs/hoppip-heart-hoppip-pixel-BXVRf5GyMlElO', 'https://giphy.com/gifs/1yld7nW3oQ2IyRubUm', 'https://giphy.com/gifs/breakfast-bacon-egg-3oEdv9R4D62GPrVY4g', 'https://giphy.com/gifs/80s-synthwave-aesthetic-84SFZf1BKgzeny1WxQ', 'https://giphy.com/gifs/hoppip-heart-hoppip-pixel-1S9kD6xm4601O', 'https://giphy.com/gifs/xWMPYx55WNhX136T0V', 'https://giphy.com/gifs/perfect-loops-9LZTcawH3mc8V2oUqk', 'https://giphy.com/gifs/art-pixel-TRebCjNbc4dIA', 'https://giphy.com/gifs/80s-synthwave-aesthetic-k81NasbqkKA5HSyJxN', 'https://giphy.com/gifs/pixel-art-scenery-pI43YlhMoPqsE', 'https://giphy.com/gifs/pixel-sky-pixelart-2wh8ugh52dGSJYrA26', 'https://giphy.com/gifs/art-pixel-rzeWnbH8Uc5Y4', 'https://giphy.com/gifs/S5uMJDmtnATLbjjw3h', 'https://giphy.com/gifs/earth-spinning-globe-l3V0megwbBeETMgZa', 'https://giphy.com/gifs/pixel-netflix-art-26hisvCylQN7VcaOI', 'https://giphy.com/gifs/pixel-art-10GVNnqO2ZoAh2', 'https://giphy.com/gifs/art-pixel-marvel-NPd2pkbsjftS3O3U9c', 'https://giphy.com/gifs/OpCIhPH16jzsL3IzRp', 'https://giphy.com/gifs/animation-nes-pixelart-26tn84fF0eL3c898c', 'https://giphy.com/gifs/pixels-16bit-picel-art-3o85xunRezGKPOkcG4', 'https://giphy.com/gifs/pixel-art-octobit-pixeltober-l3vRgqJIdbRp7Exfa']

How to get the text from element in Selenium

Considering the HTML:

<td id="balance" class="ng-binding">$315.50</td>

To identify the element you can use either of the following locator strategies:

  • Using id:

    @FindBy(how = How.ID, using = "balance")
    private WebElement balance;
  • Using cssSelector:

    @FindBy(how = How.CSS, using = "td#balance")
    private WebElement balance;
  • Using xpath:

    @FindBy(how = How.XPATH, using = "//td[@id='balance']")
    private WebElement balance;

To print the text:

  • Using getText():

    System.out.println(balance.getText())
  • Using getAttribute("innerHTML"):

    System.out.println(balance.getAttribute("innerHTML"))
  • Using getAttribute("innerText"):

    System.out.println(balance.getAttribute("innerText"))
  • Using getAttribute("textContent"):

    System.out.println(balance.getAttribute("textContent"))

Selenium findElement(By.CSS_SELECTOR)

The classnames i.e. sc-pjTqr, dzmlqP are dynamically generated and is bound to chage sooner/later. They may change next time you access the application afresh or even while next application startup. So can't be used in locators.



Solution

To identify the element with text as Continue you can use the following locator strategy:

  • Using xpath:

    continue = driver.find_element(By.XPATH, "//button[text()='Continue']")

Ideally to identify the clickable element you need to induce WebDriverWait for the element_to_be_clickable() and you can use the following locator strategy:

  • Using XPATH:

    continue = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[text()='Continue']")))
  • 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

Find items within <li> tags using Selenium

The locator strategies you have tried were a bit errorprone. The desired elements are within <li> having class attribute as product-list detail

<div class='product'> 
<div class='menuList1'> Menu1 Menu2</div>
<div class='menuList2'> aaa </div>
<ul id='productDetail' class='product-list'>
<li class='product-list detail' id='1'> Item1</li>
<li class='product-list detail' id='2'> Item2</li>
<li class='product-list detail' id='3'> Item3</li>
<li class='product-list detail' id='4'> Item4</li>
</ul>
</div>


Solution

To find the elements within the <li> tags you can use either of the following locator strategies:

  • Using css_selector:

    elms = driver.find_elements(By.CSS_SELECTOR, "div.product div.menuList2 > ul.product-list li.product-list.detail")
  • Using xpath:

    elms = driver.find_elements(By.XPATH, "//div[@class='product']//div[@class='menuList2']/ul[@class='product-list']//li[@class='product-list detail']")


Related Topics



Leave a reply



Submit