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
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright 2024 Aquality Automation
Copyright 2025 Aquality Automation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
20 changes: 11 additions & 9 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,39 @@ jobs:
displayName: Analyse code with SonarQube

steps:
- task: SonarCloudPrepare@1
- task: SonarCloudPrepare@3
displayName: 'Prepare SonarCloud analysis'
inputs:
SonarCloud: 'SonarCloud'
organization: 'aqualityautomation'
scannerMode: 'CLI'
configMode: 'file'
extraProperties: |
sonar.coverage.exclusions=**/**
extraProperties: 'sonar.coverage.exclusions=**/**'

- task: Maven@3
- task: Maven@4
displayName: 'Compile project'
inputs:
mavenPomFile: 'pom.xml'
goals: 'clean compile'
goals: 'clean'
publishJUnitResults: true
testResultsFiles: '**/surefire-reports/TEST-*.xml'
javaHomeOption: 'JDKVersion'
jdkVersionOption: '11'
jdkVersionOption: '1.11'
mavenVersionOption: 'Default'
mavenAuthenticateFeed: false
effectivePomSkip: false
sonarQubeRunAnalysis: false
continueOnError: true

- task: SonarCloudAnalyze@1
- task: SonarCloudAnalyze@3
inputs:
jdkversion: 'JAVA_HOME_21_X64'
displayName: 'Run SonarCloud code analysis'
continueOnError: true

- task: SonarCloudPublish@1
- task: SonarCloudPublish@3
displayName: 'Publish SonarCloud quality gate results'
inputs:
pollingTimeoutSec: '300'

- job: tests
displayName: Run tests
Expand Down
4 changes: 2 additions & 2 deletions 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.6.0</version>
<version>4.7.0</version>
</dependency>

<dependency>
Expand All @@ -203,7 +203,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.17.0</version>
<version>3.18.0</version>
<scope>test</scope>
</dependency>

Expand Down
22 changes: 22 additions & 0 deletions src/main/java/aquality/appium/mobile/actions/AndroidActions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package aquality.appium.mobile.actions;

import aquality.appium.mobile.application.AqualityServices;
import io.appium.java_client.android.AndroidDriver;

import java.util.HashMap;
import java.util.Map;

public class AndroidActions implements IAndroidActions {
@Override
public void startActivity(String appPackage, String appActivity, boolean stopApp) {
AqualityServices.getLocalizedLogger().info("loc.application.android.activity.start", appPackage, appActivity);
Map<String, Object> args = new HashMap<>();
args.put("intent", String.format("%s/%s", appPackage, appActivity));
args.put("package", appPackage);
args.put("stop", stopApp);
AqualityServices.getApplication().executeScript("mobile: startActivity", args);
AqualityServices.getConditionalWait().waitFor(
driver -> appActivity.equals(((AndroidDriver)driver).currentActivity()),
String.format("Activity %s was not started", appActivity));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,11 @@ public interface IActionsModule extends IConfigurationsModule {
default Class<? extends ITouchActions> getTouchActionsImplementation() {
return TouchActions.class;
}

/**
* @return class which implements {@link IAndroidActions}
*/
default Class<? extends IAndroidActions> getAndroidActionsImplementation() {
return AndroidActions.class;
}
}
36 changes: 36 additions & 0 deletions src/main/java/aquality/appium/mobile/actions/IAndroidActions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package aquality.appium.mobile.actions;

import io.appium.java_client.android.Activity;

/**
* Extensions for Android applications.
*/
public interface IAndroidActions {

/**
* Starts application activity.
* @param activity Activity to start.
* @param stopApp True if you need to stop currently running application, false otherwise.
*/
default void startActivity(Activity activity, boolean stopApp) {
startActivity(activity.getAppPackage(), activity.getAppActivity(), stopApp);
}

/**
* Starts application activity.
* Currently running application will be stopped.
* @param appPackage Package of the target application.
* @param appActivity Target activity.
*/
default void startActivity(String appPackage, String appActivity) {
startActivity(appPackage, appActivity, true);
}

/**
* Starts application activity.
* @param appPackage Package of the target application.
* @param appActivity Target activity.
* @param stopApp True if you need to stop currently running application, false otherwise.
*/
void startActivity(String appPackage, String appActivity, boolean stopApp);
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,27 @@ protected void doWithRetry(Runnable function) {
.doWithRetry(function, Collections.singletonList(WebDriverException.class));
}

@Override
public <T> T executeScript(String script, Map<String, Object> params) {
return doWithRetry(() -> {
String argsString = params == null || params.isEmpty() ? "" : ", " + params;
localizedLogger.info("loc.application.execute.script", script + argsString);
T result = CommandExecutionHelper.executeScript(getDriver().assertExtensionExists(script), script, params);
if (result != null) {
localizedLogger.info("loc.application.script.result", result);
}
return result;
});
}

@Override
public String getId() {
final String iosExtName = "mobile: activeAppInfo";
return doWithRetry(() -> {
if (PlatformName.ANDROID == getPlatformName()) {
return ((AndroidDriver) getDriver()).getCurrentPackage();
}
Map<String, Object> result = CommandExecutionHelper.executeScript(getDriver().assertExtensionExists(iosExtName), iosExtName);
Map<String, Object> result = executeScript(iosExtName, null);
return String.valueOf(Objects.requireNonNull(result).get("bundleId"));
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package aquality.appium.mobile.application;

import aquality.appium.mobile.actions.IAndroidActions;
import aquality.appium.mobile.actions.ITouchActions;
import aquality.appium.mobile.configuration.IApplicationProfile;
import aquality.appium.mobile.configuration.IConfiguration;
Expand Down Expand Up @@ -200,4 +201,13 @@ public static IConfiguration getConfiguration() {
public static ITouchActions getTouchActions() {
return get(ITouchActions.class);
}

/**
* Gets the utility used to perform Android-specific actions.
*
* @return instance of Android actions.
*/
public static IAndroidActions getAndroidActions() {
return get(IAndroidActions.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import org.openqa.selenium.remote.service.DriverService;

import java.time.Duration;
import java.util.Collections;
import java.util.Map;

public interface IMobileApplication extends IApplication {
/**
Expand Down Expand Up @@ -63,6 +65,23 @@ default InteractsWithApps appManagement() {
*/
ApplicationState getState(String appId);

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

/**
* Execute application script
* @param script script
* @return result of the script execution.
*/
default <T> T executeScript(String script) {
return executeScript(script, Collections.emptyMap());
}

/**
* Installs an application.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package aquality.appium.mobile.application;

import aquality.appium.mobile.actions.IActionsModule;
import aquality.appium.mobile.actions.IAndroidActions;
import aquality.appium.mobile.actions.ITouchActions;
import aquality.appium.mobile.configuration.IApplicationProfile;
import aquality.appium.mobile.configuration.IConfiguration;
Expand Down Expand Up @@ -31,5 +32,6 @@ protected void configure() {
bind(IScreenFactory.class).to(getScreenFactoryImplementation());
bind(ITouchActionsConfiguration.class).to(getTouchActionsConfigurationImplementation());
bind(ITouchActions.class).to(getTouchActionsImplementation());
bind(IAndroidActions.class).to(getAndroidActionsImplementation());
}
}
2 changes: 2 additions & 0 deletions src/main/resources/localization/be.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"loc.application.ready": "Праграма на платформе '%1$s' гатовая...",
"loc.application.implicit.timeout": "Задаем таймаўт implicit(няяўнага) чакання: '%1$s' сек.",
"loc.application.android.activity.start": "Стартуем '%1$s' актыўнасць Android праграмы ў пакеце '%2$s'",
"loc.application.execute.script": "Выконваем скрыпт '%s'",
"loc.application.script.result": "Вынік выканання скрыпту: '%s'",
"loc.button": "Кнопка",
"loc.checkbox": "Чэкбокс",
"loc.checkable.is.checked": "Атрымліваем стан",
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/localization/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"loc.application.ready": "Application on platform '%1$s' is ready...",
"loc.application.implicit.timeout": "Set implicit timeout '%1$s' in seconds",
"loc.application.android.activity.start": "Starting the '%1$s' activity of the Android app at package '%2$s'",
"loc.application.execute.script": "Executing script '%s'",
"loc.application.script.result": "Script result: '%s'",
"loc.button": "Button",
"loc.checkbox": "CheckBox",
"loc.checkable.is.checked": "Getting state",
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/localization/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"loc.application.ready": "Aplikacja na platformie '%1$s' jest gotowa...",
"loc.application.implicit.timeout": "Ustawianie implicit(niejawnego) limitu czasu '%1$s' sek.",
"loc.application.android.activity.start": "Rozpoczęcie aktywności '%1$s' aplikacji Android w pakiecie '%2$s'",
"loc.application.execute.script": "Wykonywanie skryptu: '%s'",
"loc.application.script.result": "Wynik wykonania skryptu: '%s'",
"loc.button": "Przycisk",
"loc.checkbox": "Pole wyboru",
"loc.checkable.is.checked": "Uzyskiwanie stanu",
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/localization/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"loc.application.ready": "Приложение на платформе '%1$s' готово...",
"loc.application.implicit.timeout": "Установка таймаута implicit(неявного) ожидания: '%1$s' сек.",
"loc.application.android.activity.start": "Стартуем '%1$s' активность Android приложения в пакете '%2$s'",
"loc.application.execute.script": "Исполнение скрипта '%s'",
"loc.application.script.result": "Результат исполнения скрипта: '%s'",
"loc.button": "Кнопка",
"loc.checkbox": "Чекбокс",
"loc.checkable.is.checked": "Получение состояния",
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/localization/uk.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"loc.application.ready": "Програма на платформі '%1$s' готова...",
"loc.application.implicit.timeout": "Встановлення implicit(неявного) часу очікування: '%1$s' сек.",
"loc.application.android.activity.start": "Запуск активності '%1$s' програми Android у пакеті '%2$s'",
"loc.application.execute.script": "Виконання скрипта '%s'",
"loc.application.script.result": "Результат виконання скрипта: '%s'",
"loc.button": "Кнопка",
"loc.checkbox": "Чекбокс",
"loc.checkable.is.checked": "Отримання стану",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,15 @@
import aquality.appium.mobile.application.AqualityServices;
import aquality.appium.mobile.screens.Screen;
import io.appium.java_client.android.Activity;
import io.appium.java_client.android.AndroidDriver;
import org.openqa.selenium.By;

import java.util.HashMap;
import java.util.Map;

public abstract class AndroidScreen extends Screen {

protected AndroidScreen(By locator, String name) {
super(locator, name);
}

protected void startActivity(Activity activity) {
AqualityServices.getLocalizedLogger().info("loc.application.android.activity.start",
activity.getAppActivity(),
activity.getAppPackage());
AndroidDriver driver = (AndroidDriver) AqualityServices.getApplication().getDriver();
Map<String, Object> params = new HashMap<>();
params.put("intent", String.format("%s/%s", activity.getAppPackage(), activity.getAppActivity()));
params.put("package", activity.getAppPackage());
driver.executeScript("mobile: startActivity", params);
AqualityServices.getAndroidActions().startActivity(activity.getAppPackage(), activity.getAppActivity(), false);
}
}
Loading