Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ trigger:
- master

pool:
vmImage: 'macOS-latest'
vmImage: 'macOS-14'

jobs:
- job: sonar
Expand Down Expand Up @@ -44,6 +44,7 @@ jobs:
pollingTimeoutSec: '300'

- job: tests
timeoutInMinutes: 60
displayName: Run tests
strategy:
maxParallel: 2
Expand All @@ -55,11 +56,12 @@ jobs:

variables:
ANDROID_EMU_NAME: test
ANDROID_SDK_ID: system-images;android-30;google_apis_playstore;x86_64
ANDROID_SDK_ID: system-images;android-29;google_apis_playstore;x86_64

steps:
- task: CmdLine@2
displayName: 'Configure Appium and Android SDK'
timeoutInMinutes: 15
inputs:
script: |
echo "Configuring Environment"
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@
<dependency>
<groupId>com.github.aquality-automation</groupId>
<artifactId>aquality-selenium-core</artifactId>
<version>4.8.0</version>
<version>4.9.0</version>
Comment thread
mialeska marked this conversation as resolved.
</dependency>

<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
public interface IMobileApplication extends IApplication {
/**
* Provides default timeout for terminate methods.
*
* @return default timeout for waiting until the application is terminated.
*/
static Duration getDefaultTerminateTimeout() {
Expand Down Expand Up @@ -67,15 +68,19 @@ default InteractsWithApps appManagement() {

/**
* Execute application script
*
* @param script script
* @param params parameters
* @param <T> type of the result
* @return result of the script execution.
*/
<T> T executeScript(String script, Map<String, Object> params);

/**
* Execute application script
*
* @param script script
* @param <T> type of the result
* @return result of the script execution.
*/
default <T> T executeScript(String script) {
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/aquality/appium/mobile/screens/IScreen.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,22 @@
public interface IScreen extends IForm {
/**
* Locator for specified screen
*
* @return locator
*/
By getLocator();

/**
* Name of specified screen
*
* @return name
*/
String getName();

/**
* Size of the element described by screen locator.
*
* @return size
*/
Dimension getSize();

Expand Down
7 changes: 5 additions & 2 deletions src/main/java/aquality/appium/mobile/screens/Screen.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ public abstract class Screen extends Form<IElement> implements IScreen {

/**
* Constructor with parameters
*
* @param locator Locator of the screen
* @param name Name of the screen
*/
protected Screen(By locator, String name) {
super(IElement.class);
Expand All @@ -50,7 +53,7 @@ public String getName() {

@Override
public Dimension getSize() {
return screenElement.visual().getSize();
return screenElement.visual().getSize();
}

@Override
Expand All @@ -68,7 +71,7 @@ protected IElement getScreenElement() {
return screenElement;
}

protected IElementFactory getElementFactory(){
protected IElementFactory getElementFactory() {
return AqualityServices.getElementFactory();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ public interface IScreenFactory {

/**
* Returns an implementation of a particular app screen.
* @param <T> Type of desired application screen.
*
* @param <T> Type of desired application screen.
* @param clazz Class of desired application screen.
* @return Instance of desired application screen.
*/
<T extends IScreen> T getScreen(Class<T> clazz);
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package samples.android.nativeapp.apidemos;

import aquality.appium.mobile.application.AqualityServices;
import aquality.appium.mobile.elements.interfaces.IButton;
import aquality.appium.mobile.screens.Screen;
import aquality.selenium.core.configurations.ITimeoutConfiguration;
import io.appium.java_client.android.Activity;
import org.openqa.selenium.By;
import samples.android.nativeapp.apidemos.screens.AlertsMenuScreen;
import samples.android.nativeapp.apidemos.screens.AndroidScreen;
import samples.android.nativeapp.apidemos.screens.InvokeSearchScreen;
import samples.android.nativeapp.apidemos.screens.ViewControlsScreen;
import samples.android.nativeapp.apidemos.screens.ViewTabsScrollableScreen;
import org.openqa.selenium.WebDriverException;
import samples.android.nativeapp.apidemos.screens.*;

import java.lang.reflect.InvocationTargetException;
import java.util.Collections;

public enum ApplicationActivity {

Expand Down Expand Up @@ -38,14 +38,17 @@ public <T extends AndroidScreen> T open() {
public <T extends AndroidScreen> T getScreen() {
try {
return (T) screen.getDeclaredConstructor().newInstance();
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
InvocationTargetException e) {
AqualityServices.getLogger().debug(e.getMessage());
throw new IllegalArgumentException("Something went wrong during screen getting");
}
}

private static class ActivityScreen extends AndroidScreen {
private final Activity activity;
private final IButton btnWait = getElementFactory().getButton(By.id("android:id/aerr_wait"), "Wait");
private final IButton btnCloseApp = getElementFactory().getButton(By.id("android:id/aerr_close"), "Close app");

ActivityScreen(Activity activity) {
super(By.name(activity.getAppActivity()), activity.getAppActivity());
Expand All @@ -54,6 +57,21 @@ private static class ActivityScreen extends AndroidScreen {

void open() {
startActivity(activity);
// workaround to handle System UI isn't responding dialog
ITimeoutConfiguration timeoutConfiguration = AqualityServices.getConfiguration().getTimeoutConfiguration();
boolean result = AqualityServices.getConditionalWait().waitFor(() ->
{
if (!btnWait.state().waitForDisplayed()) {
return true;
}
btnWait.click();
return btnWait.state().waitForNotDisplayed();
}, timeoutConfiguration.getCommand(),
timeoutConfiguration.getCondition(),
Collections.singletonList(WebDriverException.class));
if (!result) {
btnCloseApp.click();
}
}
}
}
22 changes: 15 additions & 7 deletions src/test/java/samples/android/web/WebTextBoxTest.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package samples.android.web;

import aquality.appium.mobile.application.AqualityServices;
import aquality.appium.mobile.elements.interfaces.IButton;
import aquality.appium.mobile.elements.interfaces.ITextBox;
import aquality.selenium.core.configurations.ITimeoutConfiguration;
import io.appium.java_client.android.AndroidDriver;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
Expand All @@ -11,18 +13,24 @@
public class WebTextBoxTest extends AndroidWebTest {

private static final String VALUE_TO_SUBMIT = "quality assurance";
private static final ITextBox txbSearch = AqualityServices.getElementFactory().getTextBox(By.id("searchInput"), "Search");
private static final IButton btnOverlayToggle = AqualityServices.getElementFactory().getButton(By.className("button-collapse"), "Toggle Overlay");
private static final IButton btnCloseBanner = AqualityServices.getElementFactory().getButton(By.className("overlay-banner-close"), "Close banner");
Comment thread
mialeska marked this conversation as resolved.

@Test
public void testTextBoxInteraction() {
AqualityServices.getApplication().getDriver().get("https://wikipedia.org");
ITextBox txbSearch = AqualityServices.getElementFactory().getTextBox(By.id("searchInput"), "Search");
txbSearch.state().waitForClickable();
if (btnOverlayToggle.state().isDisplayed()) {
btnOverlayToggle.click();
btnCloseBanner.click();
}
txbSearch.type(VALUE_TO_SUBMIT);
Assert.assertEquals(VALUE_TO_SUBMIT, txbSearch.getValue(), "Submitted value should match to expected");
txbSearch.clear();
Assert.assertEquals("", txbSearch.getValue(), "Value should be cleared");
txbSearch.click();
checkUnfocus(txbSearch);
checkUnfocus();
txbSearch.focus();
Assert.assertTrue(isKeyboardShown(true), "Keyboard should be shown when focus successful");
txbSearch.typeSecret(VALUE_TO_SUBMIT);
Expand All @@ -35,17 +43,17 @@ public void testTextBoxInteraction() {
Assert.assertTrue(txbSearch.state().waitForNotDisplayed(), "text field should disappear after the submit");
}

private void checkUnfocus(ITextBox txbSearch) {
private void checkUnfocus() {
txbSearch.unfocus();
Assert.assertFalse(isKeyboardShown(false), "Keyboard should not be shown when unfocus successful");
}

@SuppressWarnings("unchecked")
private boolean isKeyboardShown(boolean expectedStateToWait) {
ITimeoutConfiguration timeoutConfiguration = AqualityServices.getConfiguration().getTimeoutConfiguration();
boolean waitResult = AqualityServices.getConditionalWait()
.waitFor(driver -> ((AndroidDriver)driver).isKeyboardShown() == expectedStateToWait,
AqualityServices.getConfiguration().getTimeoutConfiguration().getCommand(),
AqualityServices.getConfiguration().getTimeoutConfiguration().getPollingInterval().multipliedBy(10),
.waitFor(driver -> ((AndroidDriver) driver).isKeyboardShown() == expectedStateToWait,
timeoutConfiguration.getCommand(),
timeoutConfiguration.getPollingInterval().multipliedBy(10),
String.format("is keyboard shown condition should be %s", expectedStateToWait));
return expectedStateToWait == waitResult;
}
Expand Down
3 changes: 2 additions & 1 deletion src/test/resources/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"platformName": "Android",
"automationName": "UIAutomator2",
"eventTimings": true,
"uiautomator2ServerInstallTimeout": 30000
"uiautomator2ServerInstallTimeout": 30000,
"uiautomator2ServerLaunchTimeout": 60000
}
},
"ios": {
Expand Down
Loading