Ну у меня из-за специфики проекта, как плюс это считаю, повторяются многие элементы и локаторы на страницах, но может быть такое что в разных блоках страницы то уже структурирую по компонентам и степам к ним и объединяю в страницы это всё чудо.
Т.к. есть кастомные решения для выпадаек и для кнопок, то есть объекты со специфическими методами для их манипуляций.
public class ProductButton extends AbstractElement{
@FindBy(css = "a.ga-add-to-cart")
public SelenideElement buttonAddToCart;
@FindBy(css = "a.button-preorder")
public SelenideElement buttonPreOrder;
@FindBy(css = "span.in-cart > a")
public SelenideElement buttonInCart;
@FindBy(name = "btn-minus")
public SelenideElement buttonMinus;
@FindBy(name = "quantity")
public SelenideElement fieldQuantity;
@FindBy(name = "btn-plus")
public SelenideElement buttonPlus;
@FindBy(css = "span.icon")
public SelenideElement labelStockWithIcon;}
Это всё может находится на разных страницах и может в разных блоках, поэтому есть такая штука в объекте какого-то блока
@FindBy(css = "div.product-button-wrapper") public ProductButton productButton;
Далее, эту кнопку мне нужно найти для определённого товара на странице по id, к примеру на странице категорий. А страница категорий состоит из “строк/блоков” каждой единицы товара и чтобы взять определённого товара блок и только в нём работать есть акая штука:
public class ProductList extends AbstractElement {
public ProductsLineBlock findProductByIDInTags(String id, String tagName) {
return initContainer($(String.format("%s[data-id='%s']", tagName, id)),
ProductsLineBlock.class);
}
}
Именно так потому что вид страницы может быть в виде таблицы, строк с расширенным описанием или строк без описание. И таким способом я дальше могу работать с локаторами которые содержатся в ProductsLineBlock. В котором есть особенная кнопка “Купить”
Вот что содержится в AbstractElement
public abstract class AbstractElement extends ElementsContainer{
protected <T extends AbstractElement> T initContainer(SelenideElement element, Class<? extends AbstractElement> type) {
T result;
try {
result = (T) type.newInstance();
} catch (Exception e) {
throw new RuntimeException("Failed to create elements container for element", e);
}
PageFactory.initElements(new SelenideFieldDecorator(element), result);
result.setSelf(element);
return result;
}
Вот к примеру кастомная выпадайка и метод для неё
public class CustomDropdown extends AbstractElement {
public void selectItem(String nameOfItem){
getSelf().click();
$(byXpath(String.format("//span[.='%s']", nameOfItem))).scrollTo().click();
}}
Таких кастомных 3 штуки есть, + есть аналог для номера телефона и выбора кода страны, составной элемент с инпутом и выпадайкой
Также есть кастомные элементы это поиск, у него есть выпадайка с перечнем категорий в которых искать, + составной из двух блоков быстрый поиск.
Это всё классы компоненты страниц и из них я уже леплю степы для них, которые объединяю в пакеты страниц.
Пример теста: public class TestTest extends BaseTest {
@Test
public void olo(){
Configuration.baseUrl = TestData.urlMainPageGSMCom;
addProductViaAjaxUrl(simpleProduct);
open(urlCheckout);
CheckoutContactInformationSteps checkoutContactInformationSteps = getStepsFrom(CheckoutContactInformationSteps.class);
checkoutContactInformationSteps.testMethod();
}
}
Где getSteps это:
protected static <T> T getStepsFrom(Class<? extends AbstractSteps> pageObjectClass) {
return (T) page(pageObjectClass);
}
ну и testMethod
public CheckoutContactInformationSteps testMethod(){
this.checkoutContactInformation.customCountry.selectItem(TURKEY);
this.checkoutContactInformation.customPhone.setPhoneByCountry(TURKEY, TestData.CONTACT_NUMBER);
return this;
}