Simplify mobile page objects and stabilize ID-based components
This commit is contained in:
@@ -1,25 +1,27 @@
|
|||||||
package ru.otus.mobile.component;
|
package ru.otus.mobile.component;
|
||||||
|
|
||||||
|
import com.codeborne.selenide.SelenideElement;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import ru.otus.mobile.config.MobileConfig;
|
import io.appium.java_client.AppiumBy;
|
||||||
|
|
||||||
|
import static com.codeborne.selenide.appium.SelenideAppium.$;
|
||||||
|
|
||||||
public final class AlertDialogComponent extends BaseMobileComponent {
|
public final class AlertDialogComponent extends BaseMobileComponent {
|
||||||
|
private final SelenideElement positiveButton;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public AlertDialogComponent(MobileConfig config) {
|
public AlertDialogComponent() {
|
||||||
super(config);
|
this($(AppiumBy.id("android:id/content")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public AlertDialogComponent(SelenideElement root) {
|
||||||
|
super(root);
|
||||||
|
this.positiveButton = byIdInRoot("android:id/button1");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void acceptIfVisible() {
|
public void acceptIfVisible() {
|
||||||
if (exists("android:id/button1")) {
|
if (positiveButton.exists()) {
|
||||||
tap("android:id/button1");
|
positiveButton.click();
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (byText("OK").exists()) {
|
|
||||||
byText("OK").click();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (byText("ОК").exists()) {
|
|
||||||
byText("ОК").click();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,22 @@
|
|||||||
package ru.otus.mobile.component;
|
package ru.otus.mobile.component;
|
||||||
|
|
||||||
import ru.otus.mobile.config.MobileConfig;
|
import com.codeborne.selenide.ElementsCollection;
|
||||||
|
import com.codeborne.selenide.SelenideElement;
|
||||||
|
import io.appium.java_client.AppiumBy;
|
||||||
import ru.otus.mobile.page.AbsPageObject;
|
import ru.otus.mobile.page.AbsPageObject;
|
||||||
|
|
||||||
public abstract class BaseMobileComponent extends AbsPageObject {
|
public abstract class BaseMobileComponent extends AbsPageObject {
|
||||||
protected BaseMobileComponent(MobileConfig config) {
|
protected final SelenideElement root;
|
||||||
super(config);
|
|
||||||
|
protected BaseMobileComponent(SelenideElement root) {
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SelenideElement byIdInRoot(String id) {
|
||||||
|
return root.$(AppiumBy.id(fullIdValue(id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ElementsCollection allByIdInRoot(String id) {
|
||||||
|
return root.$$(AppiumBy.id(fullIdValue(id)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,31 @@
|
|||||||
package ru.otus.mobile.component;
|
package ru.otus.mobile.component;
|
||||||
|
|
||||||
|
import com.codeborne.selenide.SelenideElement;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import ru.otus.mobile.config.MobileConfig;
|
import io.appium.java_client.AppiumBy;
|
||||||
|
|
||||||
|
import static com.codeborne.selenide.appium.SelenideAppium.$;
|
||||||
|
|
||||||
public final class BottomNavigationComponent extends BaseMobileComponent {
|
public final class BottomNavigationComponent extends BaseMobileComponent {
|
||||||
|
private final SelenideElement mineMenu;
|
||||||
|
private final SelenideElement usersMenu;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public BottomNavigationComponent(MobileConfig config) {
|
public BottomNavigationComponent() {
|
||||||
super(config);
|
this($(AppiumBy.id(fullIdValue("bottom_navigation"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
public BottomNavigationComponent(SelenideElement root) {
|
||||||
|
super(root);
|
||||||
|
this.mineMenu = byIdInRoot("mine_menu");
|
||||||
|
this.usersMenu = byIdInRoot("users_menu");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void openWishlists() {
|
public void openWishlists() {
|
||||||
tap("mine_menu");
|
mineMenu.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void openUsers() {
|
public void openUsers() {
|
||||||
tap("users_menu");
|
usersMenu.click();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,35 @@
|
|||||||
package ru.otus.mobile.component;
|
package ru.otus.mobile.component;
|
||||||
|
|
||||||
|
import com.codeborne.selenide.SelenideElement;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import ru.otus.mobile.config.MobileConfig;
|
import io.appium.java_client.AppiumBy;
|
||||||
|
|
||||||
|
import static com.codeborne.selenide.appium.SelenideAppium.$;
|
||||||
|
|
||||||
public final class GiftFormComponent extends BaseMobileComponent {
|
public final class GiftFormComponent extends BaseMobileComponent {
|
||||||
|
private final SelenideElement nameInput;
|
||||||
|
private final SelenideElement priceInput;
|
||||||
|
private final SelenideElement saveButton;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public GiftFormComponent(MobileConfig config) {
|
public GiftFormComponent() {
|
||||||
super(config);
|
this($(AppiumBy.id("android:id/content")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public GiftFormComponent(SelenideElement root) {
|
||||||
|
super(root);
|
||||||
|
this.nameInput = byIdInRoot("name_input");
|
||||||
|
this.priceInput = byIdInRoot("price_input");
|
||||||
|
this.saveButton = byIdInRoot("save_button");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save(String name, String price) {
|
public void save(String name, String price) {
|
||||||
type("name_input", name);
|
nameInput.click();
|
||||||
type("price_input", price);
|
nameInput.clear();
|
||||||
tap("save_button");
|
nameInput.sendKeys(name);
|
||||||
|
priceInput.click();
|
||||||
|
priceInput.clear();
|
||||||
|
priceInput.sendKeys(price);
|
||||||
|
saveButton.click();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package ru.otus.mobile.component;
|
||||||
|
|
||||||
|
import com.codeborne.selenide.SelenideElement;
|
||||||
|
|
||||||
|
import static com.codeborne.selenide.Condition.text;
|
||||||
|
|
||||||
|
public final class GiftItemComponent extends BaseMobileComponent {
|
||||||
|
private final SelenideElement title;
|
||||||
|
private final SelenideElement editButton;
|
||||||
|
|
||||||
|
public GiftItemComponent(SelenideElement root) {
|
||||||
|
super(root);
|
||||||
|
this.title = byIdInRoot("title");
|
||||||
|
this.editButton = byIdInRoot("edit_button");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String titleText() {
|
||||||
|
return title.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shouldHaveTitle(String value) {
|
||||||
|
title.shouldHave(text(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void open() {
|
||||||
|
title.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void edit() {
|
||||||
|
editButton.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package ru.otus.mobile.component;
|
||||||
|
|
||||||
|
import com.codeborne.selenide.ElementsCollection;
|
||||||
|
import com.codeborne.selenide.SelenideElement;
|
||||||
|
import io.appium.java_client.AppiumBy;
|
||||||
|
|
||||||
|
public final class GiftsContentComponent extends BaseMobileComponent {
|
||||||
|
private final ElementsCollection items;
|
||||||
|
|
||||||
|
public GiftsContentComponent(SelenideElement root) {
|
||||||
|
super(root);
|
||||||
|
this.items = root.$$(AppiumBy.id(fullIdValue("gift_item")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public GiftItemComponent get(int index) {
|
||||||
|
return new GiftItemComponent(items.get(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
public GiftItemComponent first() {
|
||||||
|
return get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GiftItemComponent byTitle(String title) {
|
||||||
|
for (int i = 0; i < items.size(); i++) {
|
||||||
|
GiftItemComponent item = get(i);
|
||||||
|
if (title.equals(item.titleText())) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalStateException("Gift with title '" + title + "' was not found.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package ru.otus.mobile.component;
|
||||||
|
|
||||||
|
import com.codeborne.selenide.SelenideElement;
|
||||||
|
|
||||||
|
public final class TopBarComponent extends BaseMobileComponent {
|
||||||
|
public TopBarComponent(SelenideElement root) {
|
||||||
|
super(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openUsersFilter() {
|
||||||
|
if (byId("filter").exists()) {
|
||||||
|
byId("filter").click();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (byId("users_filter").exists()) {
|
||||||
|
byId("users_filter").click();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (byId("filter_button").exists()) {
|
||||||
|
byId("filter_button").click();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (byId("action_filter").exists()) {
|
||||||
|
byId("action_filter").click();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new IllegalStateException("Filter button was not found on Users screen.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package ru.otus.mobile.component;
|
||||||
|
|
||||||
|
import com.codeborne.selenide.SelenideElement;
|
||||||
|
|
||||||
|
public final class UserItemComponent extends BaseMobileComponent {
|
||||||
|
private final SelenideElement username;
|
||||||
|
|
||||||
|
public UserItemComponent(SelenideElement root) {
|
||||||
|
super(root);
|
||||||
|
this.username = byIdInRoot("username");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String usernameText() {
|
||||||
|
return username.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void open() {
|
||||||
|
username.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package ru.otus.mobile.component;
|
||||||
|
|
||||||
|
import com.codeborne.selenide.ElementsCollection;
|
||||||
|
import com.codeborne.selenide.SelenideElement;
|
||||||
|
import io.appium.java_client.AppiumBy;
|
||||||
|
|
||||||
|
public final class UsersContentComponent extends BaseMobileComponent {
|
||||||
|
private final ElementsCollection items;
|
||||||
|
|
||||||
|
public UsersContentComponent(SelenideElement root) {
|
||||||
|
super(root);
|
||||||
|
this.items = root.$$(AppiumBy.id(fullIdValue("user_item")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserItemComponent get(int index) {
|
||||||
|
return new UserItemComponent(items.get(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserItemComponent first() {
|
||||||
|
return get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserItemComponent byUsername(String username) {
|
||||||
|
for (int i = 0; i < items.size(); i++) {
|
||||||
|
UserItemComponent item = get(i);
|
||||||
|
if (username.equals(item.usernameText())) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalStateException("User with username '" + username + "' was not found.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package ru.otus.mobile.component;
|
||||||
|
|
||||||
|
import com.codeborne.selenide.SelenideElement;
|
||||||
|
|
||||||
|
public final class UsersFilterComponent extends BaseMobileComponent {
|
||||||
|
public UsersFilterComponent(SelenideElement root) {
|
||||||
|
super(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyByUsername(String username) {
|
||||||
|
SelenideElement filterInput = filterInput();
|
||||||
|
SelenideElement applyButton = applyButton();
|
||||||
|
filterInput.click();
|
||||||
|
filterInput.clear();
|
||||||
|
filterInput.sendKeys(username);
|
||||||
|
applyButton.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
private SelenideElement filterInput() {
|
||||||
|
if (byIdInRoot("username_input").exists()) {
|
||||||
|
return byIdInRoot("username_input");
|
||||||
|
}
|
||||||
|
if (byIdInRoot("filter_input").exists()) {
|
||||||
|
return byIdInRoot("filter_input");
|
||||||
|
}
|
||||||
|
if (byIdInRoot("users_filter_input").exists()) {
|
||||||
|
return byIdInRoot("users_filter_input");
|
||||||
|
}
|
||||||
|
return byIdInRoot("username_filter_input");
|
||||||
|
}
|
||||||
|
|
||||||
|
private SelenideElement applyButton() {
|
||||||
|
if (byIdInRoot("apply_button").exists()) {
|
||||||
|
return byIdInRoot("apply_button");
|
||||||
|
}
|
||||||
|
return byIdInRoot("apply");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,30 @@
|
|||||||
package ru.otus.mobile.component;
|
package ru.otus.mobile.component;
|
||||||
|
|
||||||
|
import com.codeborne.selenide.SelenideElement;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import ru.otus.mobile.config.MobileConfig;
|
import io.appium.java_client.AppiumBy;
|
||||||
|
|
||||||
|
import static com.codeborne.selenide.appium.SelenideAppium.$;
|
||||||
|
|
||||||
public final class WishlistFormComponent extends BaseMobileComponent {
|
public final class WishlistFormComponent extends BaseMobileComponent {
|
||||||
|
private final SelenideElement titleInput;
|
||||||
|
private final SelenideElement saveButton;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public WishlistFormComponent(MobileConfig config) {
|
public WishlistFormComponent() {
|
||||||
super(config);
|
this($(AppiumBy.id("android:id/content")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public WishlistFormComponent(SelenideElement root) {
|
||||||
|
super(root);
|
||||||
|
this.titleInput = byIdInRoot("title_input");
|
||||||
|
this.saveButton = byIdInRoot("save_button");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save(String title) {
|
public void save(String title) {
|
||||||
type("title_input", title);
|
titleInput.click();
|
||||||
tap("save_button");
|
titleInput.clear();
|
||||||
|
titleInput.sendKeys(title);
|
||||||
|
saveButton.click();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package ru.otus.mobile.component;
|
||||||
|
|
||||||
|
import com.codeborne.selenide.SelenideElement;
|
||||||
|
|
||||||
|
import static com.codeborne.selenide.Condition.text;
|
||||||
|
|
||||||
|
public final class WishlistItemComponent extends BaseMobileComponent {
|
||||||
|
private final SelenideElement title;
|
||||||
|
private final SelenideElement editButton;
|
||||||
|
|
||||||
|
public WishlistItemComponent(SelenideElement root) {
|
||||||
|
super(root);
|
||||||
|
this.title = byIdInRoot("title");
|
||||||
|
this.editButton = byIdInRoot("edit_button");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String titleText() {
|
||||||
|
return title.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shouldHaveTitle(String value) {
|
||||||
|
title.shouldHave(text(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void open() {
|
||||||
|
title.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void edit() {
|
||||||
|
editButton.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package ru.otus.mobile.component;
|
||||||
|
|
||||||
|
import com.codeborne.selenide.ElementsCollection;
|
||||||
|
import com.codeborne.selenide.SelenideElement;
|
||||||
|
import io.appium.java_client.AppiumBy;
|
||||||
|
|
||||||
|
public final class WishlistsContentComponent extends BaseMobileComponent {
|
||||||
|
private final ElementsCollection items;
|
||||||
|
|
||||||
|
public WishlistsContentComponent(SelenideElement root) {
|
||||||
|
super(root);
|
||||||
|
this.items = root.$$(AppiumBy.id(fullIdValue("wishlist_item")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public WishlistItemComponent get(int index) {
|
||||||
|
return new WishlistItemComponent(items.get(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
public WishlistItemComponent first() {
|
||||||
|
return get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WishlistItemComponent byTitle(String title) {
|
||||||
|
for (int i = 0; i < items.size(); i++) {
|
||||||
|
WishlistItemComponent item = get(i);
|
||||||
|
if (title.equals(item.titleText())) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalStateException("Wishlist with title '" + title + "' was not found.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,19 +1,11 @@
|
|||||||
package ru.otus.mobile.page;
|
package ru.otus.mobile.page;
|
||||||
|
|
||||||
import ru.otus.mobile.component.BottomNavigationComponent;
|
import ru.otus.mobile.component.BottomNavigationComponent;
|
||||||
import ru.otus.mobile.config.MobileConfig;
|
|
||||||
|
|
||||||
public abstract class AbsBasePage extends AbsPageObject {
|
public abstract class AbsBasePage extends AbsPageObject {
|
||||||
protected final BottomNavigationComponent bottomNavigation;
|
protected final BottomNavigationComponent bottomNavigation;
|
||||||
private final MobileConfig config;
|
|
||||||
|
|
||||||
protected AbsBasePage(MobileConfig config, BottomNavigationComponent bottomNavigation) {
|
protected AbsBasePage(BottomNavigationComponent bottomNavigation) {
|
||||||
super(config);
|
|
||||||
this.config = config;
|
|
||||||
this.bottomNavigation = bottomNavigation;
|
this.bottomNavigation = bottomNavigation;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected MobileConfig config() {
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,45 +1,24 @@
|
|||||||
package ru.otus.mobile.page;
|
package ru.otus.mobile.page;
|
||||||
|
|
||||||
import com.codeborne.selenide.CollectionCondition;
|
|
||||||
import com.codeborne.selenide.Condition;
|
import com.codeborne.selenide.Condition;
|
||||||
import com.codeborne.selenide.SelenideElement;
|
import com.codeborne.selenide.SelenideElement;
|
||||||
import com.codeborne.selenide.WebDriverRunner;
|
import com.codeborne.selenide.WebDriverRunner;
|
||||||
import com.codeborne.selenide.appium.SelenideAppiumCollection;
|
import com.codeborne.selenide.appium.SelenideAppiumCollection;
|
||||||
import io.appium.java_client.AppiumBy;
|
import io.appium.java_client.AppiumBy;
|
||||||
import ru.otus.mobile.config.MobileConfig;
|
|
||||||
|
|
||||||
import static com.codeborne.selenide.appium.SelenideAppium.$$;
|
import static com.codeborne.selenide.appium.SelenideAppium.$$;
|
||||||
import static com.codeborne.selenide.appium.SelenideAppium.$;
|
import static com.codeborne.selenide.appium.SelenideAppium.$;
|
||||||
|
|
||||||
public abstract class AbsPageObject {
|
public abstract class AbsPageObject {
|
||||||
private final MobileConfig config;
|
private static final String APP_PACKAGE_PROPERTY = "app.package";
|
||||||
|
private static final String DEFAULT_APP_PACKAGE = "ru.otus.wishlist";
|
||||||
protected AbsPageObject(MobileConfig config) {
|
|
||||||
this.config = config;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected SelenideElement byId(String id) {
|
protected SelenideElement byId(String id) {
|
||||||
return $(AppiumBy.id(fullId(id)));
|
return $(AppiumBy.id(fullIdValue(id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SelenideAppiumCollection allById(String id) {
|
protected SelenideAppiumCollection allById(String id) {
|
||||||
return $$(AppiumBy.id(fullId(id)));
|
return $$(AppiumBy.id(fullIdValue(id)));
|
||||||
}
|
|
||||||
|
|
||||||
protected SelenideElement byText(String text) {
|
|
||||||
return $(AppiumBy.androidUIAutomator("new UiSelector().text(\"" + escape(text) + "\")"));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected SelenideElement byTextContains(String text) {
|
|
||||||
return $(AppiumBy.androidUIAutomator("new UiSelector().textContains(\"" + escape(text) + "\")"));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected SelenideElement byUiAutomator(String selector) {
|
|
||||||
return $(AppiumBy.androidUIAutomator(selector));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected SelenideElement byXpath(String xpath) {
|
|
||||||
return $(AppiumBy.xpath(xpath));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void type(String id, String value) {
|
protected void type(String id, String value) {
|
||||||
@@ -57,47 +36,15 @@ public abstract class AbsPageObject {
|
|||||||
return byId(id).exists();
|
return byId(id).exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void shouldHaveItems(String id) {
|
|
||||||
allById(id).shouldHave(CollectionCondition.sizeGreaterThan(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected SelenideElement scrollToText(String text) {
|
|
||||||
String selector = "new UiScrollable(new UiSelector().scrollable(true))"
|
|
||||||
+ ".scrollIntoView(new UiSelector().textContains(\"" + escape(text) + "\"))";
|
|
||||||
return $(AppiumBy.androidUIAutomator(selector));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void back() {
|
protected void back() {
|
||||||
WebDriverRunner.getWebDriver().navigate().back();
|
WebDriverRunner.getWebDriver().navigate().back();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String xpathLiteral(String value) {
|
protected static String fullIdValue(String id) {
|
||||||
if (!value.contains("\"")) {
|
|
||||||
return "\"" + value + "\"";
|
|
||||||
}
|
|
||||||
if (!value.contains("'")) {
|
|
||||||
return "'" + value + "'";
|
|
||||||
}
|
|
||||||
String[] parts = value.split("\"");
|
|
||||||
StringBuilder builder = new StringBuilder("concat(");
|
|
||||||
for (int i = 0; i < parts.length; i++) {
|
|
||||||
if (i > 0) {
|
|
||||||
builder.append(", '\"', ");
|
|
||||||
}
|
|
||||||
builder.append("\"").append(parts[i]).append("\"");
|
|
||||||
}
|
|
||||||
builder.append(")");
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String fullId(String id) {
|
|
||||||
if (id.contains(":")) {
|
if (id.contains(":")) {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
return config.appPackage() + ":id/" + id;
|
String appPackage = System.getProperty(APP_PACKAGE_PROPERTY, DEFAULT_APP_PACKAGE);
|
||||||
}
|
return appPackage + ":id/" + id;
|
||||||
|
|
||||||
private String escape(String value) {
|
|
||||||
return value.replace("\"", "\\\"");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,34 +3,39 @@ package ru.otus.mobile.page;
|
|||||||
import com.codeborne.selenide.Condition;
|
import com.codeborne.selenide.Condition;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import ru.otus.mobile.component.BottomNavigationComponent;
|
import ru.otus.mobile.component.BottomNavigationComponent;
|
||||||
|
import ru.otus.mobile.component.GiftsContentComponent;
|
||||||
import ru.otus.mobile.component.GiftFormComponent;
|
import ru.otus.mobile.component.GiftFormComponent;
|
||||||
import ru.otus.mobile.config.MobileConfig;
|
|
||||||
|
|
||||||
public final class GiftsPage extends AbsBasePage {
|
public final class GiftsPage extends AbsBasePage {
|
||||||
private final GiftFormComponent form;
|
private final GiftFormComponent form;
|
||||||
|
private final com.codeborne.selenide.SelenideElement addButton = byId("add_button");
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public GiftsPage(MobileConfig config, BottomNavigationComponent bottomNavigation, GiftFormComponent form) {
|
public GiftsPage(BottomNavigationComponent bottomNavigation, GiftFormComponent form) {
|
||||||
super(config, bottomNavigation);
|
super(bottomNavigation);
|
||||||
this.form = form;
|
this.form = form;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createGift(String name) {
|
public void createGift(String name) {
|
||||||
tap("add_button");
|
addButton.click();
|
||||||
form.save(name, "100");
|
form.save(name, "100");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void editGift(String oldName, String newName) {
|
public void editGift(String oldName, String newName) {
|
||||||
openGift(oldName);
|
openGift(oldName);
|
||||||
tap("edit_button");
|
content().byTitle(oldName).edit();
|
||||||
form.save(newName, "100");
|
form.save(newName, "100");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shouldSeeGift(String name) {
|
public void shouldSeeGift(String name) {
|
||||||
scrollToText(name).shouldBe(Condition.visible);
|
content().byTitle(name).shouldHaveTitle(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openGift(String name) {
|
private void openGift(String name) {
|
||||||
scrollToText(name).click();
|
content().byTitle(name).open();
|
||||||
|
}
|
||||||
|
|
||||||
|
private GiftsContentComponent content() {
|
||||||
|
return new GiftsContentComponent(byId("gifts_content"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,15 +2,13 @@ package ru.otus.mobile.page;
|
|||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import ru.otus.mobile.component.AlertDialogComponent;
|
import ru.otus.mobile.component.AlertDialogComponent;
|
||||||
import ru.otus.mobile.config.MobileConfig;
|
|
||||||
import ru.otus.mobile.config.TestAccount;
|
import ru.otus.mobile.config.TestAccount;
|
||||||
|
|
||||||
public final class LoginPage extends AbsPageObject {
|
public final class LoginPage extends AbsPageObject {
|
||||||
private final AlertDialogComponent alertDialog;
|
private final AlertDialogComponent alertDialog;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public LoginPage(MobileConfig config, AlertDialogComponent alertDialog) {
|
public LoginPage(AlertDialogComponent alertDialog) {
|
||||||
super(config);
|
|
||||||
this.alertDialog = alertDialog;
|
this.alertDialog = alertDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,69 +1,55 @@
|
|||||||
package ru.otus.mobile.page;
|
package ru.otus.mobile.page;
|
||||||
|
|
||||||
import com.codeborne.selenide.Condition;
|
import com.codeborne.selenide.Condition;
|
||||||
import com.codeborne.selenide.CollectionCondition;
|
|
||||||
import com.codeborne.selenide.SelenideElement;
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import ru.otus.mobile.component.BottomNavigationComponent;
|
import ru.otus.mobile.component.BottomNavigationComponent;
|
||||||
import ru.otus.mobile.config.MobileConfig;
|
import ru.otus.mobile.component.GiftsContentComponent;
|
||||||
|
import ru.otus.mobile.component.TopBarComponent;
|
||||||
|
import ru.otus.mobile.component.UsersContentComponent;
|
||||||
|
import ru.otus.mobile.component.UsersFilterComponent;
|
||||||
|
import ru.otus.mobile.component.WishlistsContentComponent;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
|
||||||
public final class UsersPage extends AbsBasePage {
|
public final class UsersPage extends AbsBasePage {
|
||||||
|
private final TopBarComponent topBar;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public UsersPage(MobileConfig config, BottomNavigationComponent bottomNavigation) {
|
public UsersPage(BottomNavigationComponent bottomNavigation) {
|
||||||
super(config, bottomNavigation);
|
super(bottomNavigation);
|
||||||
|
this.topBar = new TopBarComponent(byId("android:id/content"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void open() {
|
public void open() {
|
||||||
bottomNavigation.openUsers();
|
bottomNavigation.openUsers();
|
||||||
byId("users_content").shouldBe(Condition.visible);
|
usersContentRoot().shouldBe(Condition.visible, Duration.ofSeconds(15));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void filterByUsername(String username) {
|
public void filterByUsername(String username) {
|
||||||
openFilter();
|
topBar.openUsersFilter();
|
||||||
SelenideElement input = filterInput().shouldBe(Condition.visible, Duration.ofSeconds(15));
|
byId("users_filter_bottom_sheet").shouldBe(Condition.visible, Duration.ofSeconds(15));
|
||||||
input.clear();
|
new UsersFilterComponent(byId("users_filter_bottom_sheet")).applyByUsername(username);
|
||||||
input.setValue(username);
|
byId("user_item").shouldBe(Condition.visible, Duration.ofSeconds(15));
|
||||||
applyFilter();
|
|
||||||
byTextContains(username).shouldBe(Condition.visible, Duration.ofSeconds(15));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void openUser(String username) {
|
public void openUser(String username) {
|
||||||
String appPackage = config().appPackage();
|
usersContent().byUsername(username).open();
|
||||||
String xpath = "//android.widget.TextView[@resource-id='" + appPackage + ":id/username'"
|
|
||||||
+ " and @text=" + xpathLiteral(username) + "]";
|
|
||||||
SelenideElement user = byXpath(xpath);
|
|
||||||
if (user.exists()) {
|
|
||||||
user.shouldBe(Condition.visible, Duration.ofSeconds(15)).click();
|
|
||||||
} else {
|
|
||||||
scrollToText(username).shouldBe(Condition.visible, Duration.ofSeconds(15)).click();
|
|
||||||
}
|
|
||||||
byTextContains(username).shouldBe(Condition.visible, Duration.ofSeconds(15));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void openFirstWishlist() {
|
public void openFirstWishlist() {
|
||||||
allById("wishlist_item")
|
wishlistsContent().get(0).open();
|
||||||
.shouldHave(CollectionCondition.sizeGreaterThan(0), Duration.ofSeconds(15))
|
|
||||||
.first()
|
|
||||||
.shouldBe(Condition.visible, Duration.ofSeconds(15))
|
|
||||||
.click();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void openWishlist(String name) {
|
public void openWishlist(String name) {
|
||||||
scrollToText(name).shouldBe(Condition.visible, Duration.ofSeconds(15)).click();
|
wishlistsContent().byTitle(name).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void openFirstGift() {
|
public void openFirstGift() {
|
||||||
allById("gift_item")
|
new GiftsContentComponent(byId("gifts_content")).get(0).open();
|
||||||
.shouldHave(CollectionCondition.sizeGreaterThan(0), Duration.ofSeconds(15))
|
|
||||||
.first()
|
|
||||||
.shouldBe(Condition.visible, Duration.ofSeconds(15))
|
|
||||||
.click();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void openGift(String name) {
|
public void openGift(String name) {
|
||||||
scrollToText(name).shouldBe(Condition.visible, Duration.ofSeconds(15)).click();
|
new GiftsContentComponent(byId("gifts_content")).byTitle(name).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isReserved() {
|
public boolean isReserved() {
|
||||||
@@ -71,87 +57,29 @@ public final class UsersPage extends AbsBasePage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void toggleReservation() {
|
public void toggleReservation() {
|
||||||
tap("reserved");
|
byId("reserved").shouldBe(Condition.visible).click();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openFilter() {
|
private UsersContentComponent usersContent() {
|
||||||
if (byId("users_filter").exists()) {
|
return new UsersContentComponent(usersContentRoot());
|
||||||
tap("users_filter");
|
|
||||||
byId("users_filter_bottom_sheet").shouldBe(Condition.visible, Duration.ofSeconds(15));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (byId("filter_button").exists()) {
|
|
||||||
tap("filter_button");
|
|
||||||
byId("users_filter_bottom_sheet").shouldBe(Condition.visible, Duration.ofSeconds(15));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (byId("action_filter").exists()) {
|
|
||||||
tap("action_filter");
|
|
||||||
byId("users_filter_bottom_sheet").shouldBe(Condition.visible, Duration.ofSeconds(15));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SelenideElement button = byUiAutomator("new UiSelector().descriptionContains(\"Фильтр\")");
|
|
||||||
if (button.exists()) {
|
|
||||||
button.click();
|
|
||||||
byId("users_filter_bottom_sheet").shouldBe(Condition.visible, Duration.ofSeconds(15));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
button = byUiAutomator("new UiSelector().descriptionContains(\"Filter\")");
|
|
||||||
if (button.exists()) {
|
|
||||||
button.click();
|
|
||||||
byId("users_filter_bottom_sheet").shouldBe(Condition.visible, Duration.ofSeconds(15));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw new IllegalStateException("Filter button was not found on Users screen.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private SelenideElement filterInput() {
|
private WishlistsContentComponent wishlistsContent() {
|
||||||
if (byId("filter_input").exists()) {
|
return new WishlistsContentComponent(wishlistsContentRoot());
|
||||||
return byId("filter_input");
|
|
||||||
}
|
|
||||||
if (byId("username_filter_input").exists()) {
|
|
||||||
return byId("username_filter_input");
|
|
||||||
}
|
|
||||||
if (byId("users_filter_input").exists()) {
|
|
||||||
return byId("users_filter_input");
|
|
||||||
}
|
|
||||||
if (byId("username_input").exists()) {
|
|
||||||
return byId("username_input");
|
|
||||||
}
|
|
||||||
if (byId("search_src_text").exists()) {
|
|
||||||
return byId("search_src_text");
|
|
||||||
}
|
|
||||||
if (byId("query_text").exists()) {
|
|
||||||
return byId("query_text");
|
|
||||||
}
|
|
||||||
String appPackage = config().appPackage();
|
|
||||||
SelenideElement editText = byXpath(
|
|
||||||
"//android.view.ViewGroup[@resource-id='" + appPackage + ":id/users_filter_bottom_sheet']"
|
|
||||||
+ "//android.widget.EditText"
|
|
||||||
);
|
|
||||||
if (editText.exists()) {
|
|
||||||
return editText;
|
|
||||||
}
|
|
||||||
throw new IllegalStateException("Filter input was not found on Users screen.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyFilter() {
|
private com.codeborne.selenide.SelenideElement usersContentRoot() {
|
||||||
if (byId("apply_button").exists()) {
|
if (byId("users_content").exists()) {
|
||||||
tap("apply_button");
|
return byId("users_content");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (byId("apply").exists()) {
|
return byId("users");
|
||||||
tap("apply");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (byText("ПРИМЕНИТЬ").exists()) {
|
|
||||||
byText("ПРИМЕНИТЬ").click();
|
private com.codeborne.selenide.SelenideElement wishlistsContentRoot() {
|
||||||
return;
|
if (byId("wishlists_content").exists()) {
|
||||||
|
return byId("wishlists_content");
|
||||||
}
|
}
|
||||||
if (byText("APPLY").exists()) {
|
return byId("wishlists");
|
||||||
byText("APPLY").click();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw new IllegalStateException("Apply filter button was not found on Users filter screen.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,72 +1,67 @@
|
|||||||
package ru.otus.mobile.page;
|
package ru.otus.mobile.page;
|
||||||
|
|
||||||
import com.codeborne.selenide.Condition;
|
import com.codeborne.selenide.Condition;
|
||||||
import com.codeborne.selenide.CollectionCondition;
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import ru.otus.mobile.component.BottomNavigationComponent;
|
import ru.otus.mobile.component.BottomNavigationComponent;
|
||||||
|
import ru.otus.mobile.component.WishlistsContentComponent;
|
||||||
import ru.otus.mobile.component.WishlistFormComponent;
|
import ru.otus.mobile.component.WishlistFormComponent;
|
||||||
import ru.otus.mobile.config.MobileConfig;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
public final class WishlistsPage extends AbsBasePage {
|
public final class WishlistsPage extends AbsBasePage {
|
||||||
private final WishlistFormComponent form;
|
private final WishlistFormComponent form;
|
||||||
|
private final com.codeborne.selenide.SelenideElement addButton = byId("add_button");
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public WishlistsPage(MobileConfig config, BottomNavigationComponent bottomNavigation, WishlistFormComponent form) {
|
public WishlistsPage(BottomNavigationComponent bottomNavigation, WishlistFormComponent form) {
|
||||||
super(config, bottomNavigation);
|
super(bottomNavigation);
|
||||||
this.form = form;
|
this.form = form;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void open() {
|
public void open() {
|
||||||
bottomNavigation.openWishlists();
|
bottomNavigation.openWishlists();
|
||||||
byId("wishlists_content").shouldBe(Condition.visible);
|
contentRoot().shouldBe(Condition.visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createWishlist(String name) {
|
public void createWishlist(String name) {
|
||||||
tap("add_button");
|
addButton.click();
|
||||||
form.save(name);
|
form.save(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void editWishlist(String oldName, String newName) {
|
public void editWishlist(String oldName, String newName) {
|
||||||
ensureWishlistsList();
|
ensureWishlistsList();
|
||||||
editButtonFor(oldName).shouldBe(Condition.visible).click();
|
content().byTitle(oldName).edit();
|
||||||
form.save(newName);
|
form.save(newName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shouldSeeWishlist(String name) {
|
public void shouldSeeWishlist(String name) {
|
||||||
scrollToText(name).shouldBe(Condition.visible);
|
content().byTitle(name).shouldHaveTitle(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void openWishlist(String name) {
|
public void openWishlist(String name) {
|
||||||
scrollToText(name).click();
|
content().byTitle(name).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void openFirstWishlist() {
|
public void openFirstWishlist() {
|
||||||
allById("wishlist_item")
|
content().first().open();
|
||||||
.shouldHave(CollectionCondition.sizeGreaterThan(0), Duration.ofSeconds(15))
|
|
||||||
.first()
|
|
||||||
.shouldBe(Condition.visible, Duration.ofSeconds(15))
|
|
||||||
.click();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensureWishlistsList() {
|
private void ensureWishlistsList() {
|
||||||
if (exists("wishlist_item") || exists("wishlists")) {
|
if (exists("wishlist_item") || contentRoot().exists()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (exists("gifts_content") || exists("gift_item") || exists("add_button")) {
|
if (exists("gifts_content") || exists("gift_item") || exists("add_button")) {
|
||||||
back();
|
back();
|
||||||
}
|
}
|
||||||
byId("wishlists_content").shouldBe(Condition.visible);
|
contentRoot().shouldBe(Condition.visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
private com.codeborne.selenide.SelenideElement editButtonFor(String name) {
|
private WishlistsContentComponent content() {
|
||||||
String full = config().appPackage();
|
return new WishlistsContentComponent(contentRoot());
|
||||||
String xpath = "//androidx.recyclerview.widget.RecyclerView[@resource-id='" + full + ":id/wishlists']"
|
}
|
||||||
+ "//android.view.ViewGroup[@resource-id='" + full + ":id/wishlist_item'"
|
|
||||||
+ " and .//android.widget.TextView[@resource-id='" + full + ":id/title'"
|
private com.codeborne.selenide.SelenideElement contentRoot() {
|
||||||
+ " and contains(@text," + xpathLiteral(name) + ")]]"
|
if (byId("wishlists_content").exists()) {
|
||||||
+ "//android.widget.Button[@resource-id='" + full + ":id/edit_button']";
|
return byId("wishlists_content");
|
||||||
return byXpath(xpath);
|
}
|
||||||
|
return byId("wishlists");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user