Selenium Page Factory with JSON and Properties
Selenium Page Factory helps us to implement the Page Object Model design pattern. One of the limitations with the page factory however, is that we can’t read locators from an external resource like a property file or a JSON. To achieve this I have developed custom page factory which is available in maven central.
An example project on the usage is available in github.
In Maven,
In Gradle,
HOW TO USE
If we have a JSON for example,
- name : name of the locator (forgottenPasswordLinkInAlert)
- type : type of the locator ( xpath, css, id etc..)
- value : value of the locator (//div[@role=’alert’)
@SearchBy
- The @FilePath value must be the path to the json
- The nameOfTheLocator value is optional. By default, the variable name is picked up.
Page Factory Initialization
@SearchAll & @SearchBys
There is also support to use @SearchAll just like @FindAll
There is also support to use @SearchBys just like @FindBys
HANDLING DYNAMIC LOCATORS
Let us assume we have a json link below,
[
{
"name": "multipleParamsLink",
"type": "xpath",
"value": "//a[normalize-space()='%1$s']/following-sibling::a[normalize-space()='%2$s']/following-sibling::a[normalize-space()='%3$s']/following-sibling::a[normalize-space()='%4$s']"
}
]
Internally, String.format is used.
Observe %s or %1$s, %2$s and so on are important. These are the params that get replaced.
PageFactory.initElements(new SearchWithFieldDecorator(new FileBasedElementLocatorFactory(driver, this)), this);
protected ByLocators byLocators;
public InitPageObjects(WebDriver driver) {
this.driver = driver;
byLocators = PageFactoryLoader.newInstance().initElements(ByLocators.class);
}
byLocators = PageFactoryLoader.newInstance().initElements(ByLocators.class);
@FilePath(value = "classpath:page_objects/json/page_objects.json")
protected interface ByLocators {
@SearchBy
By multipleParamsLink(String about, String advertising, String business, String howSearchWorks);
}
USAGE
By imagesRelativeLink = RelativeLocator.with(byLocators.linkByText("Images")).toRightOf(byLocators.linkByText("Gmail"));
driver.findElement(imagesRelativeLink).click();
TYPE
type we provide in JSON is case-sensitive
Below is a list of all the types supported
- id
- css
- className
- xpath
- linkText
- partialLinkText
- name
- tagName
- accessibilityId
- uiautomator
- IosUIautomation
- iosClassChain
- androidViewTag
- iOSNsPredicateString
- image
- windowsAutomation
- custom