I want to write my own locator to access the elements. WebDriver’s API offers currently eight locators allowing to retrieve elements by id, name attribute, tag name, complete or partial link text, XPath, class name, and css selector. However those default locators not enough for me now because I have to access the elements through a new attribute. Let me give an xample so that you can understand what I really want here.
Example: Choose your username:
Now I want to write a code so that I can access the username button using the myLocator locator like:
*driver.findElement(By.myLocator("username")).*
It would be very helpful if anybody can give us some good idea how could I rewrite the BY class to add my own locator.
Thank you in advance for your help.
Selenium supports 8 different types of locators namely id, name, className, tagName, linkText, partialLinkText, CSS selector and xpath.
ID locator in Selenium is the most preferred and fastest way to locate desired WebElements on the page. ID Selenium locators are unique for each element in the DOM. Since IDs are unique for each element on the page, it is considered the fastest and safest method to locate elements.
Aim for the long-hanging fruit One of Selenium best practices for locators is to always look for unique stuff. In ~90% of cases, we're talking about unique IDs. The remaining 10% account for things like unique name tags, link content (anchor texts), or links that you can use in combination with parent-child structures.
using c#
using OpenQA.Selenium;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public class ImageBy : By
{
public ImageBy(string imageByString)
{
FindElementMethod = (ISearchContext context) =>
{
IWebElement mockElement = context.FindElement(By.XPath("//img[@src='" + imageByString + "']"));
return mockElement;
};
FindElementsMethod = (ISearchContext context) =>
{
ReadOnlyCollection<IWebElement> mockElements = context.FindElements(By.XPath("//img[@src='" + imageByString + "']"));
return mockElements;
};
}
}
and the usage would be as follows
[FindsBy(How = How.Custom, Using = @"/path/to/img", CustomFinderType = typeof(ImageBy) )]
private IWebElement MenuStartButton = null;
Using Java
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.WebElement;
public class ByImageSrc extends By
{
private final String imageByString;
public ByImageSrc(String imageByString)
{
this.imageByString = imageByString;
}
@Override
public List<WebElement> findElements(SearchContext context)
{
List<WebElement> mockElements = context.findElements(By.xpath("//img[@src='" + imageByString + "']"));
return mockElements;
}
}
usage :
WebElement element = driver.findElement(new ByImageSrc("/path/to/image"));
You would need to subclass the By
class and provide an implementation for findElement
and findElements
methods, since this is where the 'meat' of the actual element finding occurs.
You should then be able to use it with the normal driver.FindElement
then.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With