J'ai trouvé quelques indices ici: https://stackoverflow.com/a/3987430/1073584 et finalement réussi à obtenir ce que je voulais en mettant en place 3 classes: CustomPageFactory, CustomElementLocator, CustomAnnotations.
Maintenant, je suis en mesure d'extérioriser mes localisateurs à Typesafe config et utiliser le code suivant pour initialiser la page des objets
// ======= LoginPage
public class LoginPage extends AbstractPage {
Config config;
@FindBy(using = "CONFIG") // take locator from config
WebElement passwordFld;
// .. other fields skipped
public LoginPage(WebDriver webDriver, Config config) throws IOException {
super(webDriver);
this.config = config;
PageFactory.initElements(new CustomPageFactory(webDriver, config), this);
}
}
// == === login.page.typesafe.config:
passwordFld = {
name = "password field"
}
// ============= CustomPageFactory
package com.company.pages.support;
import com.typesafe.config.Config;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.pagefactory.ElementLocator;
import org.openqa.selenium.support.pagefactory.ElementLocatorFactory;
import java.lang.reflect.Field;
public class CustomPageFactory implements ElementLocatorFactory {
private Config config;
private WebDriver driver;
public CustomPageFactory(WebDriver driver, Config config) {
this.driver = driver;
this.config = config;
}
public ElementLocator createLocator(Field field) {
return new CustomElementLocator(driver, field, config);
}
}
// ================ = CustomElementLocator
package com.company.pages.support;
import com.typesafe.config.Config;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.support.pagefactory.DefaultElementLocator;
import java.lang.reflect.Field;
public class CustomElementLocator extends DefaultElementLocator {
private Config config;
public CustomElementLocator(SearchContext searchContext, Field field, Config config) {
super(searchContext, new CustomAnnotations(field, config));
this.config = config;
}
}
// ====== CustomAnnotations
package com.company.pages.support;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigObject;
import org.openqa.selenium.By;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.pagefactory.Annotations;
import java.lang.reflect.Field;
public class CustomAnnotations extends Annotations {
Config config;
public CustomAnnotations(Field field, Config config) {
super(field);
this.config = config;
}
@Override
protected By buildByFromShortFindBy(FindBy findBy) {
if (findBy.using().equals("CONFIG")) {
if (null != config) {
ConfigObject fieldLocators = config.getObject(getField().getName());
if (fieldLocators.keySet().contains("className"))
return By.className(fieldLocators.get("className").unwrapped().toString());
if (fieldLocators.keySet().contains("css"))
return By.cssSelector(fieldLocators.get("css").unwrapped().toString());
if (fieldLocators.keySet().contains("id"))
return By.id(fieldLocators.get("id").unwrapped().toString());
if (fieldLocators.keySet().contains("linkText"))
return By.linkText(fieldLocators.get("linkText").unwrapped().toString());
if (fieldLocators.keySet().contains("name"))
return By.name(fieldLocators.get("name").unwrapped().toString());
if (fieldLocators.keySet().contains("partialLinkText"))
return By.partialLinkText(fieldLocators.get("partialLinkText").unwrapped().toString());
if (fieldLocators.keySet().contains("tagName"))
return By.tagName(fieldLocators.get("tagName").unwrapped().toString());
if (fieldLocators.keySet().contains("xpath"))
return By.xpath(fieldLocators.get("xpath").unwrapped().toString());
}
}
return super.buildByFromShortFindBy(findBy);
}
}
Vos localisateurs changer beaucoup? Pourquoi voulez-vous les lire à partir d'un fichier externe au lieu de simplement les placer dans vos objets de page où ils sont facilement trouvés et organisés? – JeffC
1. J'essaye d'écrire le test agnostique de plate-forme pour des dispositifs d'IOS et android et ne veux pas dupliquer des objets de page 2. La localisation d'UI pourrait être le point suivant où les localisateurs externalisés sont utiles 3. Certains locators peuvent changer dans l'exécution (éléments triés dans un autre ordre, etc) – ludenus