Проблема с передачей Permissions на эмулятор

Хай. Как на 6м андрюхе Апиумом заавтоматить setPermissions?
Потому что на никак не могу без “ручного” подтверждения доступа ранит тесты:

Капабилити autoAcceptAlerts=true не помогает?

Неа. Пробовал. Да и, если не ошибаюсь, это же для яблофонов капабилитя?

Средствами аппиума можно прокликивать. Мы создавали отдельный виджет для этого попапа и в течении заданного интервала прокликивали allow, пока он не пропадал.

Костылем подперлы?)) Как по мне то это не выход.
Код можно посмотреть?

Я сделал так:
PageObject:

public class PermissionForm extends Screen{
    public PermissionForm(WebDriver appiumDriver) {
        super(appiumDriver);
    }

    @FindBy(how = How.ID, using = "permission_allow_button")
    private WebElement allowButton;

    @FindBy(how = How.ID, using = "permission_message")
    private WebElement getPermissionText;

    public void allowPermission(){
        AllureLogger.logToAllure("Allow next permission" + getPermissionText.getText());
        allowButton.click();
    }

    public boolean isFormIsVisible(){
        return getPermissionText.isDisplayed();
    }
}

setup method in @BeforeSuite

    @BeforeSuite
    @Parameters({"platformVersion", "mobileDeviceName"})
    public void setup(String platformVersion,
                      String mobileDeviceName)
            throws Exception {
        String timeout = PropertyLoader.loadProperty("timeout.implicit");
        String appType = PropertyLoader.loadProperty("appium.app.type");
        appiumDriver = AppiumDriverFactory.getAppiumDriver(platformVersion, mobileDeviceName);
        appiumDriver.manage().timeouts().implicitlyWait(Integer.valueOf(timeout), TimeUnit.SECONDS);
        PermissionForm permissionForm = PageFactory.initElements(appiumDriver, PermissionForm.class);
        if (platformVersion.contains("6.0") && permissionForm.isFormIsVisible()){
            permissionForm.allowPermission();
            Thread.sleep(2000);
            permissionForm.allowPermission();
        }

Самый простой вариант - это собирать приложение с target SDK = 22, если это возможно. Тогда permissions не будут запрашиваться.

Ну почему же костылем? Если юзер видит этот попап, и от него нельзя так просто избавиться, как в случае с SDK < 22, то что тут еще обсуждать? :slight_smile: Надо просто закрывать и продолжать работу.

Следующий код будет кликать по кнопке, пока она не пропадет (диалог может появляться несколько раз подряд), или не сработает глобальный таймаут.

@Getter
public class PermissionPopup extends Widget {

	@AndroidFindBy(id = "permission_allow_button")
	private MobileElement buttonAllow;

	protected PermissionPopup(final WebElement element) {
		super(element);
	}

	public void allow(final BiFunction<MobileElement, Long, Boolean> waitCondition) {
		await().atMost(ELEMENT_WAIT_TIMEOUT, TimeUnit.SECONDS)
				.pollInterval(POLLING_INTERVAL, TimeUnit.SECONDS)
				.ignoreExceptions()
				.until(() -> {
					final boolean isVisible = waitCondition.apply(buttonAllow, ELEMENT_DISPLAY_TIMEOUT);
					if (isVisible)
						buttonAllow.click();
					return !isVisible;
				});
	}
}

Поведение ожидания элемента можно параметризовать чем угодно. К примеру:

permissionsPopup.allow(this::isElementDisplayed);
1 лайк

У меня какаято лажа получается:
PermissionPopup.class

    public PermissionPopup(WebDriver appiumDriver) {
        super(appiumDriver);
    }

    @FindBy(how = How.ID, using = "permission_allow_button")
    private WebElement buttonAllow;

    @FindBy(how = How.ID, using = "permission_message")
    private WebElement getPermissionText;

    public void allow(final BiFunction<WebElement, Long, Boolean> waitCondition) throws FileNotFoundException {

        await().until(() -> {
                    final boolean isVisible = waitCondition.apply(buttonAllow, Long.valueOf(10));
                    if (isVisible)
                        buttonAllow.click();
                    return !isVisible;
                });
    }

    public void allowAllPermissions() throws FileNotFoundException {
        allow(this::isFormIsVisible);
    }

    private Boolean isFormIsVisible(WebElement webElement, Long aLong) {
        return getPermissionText.isDisplayed();
    }

Стектрейс:

org.awaitility.core.ConditionTimeoutException: Condition with utility.PermissionPopup was not fulfilled within 10 seconds.

В моем примере задан глобальный таймаут для всех попапов, который контролируется через вызов atMost. Т.е. он должен быть больше локального таймаута для единственного элемента, проверяющегося в until.

Если вы явно не задаете глобальный таймаут, то используется дефолтный - 10 сек. Т.к. у вас дефолтный равен локальному, то независимо от результата операции в until, вы в любом случае получаете timeout exception.

1 лайк

это не возможно. Да и подстраивать код ПО под тесты, как по мне - плохой варик…

Все, я поплыл :slight_smile: … Сделал все так как у Вас:

    public void allow(final BiFunction<WebElement, Long, Boolean> waitCondition) throws FileNotFoundException {
        Long waitTimeOut = 20L;
        Long pollingInterval = 5L;
        Long elementDisplayTimeout = 20L;

        await().atMost(waitTimeOut, TimeUnit.SECONDS)
                .pollInterval(pollingInterval, TimeUnit.SECONDS)
                .ignoreExceptions()
                .until(() -> {
                    final boolean isVisible = waitCondition.apply(buttonAllow, elementDisplayTimeout);
                    if (isVisible)
                        buttonAllow.click();
                    return !isVisible;
                });
    }
    
    public void allowAllPermissions() throws FileNotFoundException {
        allow(this::isFormIsVisible);
    }

    private Boolean isFormIsVisible(WebElement webElement, Long aLong) {
        return getPermissionText.isDisplayed();
    }

Глобальний таймаут равен 15 секундам:

timeout.implicit=15
---
String timeout = PropertyLoader.loadProperty("timeout.implicit");
appiumDriver.manage().timeouts().implicitlyWait(Integer.valueOf(timeout), TimeUnit.SECONDS);
  • waitTimeout должен быть больше elementDisplayTimeout; к слову, он у вас вообще не задействован; я хоть и не показал, но в моем примере этот таймаут использовался для explicit waits, потому собственно и передавалась BiFunction; при вашем подходе достаточно Function<WebElement, Boolean>;
  • implicitWait будет лочить выполнение until на <=15 сек, что естественно повлияет и на глобальный таймаут.
1 лайк

Сделал все как показано в “матчасти” и все поехало - appium/java-client