From 5999cebe19e564e4568a998aa16776762444d663 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Nov 2020 12:41:37 +0530 Subject: [PATCH 001/619] build(deps): bump spring-context from 5.2.9.RELEASE to 5.3.0 (#1407) Bumps [spring-context](https://github.com/spring-projects/spring-framework) from 5.2.9.RELEASE to 5.3.0. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v5.2.9.RELEASE...v5.3.0) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 00408e324..6b5ad223e 100644 --- a/build.gradle +++ b/build.gradle @@ -76,7 +76,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.11' implementation 'commons-io:commons-io:2.8.0' - implementation 'org.springframework:spring-context:5.2.9.RELEASE' + implementation 'org.springframework:spring-context:5.3.0' implementation 'org.aspectj:aspectjweaver:1.9.6' implementation 'org.slf4j:slf4j-api:1.7.30' From c4060efb9d549f8ae755b9351166576e2d22d2e6 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 9 Nov 2020 20:10:23 +0300 Subject: [PATCH 002/619] feat: Add ability to set multiple settings (#1409) --- .../io/appium/java_client/HasSettings.java | 28 +++++++++++++++++++ .../io/appium/java_client/MobileCommand.java | 7 +++-- .../java_client/android/SettingTest.java | 21 ++++++++++++++ .../appium/java_client/ios/SettingTest.java | 27 +++++++++++++++--- 4 files changed, 77 insertions(+), 6 deletions(-) diff --git a/src/main/java/io/appium/java_client/HasSettings.java b/src/main/java/io/appium/java_client/HasSettings.java index 2d6045846..8210123a7 100644 --- a/src/main/java/io/appium/java_client/HasSettings.java +++ b/src/main/java/io/appium/java_client/HasSettings.java @@ -21,7 +21,10 @@ import org.openqa.selenium.remote.Response; +import java.util.EnumMap; import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; public interface HasSettings extends ExecutesMethod { @@ -52,6 +55,31 @@ default HasSettings setSetting(String settingName, Object value) { return this; } + /** + * Sets settings for this test session. + * + * @param settings a map with settings, where key is the setting name you wish to set and value is the value of + * the setting. + * @return Self instance for chaining. + */ + default HasSettings setSettings(EnumMap settings) { + Map convertedSettings = settings.entrySet().stream() + .collect(Collectors.toMap(e -> e.getKey().toString(), Entry::getValue)); + return setSettings(convertedSettings); + } + + /** + * Sets settings for this test session. + * + * @param settings a map with settings, where key is the setting name you wish to set and value is the value of + * the setting. + * @return Self instance for chaining. + */ + default HasSettings setSettings(Map settings) { + CommandExecutionHelper.execute(this, setSettingsCommand(settings)); + return this; + } + /** * Get settings stored for this test session It's probably better to use a * convenience function, rather than use this function directly. Try finding diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index df50c962f..f601aaab7 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -481,8 +481,11 @@ public static ImmutableMap prepareArguments(String[] params, } public static Map.Entry> setSettingsCommand(String setting, Object value) { - return new AbstractMap.SimpleEntry<>(SET_SETTINGS, prepareArguments("settings", - prepareArguments(setting, value))); + return setSettingsCommand(prepareArguments(setting, value)); + } + + public static Map.Entry> setSettingsCommand(Map settings) { + return new AbstractMap.SimpleEntry<>(SET_SETTINGS, prepareArguments("settings", settings)); } /** diff --git a/src/test/java/io/appium/java_client/android/SettingTest.java b/src/test/java/io/appium/java_client/android/SettingTest.java index 559c1ba69..52963e566 100644 --- a/src/test/java/io/appium/java_client/android/SettingTest.java +++ b/src/test/java/io/appium/java_client/android/SettingTest.java @@ -4,6 +4,9 @@ import org.junit.Test; import java.time.Duration; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; import static org.junit.Assert.assertEquals; @@ -103,6 +106,24 @@ public class SettingTest extends BaseAndroidTest { .get("shouldUseCompactResponses")); } + @Test public void setMultipleSettings() { + EnumMap enumSettings = new EnumMap<>(Setting.class); + enumSettings.put(Setting.IGNORE_UNIMPORTANT_VIEWS, true); + enumSettings.put(Setting.ELEMENT_RESPONSE_ATTRIBUTES, "type,label"); + driver.setSettings(enumSettings); + Map actual = driver.getSettings(); + assertEquals(true, actual.get(Setting.IGNORE_UNIMPORTANT_VIEWS.toString())); + assertEquals("type,label", actual.get(Setting.ELEMENT_RESPONSE_ATTRIBUTES.toString())); + + Map mapSettings = new HashMap<>(); + mapSettings.put(Setting.IGNORE_UNIMPORTANT_VIEWS.toString(), false); + mapSettings.put(Setting.ELEMENT_RESPONSE_ATTRIBUTES.toString(), ""); + driver.setSettings(mapSettings); + actual = driver.getSettings(); + assertEquals(false, actual.get(Setting.IGNORE_UNIMPORTANT_VIEWS.toString())); + assertEquals("", actual.get(Setting.ELEMENT_RESPONSE_ATTRIBUTES.toString())); + } + private void assertJSONElementContains(Setting setting, long value) { assertEquals(driver.getSettings().get(setting.toString()), value); } diff --git a/src/test/java/io/appium/java_client/ios/SettingTest.java b/src/test/java/io/appium/java_client/ios/SettingTest.java index d48d2c64d..9d0fbcf80 100644 --- a/src/test/java/io/appium/java_client/ios/SettingTest.java +++ b/src/test/java/io/appium/java_client/ios/SettingTest.java @@ -22,6 +22,9 @@ import static org.junit.Assert.assertEquals; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; public class SettingTest extends AppIOSTest { @@ -34,10 +37,10 @@ public class SettingTest extends AppIOSTest { } @Test public void testSetElementResponseAttributes() { - assertEquals("type,label", driver.getSettings() + assertEquals("", driver.getSettings() .get(Setting.ELEMENT_RESPONSE_ATTRIBUTES.toString())); - driver.setElementResponseAttributes("name"); - assertEquals("name", driver.getSettings() + driver.setElementResponseAttributes("type,label"); + assertEquals("type,label", driver.getSettings() .get(Setting.ELEMENT_RESPONSE_ATTRIBUTES.toString())); } @@ -94,5 +97,21 @@ public class SettingTest extends AppIOSTest { .get("shouldUseCompactResponses")); } - + @Test public void setMultipleSettings() { + EnumMap enumSettings = new EnumMap<>(Setting.class); + enumSettings.put(Setting.IGNORE_UNIMPORTANT_VIEWS, true); + enumSettings.put(Setting.ELEMENT_RESPONSE_ATTRIBUTES, "type,label"); + driver.setSettings(enumSettings); + Map actual = driver.getSettings(); + assertEquals(true, actual.get(Setting.IGNORE_UNIMPORTANT_VIEWS.toString())); + assertEquals("type,label", actual.get(Setting.ELEMENT_RESPONSE_ATTRIBUTES.toString())); + + Map mapSettings = new HashMap<>(); + mapSettings.put(Setting.IGNORE_UNIMPORTANT_VIEWS.toString(), false); + mapSettings.put(Setting.ELEMENT_RESPONSE_ATTRIBUTES.toString(), ""); + driver.setSettings(mapSettings); + actual = driver.getSettings(); + assertEquals(false, actual.get(Setting.IGNORE_UNIMPORTANT_VIEWS.toString())); + assertEquals("", actual.get(Setting.ELEMENT_RESPONSE_ATTRIBUTES.toString())); + } } From 81e0f21754ee534ee7d94c1a72ee5f2307c030d4 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Tue, 10 Nov 2020 10:50:47 +0100 Subject: [PATCH 003/619] chore: Update unstable tests (#1410) --- .azure-templates/bootstrap_steps.yml | 10 ++++ azure-pipelines.yml | 53 ++++++++++--------- build.gradle | 2 +- .../java/io/appium/java_client/TestUtils.java | 30 +++++++++++ .../java_client/android/BaseAndroidTest.java | 1 - .../appium/java_client/ios/IOSDriverTest.java | 43 ++++++--------- 6 files changed, 86 insertions(+), 53 deletions(-) create mode 100644 .azure-templates/bootstrap_steps.yml diff --git a/.azure-templates/bootstrap_steps.yml b/.azure-templates/bootstrap_steps.yml new file mode 100644 index 000000000..9f4e3032b --- /dev/null +++ b/.azure-templates/bootstrap_steps.yml @@ -0,0 +1,10 @@ +steps: + - task: NodeTool@0 + inputs: + versionSpec: "$(NODE_VERSION)" + - script: | + npm config delete prefix + npm config set prefix $NVM_DIR/versions/node/`node --version` + node --version + + npm install -g appium@beta diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f2d020e67..91256cf5c 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -9,52 +9,55 @@ pool: variables: ANDROID_EMU_NAME: test ANDROID_EMU_ABI: x86 - ANDROID_EMU_TARGET: android-27 - ANDROID_EMU_TAG: google_apis + ANDROID_EMU_TARGET: android-28 + ANDROID_EMU_TAG: default XCODE_VERSION: 11.5 IOS_PLATFORM_VERSION: 13.5 IOS_DEVICE_NAME: iPhone X + NODE_VERSION: 12.x + JDK_VERSION: 1.8 jobs: -- job: E2E_Tests - timeoutInMinutes: '60' +- job: Android_E2E_Tests +# timeoutInMinutes: '90' steps: - - task: NodeTool@0 - inputs: - versionSpec: '12.x' - + - template: .azure-templates/bootstrap_steps.yml - script: | - echo "Configuring Environment" echo "y" | $ANDROID_HOME/tools/bin/sdkmanager --install 'system-images;$(ANDROID_EMU_TARGET);$(ANDROID_EMU_TAG);$(ANDROID_EMU_ABI)' echo "no" | $ANDROID_HOME/tools/bin/avdmanager create avd -n "$(ANDROID_EMU_NAME)" -k 'system-images;$(ANDROID_EMU_TARGET);$(ANDROID_EMU_TAG);$(ANDROID_EMU_ABI)' --force echo $ANDROID_HOME/emulator/emulator -list-avds echo "Starting emulator" - nohup $ANDROID_HOME/emulator/emulator -avd "$(ANDROID_EMU_NAME)" -no-snapshot > /dev/null 2>&1 & + nohup $ANDROID_HOME/emulator/emulator -avd "$(ANDROID_EMU_NAME)" -no-snapshot -delay-adb > /dev/null 2>&1 & $ANDROID_HOME/platform-tools/adb wait-for-device - while [[ $? -ne 0 ]]; do sleep 1; $ANDROID_HOME/platform-tools/adb shell pm list packages; done; - $ANDROID_HOME/platform-tools/adb devices + $ANDROID_HOME/platform-tools/adb devices -l echo "Emulator started" - + displayName: Emulator configuration + - task: Gradle@2 + inputs: + gradleWrapperFile: 'gradlew' + gradleOptions: '-Xmx3072m' + javaHomeOption: 'JDKVersion' + jdkVersionOption: "$(JDK_VERSION)" + jdkArchitectureOption: 'x64' + publishJUnitResults: true + tasks: 'build' + options: 'uiAutomationTest -x checkstyleTest -x test -x signMavenJavaPublication' +- job: iOS_E2E_Tests +# timeoutInMinutes: '90' + steps: + - template: .azure-templates/bootstrap_steps.yml + - script: | sudo xcode-select -s /Applications/Xcode_$(XCODE_VERSION).app/Contents/Developer xcrun simctl list - - npm config delete prefix - npm config set prefix $NVM_DIR/versions/node/`node --version` - node --version - - npm install -g appium@beta - appium --version - - java -version - + displayName: Simulator configuration - task: Gradle@2 inputs: gradleWrapperFile: 'gradlew' gradleOptions: '-Xmx3072m' javaHomeOption: 'JDKVersion' - jdkVersionOption: '1.8' + jdkVersionOption: "$(JDK_VERSION)" jdkArchitectureOption: 'x64' publishJUnitResults: true tasks: 'build' - options: 'xcuiTest uiAutomationTest -x checkstyleTest -x test -x signMavenJavaPublication' + options: 'xcuiTest -x checkstyleTest -x test -x signMavenJavaPublication' diff --git a/build.gradle b/build.gradle index 6b5ad223e..7405b25a5 100644 --- a/build.gradle +++ b/build.gradle @@ -227,7 +227,7 @@ task uiAutomationTest( type: Test ) { testLogging.showStandardStreams = true testLogging.exceptionFormat = 'full' filter { - includeTestsMatching '*.SettingTest' + includeTestsMatching 'io.appium.java_client.android.SettingTest' includeTestsMatching 'io.appium.java_client.android.ClipboardTest' includeTestsMatching '*.AndroidAppStringsTest' } diff --git a/src/test/java/io/appium/java_client/TestUtils.java b/src/test/java/io/appium/java_client/TestUtils.java index 4195d4ef9..c0b55e5f0 100644 --- a/src/test/java/io/appium/java_client/TestUtils.java +++ b/src/test/java/io/appium/java_client/TestUtils.java @@ -1,5 +1,7 @@ package io.appium.java_client; +import org.openqa.selenium.TimeoutException; + import java.io.IOException; import java.net.DatagramSocket; import java.net.InetAddress; @@ -9,6 +11,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.time.Duration; +import java.util.function.Supplier; public class TestUtils { public static String getLocalIp4Address() throws SocketException, UnknownHostException { @@ -34,4 +38,30 @@ public static String resourceAsString(String resourcePath) { throw new RuntimeException(e); } } + + public static void waitUntilTrue(Supplier func, Duration timeout, Duration interval) { + long started = System.currentTimeMillis(); + RuntimeException lastError = null; + while (System.currentTimeMillis() - started < timeout.toMillis()) { + lastError = null; + try { + Boolean result = func.get(); + if (result != null && result) { + return; + } + //noinspection BusyWait + Thread.sleep(interval.toMillis()); + } catch (RuntimeException | InterruptedException e) { + if (e instanceof InterruptedException) { + throw new RuntimeException(e); + } else { + lastError = (RuntimeException) e; + } + } + } + if (lastError != null) { + throw lastError; + } + throw new TimeoutException(String.format("Condition unmet after %sms timeout", timeout.toMillis())); + } } diff --git a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java b/src/test/java/io/appium/java_client/android/BaseAndroidTest.java index 1e12834d1..3ebaa5dbf 100644 --- a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java +++ b/src/test/java/io/appium/java_client/android/BaseAndroidTest.java @@ -39,7 +39,6 @@ public class BaseAndroidTest { @BeforeClass public static void beforeClass() { service = AppiumDriverLocalService.buildDefaultService(); service.start(); - if (service == null || !service.isRunning()) { throw new AppiumServerHasNotBeenStartedLocallyException( "An appium server node is not started!"); diff --git a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java b/src/test/java/io/appium/java_client/ios/IOSDriverTest.java index 995ac4c58..40ecb5a9b 100644 --- a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSDriverTest.java @@ -16,22 +16,18 @@ package io.appium.java_client.ios; -import static org.hamcrest.Matchers.empty; +import static io.appium.java_client.TestUtils.waitUntilTrue; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.lessThan; -import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import io.appium.java_client.MobileElement; import io.appium.java_client.appmanagement.ApplicationState; import io.appium.java_client.remote.HideKeyboardStrategy; -import io.appium.java_client.remote.MobileCapabilityType; import org.junit.Ignore; import org.junit.Test; @@ -90,8 +86,8 @@ public void getDeviceTimeTest() { } @Test public void pullFileTest() { - byte[] data = driver.pullFile("@io.appium.TestApp/TestApp"); - assert (data.length > 0); + byte[] data = driver.pullFile(String.format("@%s/TestApp", BUNDLE_ID)); + assertThat(data.length, greaterThan(0)); } @Test public void keyboardTest() { @@ -106,31 +102,25 @@ public void getDeviceTimeTest() { assertThat(System.currentTimeMillis() - msStarted, greaterThan(3000L)); } - @Test public void applicationsManagementTest() throws InterruptedException { - // This only works since Xcode9 - try { - if (Double.parseDouble( - (String) driver.getCapabilities() - .getCapability(MobileCapabilityType.PLATFORM_VERSION)) < 11) { - return; - } - } catch (NumberFormatException | NullPointerException e) { - return; - } + @Test public void applicationsManagementTest() { assertThat(driver.queryAppState(BUNDLE_ID), equalTo(ApplicationState.RUNNING_IN_FOREGROUND)); - Thread.sleep(500); driver.runAppInBackground(Duration.ofSeconds(-1)); - assertThat(driver.queryAppState(BUNDLE_ID), lessThan(ApplicationState.RUNNING_IN_FOREGROUND)); - Thread.sleep(500); + waitUntilTrue( + () -> driver.queryAppState(BUNDLE_ID).ordinal() < ApplicationState.RUNNING_IN_FOREGROUND.ordinal(), + Duration.ofSeconds(10), Duration.ofSeconds(1)); driver.activateApp(BUNDLE_ID); - assertThat(driver.queryAppState(BUNDLE_ID), equalTo(ApplicationState.RUNNING_IN_FOREGROUND)); + waitUntilTrue( + () -> driver.queryAppState(BUNDLE_ID) == ApplicationState.RUNNING_IN_FOREGROUND, + Duration.ofSeconds(10), Duration.ofSeconds(1)); } @Test public void putAIntoBackgroundWithoutRestoreTest() { - assertThat(driver.findElementsById("IntegerA"), is(not(empty()))); + waitUntilTrue(() -> !driver.findElementsById("IntegerA").isEmpty(), + Duration.ofSeconds(10), Duration.ofSeconds(1)); driver.runAppInBackground(Duration.ofSeconds(-1)); - assertThat(driver.findElementsById("IntegerA"), is(empty())); - driver.launchApp(); + waitUntilTrue(() -> driver.findElementsById("IntegerA").isEmpty(), + Duration.ofSeconds(10), Duration.ofSeconds(1)); + driver.activateApp(BUNDLE_ID); } @Ignore @@ -138,6 +128,7 @@ public void getDeviceTimeTest() { driver.toggleTouchIDEnrollment(true); driver.performTouchID(true); driver.performTouchID(false); + //noinspection SimplifiableAssertion assertEquals(true, true); } } From ce44fc51d6c1418407f375df94a7a6d40d3805b0 Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Tue, 17 Nov 2020 15:15:41 +0530 Subject: [PATCH 004/619] Release 7.4.0 and update release notes --- README.md | 32 ++++++++++++++++++++++++++++++++ build.gradle | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 15900ab6e..c1bc98cd8 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,38 @@ dependencies { ``` ## Changelog +*7.4.0* +- **[ENHANCEMENTS]** + - Add ability to set multiple settings. [#1409](https://github.com/appium/java-client/pull/1409) + - Support to execute Chrome DevTools Protocol commands against Android Chrome browser session. [#1375](https://github.com/appium/java-client/pull/1375) + - Add new upload options i.e withHeaders, withFormFields and withFileFieldName. [#1342](https://github.com/appium/java-client/pull/1342) + - Add AndroidOptions and iOSOptions. [#1331](https://github.com/appium/java-client/pull/1331) + - Add idempotency key to session creation requests. [#1327](https://github.com/appium/java-client/pull/1327) + - Add support for Android capability types: `buildToolsVersion`, `enforceAppInstall`, `ensureWebviewsHavePages`, `webviewDevtoolsPort`, and `remoteAppsCacheLimit`. [#1326](https://github.com/appium/java-client/pull/1326) + - Added OTHER_APPS and PRINT_PAGE_SOURCE_ON_FIND_FAILURE Mobile Capability Types. [#1323](https://github.com/appium/java-client/pull/1323) + - Make settings available for all AppiumDriver instances. [#1318](https://github.com/appium/java-client/pull/1318) + - Add wrappers for the Windows screen recorder. [#1313](https://github.com/appium/java-client/pull/1313) + - Add GitHub Action validating Gradle wrapper. [#1296](https://github.com/appium/java-client/pull/1296) + - Add support for Android viewmatcher. [#1293](https://github.com/appium/java-client/pull/1293) + - Update web view detection algorithm for iOS tests. [#1294](https://github.com/appium/java-client/pull/1294) + - Add allow-insecure and deny-insecure server flags. [#1282](https://github.com/appium/java-client/pull/1282) +- **[BUG FIX]** + - Fix jitpack build failures. [#1389](https://github.com/appium/java-client/pull/1389) + - Fix parse platformName if it is passed as enum item. [#1369](https://github.com/appium/java-client/pull/1369) + - Increase the timeout for graceful AppiumDriverLocalService termination. [#1354](https://github.com/appium/java-client/pull/1354) + - Avoid casting to RemoteWebElement in ElementOptions. [#1345](https://github.com/appium/java-client/pull/1345) + - Properly translate desiredCapabilities into a command line argument. [#1337](https://github.com/appium/java-client/pull/1337) + - Change getDeviceTime to call the `mobile` implementation. [#1332](https://github.com/appium/java-client/pull/1332) + - Remove appiumVersion from MobileCapabilityType. [#1325](https://github.com/appium/java-client/pull/1325) + - Set appropriate fluent wait timeouts. [#1316](https://github.com/appium/java-client/pull/1316) +- **[DOCUMENTATION UPDATES]** + - Update Appium Environment Troubleshooting. [#1358](https://github.com/appium/java-client/pull/1358) + - Address warnings printed by docs linter. [#1355](https://github.com/appium/java-client/pull/1355) + - Add java docs for various Mobile Options. [#1331](https://github.com/appium/java-client/pull/1331) + - Add AndroidFindBy, iOSXCUITFindBy and WindowsFindBy docs. [#1311](https://github.com/appium/java-client/pull/1311) + - Renamed maim.js to main.js. [#1277](https://github.com/appium/java-client/pull/1277) + - Improve Readability of Issue Template. [#1260](https://github.com/appium/java-client/pull/1260) + *7.3.0* - **[ENHANCEMENTS]** - Add support for logging custom events on the Appium Server. [#1262](https://github.com/appium/java-client/pull/1262) diff --git a/build.gradle b/build.gradle index 7405b25a5..f0ef66b56 100644 --- a/build.gradle +++ b/build.gradle @@ -128,7 +128,7 @@ publishing { mavenJava(MavenPublication) { groupId = 'io.appium' artifactId = 'java-client' - version = '7.3.0' + version = '7.4.0' from components.java pom { name = 'java-client' From 7d27bdf74098077ef63580478bd2091af541f295 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 22 Nov 2020 12:25:36 +0530 Subject: [PATCH 005/619] build(deps): bump spring-context from 5.3.0 to 5.3.1 (#1413) Bumps [spring-context](https://github.com/spring-projects/spring-framework) from 5.3.0 to 5.3.1. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.0...v5.3.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f0ef66b56..df8bf50fb 100644 --- a/build.gradle +++ b/build.gradle @@ -76,7 +76,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.11' implementation 'commons-io:commons-io:2.8.0' - implementation 'org.springframework:spring-context:5.3.0' + implementation 'org.springframework:spring-context:5.3.1' implementation 'org.aspectj:aspectjweaver:1.9.6' implementation 'org.slf4j:slf4j-api:1.7.30' From 0c96287e721c412a515f435d4622387ab8018c09 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Sun, 22 Nov 2020 09:56:03 +0300 Subject: [PATCH 006/619] chore: upgrade to Gradle 6.7.1 (#1414) --- build.gradle | 5 ++++- gradle/wrapper/gradle-wrapper.jar | Bin 58695 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 ++ gradlew.bat | 25 +++++++---------------- 5 files changed, 14 insertions(+), 20 deletions(-) diff --git a/build.gradle b/build.gradle index df8bf50fb..34f890170 100644 --- a/build.gradle +++ b/build.gradle @@ -45,6 +45,9 @@ compileJava { // https://www.ibm.com/support/knowledgecenter/SS8PJ7_9.7.0/org.eclipse.jdt.doc.user/tasks/task-using_batch_compiler.htm '-warn:-unused,-unchecked,-raw,-serial,-suppress', ] + + // https://github.com/gradle/gradle/issues/12904 + options.headerOutputDirectory.convention(null) } dependencies { @@ -193,7 +196,7 @@ signing { } wrapper { - gradleVersion = '6.6.1' + gradleVersion = '6.7.1' distributionType = Wrapper.DistributionType.ALL } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index f3d88b1c2faf2fc91d853cd5d4242b5547257070..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f 100644 GIT binary patch delta 12842 zcmY+q1ymhDmoSOmQr324hm`&0SZbS3R18r37J8Z0F-T>@gIK` zatajf2b1lO#&E_RnGDF51uk%8Wcxm3`%Yhe7Psx?*?eZ?8M9_+G(?L=s^OG1n#S(NP3gF?2Mr2^f5E7sM~iVC`Rn;(-^MZ zZu*ZXB;XmgvPls(e#)MMTObsEx9oNz-K?AmQ8pP&P7vqx*=5zxjU+ye_1R<%KSg1? z7H&Yh))(Ke!Pa+aVuWxPKa_~Qo_IH}*;tV8n~O*Xa?t3P^9=L%=wOL1=~{LVv}mU8Q#e6s>v}iV8cDP|EdY)`dp≶7^21 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

XiM^r_M1uFTw)(UPqqUJ zed7DJQvOpplYJoNl`A3a2Zr~v)Y}K|*%d7?8;dC*Af}0=(EXrk7hP8PM4v)ZawEv0 z5j5q_6vilv4*ppZ3Wke7%8b`odJu26#YseA?$sP8?@d?TpACTX`G^?%K=Hly9Y$Tj z5`i!}-WH0lQ3yt-&Pf&Z)OxjKfAZ3X`YI2)5o@9EiOA}?kX`^rk;yaOh^Li4VHcT& zd6ztJz^`H!8>cL)a%?Lnofzo0$WPrgkNcP#u@{%~EvA7g#go z+Q4$Q^o_MJTE0G_&9@cgp)WF>2zo>AG}C|(~E^_?ijc2EQ>> zFH1Lxc@i!gDHxvEsrfc+Kiz3Q6Z*NM+U6DH6*-Fv{YDY4>U&eegGH~Xmk~!sd6fw2 z!6^4(MZWhzf(xs6BHy=oS+dir0_JW(j*AIu$9&&p@}T;&6s7(yYidEdkp6pk9}Z(F zk6lG`d!HcJWP{7X)&P5FW;XWU6;zke2e+g*#1kW4L0Auj5pVA45Bhzt{8lj)XyMHu z0p;Q}t*NLnXbGQOTC9WdOQsX;_yLThOP$mzcEbqSBifmDecV;Fqhtm#KxfJTMhY!K zw{1L9za2QtuIWXu0ZYm@Uy72(9^vYajuP$(VAKn+&Jp z!%S;#BqO;02)n~6pFYK8oRC6wXx@kyb?VENM7l?NFg)%^=q4aZ* zwVCZxA8lalF&n`vk#gxD@!9~Aktc+h2UUUax3q2XKQLuL@CpVEpx2IyiH3bALY+Oi zDydtacE1Z|$z5qsCG=%F{}8_ozwieWuM4VcDesuu+wX&YjHm^Ryx)pVtiSLpch7<` zIw9QM%I;(VG9~#Rw2JNt+;?_=O2lA#YSudpgsM`e&(}1 zGdj7U)St4`+Cj#Vn>a;Bj~Q3S1G54;gzq)`b_Hh~ip(`BK#GMkI*RUcK+6ycjl?QN zP%sH5*R$$6A&8j8O4iFJhuHMXLJm|drH+=!_{`60&+tC8*m3Z=YsR@~%eaZyWQI|W zie7;BRL6`LR+4B{%FY~;-^*1GGTCLp!U6VoS36GUAWv$Rcc#|a7DD01{QPB=VyT)? z+1ZV>P=bP1;>v-+j0;BwenO`EKcIbmB3$r*@a~=?5#KB_R$3bTg zOjEutZmWuylIJQEM?28D!4uA#0CZEJHar0TFAW|NwP;WL|EIb_L2>;}e*N!K9E61S zH&u@m!n#CH{C_j}{#ybCRU8z7`Cs{b>@bxSkp3lOm`qAYgB>npnw%V>w}t_+S_Z)s zFhGKq^e%m@=^@sD0CJdAK=`Upbr}?}N zf;snqpt#dOwhxFg82(%Tw=ND+@`O0JGeOWd7-3R8A%Yu%FhiaYXD>p?t2+o%_1CKE z{g(>=g%}X(O%M!}KZK%$7-F<34wD-24`y$WLDv6z?ty=_b)Oi*x&?v}3j0f`AV3HL zWPAYw!XNs-1EmZ9=d=$6LAJISVJ4&gQM5=bh{!f0OmFNz8oMnGgOl_RK5VPP3@87C zpLS$muCo5YTmOslSjFLb`AXIJ@1|O{pm5r z9MxUb-8HMe*|TpFa%dE?+7}MVQ-A-N8wvtq85ROU2%KYt4etC52X0%W08haQgGSU| zvw=K$djTYSLy@4My_Te_8JcZp8Oozg{-ey>*Nm7BkGrX(M~HU6N16U>DSj<`;cy`u zR?0B23zx|*o1V=#fLZ=wd6*NfWjC`pqA^mt>DTZjGBeX`0ZK>Qgxz+37Dyb#NT4WT zl@7Lmh{WdY*h%e_bo6(oXKw=`(9=mft10fOR4< zCOUungtJZPAM~qw4Ydy9PhvYTi1ZRqR5nY)?OX2O3FJ6VXy&`&H%^U|d>N>@f zQ}Cd;DV}_bNiVTW8HcUJDRvXCUwGx|(r2-KbXY>jpd!~jmt(

p*eWM!w;MI3hb2}DlKZV3$r+FsPh`1u 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 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -51,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -61,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell From 0e023aa780b94f205417cc8683ccd5f31ef91453 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 30 Nov 2020 11:17:39 +0300 Subject: [PATCH 007/619] Fix the configuration of `selenium-java` dependency (#1417) https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_separation --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 34f890170..a684b81dd 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ import org.apache.tools.ant.filters.* plugins { - id 'java' + id 'java-library' id 'idea' id 'maven-publish' id 'eclipse' @@ -53,7 +53,7 @@ compileJava { dependencies { compileOnly('org.projectlombok:lombok:1.18.12') annotationProcessor('org.projectlombok:lombok:1.18.12') - implementation ("org.seleniumhq.selenium:selenium-java") { + api ("org.seleniumhq.selenium:selenium-java") { version { strictly "${project.property('selenium.version')}" } From 57287df6500eddd20f03e85b94368f53d8d7a6d2 Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Mon, 30 Nov 2020 16:25:13 +0530 Subject: [PATCH 008/619] Release 7.4.1 and update release notes --- README.md | 7 +++++++ build.gradle | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c1bc98cd8..9b242ba3f 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,13 @@ dependencies { ``` ## Changelog +*7.4.1* +- **[BUG FIX]** + - Fix the configuration of `selenium-java` dependency. [#1417](https://github.com/appium/java-client/pull/1417) +- **[DEPENDENCY UPDATES]** + - `gradle` was updated to 6.7.1. + + *7.4.0* - **[ENHANCEMENTS]** - Add ability to set multiple settings. [#1409](https://github.com/appium/java-client/pull/1409) diff --git a/build.gradle b/build.gradle index a684b81dd..d141fc955 100644 --- a/build.gradle +++ b/build.gradle @@ -131,7 +131,7 @@ publishing { mavenJava(MavenPublication) { groupId = 'io.appium' artifactId = 'java-client' - version = '7.4.0' + version = '7.4.1' from components.java pom { name = 'java-client' From 458cd69bfc90bb3886de24dba667c394807497a4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Dec 2020 10:29:03 +0530 Subject: [PATCH 009/619] build(deps): bump lombok from 1.18.14 to 1.18.16 (#1406) Bumps [lombok](https://github.com/rzwitserloot/lombok) from 1.18.14 to 1.18.16. - [Release notes](https://github.com/rzwitserloot/lombok/releases) - [Changelog](https://github.com/rzwitserloot/lombok/blob/master/doc/changelog.markdown) - [Commits](https://github.com/rzwitserloot/lombok/compare/v1.18.14...v1.18.16) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index d141fc955..56b71ad16 100644 --- a/build.gradle +++ b/build.gradle @@ -24,7 +24,7 @@ configurations { dependencies { ecj 'org.eclipse.jdt:ecj:3.23.0' - lombok 'org.projectlombok:lombok:1.18.14' + lombok 'org.projectlombok:lombok:1.18.16' } java { @@ -51,7 +51,7 @@ compileJava { } dependencies { - compileOnly('org.projectlombok:lombok:1.18.12') + compileOnly('org.projectlombok:lombok:1.18.16') annotationProcessor('org.projectlombok:lombok:1.18.12') api ("org.seleniumhq.selenium:selenium-java") { version { From 59d7d997d516188e82dbd3a4469bb9ac896d1b5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zuzana=20Krej=C4=8Dov=C3=A1?= Date: Thu, 3 Dec 2020 08:29:40 +0100 Subject: [PATCH 010/619] feat: Add 'boundElementsByIndex' to Settings (added in appium 1.18.0) (#1418) --- src/main/java/io/appium/java_client/Setting.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/io/appium/java_client/Setting.java b/src/main/java/io/appium/java_client/Setting.java index 90197b4ce..b5b84ca16 100644 --- a/src/main/java/io/appium/java_client/Setting.java +++ b/src/main/java/io/appium/java_client/Setting.java @@ -44,6 +44,7 @@ public enum Setting { MJPEG_SCALING_FACTOR("mjpegScalingFactor"), KEYBOARD_AUTOCORRECTION("keyboardAutocorrection"), KEYBOARD_PREDICTION("keyboardPrediction"), + BOUND_ELEMENTS_BY_INDEX("boundElementsByIndex"), // Android and iOS SHOULD_USE_COMPACT_RESPONSES("shouldUseCompactResponses"), ELEMENT_RESPONSE_ATTRIBUTES("elementResponseAttributes"), From a8c3c794262672a0ce3dd9451e834c4bfcd280fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Dec 2020 21:12:37 +0530 Subject: [PATCH 011/619] build(deps): bump org.owasp.dependencycheck from 6.0.2 to 6.0.3 (#1408) Bumps org.owasp.dependencycheck from 6.0.2 to 6.0.3. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 56b71ad16..f16d3eac0 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '6.0.2' + id 'org.owasp.dependencycheck' version '6.0.3' id 'com.github.johnrengelman.shadow' version '6.1.0' } From 80d187b260d227cc467a1bb07df83b4a938ef981 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Dec 2020 15:48:06 +0530 Subject: [PATCH 012/619] build(deps): bump webdrivermanager from 4.2.0 to 4.2.2 (#1400) Bumps [webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 4.2.0 to 4.2.2. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-4.2.0...webdrivermanager-4.2.2) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f16d3eac0..d810b63b2 100644 --- a/build.gradle +++ b/build.gradle @@ -85,7 +85,7 @@ dependencies { testImplementation 'junit:junit:4.13.1' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '4.2.0') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '4.2.2') { exclude group: 'org.seleniumhq.selenium' } } From 0be00cdb60a070f31eeb33b15dbb51858efb20c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Dec 2020 14:02:25 +0530 Subject: [PATCH 013/619] build(deps): bump spring-context from 5.3.1 to 5.3.2 (#1420) Bumps [spring-context](https://github.com/spring-projects/spring-framework) from 5.3.1 to 5.3.2. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.1...v5.3.2) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index d810b63b2..514ed0df3 100644 --- a/build.gradle +++ b/build.gradle @@ -79,7 +79,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.11' implementation 'commons-io:commons-io:2.8.0' - implementation 'org.springframework:spring-context:5.3.1' + implementation 'org.springframework:spring-context:5.3.2' implementation 'org.aspectj:aspectjweaver:1.9.6' implementation 'org.slf4j:slf4j-api:1.7.30' From a5f16210000bd936e689500b85175df94ed5a771 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 22 Dec 2020 16:10:47 +0300 Subject: [PATCH 014/619] fix: Use lower case for Windows platform key in ElementMap (#1421) --- src/main/java/io/appium/java_client/internal/ElementMap.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/appium/java_client/internal/ElementMap.java b/src/main/java/io/appium/java_client/internal/ElementMap.java index 5522f7cb4..daeb644fb 100644 --- a/src/main/java/io/appium/java_client/internal/ElementMap.java +++ b/src/main/java/io/appium/java_client/internal/ElementMap.java @@ -37,7 +37,7 @@ public enum ElementMap { IOS_XCUI_TEST(AutomationName.IOS_XCUI_TEST.toLowerCase(), IOSElement.class), ANDROID_UI_AUTOMATOR(MobilePlatform.ANDROID.toLowerCase(), AndroidElement.class), IOS_UI_AUTOMATION(MobilePlatform.IOS.toLowerCase(), IOSElement.class), - WINDOWS(MobilePlatform.WINDOWS, WindowsElement.class); + WINDOWS(MobilePlatform.WINDOWS.toLowerCase(), WindowsElement.class); private static final Map mobileElementMap; From 2d32ed1ba405fac3fc07223039e4394db6f5c646 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Jan 2021 18:21:51 +0530 Subject: [PATCH 015/619] build(deps): bump org.owasp.dependencycheck from 6.0.3 to 6.0.4 (#1425) Bumps org.owasp.dependencycheck from 6.0.3 to 6.0.4. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 514ed0df3..b425c7e5e 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '6.0.3' + id 'org.owasp.dependencycheck' version '6.0.4' id 'com.github.johnrengelman.shadow' version '6.1.0' } From f573237fba116f425f03b71b40702cdb2305d41d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Jan 2021 18:22:38 +0530 Subject: [PATCH 016/619] build(deps): bump ecj from 3.23.0 to 3.24.0 (#1422) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b425c7e5e..16a87408d 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ configurations { } dependencies { - ecj 'org.eclipse.jdt:ecj:3.23.0' + ecj 'org.eclipse.jdt:ecj:3.24.0' lombok 'org.projectlombok:lombok:1.18.16' } From 3f438a6bb58792cadbb338b6290f0dcd791a0f15 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Jan 2021 17:38:34 +0530 Subject: [PATCH 017/619] build(deps): bump org.owasp.dependencycheck from 6.0.4 to 6.0.5 (#1427) Bumps org.owasp.dependencycheck from 6.0.4 to 6.0.5. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 16a87408d..adf941030 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '6.0.4' + id 'org.owasp.dependencycheck' version '6.0.5' id 'com.github.johnrengelman.shadow' version '6.1.0' } From ad3b5fb4f750ef233e6ffc84402288dd30fcfdc5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Jan 2021 11:02:52 +0530 Subject: [PATCH 018/619] build(deps): bump webdrivermanager from 4.2.2 to 4.3.1 (#1429) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index adf941030..459ffdbe3 100644 --- a/build.gradle +++ b/build.gradle @@ -85,7 +85,7 @@ dependencies { testImplementation 'junit:junit:4.13.1' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '4.2.2') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '4.3.1') { exclude group: 'org.seleniumhq.selenium' } } From eef3b83c98a6b065f57a0306a1af8a1783098b46 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Jan 2021 11:03:29 +0530 Subject: [PATCH 019/619] build(deps): bump spring-context from 5.3.2 to 5.3.3 (#1428) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 459ffdbe3..e07170c22 100644 --- a/build.gradle +++ b/build.gradle @@ -79,7 +79,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.11' implementation 'commons-io:commons-io:2.8.0' - implementation 'org.springframework:spring-context:5.3.2' + implementation 'org.springframework:spring-context:5.3.3' implementation 'org.aspectj:aspectjweaver:1.9.6' implementation 'org.slf4j:slf4j-api:1.7.30' From 43d6514b224e0975653695a45e04d73522ed485e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Feb 2021 18:59:31 +0530 Subject: [PATCH 020/619] build(deps): bump org.owasp.dependencycheck from 6.0.5 to 6.1.0 (#1434) Bumps org.owasp.dependencycheck from 6.0.5 to 6.1.0. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e07170c22..e2f5e9cdb 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '6.0.5' + id 'org.owasp.dependencycheck' version '6.1.0' id 'com.github.johnrengelman.shadow' version '6.1.0' } From e9ca49040098fa8475e8160720f908841be12fc8 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 4 Feb 2021 15:21:41 +0300 Subject: [PATCH 021/619] build: remove JCenter repository (#1438) https://jfrog.com/blog/into-the-sunset-bintray-jcenter-gocenter-and-chartcenter/ --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index e2f5e9cdb..0c38bffc4 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,6 @@ plugins { } repositories { - jcenter() mavenCentral() } From ff10d910eae1706d4e0b4888979b9e4ffc91e35d Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 4 Feb 2021 22:09:03 +0100 Subject: [PATCH 022/619] feat: Add Mac2Driver (#1439) --- .../java_client/mac/FindsByClassChain.java | 50 ++++++ .../java_client/mac/FindsByNsPredicate.java | 50 ++++++ .../io/appium/java_client/mac/Mac2Driver.java | 101 ++++++++++++ .../appium/java_client/mac/Mac2Element.java | 23 +++ .../mac/Mac2StartScreenRecordingOptions.java | 152 ++++++++++++++++++ .../mac/Mac2StopScreenRecordingOptions.java | 28 ++++ .../java_client/remote/AutomationName.java | 1 + .../java_client/remote/MobilePlatform.java | 1 + 8 files changed, 406 insertions(+) create mode 100644 src/main/java/io/appium/java_client/mac/FindsByClassChain.java create mode 100644 src/main/java/io/appium/java_client/mac/FindsByNsPredicate.java create mode 100644 src/main/java/io/appium/java_client/mac/Mac2Driver.java create mode 100644 src/main/java/io/appium/java_client/mac/Mac2Element.java create mode 100644 src/main/java/io/appium/java_client/mac/Mac2StartScreenRecordingOptions.java create mode 100644 src/main/java/io/appium/java_client/mac/Mac2StopScreenRecordingOptions.java diff --git a/src/main/java/io/appium/java_client/mac/FindsByClassChain.java b/src/main/java/io/appium/java_client/mac/FindsByClassChain.java new file mode 100644 index 000000000..3d4eaffcc --- /dev/null +++ b/src/main/java/io/appium/java_client/mac/FindsByClassChain.java @@ -0,0 +1,50 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appium.java_client.mac; + +import io.appium.java_client.FindsByFluentSelector; +import io.appium.java_client.MobileSelector; +import org.openqa.selenium.WebElement; + +import java.util.List; + +public interface FindsByClassChain extends FindsByFluentSelector { + + /** + * Perform single element lookup by class chain expression. + * Read https://github.com/appium/appium-mac2-driver#element-location + * for more details on elements location strategies supported by Mac2 driver. + * + * @param using A valid class chain lookup expression. + * @return The found element + */ + default T findElementByClassChain(String using) { + return findElement(MobileSelector.IOS_CLASS_CHAIN.toString(), using); + } + + /** + * Perform multiple elements lookup by class chain search expression. + * Read https://github.com/appium/appium-mac2-driver#element-location + * for more details on elements location strategies supported by Mac2 driver. + * + * @param using A valid class chain lookup expression. + * @return The array of found elements or an empty one if no matches have been found. + */ + default List findElementsByClassChain(String using) { + return findElements(MobileSelector.IOS_CLASS_CHAIN.toString(), using); + } +} diff --git a/src/main/java/io/appium/java_client/mac/FindsByNsPredicate.java b/src/main/java/io/appium/java_client/mac/FindsByNsPredicate.java new file mode 100644 index 000000000..665732eb3 --- /dev/null +++ b/src/main/java/io/appium/java_client/mac/FindsByNsPredicate.java @@ -0,0 +1,50 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appium.java_client.mac; + +import io.appium.java_client.FindsByFluentSelector; +import io.appium.java_client.MobileSelector; +import org.openqa.selenium.WebElement; + +import java.util.List; + +public interface FindsByNsPredicate extends FindsByFluentSelector { + + /** + * Perform single element lookup by predicate search expression. + * Read https://github.com/appium/appium-mac2-driver#element-location + * for more details on elements location strategies supported by Mac2 driver. + * + * @param using A valid predicate lookup expression. + * @return The found element + */ + default T findElementByNsPredicate(String using) { + return findElement(MobileSelector.IOS_PREDICATE_STRING.toString(), using); + } + + /** + * Perform multiple elements lookup by predicate search expression. + * Read https://github.com/appium/appium-mac2-driver#element-location + * for more details on elements location strategies supported by Mac2 driver. + * + * @param using A valid predicate lookup expression. + * @return The array of found elements or an empty one if no matches have been found. + */ + default List findElementsByNsPredicate(String using) { + return findElements(MobileSelector.IOS_PREDICATE_STRING.toString(), using); + } +} diff --git a/src/main/java/io/appium/java_client/mac/Mac2Driver.java b/src/main/java/io/appium/java_client/mac/Mac2Driver.java new file mode 100644 index 000000000..d76eaf5d7 --- /dev/null +++ b/src/main/java/io/appium/java_client/mac/Mac2Driver.java @@ -0,0 +1,101 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appium.java_client.mac; + +import io.appium.java_client.AppiumDriver; +import io.appium.java_client.HasSettings; +import io.appium.java_client.internal.CapabilityHelpers; +import io.appium.java_client.remote.AutomationName; +import io.appium.java_client.remote.MobileCapabilityType; +import io.appium.java_client.screenrecording.CanRecordScreen; +import io.appium.java_client.service.local.AppiumDriverLocalService; +import io.appium.java_client.service.local.AppiumServiceBuilder; +import org.openqa.selenium.Capabilities; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.remote.DesiredCapabilities; +import org.openqa.selenium.remote.HttpCommandExecutor; +import org.openqa.selenium.remote.http.HttpClient; + +import java.net.URL; + +import static io.appium.java_client.remote.MobilePlatform.MAC; +import static org.openqa.selenium.remote.CapabilityType.PLATFORM_NAME; + +/** + * Mac2Driver is an officially supported Appium driver + * created to automate Mac OS apps. The driver uses W3C + * WebDriver protocol and is built on top of Apple's XCTest + * automation framework. Read https://github.com/appium/appium-mac2-driver + * for more details on how to configure and use it. + * + * @since Appium 1.20.0 + */ +public class Mac2Driver + extends AppiumDriver implements CanRecordScreen, FindsByClassChain, + FindsByNsPredicate, HasSettings { + public Mac2Driver(HttpCommandExecutor executor, Capabilities capabilities) { + super(executor, prepareCaps(capabilities)); + } + + public Mac2Driver(URL remoteAddress, Capabilities desiredCapabilities) { + super(remoteAddress, prepareCaps(desiredCapabilities)); + } + + public Mac2Driver(URL remoteAddress, HttpClient.Factory httpClientFactory, Capabilities desiredCapabilities) { + super(remoteAddress, httpClientFactory, prepareCaps(desiredCapabilities)); + } + + public Mac2Driver(AppiumDriverLocalService service, Capabilities desiredCapabilities) { + super(service, prepareCaps(desiredCapabilities)); + } + + public Mac2Driver(AppiumDriverLocalService service, HttpClient.Factory httpClientFactory, + Capabilities desiredCapabilities) { + super(service, httpClientFactory, prepareCaps(desiredCapabilities)); + } + + public Mac2Driver(AppiumServiceBuilder builder, Capabilities desiredCapabilities) { + super(builder, prepareCaps(desiredCapabilities)); + } + + public Mac2Driver(AppiumServiceBuilder builder, HttpClient.Factory httpClientFactory, + Capabilities desiredCapabilities) { + super(builder, httpClientFactory, prepareCaps(desiredCapabilities)); + } + + public Mac2Driver(HttpClient.Factory httpClientFactory, Capabilities desiredCapabilities) { + super(httpClientFactory, prepareCaps(desiredCapabilities)); + } + + public Mac2Driver(Capabilities desiredCapabilities) { + super(prepareCaps(desiredCapabilities)); + } + + private static Capabilities prepareCaps(Capabilities originalCaps) { + DesiredCapabilities dc = new DesiredCapabilities(originalCaps); + if (originalCaps.getCapability(PLATFORM_NAME) == null) { + dc.setCapability(PLATFORM_NAME, MAC); + } + String automationName = CapabilityHelpers.getCapability(originalCaps, + MobileCapabilityType.AUTOMATION_NAME, String.class); + if (!AutomationName.MAC2.equalsIgnoreCase(automationName)) { + dc.setCapability(CapabilityHelpers.APPIUM_PREFIX + + MobileCapabilityType.AUTOMATION_NAME, AutomationName.MAC2); + } + return dc; + } +} diff --git a/src/main/java/io/appium/java_client/mac/Mac2Element.java b/src/main/java/io/appium/java_client/mac/Mac2Element.java new file mode 100644 index 000000000..905bada6e --- /dev/null +++ b/src/main/java/io/appium/java_client/mac/Mac2Element.java @@ -0,0 +1,23 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appium.java_client.mac; + +import io.appium.java_client.MobileElement; + +public class Mac2Element extends MobileElement implements + FindsByClassChain, FindsByNsPredicate { +} diff --git a/src/main/java/io/appium/java_client/mac/Mac2StartScreenRecordingOptions.java b/src/main/java/io/appium/java_client/mac/Mac2StartScreenRecordingOptions.java new file mode 100644 index 000000000..45c573126 --- /dev/null +++ b/src/main/java/io/appium/java_client/mac/Mac2StartScreenRecordingOptions.java @@ -0,0 +1,152 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appium.java_client.mac; + +import com.google.common.collect.ImmutableMap; +import io.appium.java_client.screenrecording.BaseStartScreenRecordingOptions; + +import java.time.Duration; +import java.util.Map; + +import static java.util.Optional.ofNullable; + +public class Mac2StartScreenRecordingOptions + extends BaseStartScreenRecordingOptions { + private Integer fps; + private String videoFilter; + private String preset; + private Boolean captureCursor; + private Boolean captureClicks; + private Integer deviceId; + + public static Mac2StartScreenRecordingOptions startScreenRecordingOptions() { + return new Mac2StartScreenRecordingOptions(); + } + + /** + * The count of frames per second in the resulting video. + * Increasing fps value also increases the size of the resulting + * video file and the CPU usage. + * + * @param fps The actual frames per second value. + * The default value is 15. + * @return self instance for chaining. + */ + public Mac2StartScreenRecordingOptions withFps(int fps) { + this.fps = fps; + return this; + } + + /** + * Whether to capture the mouse cursor while recording + * the screen. Disabled by default. + * + * @return self instance for chaining. + */ + public Mac2StartScreenRecordingOptions enableCursorCapture() { + this.captureCursor = true; + return this; + } + + /** + * Whether to capture the click gestures while recording + * the screen. Disabled by default. + * + * @return self instance for chaining. + */ + public Mac2StartScreenRecordingOptions enableClicksCapture() { + this.captureClicks = true; + return this; + } + + /** + * Screen device index to use for the recording. + * The list of available devices could be retrieved using + * `ffmpeg -f avfoundation -list_devices true -i` command. + * This option is mandatory and must be always provided. + * + * @param deviceId The valid screen device identifier. + * @return self instance for chaining. + */ + public Mac2StartScreenRecordingOptions withDeviceId(Integer deviceId) { + this.deviceId = deviceId; + return this; + } + + /** + * The video filter spec to apply for ffmpeg. + * See https://trac.ffmpeg.org/wiki/FilteringGuide for more details on the possible values. + * Example: Set it to `scale=ifnot(gte(iw\,1024)\,iw\,1024):-2` in order to limit the video width + * to 1024px. The height will be adjusted automatically to match the actual screen aspect ratio. + * + * @param videoFilter Valid ffmpeg video filter spec string. + * @return self instance for chaining. + */ + public Mac2StartScreenRecordingOptions withVideoFilter(String videoFilter) { + this.videoFilter = videoFilter; + return this; + } + + /** + * A preset is a collection of options that will provide a certain encoding speed to compression ratio. + * A slower preset will provide better compression (compression is quality per filesize). + * This means that, for example, if you target a certain file size or constant bit rate, you will + * achieve better quality with a slower preset. Read https://trac.ffmpeg.org/wiki/Encode/H.264 + * for more details. + * + * @param preset One of the supported encoding presets. Possible values are: + * - ultrafast + * - superfast + * - veryfast (default) + * - faster + * - fast + * - medium + * - slow + * - slower + * - veryslow + * @return self instance for chaining. + */ + public Mac2StartScreenRecordingOptions withPreset(String preset) { + this.preset = preset; + return this; + } + + /** + * The maximum recording time. The default value is 600 seconds (10 minutes). + * The minimum time resolution unit is one second. + * + * @param timeLimit The actual time limit of the recorded video. + * @return self instance for chaining. + */ + @Override + public Mac2StartScreenRecordingOptions withTimeLimit(Duration timeLimit) { + return super.withTimeLimit(timeLimit); + } + + @Override + public Map build() { + final ImmutableMap.Builder builder = ImmutableMap.builder(); + builder.putAll(super.build()); + ofNullable(fps).map(x -> builder.put("fps", x)); + ofNullable(preset).map(x -> builder.put("preset", x)); + ofNullable(videoFilter).map(x -> builder.put("videoFilter", x)); + ofNullable(captureClicks).map(x -> builder.put("captureClicks", x)); + ofNullable(captureCursor).map(x -> builder.put("captureCursor", x)); + ofNullable(deviceId).map(x -> builder.put("deviceId", x)); + return builder.build(); + } +} diff --git a/src/main/java/io/appium/java_client/mac/Mac2StopScreenRecordingOptions.java b/src/main/java/io/appium/java_client/mac/Mac2StopScreenRecordingOptions.java new file mode 100644 index 000000000..8984460be --- /dev/null +++ b/src/main/java/io/appium/java_client/mac/Mac2StopScreenRecordingOptions.java @@ -0,0 +1,28 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appium.java_client.mac; + +import io.appium.java_client.screenrecording.BaseStopScreenRecordingOptions; + +public class Mac2StopScreenRecordingOptions extends + BaseStopScreenRecordingOptions { + + public static Mac2StopScreenRecordingOptions stopScreenRecordingOptions() { + return new Mac2StopScreenRecordingOptions(); + } + +} diff --git a/src/main/java/io/appium/java_client/remote/AutomationName.java b/src/main/java/io/appium/java_client/remote/AutomationName.java index ce85512c1..2f9cdf11f 100644 --- a/src/main/java/io/appium/java_client/remote/AutomationName.java +++ b/src/main/java/io/appium/java_client/remote/AutomationName.java @@ -25,4 +25,5 @@ public interface AutomationName { String ANDROID_UIAUTOMATOR2 = "UIAutomator2"; String YOUI_ENGINE = "youiengine"; String ESPRESSO = "Espresso"; + String MAC2 = "Mac2"; } diff --git a/src/main/java/io/appium/java_client/remote/MobilePlatform.java b/src/main/java/io/appium/java_client/remote/MobilePlatform.java index 07ecc8223..97e8deaf3 100644 --- a/src/main/java/io/appium/java_client/remote/MobilePlatform.java +++ b/src/main/java/io/appium/java_client/remote/MobilePlatform.java @@ -23,4 +23,5 @@ public interface MobilePlatform { String FIREFOX_OS = "FirefoxOS"; String WINDOWS = "Windows"; String TVOS = "tvOS"; + String MAC = "Mac"; } From d5ec15a7cb48b5729d0f155f5edd41feb2c3450e Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 19 Feb 2021 15:08:55 +0100 Subject: [PATCH 023/619] feat: Add support of multiple image occurrences (#1445) --- .../OccurrenceMatchingOptions.java | 29 +++++++++++++++++ .../OccurrenceMatchingResult.java | 31 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingOptions.java b/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingOptions.java index baad10d2a..e2990ea23 100644 --- a/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingOptions.java +++ b/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingOptions.java @@ -24,6 +24,8 @@ public class OccurrenceMatchingOptions extends BaseComparisonOptions { private Double threshold; + private Boolean multiple; + private Integer matchNeighbourThreshold; /** * At what normalized threshold to reject an occurrence. @@ -36,11 +38,38 @@ public OccurrenceMatchingOptions withThreshold(double threshold) { return this; } + /** + * Whether to enable the support of multiple image occurrences. + * + * @since Appium 1.21.0 + * @return self instance for chaining. + */ + public OccurrenceMatchingOptions enableMultiple() { + this.multiple = true; + return this; + } + + /** + * The pixel distance between matches we consider + * to be part of the same template match. This option is only + * considered if multiple matches mode is enabled. + * 10 pixels by default. + * + * @since Appium 1.21.0 + * @return self instance for chaining. + */ + public OccurrenceMatchingOptions withMatchNeighbourThreshold(int threshold) { + this.matchNeighbourThreshold = threshold; + return this; + } + @Override public Map build() { final ImmutableMap.Builder builder = ImmutableMap.builder(); builder.putAll(super.build()); ofNullable(threshold).map(x -> builder.put("threshold", x)); + ofNullable(matchNeighbourThreshold).map(x -> builder.put("matchNeighbourThreshold", x)); + ofNullable(multiple).map(x -> builder.put("multiple", x)); return builder.build(); } } diff --git a/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingResult.java b/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingResult.java index 273747247..256a1636a 100644 --- a/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingResult.java +++ b/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingResult.java @@ -18,13 +18,23 @@ import org.openqa.selenium.Rectangle; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; public class OccurrenceMatchingResult extends ComparisonResult { private static final String RECT = "rect"; + private static final String MULTIPLE = "multiple"; + + private final boolean isAtRoot; public OccurrenceMatchingResult(Map input) { + this(input, true); + } + + private OccurrenceMatchingResult(Map input, boolean isAtRoot) { super(input); + this.isAtRoot = isAtRoot; } /** @@ -37,4 +47,25 @@ public Rectangle getRect() { //noinspection unchecked return mapToRect((Map) getCommandResult().get(RECT)); } + + /** + * Returns the list of multiple matches (if any). + * This property only works if the `multiple` option is enabled. + * + * @since Appium 1.21.0 + * @return The list containing properties of each single match or an empty list. + * @throws IllegalStateException If the accessor is called on a non-root match instance. + */ + public List getMultiple() { + if (!isAtRoot) { + throw new IllegalStateException("Only the root match could contain multiple submatches"); + } + verifyPropertyPresence(MULTIPLE); + + //noinspection unchecked + List> multiple = (List>) getCommandResult().get(MULTIPLE); + return multiple.stream() + .map((m) -> new OccurrenceMatchingResult(m, false)) + .collect(Collectors.toList()); + } } From c14054ed9e95b7499c90a09a098b675529c86237 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Feb 2021 20:20:20 +0530 Subject: [PATCH 024/619] build(deps): bump spring-context from 5.3.3 to 5.3.4 (#1446) Bumps [spring-context](https://github.com/spring-projects/spring-framework) from 5.3.3 to 5.3.4. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.3...v5.3.4) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0c38bffc4..3f468ea2b 100644 --- a/build.gradle +++ b/build.gradle @@ -78,7 +78,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.11' implementation 'commons-io:commons-io:2.8.0' - implementation 'org.springframework:spring-context:5.3.3' + implementation 'org.springframework:spring-context:5.3.4' implementation 'org.aspectj:aspectjweaver:1.9.6' implementation 'org.slf4j:slf4j-api:1.7.30' From 08826a7412515d982f5f682adba6af987702329b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Mar 2021 09:21:50 +0300 Subject: [PATCH 025/619] build(deps): bump commons-lang3 from 3.11 to 3.12.0 (#1447) Bumps commons-lang3 from 3.11 to 3.12.0. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3f468ea2b..7ff656454 100644 --- a/build.gradle +++ b/build.gradle @@ -76,7 +76,7 @@ dependencies { implementation 'org.apache.httpcomponents:httpclient:4.5.13' implementation 'cglib:cglib:3.3.0' implementation 'commons-validator:commons-validator:1.7' - implementation 'org.apache.commons:commons-lang3:3.11' + implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.8.0' implementation 'org.springframework:spring-context:5.3.4' implementation 'org.aspectj:aspectjweaver:1.9.6' From f726f3beddb3294684f1f441e865afc334dfc2f8 Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Sat, 13 Mar 2021 16:59:38 +0530 Subject: [PATCH 026/619] Release 7.5.0 and update release notes --- README.md | 16 ++++++++++++++++ build.gradle | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9b242ba3f..70fbf9242 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,22 @@ dependencies { ``` ## Changelog +*7.5.0* +- **[ENHANCEMENTS]** + - Add support for Appium Mac2Driver. [#1439](https://github.com/appium/java-client/pull/1439) + - Add support for multiple image occurrences. [#1445](https://github.com/appium/java-client/pull/1445) + - `BOUND_ELEMENTS_BY_INDEX` Setting was added. [#1418](https://github.com/appium/java-client/pull/1418) +- **[BUG FIX]** + - Use lower case for Windows platform key in ElementMap. [#1421](https://github.com/appium/java-client/pull/1421) +- **[DEPENDENCY UPDATES]** + - `org.apache.commons:commons-lang3` was updated to 3.12.0. + - `org.springframework:spring-context` was updated to 5.3.4. + - `org.owasp.dependencycheck` was updated to 6.1.0. + - `io.github.bonigarcia:webdrivermanager` was updated to 4.3.1. + - `org.eclipse.jdt:ecj` was updated to 3.24.0. + - `org.projectlombok:lombok` was updated to 1.18.16. + - `jcenter` repository was removed. + *7.4.1* - **[BUG FIX]** - Fix the configuration of `selenium-java` dependency. [#1417](https://github.com/appium/java-client/pull/1417) diff --git a/build.gradle b/build.gradle index 7ff656454..9fbc58bda 100644 --- a/build.gradle +++ b/build.gradle @@ -130,7 +130,7 @@ publishing { mavenJava(MavenPublication) { groupId = 'io.appium' artifactId = 'java-client' - version = '7.4.1' + version = '7.5.0' from components.java pom { name = 'java-client' From 03cbed0b2be49392126135af5c5107bfe9b75da1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Mar 2021 17:41:54 +0530 Subject: [PATCH 027/619] build(deps): bump org.owasp.dependencycheck from 6.1.0 to 6.1.2 (#1449) Bumps org.owasp.dependencycheck from 6.1.0 to 6.1.2. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9fbc58bda..b0572a287 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '6.1.0' + id 'org.owasp.dependencycheck' version '6.1.2' id 'com.github.johnrengelman.shadow' version '6.1.0' } From 9a2124c76315b24893079b9f1b3b2ae376e11686 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Mar 2021 17:59:27 +0530 Subject: [PATCH 028/619] build(deps): bump ecj from 3.24.0 to 3.25.0 (#1452) Bumps ecj from 3.24.0 to 3.25.0. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b0572a287..9aa8b2f62 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ configurations { } dependencies { - ecj 'org.eclipse.jdt:ecj:3.24.0' + ecj 'org.eclipse.jdt:ecj:3.25.0' lombok 'org.projectlombok:lombok:1.18.16' } From fc814ed27eec6dfb28b775b75ea1bc78c428c30a Mon Sep 17 00:00:00 2001 From: root-intruder <58737722+root-intruder@users.noreply.github.com> Date: Tue, 23 Mar 2021 15:20:44 +0100 Subject: [PATCH 029/619] fix: bring back ability to automatically quote desired capabilities on windows systems (#1454) --- .../service/local/AppiumServiceBuilder.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java index caef4d36a..dc9b669be 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java @@ -25,6 +25,8 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import io.appium.java_client.remote.AndroidMobileCapabilityType; +import io.appium.java_client.remote.MobileCapabilityType; import io.appium.java_client.service.local.flags.ServerArgument; import org.apache.commons.io.IOUtils; @@ -32,6 +34,7 @@ import org.apache.commons.lang3.SystemUtils; import org.apache.commons.validator.routines.InetAddressValidator; import org.openqa.selenium.Capabilities; +import org.openqa.selenium.Platform; import org.openqa.selenium.os.ExecutableFinder; import org.openqa.selenium.remote.BrowserType; import org.openqa.selenium.remote.DesiredCapabilities; @@ -78,6 +81,7 @@ public final class AppiumServiceBuilder private File node; private String ipAddress = BROADCAST_IP_ADDRESS; private DesiredCapabilities capabilities; + private boolean autoQuoteCapabilitiesOnWindows = false; private static final Function APPIUM_JS_NOT_EXIST_ERROR = (fullPath) -> String.format( "The main Appium script does not exist at '%s'", fullPath.getAbsolutePath()); private static final Function NODE_JS_NOT_EXIST_ERROR = (fullPath) -> @@ -86,6 +90,8 @@ public final class AppiumServiceBuilder // The first starting is slow sometimes on some environment private long startupTimeout = 120; private TimeUnit timeUnit = TimeUnit.SECONDS; + private static final List PATH_CAPABILITIES = ImmutableList.of(AndroidMobileCapabilityType.KEYSTORE_PATH, + AndroidMobileCapabilityType.CHROMEDRIVER_EXECUTABLE, MobileCapabilityType.APP); public AppiumServiceBuilder() { usingPort(DEFAULT_APPIUM_PORT); @@ -239,6 +245,21 @@ public AppiumServiceBuilder withCapabilities(DesiredCapabilities capabilities) { return this; } + /** + * Adds a desired capabilities. + * + * @param capabilities is an instance of {@link DesiredCapabilities}. + * @param autoQuoteCapabilitiesOnWindows automatically escape quote all + * capabilities when calling appium. + * This is required on windows systems only. + * @return the self-reference. + */ + public AppiumServiceBuilder withCapabilities(DesiredCapabilities capabilities, + boolean autoQuoteCapabilitiesOnWindows) { + this.autoQuoteCapabilitiesOnWindows = autoQuoteCapabilitiesOnWindows; + return withCapabilities(capabilities); + } + /** * Sets an executable appium.js. * @@ -296,7 +317,46 @@ private void loadPathToMainScript() { this.appiumJS = findMainScript(); } + private String capabilitiesToQuotedCmdlineArg() { + if (capabilities == null) { + return "{}"; + } + StringBuilder result = new StringBuilder(); + Map capabilitiesMap = capabilities.asMap(); + Set> entries = capabilitiesMap.entrySet(); + + for (Map.Entry entry : entries) { + Object value = entry.getValue(); + + if (value == null) { + continue; + } + + if (value instanceof String) { + String valueString = (String) value; + if (PATH_CAPABILITIES.contains(entry.getKey())) { + value = "\\\"" + valueString.replace("\\", "/") + "\\\""; + } else { + value = "\\\"" + valueString + "\\\""; + } + } else { + value = String.valueOf(value); + } + + String key = "\\\"" + entry.getKey() + "\\\""; + if (result.length() > 0) { + result.append(", "); + } + result.append(key).append(": ").append(value); + } + + return "{" + result.toString() + "}"; + } + private String capabilitiesToCmdlineArg() { + if (autoQuoteCapabilitiesOnWindows && Platform.getCurrent().is(Platform.WINDOWS)) { + return capabilitiesToQuotedCmdlineArg(); + } Gson gson = new GsonBuilder() .disableHtmlEscaping() .serializeNulls() From 6b485190a0d7efcbd184f9354218768309322c36 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Wed, 24 Mar 2021 17:12:16 +0900 Subject: [PATCH 030/619] feat: add iOS related find by annotations for tvOS (#1456) --- .../java_client/pagefactory/DefaultElementByBuilder.java | 2 +- .../java_client/pagefactory/bys/builder/AppiumByBuilder.java | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java b/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java index 40a990898..d31b56fe4 100644 --- a/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java +++ b/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java @@ -170,7 +170,7 @@ protected By buildMobileNativeBy() { getBys(AndroidFindBy.class, AndroidFindBys.class, AndroidFindAll.class)); } - if (isIOSXcuit() || isIOS()) { + if (isIOSXcuit() || isIOS() || isTvOS()) { return buildMobileBy(howToUseLocatorsOptional.map(HowToUseLocators::iOSXCUITAutomation).orElse(null), getBys(iOSXCUITFindBy.class, iOSXCUITFindBys.class, iOSXCUITFindAll.class)); } diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java index 827a8ecbe..3a18cf940 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java @@ -19,6 +19,7 @@ import static io.appium.java_client.remote.AutomationName.IOS_XCUI_TEST; import static io.appium.java_client.remote.MobilePlatform.ANDROID; import static io.appium.java_client.remote.MobilePlatform.IOS; +import static io.appium.java_client.remote.MobilePlatform.TVOS; import static io.appium.java_client.remote.MobilePlatform.WINDOWS; import org.openqa.selenium.By; @@ -178,6 +179,10 @@ protected boolean isIOS() { return IOS.equalsIgnoreCase(platform); } + protected boolean isTvOS() { + return TVOS.equalsIgnoreCase(platform); + } + protected boolean isIOSXcuit() { return isIOS() && IOS_XCUI_TEST.equalsIgnoreCase(automation); } From feea319e6c5691c290d43cc7016803dcf990c1cc Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Thu, 25 Mar 2021 12:20:44 +0530 Subject: [PATCH 031/619] Release 7.5.1 and update release notes --- README.md | 9 +++++++++ build.gradle | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 70fbf9242..bfcc35e51 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,15 @@ dependencies { ``` ## Changelog +*7.5.1* +- **[ENHANCEMENTS]** + - Add iOS related annotations to tvOS. [#1456](https://github.com/appium/java-client/pull/1456) +- **[BUG FIX]** + - Bring back automatic quote escaping for desired capabilities command line arguments on windows. [#1454](https://github.com/appium/java-client/pull/1454) +- **[DEPENDENCY UPDATES]** + - `org.owasp.dependencycheck` was updated to 6.1.2. + - `org.eclipse.jdt:ecj` was updated to 3.25.0. + *7.5.0* - **[ENHANCEMENTS]** - Add support for Appium Mac2Driver. [#1439](https://github.com/appium/java-client/pull/1439) diff --git a/build.gradle b/build.gradle index 9aa8b2f62..4fdaaeb50 100644 --- a/build.gradle +++ b/build.gradle @@ -130,7 +130,7 @@ publishing { mavenJava(MavenPublication) { groupId = 'io.appium' artifactId = 'java-client' - version = '7.5.0' + version = '7.5.1' from components.java pom { name = 'java-client' From e6203a6f46e89b65197450e225aaf99042c4a13f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Mar 2021 17:34:06 +0530 Subject: [PATCH 032/619] build(deps): bump org.owasp.dependencycheck from 6.1.2 to 6.1.3 (#1457) Bumps org.owasp.dependencycheck from 6.1.2 to 6.1.3. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4fdaaeb50..448d4a304 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '6.1.2' + id 'org.owasp.dependencycheck' version '6.1.3' id 'com.github.johnrengelman.shadow' version '6.1.0' } From 08d2f92a47b6bf2ca36afbcf1377453b94fda82e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Apr 2021 20:51:37 +0300 Subject: [PATCH 033/619] build(deps): bump org.owasp.dependencycheck from 6.1.3 to 6.1.5 (#1459) Bumps org.owasp.dependencycheck from 6.1.3 to 6.1.5. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 448d4a304..bf9996562 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '6.1.3' + id 'org.owasp.dependencycheck' version '6.1.5' id 'com.github.johnrengelman.shadow' version '6.1.0' } From fbba129c8e8ff1e807b03e314d83e719d25095cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Apr 2021 07:33:41 +0530 Subject: [PATCH 034/619] build(deps): bump lombok from 1.18.16 to 1.18.20 (#1460) Bumps [lombok](https://github.com/rzwitserloot/lombok) from 1.18.16 to 1.18.20. - [Release notes](https://github.com/rzwitserloot/lombok/releases) - [Changelog](https://github.com/rzwitserloot/lombok/blob/master/doc/changelog.markdown) - [Commits](https://github.com/rzwitserloot/lombok/compare/v1.18.16...v1.18.20) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index bf9996562..6ce80ef87 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ configurations { dependencies { ecj 'org.eclipse.jdt:ecj:3.25.0' - lombok 'org.projectlombok:lombok:1.18.16' + lombok 'org.projectlombok:lombok:1.18.20' } java { @@ -51,7 +51,7 @@ compileJava { dependencies { compileOnly('org.projectlombok:lombok:1.18.16') - annotationProcessor('org.projectlombok:lombok:1.18.12') + annotationProcessor('org.projectlombok:lombok:1.18.20') api ("org.seleniumhq.selenium:selenium-java") { version { strictly "${project.property('selenium.version')}" From c936f66742e7a1fb445f86331aabd3a481394abb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Apr 2021 14:04:34 +0530 Subject: [PATCH 035/619] build(deps): bump junit from 4.13.1 to 4.13.2 (#1442) Bumps [junit](https://github.com/junit-team/junit4) from 4.13.1 to 4.13.2. - [Release notes](https://github.com/junit-team/junit4/releases) - [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.13.1.md) - [Commits](https://github.com/junit-team/junit4/compare/r4.13.1...r4.13.2) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 6ce80ef87..36413c423 100644 --- a/build.gradle +++ b/build.gradle @@ -82,7 +82,7 @@ dependencies { implementation 'org.aspectj:aspectjweaver:1.9.6' implementation 'org.slf4j:slf4j-api:1.7.30' - testImplementation 'junit:junit:4.13.1' + testImplementation 'junit:junit:4.13.2' testImplementation 'org.hamcrest:hamcrest:2.2' testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '4.3.1') { exclude group: 'org.seleniumhq.selenium' From 6d68ea7fccea252d0df455147ca8db2ddadadf96 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Apr 2021 10:06:59 +0300 Subject: [PATCH 036/619] build(deps): bump spring-context from 5.3.4 to 5.3.5 (#1453) Bumps [spring-context](https://github.com/spring-projects/spring-framework) from 5.3.4 to 5.3.5. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.4...v5.3.5) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 36413c423..7c426bd13 100644 --- a/build.gradle +++ b/build.gradle @@ -78,7 +78,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.8.0' - implementation 'org.springframework:spring-context:5.3.4' + implementation 'org.springframework:spring-context:5.3.5' implementation 'org.aspectj:aspectjweaver:1.9.6' implementation 'org.slf4j:slf4j-api:1.7.30' From 0e05078d0ae8e4bebb80080790712e933e2ea666 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Apr 2021 22:28:48 +0300 Subject: [PATCH 037/619] build(deps): bump webdrivermanager from 4.3.1 to 4.4.0 (#1463) Bumps [webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 4.3.1 to 4.4.0. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-4.3.1...webdrivermanager-4.4.0) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7c426bd13..1ab759596 100644 --- a/build.gradle +++ b/build.gradle @@ -84,7 +84,7 @@ dependencies { testImplementation 'junit:junit:4.13.2' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '4.3.1') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '4.4.0') { exclude group: 'org.seleniumhq.selenium' } } From 43ff656ee555a2c3003279dddcde71be5170d3c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Apr 2021 17:47:02 +0530 Subject: [PATCH 038/619] build(deps): bump spring-context from 5.3.5 to 5.3.6 (#1464) Bumps [spring-context](https://github.com/spring-projects/spring-framework) from 5.3.5 to 5.3.6. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.5...v5.3.6) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 1ab759596..801a14af1 100644 --- a/build.gradle +++ b/build.gradle @@ -78,7 +78,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.8.0' - implementation 'org.springframework:spring-context:5.3.5' + implementation 'org.springframework:spring-context:5.3.6' implementation 'org.aspectj:aspectjweaver:1.9.6' implementation 'org.slf4j:slf4j-api:1.7.30' From 96ad4acdd3dd4b19940d6724e2f3ffeeb0227a7e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Apr 2021 17:33:38 +0300 Subject: [PATCH 039/619] build(deps): bump webdrivermanager from 4.4.0 to 4.4.1 (#1466) Bumps [webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 4.4.0 to 4.4.1. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-4.4.0...webdrivermanager-4.4.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 801a14af1..937ed4d71 100644 --- a/build.gradle +++ b/build.gradle @@ -84,7 +84,7 @@ dependencies { testImplementation 'junit:junit:4.13.2' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '4.4.0') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '4.4.1') { exclude group: 'org.seleniumhq.selenium' } } From 2a48d015d38a2c98862da6696d9534f90967cbed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 May 2021 21:09:25 +0530 Subject: [PATCH 040/619] build(deps): bump webdrivermanager from 4.4.1 to 4.4.3 (#1471) Bumps [webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 4.4.1 to 4.4.3. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-4.4.1...webdrivermanager-4.4.3) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 937ed4d71..fd1192957 100644 --- a/build.gradle +++ b/build.gradle @@ -84,7 +84,7 @@ dependencies { testImplementation 'junit:junit:4.13.2' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '4.4.1') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '4.4.3') { exclude group: 'org.seleniumhq.selenium' } } From dcc7579934d15b0aa87127f83a70b26746afdfab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 May 2021 18:06:30 +0530 Subject: [PATCH 041/619] build(deps): bump spring-context from 5.3.6 to 5.3.7 (#1472) Bumps [spring-context](https://github.com/spring-projects/spring-framework) from 5.3.6 to 5.3.7. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.6...v5.3.7) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index fd1192957..12e6c224f 100644 --- a/build.gradle +++ b/build.gradle @@ -78,7 +78,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.8.0' - implementation 'org.springframework:spring-context:5.3.6' + implementation 'org.springframework:spring-context:5.3.7' implementation 'org.aspectj:aspectjweaver:1.9.6' implementation 'org.slf4j:slf4j-api:1.7.30' From b3001672d25a42bd5033123cc6bd934d599d8f04 Mon Sep 17 00:00:00 2001 From: Dmitry Mishtal Date: Thu, 20 May 2021 19:48:19 +0300 Subject: [PATCH 042/619] fix: bind mac2element in element map for mac platform (#1474) --- src/main/java/io/appium/java_client/internal/ElementMap.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/appium/java_client/internal/ElementMap.java b/src/main/java/io/appium/java_client/internal/ElementMap.java index daeb644fb..d2f056c5d 100644 --- a/src/main/java/io/appium/java_client/internal/ElementMap.java +++ b/src/main/java/io/appium/java_client/internal/ElementMap.java @@ -23,6 +23,7 @@ import io.appium.java_client.MobileElement; import io.appium.java_client.android.AndroidElement; import io.appium.java_client.ios.IOSElement; +import io.appium.java_client.mac.Mac2Element; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.windows.WindowsElement; @@ -37,8 +38,8 @@ public enum ElementMap { IOS_XCUI_TEST(AutomationName.IOS_XCUI_TEST.toLowerCase(), IOSElement.class), ANDROID_UI_AUTOMATOR(MobilePlatform.ANDROID.toLowerCase(), AndroidElement.class), IOS_UI_AUTOMATION(MobilePlatform.IOS.toLowerCase(), IOSElement.class), - WINDOWS(MobilePlatform.WINDOWS.toLowerCase(), WindowsElement.class); - + WINDOWS(MobilePlatform.WINDOWS.toLowerCase(), WindowsElement.class), + MAC(MobilePlatform.MAC.toLowerCase(), Mac2Element.class); private static final Map mobileElementMap; From 023cf3f359058a78b000d969eed9326224f5dc1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 May 2021 19:12:26 +0530 Subject: [PATCH 043/619] build(deps): bump commons-io from 2.8.0 to 2.9.0 (#1480) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 12e6c224f..ef4b24afa 100644 --- a/build.gradle +++ b/build.gradle @@ -77,7 +77,7 @@ dependencies { implementation 'cglib:cglib:3.3.0' implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' - implementation 'commons-io:commons-io:2.8.0' + implementation 'commons-io:commons-io:2.9.0' implementation 'org.springframework:spring-context:5.3.7' implementation 'org.aspectj:aspectjweaver:1.9.6' implementation 'org.slf4j:slf4j-api:1.7.30' From 4415440ec509ba964e50428565657a8e064d0c59 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 May 2021 19:12:59 +0530 Subject: [PATCH 044/619] build(deps): bump gson from 2.8.6 to 2.8.7 (#1479) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ef4b24afa..02170dd58 100644 --- a/build.gradle +++ b/build.gradle @@ -72,7 +72,7 @@ dependencies { strictly "${project.property('selenium.version')}" } } - implementation 'com.google.code.gson:gson:2.8.6' + implementation 'com.google.code.gson:gson:2.8.7' implementation 'org.apache.httpcomponents:httpclient:4.5.13' implementation 'cglib:cglib:3.3.0' implementation 'commons-validator:commons-validator:1.7' From 927db522c2ec057f16ed8eef516b00cc6a8dc232 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 May 2021 19:15:29 +0530 Subject: [PATCH 045/619] build(deps): bump org.owasp.dependencycheck from 6.1.5 to 6.2.0 (#1478) Bumps org.owasp.dependencycheck from 6.1.5 to 6.2.0. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 02170dd58..44147faae 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '6.1.5' + id 'org.owasp.dependencycheck' version '6.2.0' id 'com.github.johnrengelman.shadow' version '6.1.0' } From 5089dbcaf804d96d57c4eb0ed16f255059a11182 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Jun 2021 15:17:54 +0300 Subject: [PATCH 046/619] build(deps): bump commons-io from 2.9.0 to 2.10.0 (#1483) Bumps commons-io from 2.9.0 to 2.10.0. --- updated-dependencies: - dependency-name: commons-io:commons-io dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 44147faae..81483536f 100644 --- a/build.gradle +++ b/build.gradle @@ -77,7 +77,7 @@ dependencies { implementation 'cglib:cglib:3.3.0' implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' - implementation 'commons-io:commons-io:2.9.0' + implementation 'commons-io:commons-io:2.10.0' implementation 'org.springframework:spring-context:5.3.7' implementation 'org.aspectj:aspectjweaver:1.9.6' implementation 'org.slf4j:slf4j-api:1.7.30' From d1e5fa7d16eada87413893cbcfe8f6b1ce82d404 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Jun 2021 16:45:24 +0300 Subject: [PATCH 047/619] build(deps): bump spring-context from 5.3.7 to 5.3.8 (#1485) Bumps [spring-context](https://github.com/spring-projects/spring-framework) from 5.3.7 to 5.3.8. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.7...v5.3.8) --- updated-dependencies: - dependency-name: org.springframework:spring-context dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 81483536f..cd04bca27 100644 --- a/build.gradle +++ b/build.gradle @@ -78,7 +78,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.10.0' - implementation 'org.springframework:spring-context:5.3.7' + implementation 'org.springframework:spring-context:5.3.8' implementation 'org.aspectj:aspectjweaver:1.9.6' implementation 'org.slf4j:slf4j-api:1.7.30' From ceac42837ffe5fe7400c54d802e96318961698a8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jun 2021 11:01:25 +0300 Subject: [PATCH 048/619] build(deps): bump ecj from 3.25.0 to 3.26.0 (#1487) Bumps ecj from 3.25.0 to 3.26.0. --- updated-dependencies: - dependency-name: org.eclipse.jdt:ecj dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index cd04bca27..e6f02ac48 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ configurations { } dependencies { - ecj 'org.eclipse.jdt:ecj:3.25.0' + ecj 'org.eclipse.jdt:ecj:3.26.0' lombok 'org.projectlombok:lombok:1.18.20' } From 979e6bdc0c472239ec8390d9cf24c064d4cc6aef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Jun 2021 11:49:28 +0530 Subject: [PATCH 049/619] build(deps): bump slf4j-api from 1.7.30 to 1.7.31 (#1486) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e6f02ac48..3afc246f8 100644 --- a/build.gradle +++ b/build.gradle @@ -80,7 +80,7 @@ dependencies { implementation 'commons-io:commons-io:2.10.0' implementation 'org.springframework:spring-context:5.3.8' implementation 'org.aspectj:aspectjweaver:1.9.6' - implementation 'org.slf4j:slf4j-api:1.7.30' + implementation 'org.slf4j:slf4j-api:1.7.31' testImplementation 'junit:junit:4.13.2' testImplementation 'org.hamcrest:hamcrest:2.2' From 93a95fc689a116ac14f3bf8739037033a63f03f3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Jun 2021 22:47:03 +0300 Subject: [PATCH 050/619] build(deps): bump aspectjweaver from 1.9.6 to 1.9.7 (#1490) Bumps [aspectjweaver](https://github.com/eclipse/org.aspectj) from 1.9.6 to 1.9.7. - [Release notes](https://github.com/eclipse/org.aspectj/releases) - [Commits](https://github.com/eclipse/org.aspectj/commits) --- updated-dependencies: - dependency-name: org.aspectj:aspectjweaver dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3afc246f8..948485713 100644 --- a/build.gradle +++ b/build.gradle @@ -79,7 +79,7 @@ dependencies { implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.10.0' implementation 'org.springframework:spring-context:5.3.8' - implementation 'org.aspectj:aspectjweaver:1.9.6' + implementation 'org.aspectj:aspectjweaver:1.9.7' implementation 'org.slf4j:slf4j-api:1.7.31' testImplementation 'junit:junit:4.13.2' From a1e1d1d0702b45601593dda0679babac8266f416 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 1 Jul 2021 20:52:02 +0200 Subject: [PATCH 051/619] feat: Add support of extended Android geolocation (#1492) --- .../java_client/android/AndroidDriver.java | 3 +- .../geolocation/AndroidGeoLocation.java | 125 ++++++++++++++++++ .../SupportsExtendedGeolocationCommands.java | 40 ++++++ 3 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 src/main/java/io/appium/java_client/android/geolocation/AndroidGeoLocation.java create mode 100644 src/main/java/io/appium/java_client/android/geolocation/SupportsExtendedGeolocationCommands.java diff --git a/src/main/java/io/appium/java_client/android/AndroidDriver.java b/src/main/java/io/appium/java_client/android/AndroidDriver.java index 62016e814..1994bb69a 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -33,6 +33,7 @@ import io.appium.java_client.HasOnScreenKeyboard; import io.appium.java_client.LocksDevice; import io.appium.java_client.android.connection.HasNetworkConnection; +import io.appium.java_client.android.geolocation.SupportsExtendedGeolocationCommands; import io.appium.java_client.android.nativekey.PressesKey; import io.appium.java_client.battery.HasBattery; import io.appium.java_client.remote.MobilePlatform; @@ -68,7 +69,7 @@ public class AndroidDriver HasSupportedPerformanceDataType, AuthenticatesByFinger, HasOnScreenKeyboard, CanRecordScreen, SupportsSpecialEmulatorCommands, SupportsNetworkStateManagement, ListensToLogcatMessages, HasAndroidClipboard, - HasBattery, ExecuteCDPCommand { + HasBattery, ExecuteCDPCommand, SupportsExtendedGeolocationCommands { private static final String ANDROID_PLATFORM = MobilePlatform.ANDROID; diff --git a/src/main/java/io/appium/java_client/android/geolocation/AndroidGeoLocation.java b/src/main/java/io/appium/java_client/android/geolocation/AndroidGeoLocation.java new file mode 100644 index 000000000..9ab204317 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/geolocation/AndroidGeoLocation.java @@ -0,0 +1,125 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appium.java_client.android.geolocation; + +import com.google.common.collect.ImmutableMap; + +import java.util.Map; + +import static java.util.Optional.ofNullable; + +public class AndroidGeoLocation { + private Double longitude; + private Double latitude; + private Double altitude; + private Integer satellites; + private Double speed; + + /** + * Initializes AndroidLocation instance. + */ + public AndroidGeoLocation() { + + } + + /** + * Initializes AndroidLocation instance with longitude and latitude values. + * + * @param longitude longitude value + * @param latitude latitude value + */ + public AndroidGeoLocation(double longitude, double latitude) { + this.longitude = longitude; + this.latitude = latitude; + } + + /** + * Sets geo longitude value. This value is required to set. + * + * @param longitude geo longitude + * @return self instance for chaining + */ + public AndroidGeoLocation withLongitude(double longitude) { + this.longitude = longitude; + return this; + } + + /** + * Sets geo latitude value. This value is required to set. + * + * @param latitude geo latitude + * @return self instance for chaining + */ + public AndroidGeoLocation withLatitude(double latitude) { + this.latitude = latitude; + return this; + } + + /** + * Sets geo altitude value. + * + * @param altitude geo altitude + * @return self instance for chaining + */ + public AndroidGeoLocation withAltitude(double altitude) { + this.altitude = altitude; + return this; + } + + /** + * Sets the number of geo satellites being tracked. + * This number is respected on Emulators. + * + * @param satellites the count of satellites in range 1..12 + * @return self instance for chaining + */ + public AndroidGeoLocation withSatellites(int satellites) { + this.satellites = satellites; + return this; + } + + /** + * Sets the movement speed. It is measured in meters/second + * for real devices and in knots for emulators. + * + * @param speed the actual speed, which should be greater than zero + * @return self instance for chaining + */ + public AndroidGeoLocation withSpeed(double speed) { + this.speed = speed; + return this; + } + + /** + * Builds parameters map suitable for passing to the downstream API. + * + * @return Parameters mapping + */ + public Map build() { + ImmutableMap.Builder builder = ImmutableMap.builder(); + ofNullable(longitude).map(x -> builder.put("longitude", x)) + .orElseThrow(() -> new IllegalArgumentException( + "A valid 'longitude' must be provided")); + ofNullable(latitude).map(x -> builder.put("latitude", x)) + .orElseThrow(() -> new IllegalArgumentException( + "A valid 'latitude' must be provided")); + ofNullable(altitude).map(x -> builder.put("altitude", x)); + ofNullable(satellites).map(x -> builder.put("satellites", x)); + ofNullable(speed).map(x -> builder.put("speed", x)); + return builder.build(); + } +} diff --git a/src/main/java/io/appium/java_client/android/geolocation/SupportsExtendedGeolocationCommands.java b/src/main/java/io/appium/java_client/android/geolocation/SupportsExtendedGeolocationCommands.java new file mode 100644 index 000000000..3587ad07e --- /dev/null +++ b/src/main/java/io/appium/java_client/android/geolocation/SupportsExtendedGeolocationCommands.java @@ -0,0 +1,40 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appium.java_client.android.geolocation; + +import com.google.common.collect.ImmutableMap; +import io.appium.java_client.CommandExecutionHelper; +import io.appium.java_client.ExecutesMethod; +import org.openqa.selenium.remote.DriverCommand; + +import java.util.AbstractMap; + +public interface SupportsExtendedGeolocationCommands extends ExecutesMethod { + + /** + * Allows to set geo location with extended parameters + * available for Android platform. + * + * @param location The location object to set. + */ + default void setLocation(AndroidGeoLocation location) { + ImmutableMap parameters = ImmutableMap + .of("location", location.build()); + CommandExecutionHelper.execute(this, + new AbstractMap.SimpleEntry<>(DriverCommand.SET_LOCATION, parameters)); + } +} From 7ba73a98b57f5cf6f1d3c76c60acd47246588416 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jul 2021 18:18:03 +0300 Subject: [PATCH 052/619] build(deps): bump commons-io from 2.10.0 to 2.11.0 (#1494) Bumps commons-io from 2.10.0 to 2.11.0. --- updated-dependencies: - dependency-name: commons-io:commons-io dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 948485713..54c32f31a 100644 --- a/build.gradle +++ b/build.gradle @@ -77,7 +77,7 @@ dependencies { implementation 'cglib:cglib:3.3.0' implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' - implementation 'commons-io:commons-io:2.10.0' + implementation 'commons-io:commons-io:2.11.0' implementation 'org.springframework:spring-context:5.3.8' implementation 'org.aspectj:aspectjweaver:1.9.7' implementation 'org.slf4j:slf4j-api:1.7.31' From cfeaf498c66a4f4c38d98bf52c63571471aa3e23 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jul 2021 23:26:24 +0530 Subject: [PATCH 053/619] build(deps): bump spring-context from 5.3.8 to 5.3.9 (#1495) Bumps [spring-context](https://github.com/spring-projects/spring-framework) from 5.3.8 to 5.3.9. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.8...v5.3.9) --- updated-dependencies: - dependency-name: org.springframework:spring-context dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 54c32f31a..c6488b4e5 100644 --- a/build.gradle +++ b/build.gradle @@ -78,7 +78,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.11.0' - implementation 'org.springframework:spring-context:5.3.8' + implementation 'org.springframework:spring-context:5.3.9' implementation 'org.aspectj:aspectjweaver:1.9.7' implementation 'org.slf4j:slf4j-api:1.7.31' From 9316538cec86c82e9444f9f90e2fc39cd4cac215 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 20 Jul 2021 15:29:42 +0300 Subject: [PATCH 054/619] chore: Upgrade to Gradle 7.1.1 (#1497) --- build.gradle | 4 ++-- gradle/wrapper/gradle-wrapper.jar | Bin 59203 -> 59536 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index c6488b4e5..5afdc2207 100644 --- a/build.gradle +++ b/build.gradle @@ -107,7 +107,7 @@ tasks.withType(JacocoReport) { description = 'Generate Jacoco coverage reports after running tests' sourceSets sourceSets.main reports { - html.enabled true + html.required = true html.destination file("${buildDir}/Reports/jacoco") } } @@ -195,7 +195,7 @@ signing { } wrapper { - gradleVersion = '6.7.1' + gradleVersion = '7.1.1' distributionType = Wrapper.DistributionType.ALL } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e708b1c023ec8b20f512888fe07c5bd3ff77bb8f..7454180f2ae8848c63b8b4dea2cb829da983f2fa 100644 GIT binary patch delta 18435 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 B8dv}T delta 17845 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 X49Luk)baa85H9$5YCsTPT`SVRWMtMW diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1f3fdbc52..af7be50b1 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 4f906e0c8..744e882ed 100755 --- a/gradlew +++ b/gradlew @@ -72,7 +72,7 @@ case "`uname`" in Darwin* ) darwin=true ;; - MINGW* ) + MSYS* | MINGW* ) msys=true ;; NONSTOP* ) From c185583e8f5d99a356c0574b09af47836b5d8dde Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 20 Jul 2021 15:31:17 +0300 Subject: [PATCH 055/619] chore: Prevent duplicate builds for PRs from base repo branches (#1496) --- .github/workflows/gradle-wrapper-validation.yml | 9 ++++++++- .github/workflows/gradle.yml | 8 +++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 405a2b306..ba5a2db79 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -1,5 +1,12 @@ name: "Validate Gradle Wrapper" -on: [push, pull_request] + +on: + push: + branches: + - master + pull_request: + branches: + - master jobs: validation: diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 04241b76f..44e24a9e0 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -1,6 +1,12 @@ name: Appium Java Client CI -on: [push, pull_request] +on: + push: + branches: + - master + pull_request: + branches: + - master jobs: build: From 94d5c0050fe3e225549fa5c00ee0fbbb55c1ab5f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Aug 2021 15:58:40 +0300 Subject: [PATCH 056/619] build(deps): bump gson from 2.8.7 to 2.8.8 (#1507) Bumps [gson](https://github.com/google/gson) from 2.8.7 to 2.8.8. - [Release notes](https://github.com/google/gson/releases) - [Changelog](https://github.com/google/gson/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/gson/compare/gson-parent-2.8.7...gson-parent-2.8.8) --- updated-dependencies: - dependency-name: com.google.code.gson:gson dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 5afdc2207..a448344ec 100644 --- a/build.gradle +++ b/build.gradle @@ -72,7 +72,7 @@ dependencies { strictly "${project.property('selenium.version')}" } } - implementation 'com.google.code.gson:gson:2.8.7' + implementation 'com.google.code.gson:gson:2.8.8' implementation 'org.apache.httpcomponents:httpclient:4.5.13' implementation 'cglib:cglib:3.3.0' implementation 'commons-validator:commons-validator:1.7' From 227581b197f195ce38c3fbbc6c886936097414b1 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 23 Aug 2021 18:27:01 +0300 Subject: [PATCH 057/619] chore: Enable Dependabot for GitHub actions (#1500) --- .github/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index bcf259eb9..c082a4d00 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,3 +6,9 @@ updates: interval: weekly time: "11:00" open-pull-requests-limit: 10 +- package-ecosystem: github-actions + directory: "/" + schedule: + interval: weekly + time: "11:00" + open-pull-requests-limit: 10 From 3a3e2f9f8088247667289353068b9ded9c34cbc8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Aug 2021 16:35:29 +0300 Subject: [PATCH 058/619] build(deps): bump slf4j-api from 1.7.31 to 1.7.32 (#1501) Bumps [slf4j-api](https://github.com/qos-ch/slf4j) from 1.7.31 to 1.7.32. - [Release notes](https://github.com/qos-ch/slf4j/releases) - [Commits](https://github.com/qos-ch/slf4j/commits) --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a448344ec..d827cd41d 100644 --- a/build.gradle +++ b/build.gradle @@ -80,7 +80,7 @@ dependencies { implementation 'commons-io:commons-io:2.11.0' implementation 'org.springframework:spring-context:5.3.9' implementation 'org.aspectj:aspectjweaver:1.9.7' - implementation 'org.slf4j:slf4j-api:1.7.31' + implementation 'org.slf4j:slf4j-api:1.7.32' testImplementation 'junit:junit:4.13.2' testImplementation 'org.hamcrest:hamcrest:2.2' From bcd6881efe53713ea339a3e606dc0bc004969908 Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Mon, 30 Aug 2021 11:09:42 +0530 Subject: [PATCH 059/619] feat: allow to add custom command dynamically (#1506) --- .../io/appium/java_client/AppiumDriver.java | 29 +++++++++++++++++-- .../remote/AppiumCommandExecutor.java | 3 ++ .../io/appium/java_client/ios/AppIOSTest.java | 2 +- .../appium/java_client/ios/BaseIOSTest.java | 4 +-- .../appium/java_client/ios/IOSDriverTest.java | 29 ++++++++++++++++++- 5 files changed, 61 insertions(+), 6 deletions(-) diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index 32785d1eb..fd512197a 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -29,7 +29,6 @@ import io.appium.java_client.remote.MobileCapabilityType; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; - import org.openqa.selenium.By; import org.openqa.selenium.Capabilities; import org.openqa.selenium.DeviceRotation; @@ -39,7 +38,6 @@ import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WebElement; import org.openqa.selenium.html5.Location; - import org.openqa.selenium.remote.CapabilityType; import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.remote.DriverCommand; @@ -49,8 +47,10 @@ import org.openqa.selenium.remote.Response; import org.openqa.selenium.remote.html5.RemoteLocationContext; import org.openqa.selenium.remote.http.HttpClient; +import org.openqa.selenium.remote.http.HttpMethod; import java.net.URL; +import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -288,6 +288,31 @@ public void rotate(ScreenOrientation orientation) { ImmutableMap.of("orientation", orientation.value().toUpperCase())); } + /** + * This method is used to add custom appium commands in Appium 2.0. + * + * @param httpMethod the available {@link HttpMethod}. + * @param url The url to URL template as https://www.w3.org/TR/webdriver/#endpoints. + * @param methodName The name of custom appium command. + */ + public void addCommand(HttpMethod httpMethod, String url, String methodName) { + switch (httpMethod) { + case GET: + MobileCommand.commandRepository.put(methodName, MobileCommand.getC(url)); + break; + case POST: + MobileCommand.commandRepository.put(methodName, MobileCommand.postC(url)); + break; + case DELETE: + MobileCommand.commandRepository.put(methodName, MobileCommand.deleteC(url)); + break; + default: + throw new WebDriverException(String.format("Unsupported HTTP Method: %s. Only %s methods are supported", + httpMethod, + Arrays.toString(HttpMethod.values()))); + } + } + @Override public ScreenOrientation getOrientation() { Response response = execute(DriverCommand.GET_SCREEN_ORIENTATION); diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index ea0ade5f0..2b0f77f7e 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -241,6 +241,9 @@ public Response execute(Command command) throws WebDriverException { } }); } + if (getAdditionalCommands().containsKey(command.getName())) { + super.defineCommand(command.getName(), getAdditionalCommands().get(command.getName())); + } Response response; try { diff --git a/src/test/java/io/appium/java_client/ios/AppIOSTest.java b/src/test/java/io/appium/java_client/ios/AppIOSTest.java index 12426ebd9..bdc75a01b 100644 --- a/src/test/java/io/appium/java_client/ios/AppIOSTest.java +++ b/src/test/java/io/appium/java_client/ios/AppIOSTest.java @@ -39,4 +39,4 @@ public static void beforeClass() throws Exception { driver = new IOSDriver<>(new URL("http://" + ip + ":" + PORT + "/wd/hub"), capabilities); } } -} +} \ No newline at end of file diff --git a/src/test/java/io/appium/java_client/ios/BaseIOSTest.java b/src/test/java/io/appium/java_client/ios/BaseIOSTest.java index 45e7a8e2e..9275dd10b 100644 --- a/src/test/java/io/appium/java_client/ios/BaseIOSTest.java +++ b/src/test/java/io/appium/java_client/ios/BaseIOSTest.java @@ -31,9 +31,9 @@ public class BaseIOSTest { protected static IOSDriver driver; protected static final int PORT = 4723; public static final String DEVICE_NAME = System.getenv("IOS_DEVICE_NAME") != null - ? System.getenv("IOS_DEVICE_NAME") : "iPhone X"; + ? System.getenv("IOS_DEVICE_NAME") : "iPhone 12"; public static final String PLATFORM_VERSION = System.getenv("IOS_PLATFORM_VERSION") != null - ? System.getenv("IOS_PLATFORM_VERSION") : "11.4"; + ? System.getenv("IOS_PLATFORM_VERSION") : "14.5"; /** diff --git a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java b/src/test/java/io/appium/java_client/ios/IOSDriverTest.java index 40ecb5a9b..a1d7a0fb3 100644 --- a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSDriverTest.java @@ -22,18 +22,21 @@ import static org.hamcrest.Matchers.greaterThan; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import com.google.common.collect.ImmutableMap; import io.appium.java_client.MobileElement; import io.appium.java_client.appmanagement.ApplicationState; import io.appium.java_client.remote.HideKeyboardStrategy; import org.junit.Ignore; import org.junit.Test; - import org.openqa.selenium.By; import org.openqa.selenium.ScreenOrientation; import org.openqa.selenium.html5.Location; +import org.openqa.selenium.remote.Response; +import org.openqa.selenium.remote.http.HttpMethod; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; @@ -41,6 +44,30 @@ public class IOSDriverTest extends AppIOSTest { + @Test + public void addCustomCommandTest() { + driver.addCommand(HttpMethod.GET, "/sessions", "getSessions"); + final Response getSessions = driver.execute("getSessions"); + assertNotNull(getSessions.getSessionId()); + } + + @Test + public void addCustomCommandWithSessionIdTest() { + driver.addCommand(HttpMethod.POST, "/session/" + driver.getSessionId() + "/appium/app/launch", "launchApplication"); + final Response launchApplication = driver.execute("launchApplication"); + assertNotNull(launchApplication.getSessionId()); + } + + @Test + public void addCustomCommandWithElementIdTest() { + IOSElement intA = driver.findElementById("IntegerA"); + intA.clear(); + driver.addCommand(HttpMethod.POST, + String.format("/session/%s/appium/element/%s/value", driver.getSessionId(), intA.getId()), "setNewValue"); + final Response setNewValue = driver.execute("setNewValue", ImmutableMap.of("id", intA.getId(), "value", "8")); + assertNotNull(setNewValue.getSessionId()); + } + @Test public void getDeviceTimeTest() { String time = driver.getDeviceTime(); From 94b30221fb602b7a62c33d26a168d95ff77a4d2a Mon Sep 17 00:00:00 2001 From: Manoj Kumar Date: Fri, 3 Sep 2021 17:57:05 +0530 Subject: [PATCH 060/619] feat: Add new flags to support Appium 2.0 (#1511) --- .../local/flags/GeneralServerFlag.java | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/appium/java_client/service/local/flags/GeneralServerFlag.java b/src/main/java/io/appium/java_client/service/local/flags/GeneralServerFlag.java index d59ff750d..817deae05 100644 --- a/src/main/java/io/appium/java_client/service/local/flags/GeneralServerFlag.java +++ b/src/main/java/io/appium/java_client/service/local/flags/GeneralServerFlag.java @@ -133,7 +133,40 @@ public enum GeneralServerFlag implements ServerArgument { * Default: [] * Sample: --deny-insecure=foo,bar */ - DENY_INSECURE("--deny-insecure"); + DENY_INSECURE("--deny-insecure"), + /** + * Plugins are little programs which can be added to an Appium installation and activated, for the purpose of + * extending or modifying the behavior of pretty much any aspect of Appium. + * Plugins are available with Appium as of Appium 2.0. + * To activate all plugins, you can use the single string "all" as the value (e.g --plugins=all) + * Default: [] + * Sample: --plugins=device-farm,images + */ + PLUGINS("--plugins"), + /** + * A comma-separated list of installed driver names that should be active for this server. + * All drivers will be active by default. + * Default: [] + * Sample: --drivers=uiautomator2,xcuitest + */ + DRIVERS("--drivers"), + /** + * Base path to use as the prefix for all webdriver routes running on this server. + * Sample: --base-path=/wd/hub + */ + BASEPATH("--base-path"), + /** + * Set the default desired client arguments for a plugin. + * Default: [] + * Sample: [ '{"images":{"foo1": "bar1", "foo2": "bar2"}}' | /path/to/pluginArgs.json ] + */ + PLUGINARGS("--plugin-args"), + /** + * Set the default desired client arguments for a driver. + * Default: [] + * Sample: [ '{"xcuitest": {"foo1": "bar1", "foo2": "bar2"}}' | /path/to/driverArgs.json ] + */ + DRIVERARGS("--driver-args"); private final String arg; From 93a125e5d57f51c94c50954242d2119b5e5885bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Sep 2021 14:34:09 +0300 Subject: [PATCH 061/619] build(deps): bump actions/setup-java from 1 to 2.3.0 (#1508) * build(deps): bump actions/setup-java from 1 to 2.3.0 Bumps [actions/setup-java](https://github.com/actions/setup-java) from 1 to 2.3.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v1...v2.3.0) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Use Zulu distribution of OpenJDK https://github.com/actions/setup-java/blob/main/docs/switching-to-v2.md: > Use the `zulu` keyword if you would like to continue using the same distribution as in V1. * Fix JDK version: 1.8 -> 8 Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Valery Yatsynovich --- .github/workflows/gradle.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 44e24a9e0..dbd99a5ee 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -15,9 +15,10 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 + - name: Set up JDK 8 + uses: actions/setup-java@v2.3.0 with: - java-version: 1.8 + distribution: 'zulu' + java-version: 8 - name: Build with Gradle run: ./gradlew clean build -x signMavenJavaPublication -x test -x checkstyleTest From f8df435a9d09782d091b124c4eab07049adae0fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Sep 2021 16:48:08 +0300 Subject: [PATCH 062/619] build(deps): bump webdrivermanager from 4.4.3 to 5.0.1 (#1512) Bumps [webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 4.4.3 to 5.0.1. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-4.4.3...webdrivermanager-5.0.1) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index d827cd41d..9df08d75a 100644 --- a/build.gradle +++ b/build.gradle @@ -84,7 +84,7 @@ dependencies { testImplementation 'junit:junit:4.13.2' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '4.4.3') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.0.1') { exclude group: 'org.seleniumhq.selenium' } } From 4397523c50c99e5857ccc30e33cc85d1c0ef726b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Sep 2021 16:48:30 +0300 Subject: [PATCH 063/619] build(deps): bump org.owasp.dependencycheck from 6.2.0 to 6.3.1 (#1513) Bumps org.owasp.dependencycheck from 6.2.0 to 6.3.1. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9df08d75a..ce186c9be 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '6.2.0' + id 'org.owasp.dependencycheck' version '6.3.1' id 'com.github.johnrengelman.shadow' version '6.1.0' } From 8bec046c903c7e4947d6467e59f8f6016b2cdc04 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Sep 2021 11:27:21 +0300 Subject: [PATCH 064/619] build(deps): bump com.github.johnrengelman.shadow from 6.1.0 to 7.0.0 (#1468) Bumps com.github.johnrengelman.shadow from 6.1.0 to 7.0.0. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ce186c9be..991176d72 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ plugins { id 'checkstyle' id 'signing' id 'org.owasp.dependencycheck' version '6.3.1' - id 'com.github.johnrengelman.shadow' version '6.1.0' + id 'com.github.johnrengelman.shadow' version '7.0.0' } repositories { From 973a684809b8dbfe514abfa0d81db6dffc54096a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Sep 2021 16:34:23 +0300 Subject: [PATCH 065/619] build(deps): bump webdrivermanager from 5.0.1 to 5.0.2 (#1514) Bumps [webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.0.1 to 5.0.2. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.0.1...webdrivermanager-5.0.2) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 991176d72..67b47b56f 100644 --- a/build.gradle +++ b/build.gradle @@ -84,7 +84,7 @@ dependencies { testImplementation 'junit:junit:4.13.2' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.0.1') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.0.2') { exclude group: 'org.seleniumhq.selenium' } } From 381368c14f0d188926bc12f983af27370a917403 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Sep 2021 21:32:27 +0530 Subject: [PATCH 066/619] build(deps): bump spring-context from 5.3.9 to 5.3.10 (#1517) Bumps [spring-context](https://github.com/spring-projects/spring-framework) from 5.3.9 to 5.3.10. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.9...v5.3.10) --- updated-dependencies: - dependency-name: org.springframework:spring-context dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 67b47b56f..6213e2798 100644 --- a/build.gradle +++ b/build.gradle @@ -78,7 +78,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.11.0' - implementation 'org.springframework:spring-context:5.3.9' + implementation 'org.springframework:spring-context:5.3.10' implementation 'org.aspectj:aspectjweaver:1.9.7' implementation 'org.slf4j:slf4j-api:1.7.32' From 2f4062adddc9233471a21d5c8a87e508112405b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Sep 2021 21:32:51 +0530 Subject: [PATCH 067/619] build(deps): bump webdrivermanager from 5.0.2 to 5.0.3 (#1516) Bumps [webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.0.2 to 5.0.3. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.0.2...webdrivermanager-5.0.3) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 6213e2798..e5e16a6f9 100644 --- a/build.gradle +++ b/build.gradle @@ -84,7 +84,7 @@ dependencies { testImplementation 'junit:junit:4.13.2' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.0.2') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.0.3') { exclude group: 'org.seleniumhq.selenium' } } From f7c08a2fb591f8fc58d6ffab11d9b046435f985a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Oct 2021 14:53:55 +0300 Subject: [PATCH 068/619] build(deps): bump org.owasp.dependencycheck from 6.3.1 to 6.3.2 (#1523) Bumps org.owasp.dependencycheck from 6.3.1 to 6.3.2. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e5e16a6f9..e2558dd3e 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '6.3.1' + id 'org.owasp.dependencycheck' version '6.3.2' id 'com.github.johnrengelman.shadow' version '7.0.0' } From c7d01e749b891dad5958aa87580033d1ad3df65d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Oct 2021 15:50:06 +0300 Subject: [PATCH 069/619] build(deps): bump actions/setup-java from 2.3.0 to 2.3.1 (#1524) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v2.3.0...v2.3.1) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index dbd99a5ee..ce066fb6f 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -16,7 +16,7 @@ jobs: steps: - uses: actions/checkout@v1 - name: Set up JDK 8 - uses: actions/setup-java@v2.3.0 + uses: actions/setup-java@v2.3.1 with: distribution: 'zulu' java-version: 8 From 3466797b6627b8a1924198f4be8e95decf6db94c Mon Sep 17 00:00:00 2001 From: dr29bart Date: Thu, 7 Oct 2021 00:08:51 -0500 Subject: [PATCH 070/619] =?UTF-8?q?fix:=20[android]=20AndroidGeoLocation:?= =?UTF-8?q?=20update=20the=20constructor=20signature=20to=20mim=E2=80=A6?= =?UTF-8?q?=20(#1526)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java_client/android/geolocation/AndroidGeoLocation.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/appium/java_client/android/geolocation/AndroidGeoLocation.java b/src/main/java/io/appium/java_client/android/geolocation/AndroidGeoLocation.java index 9ab204317..f04a41fe2 100644 --- a/src/main/java/io/appium/java_client/android/geolocation/AndroidGeoLocation.java +++ b/src/main/java/io/appium/java_client/android/geolocation/AndroidGeoLocation.java @@ -39,10 +39,10 @@ public AndroidGeoLocation() { /** * Initializes AndroidLocation instance with longitude and latitude values. * - * @param longitude longitude value * @param latitude latitude value + * @param longitude longitude value */ - public AndroidGeoLocation(double longitude, double latitude) { + public AndroidGeoLocation(double latitude, double longitude) { this.longitude = longitude; this.latitude = latitude; } From 1d15347a66f1b8922e8528c9fd46907f388a055d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Oct 2021 15:15:09 +0300 Subject: [PATCH 071/619] build(deps): bump lombok from 1.18.20 to 1.18.22 (#1527) Bumps [lombok](https://github.com/projectlombok/lombok) from 1.18.20 to 1.18.22. - [Release notes](https://github.com/projectlombok/lombok/releases) - [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown) - [Commits](https://github.com/projectlombok/lombok/compare/v1.18.20...v1.18.22) --- updated-dependencies: - dependency-name: org.projectlombok:lombok dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index e2558dd3e..d7e398b19 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ configurations { dependencies { ecj 'org.eclipse.jdt:ecj:3.26.0' - lombok 'org.projectlombok:lombok:1.18.20' + lombok 'org.projectlombok:lombok:1.18.22' } java { @@ -50,7 +50,7 @@ compileJava { } dependencies { - compileOnly('org.projectlombok:lombok:1.18.16') + compileOnly('org.projectlombok:lombok:1.18.22') annotationProcessor('org.projectlombok:lombok:1.18.20') api ("org.seleniumhq.selenium:selenium-java") { version { From f951fe8676fac4a77370bcc58f25cdb1c8fd89a3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Oct 2021 15:23:51 +0300 Subject: [PATCH 072/619] build(deps): bump com.github.johnrengelman.shadow from 7.0.0 to 7.1.0 (#1528) Bumps com.github.johnrengelman.shadow from 7.0.0 to 7.1.0. --- updated-dependencies: - dependency-name: com.github.johnrengelman.shadow dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index d7e398b19..c57bdfab5 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ plugins { id 'checkstyle' id 'signing' id 'org.owasp.dependencycheck' version '6.3.2' - id 'com.github.johnrengelman.shadow' version '7.0.0' + id 'com.github.johnrengelman.shadow' version '7.1.0' } repositories { From f2e8f93fd613d6570e8ce515d4a85a70e9872305 Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Mon, 11 Oct 2021 19:26:23 +0530 Subject: [PATCH 073/619] Release 7.6.0 and update release notes --- README.md | 25 +++++++++++++++++++++++++ build.gradle | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bfcc35e51..f7d6b0c69 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,31 @@ dependencies { ``` ## Changelog +*7.6.0* +- **[ENHANCEMENTS]** + - Add custom commands dynamically [Appium 2.0]. [#1506](https://github.com/appium/java-client/pull/1506) + - New General Server flags are added [Appium 2.0]. [#1511](https://github.com/appium/java-client/pull/1511) + - Add support of extended Android geolocation. [#1492](https://github.com/appium/java-client/pull/1492) +- **[BUG FIX]** + - AndroidGeoLocation: update the constructor signature to mimic order of parameters in `org.openqa.selenium.html5.Location`. [#1526](https://github.com/appium/java-client/pull/1526) + - Prevent duplicate builds for PRs from base repo branches. [#1496](https://github.com/appium/java-client/pull/1496) + - Enable Dependabot for GitHub actions. [#1500](https://github.com/appium/java-client/pull/1500) + - bind mac2element in element map for mac platform. [#1474](https://github.com/appium/java-client/pull/1474) +- **[DEPENDENCY UPDATES]** + - `org.owasp.dependencycheck` was updated to 6.3.2. + - `org.projectlombok:lombok` was updated to 1.18.22. + - `com.github.johnrengelman.shadow` was updated to 7.1.0. + - `actions/setup-java` was updated to 2.3.1. + - `io.github.bonigarcia:webdrivermanager` was updated to 5.0.3. + - `org.springframework:spring-context` was updated to 5.3.10. + - `org.slf4j:slf4j-api` was updated to 1.7.32. + - `com.google.code.gson:gson` was updated to 2.8.8. + - `gradle` was updated to 7.1.1. + - `commons-io:commons-io` was updated to 2.11.0. + - `org.aspectj:aspectjweaver` was updated to 1.9.7. + - `org.eclipse.jdt:ecj` was updated to 3.26.0. + - `'junit:junit` was updated to 4.13.2. + *7.5.1* - **[ENHANCEMENTS]** - Add iOS related annotations to tvOS. [#1456](https://github.com/appium/java-client/pull/1456) diff --git a/build.gradle b/build.gradle index c57bdfab5..356beb536 100644 --- a/build.gradle +++ b/build.gradle @@ -130,7 +130,7 @@ publishing { mavenJava(MavenPublication) { groupId = 'io.appium' artifactId = 'java-client' - version = '7.5.1' + version = '7.6.0' from components.java pom { name = 'java-client' From 8057ac63abe8a6c8408c6a4f9fb3149c90a4ffc5 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 21 Oct 2021 05:19:34 +0300 Subject: [PATCH 074/619] refactor!: Migrate to Selenium 4 (#1531) * refactor!: migrate to Selenium 4 BREAKING CHANGE: - interface `io.appium.java_client.MobileDriver` do not extend `org.openqa.selenium.internal.FindsByClassName`, `org.openqa.selenium.internal.FindsByCssSelector`, `org.openqa.selenium.internal.FindsById`, `org.openqa.selenium.internal.FindsByLinkText`, `org.openqa.selenium.internal.FindsByName`, `org.openqa.selenium.internal.FindsByTagName`, `org.openqa.selenium.internal.FindsByXPath` interfaces anymore because they were removed in Selenium Java client; - class `io.appium.java_client.DefaultGenericMobileElement` do not implement `org.openqa.selenium.internal.FindsByClassName`, `org.openqa.selenium.internal.FindsByCssSelector`, `org.openqa.selenium.internal.FindsById`, `org.openqa.selenium.internal.FindsByLinkText`, `org.openqa.selenium.internal.FindsByName`, `org.openqa.selenium.internal.FindsByTagName`, `org.openqa.selenium.internal.FindsByXPath` interfaces anymore because they were removed in Selenium Java client; - method `String io.appium.java_client.remote.MobileOptions#getPlatformName()` is removed in favor of `Platform org.openqa.selenium.Capabilities#getPlatformName()` - method `io.appium.java_client.service.local.AppiumServiceBuilder#withStartUpTimeOut` is removed in favor of `org.openqa.selenium.remote.service.DriverService.Builder#withTimeout` * refactor!: drop Appium FindsBy* iterfaces BREAKING CHANGE: - drop Appium `FindsBy*` iterfaces in the same way it was done in Selenium java client. The removed intefraces are: `io.appium.java_client.FindsByAccessibilityId`, `io.appium.java_client.FindsByAndroidDataMatcher`, `io.appium.java_client.FindsByAndroidUIAutomator`, `io.appium.java_client.FindsByAndroidViewMatcher`, `io.appium.java_client.FindsByAndroidViewTag`, `io.appium.java_client.FindsByCustom`, `io.appium.java_client.FindsByFluentSelector`, `io.appium.java_client.FindsByImage`, `io.appium.java_client.FindsByIosClassChain`, `io.appium.java_client.FindsByIosNSPredicate`, `io.appium.java_client.FindsByWindowsAutomation`, `io.appium.java_client.mac.FindsByClassChain`, `io.appium.java_client.mac.FindsByNsPredicate` - remove methods `findElements(String by, String using)` and `findElement(String by, String using)` from `io.appium.java_client.DefaultGenericMobileDriver` and `io.appium.java_client.DefaultGenericMobileElement` because the originals of these methods are deprecated in Selenium `RemoteWebDriver` and `RemoteWebElement` and throw `UnsupportedOperationException` - remove `io.appium.java_client.MobileSelector` as it's used once, the string values from the enum are inlined in `io.appium.java_client.MobileBy.java` * fix: introduce MobileBy.className The change made in Selenium 4 (https://github.com/SeleniumHQ/selenium/commit/0aaa401fde5f4a5ecf2d2a2325221307b9bb3e89#r58091435) broke Appium `class name` selector strategy. The workaround was implemented: `MobileBy#className`. * refactor!: drop deprecated method `AppiumDriver#substituteMobilePlatform` BREAKING CHANGE: drop deprecated method `io.appium.java_client.AppiumDriver#substituteMobilePlatform` --- gradle.properties | 2 +- .../io/appium/java_client/AppiumDriver.java | 63 +- .../DefaultGenericMobileDriver.java | 103 ---- .../DefaultGenericMobileElement.java | 132 +---- .../java_client/DriverMobileCommand.java | 27 - .../java_client/FindsByAccessibilityId.java | 52 -- .../FindsByAndroidDataMatcher.java | 32 - .../FindsByAndroidUIAutomator.java | 53 -- .../FindsByAndroidViewMatcher.java | 32 - .../java_client/FindsByAndroidViewTag.java | 52 -- .../io/appium/java_client/FindsByCustom.java | 55 -- .../java_client/FindsByFluentSelector.java | 51 -- .../io/appium/java_client/FindsByImage.java | 63 -- .../java_client/FindsByIosClassChain.java | 32 - .../java_client/FindsByIosNSPredicate.java | 32 - .../java_client/FindsByWindowsAutomation.java | 50 -- .../IllegalCoordinatesException.java | 28 - .../java/io/appium/java_client/MobileBy.java | 559 ++---------------- .../io/appium/java_client/MobileDriver.java | 43 +- .../io/appium/java_client/MobileElement.java | 42 -- .../io/appium/java_client/MobileSelector.java | 41 -- .../appium/java_client/android/Activity.java | 1 - .../java_client/android/AndroidDriver.java | 15 +- .../java_client/android/AndroidElement.java | 8 +- .../java_client/android/AndroidOptions.java | 10 +- .../java_client/events/DefaultAspect.java | 13 - .../JsonToMobileElementConverter.java | 2 +- .../io/appium/java_client/ios/IOSDriver.java | 7 +- .../io/appium/java_client/ios/IOSElement.java | 5 +- .../io/appium/java_client/ios/IOSOptions.java | 10 +- .../java_client/mac/FindsByClassChain.java | 50 -- .../java_client/mac/FindsByNsPredicate.java | 50 -- .../io/appium/java_client/mac/Mac2Driver.java | 4 +- .../appium/java_client/mac/Mac2Element.java | 3 +- .../pagefactory/bys/builder/Strategies.java | 2 +- .../remote/AppiumCommandExecutor.java | 19 +- .../remote/AppiumW3CHttpCommandCodec.java | 2 +- .../java_client/remote/MobileOptions.java | 13 +- .../local/AppiumDriverLocalService.java | 26 +- .../service/local/AppiumServiceBuilder.java | 34 +- .../touch/offset/ElementOption.java | 8 +- .../java_client/windows/WindowsDriver.java | 4 +- .../java_client/windows/WindowsElement.java | 3 +- .../java_client/ws/StringWebSocketClient.java | 41 +- .../java/org/openqa/selenium/WebDriver.java | 335 +++++++++-- .../java/org/openqa/selenium/WebElement.java | 179 ++++-- .../selenium/internal/FindsByClassName.java | 28 - .../selenium/internal/FindsByCssSelector.java | 28 - .../openqa/selenium/internal/FindsById.java | 28 - .../selenium/internal/FindsByLinkText.java | 32 - .../openqa/selenium/internal/FindsByName.java | 28 - .../selenium/internal/FindsByTagName.java | 28 - .../selenium/internal/FindsByXPath.java | 28 - .../AndroidAbilityToUseSupplierTest.java | 28 +- .../android/AndroidElementTest.java | 16 +- .../android/AndroidOptionsTest.java | 7 +- .../android/AndroidSearchingTest.java | 14 +- .../java_client/android/AndroidTouchTest.java | 41 +- .../java_client/android/FingerPrintTest.java | 13 +- .../java_client/android/IntentTest.java | 3 +- .../java_client/android/UIAutomator2Test.java | 6 +- .../java_client/appium/AndroidTest.java | 16 +- .../ios/IOSElementGenerationTest.java | 8 +- .../AbilityToDefineListenersExternally.java | 16 +- .../java_client/events/BaseListenerTest.java | 82 ++- .../events/DefaultEventListenerTest.java | 19 +- .../java_client/events/EmptyWebDriver.java | 105 +--- .../events/ExtendedEventListenerTest.java | 4 +- .../java_client/events/FewInstancesTest.java | 18 +- .../java_client/events/StubWebElement.java | 97 +-- .../appium/java_client/events/StubWindow.java | 5 + ...bDriverEventListenerCompatibilityTest.java | 11 +- .../appium/java_client/ios/IOSDriverTest.java | 10 +- .../java_client/ios/IOSElementTest.java | 7 +- .../ios/IOSNativeWebTapSettingTest.java | 13 +- .../java_client/ios/IOSOptionsTest.java | 3 +- .../java_client/ios/IOSSearchingTest.java | 16 +- .../appium/java_client/ios/IOSTouchTest.java | 27 +- .../java_client/ios/IOSWebViewTest.java | 10 +- 79 files changed, 756 insertions(+), 2427 deletions(-) delete mode 100644 src/main/java/io/appium/java_client/DriverMobileCommand.java delete mode 100644 src/main/java/io/appium/java_client/FindsByAccessibilityId.java delete mode 100644 src/main/java/io/appium/java_client/FindsByAndroidDataMatcher.java delete mode 100644 src/main/java/io/appium/java_client/FindsByAndroidUIAutomator.java delete mode 100644 src/main/java/io/appium/java_client/FindsByAndroidViewMatcher.java delete mode 100644 src/main/java/io/appium/java_client/FindsByAndroidViewTag.java delete mode 100644 src/main/java/io/appium/java_client/FindsByCustom.java delete mode 100644 src/main/java/io/appium/java_client/FindsByFluentSelector.java delete mode 100644 src/main/java/io/appium/java_client/FindsByImage.java delete mode 100644 src/main/java/io/appium/java_client/FindsByIosClassChain.java delete mode 100644 src/main/java/io/appium/java_client/FindsByIosNSPredicate.java delete mode 100644 src/main/java/io/appium/java_client/FindsByWindowsAutomation.java delete mode 100644 src/main/java/io/appium/java_client/IllegalCoordinatesException.java delete mode 100644 src/main/java/io/appium/java_client/MobileSelector.java delete mode 100644 src/main/java/io/appium/java_client/mac/FindsByClassChain.java delete mode 100644 src/main/java/io/appium/java_client/mac/FindsByNsPredicate.java delete mode 100644 src/main/java/org/openqa/selenium/internal/FindsByClassName.java delete mode 100644 src/main/java/org/openqa/selenium/internal/FindsByCssSelector.java delete mode 100644 src/main/java/org/openqa/selenium/internal/FindsById.java delete mode 100644 src/main/java/org/openqa/selenium/internal/FindsByLinkText.java delete mode 100644 src/main/java/org/openqa/selenium/internal/FindsByName.java delete mode 100644 src/main/java/org/openqa/selenium/internal/FindsByTagName.java delete mode 100644 src/main/java/org/openqa/selenium/internal/FindsByXPath.java diff --git a/gradle.properties b/gradle.properties index 9bd535700..d2d4a6a43 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,4 +7,4 @@ signing.secretKeyRingFile=PathToYourKeyRingFile ossrhUsername=your-jira-id ossrhPassword=your-jira-password -selenium.version=3.141.59 +selenium.version=4.0.0 diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index fd512197a..1e880c569 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -68,8 +68,7 @@ */ @SuppressWarnings("unchecked") public class AppiumDriver - extends DefaultGenericMobileDriver implements ComparesImages, FindsByImage, FindsByCustom, - ExecutesDriverScript, LogsEvents, HasSettings { + extends DefaultGenericMobileDriver implements ComparesImages, ExecutesDriverScript, LogsEvents, HasSettings { private static final ErrorHandler errorHandler = new ErrorHandler(new ErrorCodesMobile(), true); // frequently used command parameters @@ -134,23 +133,6 @@ public AppiumDriver(Capabilities desiredCapabilities) { this(AppiumDriverLocalService.buildDefaultService(), desiredCapabilities); } - /** - * Changes platform name and returns new capabilities. - * - * @param originalCapabilities the given {@link Capabilities}. - * @param newPlatform a {@link MobileCapabilityType#PLATFORM_NAME} value which has - * to be set up - * @return {@link Capabilities} with changed mobile platform value - * @deprecated Please use {@link #updateDefaultPlatformName(Capabilities, String)} instead - */ - @Deprecated - protected static Capabilities substituteMobilePlatform(Capabilities originalCapabilities, - String newPlatform) { - DesiredCapabilities dc = new DesiredCapabilities(originalCapabilities); - dc.setCapability(PLATFORM_NAME, newPlatform); - return dc; - } - /** * Changes platform name if it is not set and returns new capabilities. * @@ -174,49 +156,6 @@ public List findElements(By by) { return super.findElements(by); } - @Override - public List findElements(String by, String using) { - return super.findElements(by, using); - } - - @Override - public List findElementsById(String id) { - return super.findElementsById(id); - } - - public List findElementsByLinkText(String using) { - return super.findElementsByLinkText(using); - } - - public List findElementsByPartialLinkText(String using) { - return super.findElementsByPartialLinkText(using); - } - - public List findElementsByTagName(String using) { - return super.findElementsByTagName(using); - } - - public List findElementsByName(String using) { - return super.findElementsByName(using); - } - - public List findElementsByClassName(String using) { - return super.findElementsByClassName(using); - } - - public List findElementsByCssSelector(String using) { - return super.findElementsByCssSelector(using); - } - - public List findElementsByXPath(String using) { - return super.findElementsByXPath(using); - } - - @Override - public List findElementsByAccessibilityId(String using) { - return super.findElementsByAccessibilityId(using); - } - @Override public ExecuteMethod getExecuteMethod() { return executeMethod; diff --git a/src/main/java/io/appium/java_client/DefaultGenericMobileDriver.java b/src/main/java/io/appium/java_client/DefaultGenericMobileDriver.java index 0ca7a1dcc..e6d45f5f8 100644 --- a/src/main/java/io/appium/java_client/DefaultGenericMobileDriver.java +++ b/src/main/java/io/appium/java_client/DefaultGenericMobileDriver.java @@ -20,7 +20,6 @@ import org.openqa.selenium.By; import org.openqa.selenium.Capabilities; -import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.CommandExecutor; import org.openqa.selenium.remote.RemoteWebDriver; @@ -49,112 +48,10 @@ public DefaultGenericMobileDriver(CommandExecutor executor, Capabilities desired return super.findElements(by); } - @Override public List findElements(String by, String using) { - return super.findElements(by, using); - } - @Override public T findElement(By by) { return (T) super.findElement(by); } - @Override public T findElement(String by, String using) { - return (T) super.findElement(by, using); - } - - @Override public List findElementsById(String id) { - return super.findElementsById(id); - } - - @Override public T findElementById(String id) { - return (T) super.findElementById(id); - } - - /** - * Finds a single element by link text. - * - * @throws WebDriverException This method doesn't work against native app UI. - */ - public T findElementByLinkText(String using) throws WebDriverException { - return (T) super.findElementByLinkText(using); - } - - /** - * Finds many elements by link text. - * - * @throws WebDriverException This method doesn't work against native app UI. - */ - public List findElementsByLinkText(String using) throws WebDriverException { - return super.findElementsByLinkText(using); - } - - /** - * Finds a single element by partial link text. - * - * @throws WebDriverException This method doesn't work against native app UI. - */ - public T findElementByPartialLinkText(String using) throws WebDriverException { - return (T) super.findElementByPartialLinkText(using); - } - - /** - * Finds many elements by partial link text. - * - * @throws WebDriverException This method doesn't work against native app UI. - */ - public List findElementsByPartialLinkText(String using) throws WebDriverException { - return super.findElementsByPartialLinkText(using); - } - - public T findElementByTagName(String using) { - return (T) super.findElementByTagName(using); - } - - public List findElementsByTagName(String using) { - return super.findElementsByTagName(using); - } - - public T findElementByName(String using) { - return (T) super.findElementByName(using); - } - - public List findElementsByName(String using) { - return super.findElementsByName(using); - } - - public T findElementByClassName(String using) { - return (T) super.findElementByClassName(using); - } - - public List findElementsByClassName(String using) { - return super.findElementsByClassName(using); - } - - /** - * Finds a single element by CSS selector. - * - * @throws WebDriverException This method doesn't work against native app UI. - */ - public T findElementByCssSelector(String using) throws WebDriverException { - return (T) super.findElementByCssSelector(using); - } - - /** - * Finds many elements by CSS selector. - * - * @throws WebDriverException This method doesn't work against native app UI. - */ - public List findElementsByCssSelector(String using) throws WebDriverException { - return super.findElementsByCssSelector(using); - } - - public T findElementByXPath(String using) { - return (T) super.findElementByXPath(using); - } - - public List findElementsByXPath(String using) { - return super.findElementsByXPath(using); - } - @Override public String toString() { Capabilities capabilities = getCapabilities(); diff --git a/src/main/java/io/appium/java_client/DefaultGenericMobileElement.java b/src/main/java/io/appium/java_client/DefaultGenericMobileElement.java index 2d8154880..6e1bfc64a 100644 --- a/src/main/java/io/appium/java_client/DefaultGenericMobileElement.java +++ b/src/main/java/io/appium/java_client/DefaultGenericMobileElement.java @@ -21,13 +21,6 @@ import org.openqa.selenium.By; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WebElement; -import org.openqa.selenium.internal.FindsByClassName; -import org.openqa.selenium.internal.FindsByCssSelector; -import org.openqa.selenium.internal.FindsById; -import org.openqa.selenium.internal.FindsByLinkText; -import org.openqa.selenium.internal.FindsByName; -import org.openqa.selenium.internal.FindsByTagName; -import org.openqa.selenium.internal.FindsByXPath; import org.openqa.selenium.remote.RemoteWebElement; import org.openqa.selenium.remote.Response; @@ -35,11 +28,7 @@ import java.util.Map; @SuppressWarnings({"unchecked", "rawtypes"}) -abstract class DefaultGenericMobileElement extends RemoteWebElement - implements FindsByClassName, - FindsByCssSelector, FindsById, - FindsByLinkText, FindsByName, FindsByTagName, FindsByXPath, FindsByFluentSelector, FindsByAccessibilityId, - ExecutesMethod { +abstract class DefaultGenericMobileElement extends RemoteWebElement implements ExecutesMethod { @Override public Response execute(String driverCommand, Map parameters) { return super.execute(driverCommand, parameters); @@ -53,127 +42,8 @@ abstract class DefaultGenericMobileElement extends RemoteW return super.findElements(by); } - @Override public List findElements(String by, String using) { - return super.findElements(by, using); - } - @Override public T findElement(By by) { return (T) super.findElement(by); } - @Override public T findElement(String by, String using) { - return (T) super.findElement(by, using); - } - - @Override public List findElementsById(String id) { - return super.findElementsById(id); - } - - @Override public T findElementById(String id) { - return (T) super.findElementById(id); - } - - /** - * Finds a single element by link text. - * - * @throws WebDriverException This method doesn't work against native app UI. - */ - public T findElementByLinkText(String using) throws WebDriverException { - return (T) super.findElementByLinkText(using); - } - - /** - * Finds many elements by link text. - * - * @throws WebDriverException This method doesn't work against native app UI. - */ - public List findElementsByLinkText(String using) throws WebDriverException { - return super.findElementsByLinkText(using); - } - - /** - * Finds a single element by partial link text. - * - * @throws WebDriverException This method doesn't work against native app UI. - */ - public T findElementByPartialLinkText(String using) throws WebDriverException { - return (T) super.findElementByPartialLinkText(using); - } - - /** - * Finds many elements by partial link text. - * - * @throws WebDriverException This method doesn't work against native app UI. - */ - public List findElementsByPartialLinkText(String using) throws WebDriverException { - return super.findElementsByPartialLinkText(using); - } - - public T findElementByTagName(String using) { - return (T) super.findElementByTagName(using); - } - - public List findElementsByTagName(String using) { - return super.findElementsByTagName(using); - } - - public T findElementByName(String using) { - return (T) super.findElementByName(using); - } - - public List findElementsByName(String using) { - return super.findElementsByName(using); - } - - public T findElementByClassName(String using) { - return (T) super.findElementByClassName(using); - } - - public List findElementsByClassName(String using) { - return super.findElementsByClassName(using); - } - - /** - * Finds a single element by CSS selector. - * - * @throws WebDriverException This method doesn't work against native app UI. - */ - public T findElementByCssSelector(String using) throws WebDriverException { - return (T) super.findElementByCssSelector(using); - } - - /** - * Finds many elements by CSS selector. - * - * @throws WebDriverException This method doesn't work against native app UI. - */ - public List findElementsByCssSelector(String using) throws WebDriverException { - return super.findElementsByCssSelector(using); - } - - public T findElementByXPath(String using) { - return (T) super.findElementByXPath(using); - } - - public List findElementsByXPath(String using) { - return super.findElementsByXPath(using); - } - - /** - * {@inheritDoc} - * - * @throws WebDriverException because it may not work against native app UI. - */ - public void submit() throws WebDriverException { - super.submit(); - } - - /** - * {@inheritDoc} - * - * @throws WebDriverException because it may not work against native app UI. - */ - public String getCssValue(String propertyName) throws WebDriverException { - return super.getCssValue(propertyName); - } } diff --git a/src/main/java/io/appium/java_client/DriverMobileCommand.java b/src/main/java/io/appium/java_client/DriverMobileCommand.java deleted file mode 100644 index 9d991d3cb..000000000 --- a/src/main/java/io/appium/java_client/DriverMobileCommand.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.appium.java_client; - -/** - * An empty interface defining constants for the standard commands defined in the Mobile JSON - * wire protocol. - * - * @author jonahss@gmail.com (Jonah Stiennon) - */ -public interface DriverMobileCommand { - //TODO Jonah: we'll probably need this -} diff --git a/src/main/java/io/appium/java_client/FindsByAccessibilityId.java b/src/main/java/io/appium/java_client/FindsByAccessibilityId.java deleted file mode 100644 index 4d79a33a4..000000000 --- a/src/main/java/io/appium/java_client/FindsByAccessibilityId.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.appium.java_client; - -import org.openqa.selenium.NoSuchElementException; -import org.openqa.selenium.WebDriverException; -import org.openqa.selenium.WebElement; - -import java.util.List; - -public interface FindsByAccessibilityId extends FindsByFluentSelector { - /** - * Method performs the searching for a single element by accessibility ID selector - * and value of the given selector. - * - * @param using an accessibility ID selector - * @return The first element that matches the given selector - * - * @throws WebDriverException This method is not applicable with browser/webview UI. - * @throws NoSuchElementException when no one element is found - */ - default T findElementByAccessibilityId(String using) { - return findElement(MobileSelector.ACCESSIBILITY.toString(), using); - } - - /** - * Method performs the searching for a list of elements by accessibility ID selector - * and value of the given selector. - * - * @param using an accessibility ID selector - * @return a list of elements that match the given selector - * - * @throws WebDriverException This method is not applicable with browser/webview UI. - */ - default List findElementsByAccessibilityId(String using) { - return findElements(MobileSelector.ACCESSIBILITY.toString(), using); - } -} diff --git a/src/main/java/io/appium/java_client/FindsByAndroidDataMatcher.java b/src/main/java/io/appium/java_client/FindsByAndroidDataMatcher.java deleted file mode 100644 index a60477870..000000000 --- a/src/main/java/io/appium/java_client/FindsByAndroidDataMatcher.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.appium.java_client; - -import org.openqa.selenium.WebElement; - -import java.util.List; - -public interface FindsByAndroidDataMatcher extends FindsByFluentSelector { - - default T findElementByAndroidDataMatcher(String using) { - return findElement(MobileSelector.ANDROID_DATA_MATCHER.toString(), using); - } - - default List findElementsByAndroidDataMatcher(String using) { - return findElements(MobileSelector.ANDROID_DATA_MATCHER.toString(), using); - } -} diff --git a/src/main/java/io/appium/java_client/FindsByAndroidUIAutomator.java b/src/main/java/io/appium/java_client/FindsByAndroidUIAutomator.java deleted file mode 100644 index 50c7bafba..000000000 --- a/src/main/java/io/appium/java_client/FindsByAndroidUIAutomator.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.appium.java_client; - -import org.openqa.selenium.NoSuchElementException; -import org.openqa.selenium.WebDriverException; -import org.openqa.selenium.WebElement; - -import java.util.List; - -public interface FindsByAndroidUIAutomator extends FindsByFluentSelector { - - /** - * Method performs the searching for a single element by Android UIAutomator selector - * and value of the given selector. - * - * @param using an Android UIAutomator selector - * @return The first element that matches the given selector - * - * @throws WebDriverException This method is not applicable with browser/webview UI. - * @throws NoSuchElementException when no one element is found - */ - default T findElementByAndroidUIAutomator(String using) { - return findElement(MobileSelector.ANDROID_UI_AUTOMATOR.toString(), using); - } - - /** - * Method performs the searching for a list of elements by Android UIAutomator selector - * and value of the given selector. - * - * @param using an Android UIAutomator selector - * @return a list of elements that match the given selector - * - * @throws WebDriverException This method is not applicable with browser/webview UI. - */ - default List findElementsByAndroidUIAutomator(String using) { - return findElements(MobileSelector.ANDROID_UI_AUTOMATOR.toString(), using); - } -} diff --git a/src/main/java/io/appium/java_client/FindsByAndroidViewMatcher.java b/src/main/java/io/appium/java_client/FindsByAndroidViewMatcher.java deleted file mode 100644 index 1370cf3ae..000000000 --- a/src/main/java/io/appium/java_client/FindsByAndroidViewMatcher.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.appium.java_client; - -import org.openqa.selenium.WebElement; - -import java.util.List; - -public interface FindsByAndroidViewMatcher extends FindsByFluentSelector { - - default T findElementByAndroidViewMatcher(String using) { - return findElement(MobileSelector.ANDROID_VIEW_MATCHER.toString(), using); - } - - default List findElementsByAndroidViewMatcher(String using) { - return findElements(MobileSelector.ANDROID_VIEW_MATCHER.toString(), using); - } -} diff --git a/src/main/java/io/appium/java_client/FindsByAndroidViewTag.java b/src/main/java/io/appium/java_client/FindsByAndroidViewTag.java deleted file mode 100644 index b1db5c432..000000000 --- a/src/main/java/io/appium/java_client/FindsByAndroidViewTag.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.appium.java_client; - -import org.openqa.selenium.NoSuchElementException; -import org.openqa.selenium.WebDriverException; -import org.openqa.selenium.WebElement; - -import java.util.List; - -public interface FindsByAndroidViewTag extends FindsByFluentSelector { - /** - * Method performs the searching for a single element by view tag selector - * and value of the given selector. - * - * @param using an view tag selector - * @return The first element that matches the given selector - * - * @throws WebDriverException This method is not applicable with browser/webview UI. - * @throws NoSuchElementException when no one element is found - */ - default T findElementByAndroidViewTag(String using) { - return findElement(MobileSelector.ANDROID_VIEWTAG.toString(), using); - } - - /** - * Method performs the searching for a list of elements by view tag selector - * and value of the given selector. - * - * @param using an view tag selector - * @return a list of elements that match the given selector - * - * @throws WebDriverException This method is not applicable with browser/webview UI. - */ - default List findElementsByAndroidViewTag(String using) { - return findElements(MobileSelector.ANDROID_VIEWTAG.toString(), using); - } -} diff --git a/src/main/java/io/appium/java_client/FindsByCustom.java b/src/main/java/io/appium/java_client/FindsByCustom.java deleted file mode 100644 index f908fc424..000000000 --- a/src/main/java/io/appium/java_client/FindsByCustom.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.appium.java_client; - -import org.openqa.selenium.NoSuchElementException; -import org.openqa.selenium.WebElement; - -import java.util.List; - -public interface FindsByCustom extends FindsByFluentSelector { - /** - * Performs the lookup for a single element by sending a selector to a custom element finding - * plugin. This type of locator requires the use of the 'customFindModules' capability and a - * separately-installed element finding plugin. - * - * @param selector selector to pass to the custom element finding plugin - * @return The first element that matches the given selector - * @see - * The documentation on custom element finding plugins and their use - * @throws NoSuchElementException when no element is found - * @since Appium 1.9.2 - */ - default T findElementByCustom(String selector) { - return findElement(MobileSelector.CUSTOM.toString(), selector); - } - - /** - * Performs the lookup for a single element by sending a selector to a custom element finding - * plugin. This type of locator requires the use of the 'customFindModules' capability and a - * separately-installed element finding plugin. - * - * @param selector selector to pass to the custom element finding plugin - * @return a list of elements that match the given selector or an empty list - * @see - * The documentation on custom element finding plugins and their use - * @since Appium 1.9.2 - */ - default List findElementsByCustom(String selector) { - return findElements(MobileSelector.CUSTOM.toString(), selector); - } -} \ No newline at end of file diff --git a/src/main/java/io/appium/java_client/FindsByFluentSelector.java b/src/main/java/io/appium/java_client/FindsByFluentSelector.java deleted file mode 100644 index f545f47be..000000000 --- a/src/main/java/io/appium/java_client/FindsByFluentSelector.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.appium.java_client; - -import org.openqa.selenium.WebElement; - -import java.util.List; - -public interface FindsByFluentSelector { - - /** - * Method performs the searching for a single element by some selector defined by string - * and value of the given selector. - * - * @param by is a string selector - * @param using is a value of the given selector - * @return the first found element - * - * @throws org.openqa.selenium.WebDriverException when current session doesn't - * support the given selector or when value of the selector is not consistent. - * @throws org.openqa.selenium.NoSuchElementException when no one element is found - */ - T findElement(String by, String using); - - /** - * Method performs the searching for a list of elements by some selector defined by string - * and value of the given selector. - * - * @param by is a string selector - * @param using is a value of the given selector - * @return a list of elements - * - * @throws org.openqa.selenium.WebDriverException when current session doesn't support - * the given selector or when value of the selector is not consistent. - */ - List findElements(String by, String using); -} diff --git a/src/main/java/io/appium/java_client/FindsByImage.java b/src/main/java/io/appium/java_client/FindsByImage.java deleted file mode 100644 index 76de64fd1..000000000 --- a/src/main/java/io/appium/java_client/FindsByImage.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.appium.java_client; - -import org.openqa.selenium.NoSuchElementException; -import org.openqa.selenium.WebElement; - -import java.util.List; - -public interface FindsByImage extends FindsByFluentSelector { - /** - * Performs the lookup for a single element by matching its image template - * to the current full screen shot. This type of locator requires OpenCV libraries - * and bindings for NodeJS to be installed on the server machine. Lookup options - * fine-tuning might be done via {@link HasSettings#setSetting(Setting, Object)}. - * - * @param b64Template base64-encoded template image string. Supported image formats are the same - * as for OpenCV library. - * @return The first element that matches the given selector - * @throws NoSuchElementException when no element is found - * @see - * The documentation on Image Comparison Features - * @see - * The settings available for lookup fine-tuning - * @since Appium 1.8.2 - */ - default T findElementByImage(String b64Template) { - return findElement(MobileSelector.IMAGE.toString(), b64Template); - } - - /** - * Performs the lookup for a list of elements by matching them to image template - * in the current full screen shot. This type of locator requires OpenCV libraries - * and bindings for NodeJS to be installed on the server machine. Lookup options - * fine-tuning might be done via {@link HasSettings#setSetting(Setting, Object)}. - * - * @param b64Template base64-encoded template image string. Supported image formats are the same - * as for OpenCV library. - * @return a list of elements that match the given selector or an empty list - * @see - * The documentation on Image Comparison Features - * @see - * The settings available for lookup fine-tuning - * @since Appium 1.8.2 - */ - default List findElementsByImage(String b64Template) { - return findElements(MobileSelector.IMAGE.toString(), b64Template); - } -} diff --git a/src/main/java/io/appium/java_client/FindsByIosClassChain.java b/src/main/java/io/appium/java_client/FindsByIosClassChain.java deleted file mode 100644 index 92482663a..000000000 --- a/src/main/java/io/appium/java_client/FindsByIosClassChain.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.appium.java_client; - -import org.openqa.selenium.WebElement; - -import java.util.List; - -public interface FindsByIosClassChain extends FindsByFluentSelector { - - default T findElementByIosClassChain(String using) { - return findElement(MobileSelector.IOS_CLASS_CHAIN.toString(), using); - } - - default List findElementsByIosClassChain(String using) { - return findElements(MobileSelector.IOS_CLASS_CHAIN.toString(), using); - } -} diff --git a/src/main/java/io/appium/java_client/FindsByIosNSPredicate.java b/src/main/java/io/appium/java_client/FindsByIosNSPredicate.java deleted file mode 100644 index 84bc3ff67..000000000 --- a/src/main/java/io/appium/java_client/FindsByIosNSPredicate.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.appium.java_client; - -import org.openqa.selenium.WebElement; - -import java.util.List; - -public interface FindsByIosNSPredicate extends FindsByFluentSelector { - - default T findElementByIosNsPredicate(String using) { - return findElement(MobileSelector.IOS_PREDICATE_STRING.toString(), using); - } - - default List findElementsByIosNsPredicate(String using) { - return findElements(MobileSelector.IOS_PREDICATE_STRING.toString(), using); - } -} diff --git a/src/main/java/io/appium/java_client/FindsByWindowsAutomation.java b/src/main/java/io/appium/java_client/FindsByWindowsAutomation.java deleted file mode 100644 index 4416eb63f..000000000 --- a/src/main/java/io/appium/java_client/FindsByWindowsAutomation.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package io.appium.java_client; - -import org.openqa.selenium.NoSuchElementException; -import org.openqa.selenium.WebDriverException; -import org.openqa.selenium.WebElement; - -import java.util.List; - -public interface FindsByWindowsAutomation extends FindsByFluentSelector { - - /** - * Finds the first of elements that match the Windows UIAutomation selector supplied. - * - * @param selector a Windows UIAutomation selector - * @return The first element that matches the given selector - * @throws WebDriverException This method is not applicable with browser/webview UI. - * @throws NoSuchElementException when no one element is found - */ - default T findElementByWindowsUIAutomation(String selector) { - return findElement(MobileSelector.WINDOWS_UI_AUTOMATION.toString(), selector); - } - - /** - * Finds a list of elements that match the Windows UIAutomation selector supplied. - * - * @param selector a Windows UIAutomation selector - * @return a list of elements that match the given selector - * @throws WebDriverException This method is not applicable with browser/webview UI. - */ - default List findElementsByWindowsUIAutomation(String selector) { - return findElements(MobileSelector.WINDOWS_UI_AUTOMATION.toString(), selector); - } -} diff --git a/src/main/java/io/appium/java_client/IllegalCoordinatesException.java b/src/main/java/io/appium/java_client/IllegalCoordinatesException.java deleted file mode 100644 index 8167ad65d..000000000 --- a/src/main/java/io/appium/java_client/IllegalCoordinatesException.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.appium.java_client; - -import org.openqa.selenium.WebDriverException; - -public class IllegalCoordinatesException extends WebDriverException { - private static final long serialVersionUID = 1L; - - public IllegalCoordinatesException(String message) { - super(message); - } - -} diff --git a/src/main/java/io/appium/java_client/MobileBy.java b/src/main/java/io/appium/java_client/MobileBy.java index b8fd3d5db..183656627 100644 --- a/src/main/java/io/appium/java_client/MobileBy.java +++ b/src/main/java/io/appium/java_client/MobileBy.java @@ -20,45 +20,39 @@ import lombok.Getter; import org.apache.commons.lang3.StringUtils; import org.openqa.selenium.By; +import org.openqa.selenium.By.Remotable; import org.openqa.selenium.SearchContext; -import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WebElement; import java.io.Serializable; import java.util.List; @SuppressWarnings("serial") -public abstract class MobileBy extends By { - - private static final String ERROR_TEXT = "The class %s of the given context " - + "doesn't implement %s nor %s. Sorry. It is impossible to find something."; +public abstract class MobileBy extends By implements Remotable { @Getter(AccessLevel.PROTECTED) private final String locatorString; - private final MobileSelector selector; - - private static IllegalArgumentException formIllegalArgumentException(Class givenClass, - Class class1, Class class2) { - return new IllegalArgumentException(String.format(ERROR_TEXT, givenClass.getCanonicalName(), - class1.getCanonicalName(), class2.getCanonicalName())); - } + private final Parameters parameters; - protected MobileBy(MobileSelector selector, String locatorString) { + protected MobileBy(String selector, String locatorString) { if (StringUtils.isBlank(locatorString)) { throw new IllegalArgumentException("Must supply a not empty locator value."); } this.locatorString = locatorString; - this.selector = selector; + this.parameters = new Parameters(selector, locatorString); } @SuppressWarnings("unchecked") @Override public List findElements(SearchContext context) { - return (List) ((FindsByFluentSelector) context) - .findElements(selector.toString(), getLocatorString()); + return context.findElements(this); } @Override public WebElement findElement(SearchContext context) { - return ((FindsByFluentSelector) context) - .findElement(selector.toString(), getLocatorString()); + return context.findElement(this); + } + + @Override + public Parameters getRemoteParameters() { + return parameters; } /** @@ -168,64 +162,20 @@ public static By custom(final String selector) { return new ByCustom(selector); } + /** + * For IOS it is the full name of the XCUI element and begins with XCUIElementType. + * For Android it is the full name of the UIAutomator2 class (e.g.: android.widget.TextView) + * @param selector the class name of the element + * @return an instance of {@link ByClassName} + */ + public static By className(final String selector) { + return new ByClassName(selector); + } public static class ByAndroidUIAutomator extends MobileBy implements Serializable { - public ByAndroidUIAutomator(String uiautomatorText) { - super(MobileSelector.ANDROID_UI_AUTOMATOR, uiautomatorText); - } - - /** - * {@inheritDoc} - * - * @throws WebDriverException when current session doesn't support the given selector or when - * value of the selector is not consistent. - * @throws IllegalArgumentException when it is impossible to find something on the given - * {@link SearchContext} instance - */ - @SuppressWarnings("unchecked") - @Override - public List findElements(SearchContext context) throws WebDriverException, - IllegalArgumentException { - Class contextClass = context.getClass(); - - if (FindsByAndroidUIAutomator.class.isAssignableFrom(contextClass)) { - return FindsByAndroidUIAutomator.class.cast(context) - .findElementsByAndroidUIAutomator(getLocatorString()); - } - - if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { - return super.findElements(context); - } - - throw formIllegalArgumentException(contextClass, FindsByAndroidUIAutomator.class, - FindsByFluentSelector.class); - } - - /** - * {@inheritDoc} - * - * @throws WebDriverException when current session doesn't support the given selector or when - * value of the selector is not consistent. - * @throws IllegalArgumentException when it is impossible to find something on the given - * {@link SearchContext} instance - */ - @Override public WebElement findElement(SearchContext context) throws WebDriverException, - IllegalArgumentException { - Class contextClass = context.getClass(); - - if (FindsByAndroidUIAutomator.class.isAssignableFrom(contextClass)) { - return FindsByAndroidUIAutomator.class.cast(context) - .findElementByAndroidUIAutomator(getLocatorString()); - } - - if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { - return super.findElement(context); - } - - throw formIllegalArgumentException(contextClass, FindsByAndroidUIAutomator.class, - FindsByFluentSelector.class); + super("-android uiautomator", uiautomatorText); } @Override public String toString() { @@ -237,59 +187,7 @@ public List findElements(SearchContext context) throws WebDriverExce public static class ByAccessibilityId extends MobileBy implements Serializable { public ByAccessibilityId(String accessibilityId) { - super(MobileSelector.ACCESSIBILITY, accessibilityId); - } - - /** - * {@inheritDoc} - * - * @throws WebDriverException when current session doesn't support the given selector or when - * value of the selector is not consistent. - * @throws IllegalArgumentException when it is impossible to find something on the given - * {@link SearchContext} instance - */ - @SuppressWarnings("unchecked") - @Override - public List findElements(SearchContext context) throws WebDriverException, - IllegalArgumentException { - Class contextClass = context.getClass(); - - if (FindsByAccessibilityId.class.isAssignableFrom(contextClass)) { - return FindsByAccessibilityId.class.cast(context) - .findElementsByAccessibilityId(getLocatorString()); - } - - if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { - return super.findElements(context); - } - - throw formIllegalArgumentException(contextClass, FindsByAccessibilityId.class, - FindsByFluentSelector.class); - } - - /** - * {@inheritDoc} - * - * @throws WebDriverException when current session doesn't support the given selector or when - * value of the selector is not consistent. - * @throws IllegalArgumentException when it is impossible to find something on the given - * {@link SearchContext} instance - */ - @Override public WebElement findElement(SearchContext context) throws WebDriverException, - IllegalArgumentException { - Class contextClass = context.getClass(); - - if (FindsByAccessibilityId.class.isAssignableFrom(contextClass)) { - return FindsByAccessibilityId.class.cast(context) - .findElementByAccessibilityId(getLocatorString()); - } - - if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { - return super.findElement(context); - } - - throw formIllegalArgumentException(contextClass, FindsByAccessibilityId.class, - FindsByFluentSelector.class); + super("accessibility id", accessibilityId); } @Override public String toString() { @@ -300,56 +198,7 @@ public List findElements(SearchContext context) throws WebDriverExce public static class ByIosClassChain extends MobileBy implements Serializable { protected ByIosClassChain(String locatorString) { - super(MobileSelector.IOS_CLASS_CHAIN, locatorString); - } - - /** - * {@inheritDoc} - * - * @throws WebDriverException when current session doesn't support the given selector or when - * value of the selector is not consistent. - * @throws IllegalArgumentException when it is impossible to find something on the given - * {@link SearchContext} instance - */ - @SuppressWarnings("unchecked") - @Override public List findElements(SearchContext context) { - Class contextClass = context.getClass(); - - if (FindsByIosClassChain.class.isAssignableFrom(contextClass)) { - return FindsByIosClassChain.class.cast(context) - .findElementsByIosClassChain(getLocatorString()); - } - - if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { - return super.findElements(context); - } - - throw formIllegalArgumentException(contextClass, FindsByIosClassChain.class, - FindsByFluentSelector.class); - } - - /** - * {@inheritDoc} - * - * @throws WebDriverException when current session doesn't support the given selector or when - * value of the selector is not consistent. - * @throws IllegalArgumentException when it is impossible to find something on the given - * {@link SearchContext} instance - */ - @Override public WebElement findElement(SearchContext context) { - Class contextClass = context.getClass(); - - if (FindsByIosClassChain.class.isAssignableFrom(contextClass)) { - return FindsByIosClassChain.class.cast(context) - .findElementByIosClassChain(getLocatorString()); - } - - if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { - return super.findElement(context); - } - - throw formIllegalArgumentException(contextClass, FindsByIosClassChain.class, - FindsByFluentSelector.class); + super("-ios class chain", locatorString); } @Override public String toString() { @@ -360,176 +209,29 @@ protected ByIosClassChain(String locatorString) { public static class ByAndroidDataMatcher extends MobileBy implements Serializable { protected ByAndroidDataMatcher(String locatorString) { - super(MobileSelector.ANDROID_DATA_MATCHER, locatorString); - } - - /** - * {@inheritDoc} - * - * @throws WebDriverException when current session doesn't support the given selector or when - * value of the selector is not consistent. - * @throws IllegalArgumentException when it is impossible to find something on the given - * {@link SearchContext} instance - */ - @SuppressWarnings("unchecked") - @Override public List findElements(SearchContext context) { - Class contextClass = context.getClass(); - - if (FindsByAndroidDataMatcher.class.isAssignableFrom(contextClass)) { - return FindsByAndroidDataMatcher.class.cast(context) - .findElementsByAndroidDataMatcher(getLocatorString()); - } - - if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { - return super.findElements(context); - } - - throw formIllegalArgumentException(contextClass, FindsByAndroidDataMatcher.class, - FindsByFluentSelector.class); - } - - /** - * {@inheritDoc} - * - * @throws WebDriverException when current session doesn't support the given selector or when - * value of the selector is not consistent. - * @throws IllegalArgumentException when it is impossible to find something on the given - * {@link SearchContext} instance - */ - @Override public WebElement findElement(SearchContext context) { - Class contextClass = context.getClass(); - - if (FindsByAndroidDataMatcher.class.isAssignableFrom(contextClass)) { - return FindsByAndroidDataMatcher.class.cast(context) - .findElementByAndroidDataMatcher(getLocatorString()); - } - - if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { - return super.findElement(context); - } - - throw formIllegalArgumentException(contextClass, FindsByAndroidDataMatcher.class, - FindsByFluentSelector.class); + super("-android datamatcher", locatorString); } @Override public String toString() { - return "By.FindsByAndroidDataMatcher: " + getLocatorString(); + return "By.AndroidDataMatcher: " + getLocatorString(); } } public static class ByAndroidViewMatcher extends MobileBy implements Serializable { protected ByAndroidViewMatcher(String locatorString) { - super(MobileSelector.ANDROID_VIEW_MATCHER, locatorString); - } - - /** - * {@inheritDoc} - * - * @throws WebDriverException when current session doesn't support the given selector or when - * value of the selector is not consistent. - * @throws IllegalArgumentException when it is impossible to find something on the given - * {@link SearchContext} instance - */ - @SuppressWarnings("unchecked") - @Override public List findElements(SearchContext context) { - Class contextClass = context.getClass(); - - if (FindsByAndroidViewMatcher.class.isAssignableFrom(contextClass)) { - return FindsByAndroidViewMatcher.class.cast(context) - .findElementsByAndroidViewMatcher(getLocatorString()); - } - - if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { - return super.findElements(context); - } - - throw formIllegalArgumentException(contextClass, FindsByAndroidViewMatcher.class, - FindsByFluentSelector.class); - } - - /** - * {@inheritDoc} - * - * @throws WebDriverException when current session doesn't support the given selector or when - * value of the selector is not consistent. - * @throws IllegalArgumentException when it is impossible to find something on the given - * {@link SearchContext} instance - */ - @Override public WebElement findElement(SearchContext context) { - Class contextClass = context.getClass(); - - if (FindsByAndroidViewMatcher.class.isAssignableFrom(contextClass)) { - return FindsByAndroidViewMatcher.class.cast(context) - .findElementByAndroidViewMatcher(getLocatorString()); - } - - if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { - return super.findElement(context); - } - - throw formIllegalArgumentException(contextClass, FindsByAndroidViewMatcher.class, - FindsByFluentSelector.class); + super("-android viewmatcher", locatorString); } @Override public String toString() { - return "By.FindsByAndroidViewMatcher: " + getLocatorString(); + return "By.AndroidViewMatcher: " + getLocatorString(); } } public static class ByIosNsPredicate extends MobileBy implements Serializable { protected ByIosNsPredicate(String locatorString) { - super(MobileSelector.IOS_PREDICATE_STRING, locatorString); - } - - /** - * {@inheritDoc} - * - * @throws WebDriverException when current session doesn't support the given selector or when - * value of the selector is not consistent. - * @throws IllegalArgumentException when it is impossible to find something on the given - * {@link SearchContext} instance - */ - @SuppressWarnings("unchecked") - @Override public List findElements(SearchContext context) { - Class contextClass = context.getClass(); - - if (FindsByIosNSPredicate.class.isAssignableFrom(contextClass)) { - return FindsByIosNSPredicate.class.cast(context) - .findElementsByIosNsPredicate(getLocatorString()); - } - - if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { - return super.findElements(context); - } - - throw formIllegalArgumentException(contextClass, FindsByIosNSPredicate.class, - FindsByFluentSelector.class); - } - - /** - * {@inheritDoc} - * - * @throws WebDriverException when current session doesn't support the given selector or when - * value of the selector is not consistent. - * @throws IllegalArgumentException when it is impossible to find something on the given - * {@link SearchContext} instance - */ - @Override public WebElement findElement(SearchContext context) { - Class contextClass = context.getClass(); - - if (FindsByIosNSPredicate.class.isAssignableFrom(contextClass)) { - return FindsByIosNSPredicate.class.cast(context) - .findElementByIosNsPredicate(getLocatorString()); - } - - if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { - return super.findElement(context); - } - - throw formIllegalArgumentException(contextClass, FindsByIosNSPredicate.class, - FindsByFluentSelector.class); + super("-ios predicate string", locatorString); } @Override public String toString() { @@ -540,108 +242,15 @@ protected ByIosNsPredicate(String locatorString) { public static class ByWindowsAutomation extends MobileBy implements Serializable { protected ByWindowsAutomation(String locatorString) { - super(MobileSelector.WINDOWS_UI_AUTOMATION, locatorString); - } - - /** - * {@inheritDoc} - * - * @throws WebDriverException when current session doesn't support the given selector or when - * value of the selector is not consistent. - * @throws IllegalArgumentException when it is impossible to find something on the given - * {@link SearchContext} instance - */ - @SuppressWarnings("unchecked") - @Override public List findElements(SearchContext context) { - Class contextClass = context.getClass(); - - if (FindsByWindowsAutomation.class.isAssignableFrom(contextClass)) { - return FindsByWindowsAutomation.class.cast(context) - .findElementsByWindowsUIAutomation(getLocatorString()); - } - - if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { - return super.findElements(context); - } - - throw formIllegalArgumentException(contextClass, FindsByWindowsAutomation.class, - FindsByFluentSelector.class); + super("-windows uiautomation", locatorString); } - /** - * {@inheritDoc} - * - * @throws WebDriverException when current session doesn't support the given selector or when - * value of the selector is not consistent. - * @throws IllegalArgumentException when it is impossible to find something on the given - * {@link SearchContext} instance - */ - @Override public WebElement findElement(SearchContext context) { - Class contextClass = context.getClass(); - - if (FindsByWindowsAutomation.class.isAssignableFrom(contextClass)) { - return FindsByWindowsAutomation.class.cast(context) - .findElementByWindowsUIAutomation(getLocatorString()); - } - - if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { - return super.findElement(context); - } - - throw formIllegalArgumentException(contextClass, FindsByIosNSPredicate.class, - FindsByWindowsAutomation.class); - } } public static class ByImage extends MobileBy implements Serializable { protected ByImage(String b64Template) { - super(MobileSelector.IMAGE, b64Template); - } - - /** - * {@inheritDoc} - * - * @throws WebDriverException when current session doesn't support the given selector or when - * value of the selector is not consistent. - * @throws IllegalArgumentException when it is impossible to find something on the given - * {@link SearchContext} instance - */ - @SuppressWarnings("unchecked") - @Override public List findElements(SearchContext context) { - Class contextClass = context.getClass(); - - if (FindsByImage.class.isAssignableFrom(contextClass)) { - return FindsByImage.class.cast(context).findElementsByImage(getLocatorString()); - } - - if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { - return super.findElements(context); - } - - throw formIllegalArgumentException(contextClass, FindsByImage.class, FindsByFluentSelector.class); - } - - /** - * {@inheritDoc} - * - * @throws WebDriverException when current session doesn't support the given selector or when - * value of the selector is not consistent. - * @throws IllegalArgumentException when it is impossible to find something on the given - * {@link SearchContext} instance - */ - @Override public WebElement findElement(SearchContext context) { - Class contextClass = context.getClass(); - - if (FindsByImage.class.isAssignableFrom(contextClass)) { - return FindsByImage.class.cast(context).findElementByImage(getLocatorString()); - } - - if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { - return super.findElement(context); - } - - throw formIllegalArgumentException(contextClass, FindsByImage.class, FindsByFluentSelector.class); + super("-image", b64Template); } @Override public String toString() { @@ -652,52 +261,7 @@ protected ByImage(String b64Template) { public static class ByCustom extends MobileBy implements Serializable { protected ByCustom(String selector) { - super(MobileSelector.CUSTOM, selector); - } - - /** - * {@inheritDoc} - * - * @throws WebDriverException when current session doesn't support the given selector or when - * value of the selector is not consistent. - * @throws IllegalArgumentException when it is impossible to find something on the given - * {@link SearchContext} instance - */ - @SuppressWarnings("unchecked") - @Override public List findElements(SearchContext context) { - Class contextClass = context.getClass(); - - if (FindsByCustom.class.isAssignableFrom(contextClass)) { - return FindsByCustom.class.cast(context).findElementsByCustom(getLocatorString()); - } - - if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { - return super.findElements(context); - } - - throw formIllegalArgumentException(contextClass, FindsByCustom.class, FindsByFluentSelector.class); - } - - /** - * {@inheritDoc} - * - * @throws WebDriverException when current session doesn't support the given selector or when - * value of the selector is not consistent. - * @throws IllegalArgumentException when it is impossible to find something on the given - * {@link SearchContext} instance - */ - @Override public WebElement findElement(SearchContext context) { - Class contextClass = context.getClass(); - - if (FindsByCustom.class.isAssignableFrom(contextClass)) { - return FindsByCustom.class.cast(context).findElementByCustom(getLocatorString()); - } - - if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { - return super.findElement(context); - } - - throw formIllegalArgumentException(contextClass, FindsByCustom.class, FindsByFluentSelector.class); + super("-custom", selector); } @Override public String toString() { @@ -708,63 +272,22 @@ protected ByCustom(String selector) { public static class ByAndroidViewTag extends MobileBy implements Serializable { public ByAndroidViewTag(String tag) { - super(MobileSelector.ANDROID_VIEWTAG, tag); + super("-android viewtag", tag); } - /** - * {@inheritDoc} - * - * @throws WebDriverException when current session doesn't support the given selector or when - * value of the selector is not consistent. - * @throws IllegalArgumentException when it is impossible to find something on the given - * {@link SearchContext} instance - */ - @SuppressWarnings("unchecked") - @Override - public List findElements(SearchContext context) throws WebDriverException, - IllegalArgumentException { - Class contextClass = context.getClass(); - - if (FindsByAndroidViewTag.class.isAssignableFrom(contextClass)) { - return FindsByAndroidViewTag.class.cast(context) - .findElementsByAndroidViewTag(getLocatorString()); - } - - if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { - return super.findElements(context); - } - - throw formIllegalArgumentException(contextClass, FindsByAndroidViewTag.class, - FindsByFluentSelector.class); + @Override public String toString() { + return "By.AndroidViewTag: " + getLocatorString(); } + } + + public static class ByClassName extends MobileBy implements Serializable { - /** - * {@inheritDoc} - * - * @throws WebDriverException when current session doesn't support the given selector or when - * value of the selector is not consistent. - * @throws IllegalArgumentException when it is impossible to find something on the given - * {@link SearchContext} instance - */ - @Override public WebElement findElement(SearchContext context) throws WebDriverException, - IllegalArgumentException { - Class contextClass = context.getClass(); - - if (FindsByAndroidViewTag.class.isAssignableFrom(contextClass)) { - return FindsByAndroidViewTag.class.cast(context) - .findElementByAndroidViewTag(getLocatorString()); - } - - if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { - return super.findElement(context); - } - - throw formIllegalArgumentException(contextClass, FindsByAndroidViewTag.class, - FindsByFluentSelector.class); + protected ByClassName(String selector) { + super("class name", selector); } @Override public String toString() { - return "By.AndroidViewTag: " + getLocatorString(); + return "By.className: " + getLocatorString(); } } } diff --git a/src/main/java/io/appium/java_client/MobileDriver.java b/src/main/java/io/appium/java_client/MobileDriver.java index e982d5419..708f3b8f0 100644 --- a/src/main/java/io/appium/java_client/MobileDriver.java +++ b/src/main/java/io/appium/java_client/MobileDriver.java @@ -22,55 +22,14 @@ import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.html5.LocationContext; -import org.openqa.selenium.internal.FindsByClassName; -import org.openqa.selenium.internal.FindsByCssSelector; -import org.openqa.selenium.internal.FindsById; -import org.openqa.selenium.internal.FindsByLinkText; -import org.openqa.selenium.internal.FindsByName; -import org.openqa.selenium.internal.FindsByTagName; -import org.openqa.selenium.internal.FindsByXPath; import java.util.List; public interface MobileDriver extends WebDriver, PerformsTouchActions, ContextAware, Rotatable, - FindsByAccessibilityId, LocationContext, HidesKeyboard, HasDeviceTime, - InteractsWithFiles, InteractsWithApps, HasAppStrings, FindsByClassName, FindsByCssSelector, FindsById, - FindsByLinkText, FindsByName, FindsByTagName, FindsByXPath, FindsByFluentSelector, ExecutesMethod, + LocationContext, HidesKeyboard, HasDeviceTime, InteractsWithFiles, InteractsWithApps, HasAppStrings, ExecutesMethod, HasSessionDetails { List findElements(By by); T findElement(By by); - - T findElementByClassName(String className); - - List findElementsByClassName(String className); - - T findElementByCssSelector(String cssSelector); - - List findElementsByCssSelector(String cssSelector); - - T findElementById(String id); - - List findElementsById(String id); - - T findElementByLinkText(String linkText); - - List findElementsByLinkText(String linkText); - - T findElementByPartialLinkText(String partialLinkText); - - List findElementsByPartialLinkText(String partialLinkText); - - T findElementByName(String name); - - List findElementsByName(String name); - - T findElementByTagName(String tagName); - - List findElementsByTagName(String tagName); - - T findElementByXPath(String xPath); - - List findElementsByXPath(String xPath); } diff --git a/src/main/java/io/appium/java_client/MobileElement.java b/src/main/java/io/appium/java_client/MobileElement.java index a8decf61d..45c932b12 100644 --- a/src/main/java/io/appium/java_client/MobileElement.java +++ b/src/main/java/io/appium/java_client/MobileElement.java @@ -29,8 +29,6 @@ public abstract class MobileElement extends DefaultGenericMobileElement { - protected FileDetector fileDetector; - /** * Method returns central coordinates of an element. * @return The instance of the {@link org.openqa.selenium.Point} @@ -46,46 +44,6 @@ public Point getCenter() { return super.findElements(by); } - @Override public List findElements(String by, String using) { - return super.findElements(by, using); - } - - @Override public List findElementsById(String id) { - return super.findElementsById(id); - } - - public List findElementsByLinkText(String using) { - return super.findElementsByLinkText(using); - } - - public List findElementsByPartialLinkText(String using) { - return super.findElementsByPartialLinkText(using); - } - - public List findElementsByTagName(String using) { - return super.findElementsByTagName(using); - } - - public List findElementsByName(String using) { - return super.findElementsByName(using); - } - - public List findElementsByClassName(String using) { - return super.findElementsByClassName(using); - } - - public List findElementsByCssSelector(String using) { - return super.findElementsByCssSelector(using); - } - - public List findElementsByXPath(String using) { - return super.findElementsByXPath(using); - } - - @Override public List findElementsByAccessibilityId(String using) { - return super.findElementsByAccessibilityId(using); - } - /** * This method sets the new value of the attribute "value". * diff --git a/src/main/java/io/appium/java_client/MobileSelector.java b/src/main/java/io/appium/java_client/MobileSelector.java deleted file mode 100644 index 0fbe3284e..000000000 --- a/src/main/java/io/appium/java_client/MobileSelector.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.appium.java_client; - -public enum MobileSelector { - ACCESSIBILITY("accessibility id"), - ANDROID_UI_AUTOMATOR("-android uiautomator"), - IOS_UI_AUTOMATION("-ios uiautomation"), - IOS_PREDICATE_STRING("-ios predicate string"), - IOS_CLASS_CHAIN("-ios class chain"), - WINDOWS_UI_AUTOMATION("-windows uiautomation"), - IMAGE("-image"), - ANDROID_VIEWTAG("-android viewtag"), - ANDROID_DATA_MATCHER("-android datamatcher"), - ANDROID_VIEW_MATCHER("-android viewmatcher"), - CUSTOM("-custom"); - - private final String selector; - - MobileSelector(String selector) { - this.selector = selector; - } - - @Override public String toString() { - return selector; - } -} diff --git a/src/main/java/io/appium/java_client/android/Activity.java b/src/main/java/io/appium/java_client/android/Activity.java index da957d746..41a17dc8c 100644 --- a/src/main/java/io/appium/java_client/android/Activity.java +++ b/src/main/java/io/appium/java_client/android/Activity.java @@ -2,7 +2,6 @@ import lombok.Data; import lombok.experimental.Accessors; -import okhttp3.Interceptor; import static com.google.common.base.Preconditions.checkArgument; import static org.apache.commons.lang3.StringUtils.isBlank; diff --git a/src/main/java/io/appium/java_client/android/AndroidDriver.java b/src/main/java/io/appium/java_client/android/AndroidDriver.java index 1994bb69a..be4bd8e3d 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -26,10 +26,6 @@ import io.appium.java_client.AppiumDriver; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecuteCDPCommand; -import io.appium.java_client.FindsByAndroidDataMatcher; -import io.appium.java_client.FindsByAndroidViewMatcher; -import io.appium.java_client.FindsByAndroidUIAutomator; -import io.appium.java_client.FindsByAndroidViewTag; import io.appium.java_client.HasOnScreenKeyboard; import io.appium.java_client.LocksDevice; import io.appium.java_client.android.connection.HasNetworkConnection; @@ -63,13 +59,10 @@ */ public class AndroidDriver extends AppiumDriver - implements PressesKey, HasNetworkConnection, PushesFiles, StartsActivity, - FindsByAndroidUIAutomator, FindsByAndroidViewTag, FindsByAndroidDataMatcher, - FindsByAndroidViewMatcher, LocksDevice, HasAndroidSettings, HasAndroidDeviceDetails, - HasSupportedPerformanceDataType, AuthenticatesByFinger, HasOnScreenKeyboard, - CanRecordScreen, SupportsSpecialEmulatorCommands, - SupportsNetworkStateManagement, ListensToLogcatMessages, HasAndroidClipboard, - HasBattery, ExecuteCDPCommand, SupportsExtendedGeolocationCommands { + implements PressesKey, HasNetworkConnection, PushesFiles, StartsActivity,LocksDevice, HasAndroidSettings, + HasAndroidDeviceDetails, HasSupportedPerformanceDataType, AuthenticatesByFinger, HasOnScreenKeyboard, + CanRecordScreen, SupportsSpecialEmulatorCommands, SupportsNetworkStateManagement, ListensToLogcatMessages, + HasAndroidClipboard, HasBattery, ExecuteCDPCommand, SupportsExtendedGeolocationCommands { private static final String ANDROID_PLATFORM = MobilePlatform.ANDROID; diff --git a/src/main/java/io/appium/java_client/android/AndroidElement.java b/src/main/java/io/appium/java_client/android/AndroidElement.java index 95899e4db..5c1231c24 100644 --- a/src/main/java/io/appium/java_client/android/AndroidElement.java +++ b/src/main/java/io/appium/java_client/android/AndroidElement.java @@ -19,15 +19,9 @@ import static io.appium.java_client.android.AndroidMobileCommandHelper.replaceElementValueCommand; import io.appium.java_client.CommandExecutionHelper; -import io.appium.java_client.FindsByAndroidDataMatcher; -import io.appium.java_client.FindsByAndroidViewMatcher; -import io.appium.java_client.FindsByAndroidUIAutomator; -import io.appium.java_client.FindsByAndroidViewTag; import io.appium.java_client.MobileElement; -public class AndroidElement extends MobileElement - implements FindsByAndroidUIAutomator, FindsByAndroidDataMatcher, - FindsByAndroidViewMatcher, FindsByAndroidViewTag { +public class AndroidElement extends MobileElement { /** * This method replace current text value. * @param value a new value diff --git a/src/main/java/io/appium/java_client/android/AndroidOptions.java b/src/main/java/io/appium/java_client/android/AndroidOptions.java index 768bf75eb..780f92cd4 100644 --- a/src/main/java/io/appium/java_client/android/AndroidOptions.java +++ b/src/main/java/io/appium/java_client/android/AndroidOptions.java @@ -22,11 +22,15 @@ public class AndroidOptions extends MobileOptions { public AndroidOptions() { - setPlatformName(MobilePlatform.ANDROID); + setAndroidPlatformName(); } public AndroidOptions(Capabilities source) { - this(); - merge(source); + super(source); + setAndroidPlatformName(); + } + + private void setAndroidPlatformName() { + setPlatformName(MobilePlatform.ANDROID); } } diff --git a/src/main/java/io/appium/java_client/events/DefaultAspect.java b/src/main/java/io/appium/java_client/events/DefaultAspect.java index 345ec77ee..3ce9794be 100644 --- a/src/main/java/io/appium/java_client/events/DefaultAspect.java +++ b/src/main/java/io/appium/java_client/events/DefaultAspect.java @@ -97,19 +97,6 @@ class DefaultAspect { + "execution(* org.openqa.selenium.WebDriver.TargetLocator.*(..)) || " + "execution(* org.openqa.selenium.JavascriptExecutor.*(..)) || " + "execution(* org.openqa.selenium.ContextAware.*(..)) || " - + "execution(* io.appium.java_client.FindsByAccessibilityId.*(..)) || " - + "execution(* io.appium.java_client.FindsByAndroidUIAutomator.*(..)) || " - + "execution(* io.appium.java_client.FindsByAndroidDataMatcher.*(..)) || " - + "execution(* io.appium.java_client.FindsByAndroidViewMatcher.*(..)) || " - + "execution(* io.appium.java_client.FindsByWindowsAutomation.*(..)) || " - + "execution(* io.appium.java_client.FindsByIosNSPredicate.*(..)) || " - + "execution(* org.openqa.selenium.internal.FindsByClassName.*(..)) || " - + "execution(* org.openqa.selenium.internal.FindsByCssSelector.*(..)) || " - + "execution(* org.openqa.selenium.internal.FindsById.*(..)) || " - + "execution(* org.openqa.selenium.internal.FindsByLinkText.*(..)) || " - + "execution(* org.openqa.selenium.internal.FindsByName.*(..)) || " - + "execution(* org.openqa.selenium.internal.FindsByTagName.*(..)) || " - + "execution(* org.openqa.selenium.internal.FindsByXPath.*(..)) || " + "execution(* org.openqa.selenium.WebDriver.Window.*(..)) || " + "execution(* io.appium.java_client.android.AndroidElement.*(..)) || " + "execution(* io.appium.java_client.ios.IOSElement.*(..)) || " diff --git a/src/main/java/io/appium/java_client/internal/JsonToMobileElementConverter.java b/src/main/java/io/appium/java_client/internal/JsonToMobileElementConverter.java index 9f8674a90..d69e39312 100644 --- a/src/main/java/io/appium/java_client/internal/JsonToMobileElementConverter.java +++ b/src/main/java/io/appium/java_client/internal/JsonToMobileElementConverter.java @@ -22,9 +22,9 @@ import org.openqa.selenium.Capabilities; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.CapabilityType; +import org.openqa.selenium.remote.JsonToWebElementConverter; import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.remote.RemoteWebElement; -import org.openqa.selenium.remote.internal.JsonToWebElementConverter; import java.lang.reflect.Constructor; diff --git a/src/main/java/io/appium/java_client/ios/IOSDriver.java b/src/main/java/io/appium/java_client/ios/IOSDriver.java index 229aac70b..ffd4a8a0c 100644 --- a/src/main/java/io/appium/java_client/ios/IOSDriver.java +++ b/src/main/java/io/appium/java_client/ios/IOSDriver.java @@ -22,8 +22,6 @@ import com.google.common.collect.ImmutableMap; import io.appium.java_client.AppiumDriver; -import io.appium.java_client.FindsByIosClassChain; -import io.appium.java_client.FindsByIosNSPredicate; import io.appium.java_client.HasOnScreenKeyboard; import io.appium.java_client.HidesKeyboardWithKeyName; import io.appium.java_client.LocksDevice; @@ -59,9 +57,8 @@ */ public class IOSDriver extends AppiumDriver - implements HidesKeyboardWithKeyName, ShakesDevice, HasIOSSettings, HasOnScreenKeyboard, - LocksDevice, PerformsTouchID, FindsByIosNSPredicate, FindsByIosClassChain, - PushesFiles, CanRecordScreen, HasIOSClipboard, ListensToSyslogMessages, + implements HidesKeyboardWithKeyName, ShakesDevice, HasIOSSettings, HasOnScreenKeyboard, LocksDevice, + PerformsTouchID, PushesFiles, CanRecordScreen, HasIOSClipboard, ListensToSyslogMessages, HasBattery { private static final String IOS_DEFAULT_PLATFORM = MobilePlatform.IOS; diff --git a/src/main/java/io/appium/java_client/ios/IOSElement.java b/src/main/java/io/appium/java_client/ios/IOSElement.java index a406053a0..55aa47110 100644 --- a/src/main/java/io/appium/java_client/ios/IOSElement.java +++ b/src/main/java/io/appium/java_client/ios/IOSElement.java @@ -16,10 +16,7 @@ package io.appium.java_client.ios; -import io.appium.java_client.FindsByIosClassChain; -import io.appium.java_client.FindsByIosNSPredicate; import io.appium.java_client.MobileElement; -public class IOSElement extends MobileElement - implements FindsByIosNSPredicate, FindsByIosClassChain { +public class IOSElement extends MobileElement { } diff --git a/src/main/java/io/appium/java_client/ios/IOSOptions.java b/src/main/java/io/appium/java_client/ios/IOSOptions.java index 14af6aad6..9d4c82b6e 100644 --- a/src/main/java/io/appium/java_client/ios/IOSOptions.java +++ b/src/main/java/io/appium/java_client/ios/IOSOptions.java @@ -22,11 +22,15 @@ public class IOSOptions extends MobileOptions { public IOSOptions() { - setPlatformName(MobilePlatform.IOS); + setIOSPlatformName(); } public IOSOptions(Capabilities source) { - this(); - merge(source); + super(source); + setIOSPlatformName(); + } + + private void setIOSPlatformName() { + setPlatformName(MobilePlatform.IOS); } } diff --git a/src/main/java/io/appium/java_client/mac/FindsByClassChain.java b/src/main/java/io/appium/java_client/mac/FindsByClassChain.java deleted file mode 100644 index 3d4eaffcc..000000000 --- a/src/main/java/io/appium/java_client/mac/FindsByClassChain.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.appium.java_client.mac; - -import io.appium.java_client.FindsByFluentSelector; -import io.appium.java_client.MobileSelector; -import org.openqa.selenium.WebElement; - -import java.util.List; - -public interface FindsByClassChain extends FindsByFluentSelector { - - /** - * Perform single element lookup by class chain expression. - * Read https://github.com/appium/appium-mac2-driver#element-location - * for more details on elements location strategies supported by Mac2 driver. - * - * @param using A valid class chain lookup expression. - * @return The found element - */ - default T findElementByClassChain(String using) { - return findElement(MobileSelector.IOS_CLASS_CHAIN.toString(), using); - } - - /** - * Perform multiple elements lookup by class chain search expression. - * Read https://github.com/appium/appium-mac2-driver#element-location - * for more details on elements location strategies supported by Mac2 driver. - * - * @param using A valid class chain lookup expression. - * @return The array of found elements or an empty one if no matches have been found. - */ - default List findElementsByClassChain(String using) { - return findElements(MobileSelector.IOS_CLASS_CHAIN.toString(), using); - } -} diff --git a/src/main/java/io/appium/java_client/mac/FindsByNsPredicate.java b/src/main/java/io/appium/java_client/mac/FindsByNsPredicate.java deleted file mode 100644 index 665732eb3..000000000 --- a/src/main/java/io/appium/java_client/mac/FindsByNsPredicate.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.appium.java_client.mac; - -import io.appium.java_client.FindsByFluentSelector; -import io.appium.java_client.MobileSelector; -import org.openqa.selenium.WebElement; - -import java.util.List; - -public interface FindsByNsPredicate extends FindsByFluentSelector { - - /** - * Perform single element lookup by predicate search expression. - * Read https://github.com/appium/appium-mac2-driver#element-location - * for more details on elements location strategies supported by Mac2 driver. - * - * @param using A valid predicate lookup expression. - * @return The found element - */ - default T findElementByNsPredicate(String using) { - return findElement(MobileSelector.IOS_PREDICATE_STRING.toString(), using); - } - - /** - * Perform multiple elements lookup by predicate search expression. - * Read https://github.com/appium/appium-mac2-driver#element-location - * for more details on elements location strategies supported by Mac2 driver. - * - * @param using A valid predicate lookup expression. - * @return The array of found elements or an empty one if no matches have been found. - */ - default List findElementsByNsPredicate(String using) { - return findElements(MobileSelector.IOS_PREDICATE_STRING.toString(), using); - } -} diff --git a/src/main/java/io/appium/java_client/mac/Mac2Driver.java b/src/main/java/io/appium/java_client/mac/Mac2Driver.java index d76eaf5d7..215c28971 100644 --- a/src/main/java/io/appium/java_client/mac/Mac2Driver.java +++ b/src/main/java/io/appium/java_client/mac/Mac2Driver.java @@ -44,9 +44,7 @@ * * @since Appium 1.20.0 */ -public class Mac2Driver - extends AppiumDriver implements CanRecordScreen, FindsByClassChain, - FindsByNsPredicate, HasSettings { +public class Mac2Driver extends AppiumDriver implements CanRecordScreen, HasSettings { public Mac2Driver(HttpCommandExecutor executor, Capabilities capabilities) { super(executor, prepareCaps(capabilities)); } diff --git a/src/main/java/io/appium/java_client/mac/Mac2Element.java b/src/main/java/io/appium/java_client/mac/Mac2Element.java index 905bada6e..e41042e8d 100644 --- a/src/main/java/io/appium/java_client/mac/Mac2Element.java +++ b/src/main/java/io/appium/java_client/mac/Mac2Element.java @@ -18,6 +18,5 @@ import io.appium.java_client.MobileElement; -public class Mac2Element extends MobileElement implements - FindsByClassChain, FindsByNsPredicate { +public class Mac2Element extends MobileElement { } diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java index 718cd403c..4b853f046 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java @@ -46,7 +46,7 @@ enum Strategies { }, BYCLASSNAME("className") { @Override By getBy(Annotation annotation) { - return By.className(getValue(annotation, this)); + return MobileBy.className(getValue(annotation, this)); } }, BYID("id") { diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index 2b0f77f7e..28af10cfc 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -44,16 +44,21 @@ import org.openqa.selenium.remote.ProtocolHandshake; import org.openqa.selenium.remote.Response; import org.openqa.selenium.remote.ResponseCodec; +import org.openqa.selenium.remote.codec.w3c.W3CHttpCommandCodec; +import org.openqa.selenium.remote.http.Filter; import org.openqa.selenium.remote.http.HttpClient; +import org.openqa.selenium.remote.http.HttpHandler; import org.openqa.selenium.remote.http.HttpRequest; import org.openqa.selenium.remote.http.HttpResponse; -import org.openqa.selenium.remote.http.W3CHttpCommandCodec; +import org.openqa.selenium.remote.http.WebSocket; +import org.openqa.selenium.remote.http.WebSocket.Listener; import org.openqa.selenium.remote.service.DriverService; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; +import java.io.UncheckedIOException; import java.io.Writer; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -156,13 +161,6 @@ protected HttpClient getClient() { return getPrivateFieldValue("client", HttpClient.class); } - protected HttpClient withRequestsPatchedByIdempotencyKey(HttpClient httpClient) { - return (request) -> { - request.setHeader(IDEMPOTENCY_KEY_HEADER, UUID.randomUUID().toString().toLowerCase()); - return httpClient.execute(request); - }; - } - private Response createSession(Command command) throws IOException { if (getCommandCodec() != null) { throw new SessionNotCreatedException("Session already exists"); @@ -191,7 +189,10 @@ public Result createSession(HttpClient client, Command command) throws IOExcepti createSessionMethod.setAccessible(true); Optional result = (Optional) createSessionMethod.invoke(this, - withRequestsPatchedByIdempotencyKey(client), contentStream, counter.getCount()); + client.with(httpHandler -> req -> { + req.setHeader(IDEMPOTENCY_KEY_HEADER, UUID.randomUUID().toString().toLowerCase()); + return httpHandler.execute(req); + }), contentStream, counter.getCount()); return result.map(result1 -> { Result toReturn = result.get(); diff --git a/src/main/java/io/appium/java_client/remote/AppiumW3CHttpCommandCodec.java b/src/main/java/io/appium/java_client/remote/AppiumW3CHttpCommandCodec.java index aec7ebd75..0fe0ace05 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumW3CHttpCommandCodec.java +++ b/src/main/java/io/appium/java_client/remote/AppiumW3CHttpCommandCodec.java @@ -32,7 +32,7 @@ import org.openqa.selenium.interactions.KeyInput; import org.openqa.selenium.interactions.Sequence; -import org.openqa.selenium.remote.http.W3CHttpCommandCodec; +import org.openqa.selenium.remote.codec.w3c.W3CHttpCommandCodec; import java.util.Collection; import java.util.Map; diff --git a/src/main/java/io/appium/java_client/remote/MobileOptions.java b/src/main/java/io/appium/java_client/remote/MobileOptions.java index 6a7810f1a..bf8ea1f38 100644 --- a/src/main/java/io/appium/java_client/remote/MobileOptions.java +++ b/src/main/java/io/appium/java_client/remote/MobileOptions.java @@ -18,6 +18,7 @@ import org.openqa.selenium.Capabilities; import org.openqa.selenium.MutableCapabilities; +import org.openqa.selenium.Platform; import org.openqa.selenium.ScreenOrientation; import org.openqa.selenium.remote.CapabilityType; @@ -38,7 +39,7 @@ public MobileOptions() { * @param source is Capabilities instance to merge into new instance */ public MobileOptions(Capabilities source) { - merge(source); + super(source); } /** @@ -52,16 +53,6 @@ public T setPlatformName(String platform) { return amend(CapabilityType.PLATFORM_NAME, platform); } - /** - * Get the kind of mobile device or emulator to use. - * - * @return String representing the kind of mobile device or emulator to use. - * @see org.openqa.selenium.remote.CapabilityType#PLATFORM_NAME - */ - public String getPlatformName() { - return (String) getCapability(CapabilityType.PLATFORM_NAME); - } - /** * Set the absolute local path for the location of the App. * The or remote http URL to a {@code .ipa} file (IOS), diff --git a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java index 3e82e0de4..37851fd4b 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java @@ -22,8 +22,6 @@ import static org.slf4j.event.Level.INFO; import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import org.apache.commons.lang3.StringUtils; @@ -42,6 +40,7 @@ import java.net.URL; import java.time.Duration; import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; import java.util.function.BiConsumer; @@ -61,25 +60,22 @@ public final class AppiumDriverLocalService extends DriverService { private static final Duration DESTROY_TIMEOUT = Duration.ofSeconds(60); private final File nodeJSExec; - private final ImmutableList nodeJSArgs; - private final ImmutableMap nodeJSEnvironment; - private final long startupTimeout; - private final TimeUnit timeUnit; + private final List nodeJSArgs; + private final Map nodeJSEnvironment; + private final Duration startupTimeout; private final ReentrantLock lock = new ReentrantLock(true); //uses "fair" thread ordering policy private final ListOutputStream stream = new ListOutputStream().add(System.out); private final URL url; private CommandLine process = null; - AppiumDriverLocalService(String ipAddress, File nodeJSExec, int nodeJSPort, - ImmutableList nodeJSArgs, ImmutableMap nodeJSEnvironment, - long startupTimeout, TimeUnit timeUnit) throws IOException { - super(nodeJSExec, nodeJSPort, nodeJSArgs, nodeJSEnvironment); + AppiumDriverLocalService(String ipAddress, File nodeJSExec, int nodeJSPort, Duration startupTimeout, + List nodeJSArgs, Map nodeJSEnvironment) throws IOException { + super(nodeJSExec, nodeJSPort, startupTimeout, nodeJSArgs, nodeJSEnvironment); this.nodeJSExec = nodeJSExec; this.nodeJSArgs = nodeJSArgs; this.nodeJSEnvironment = nodeJSEnvironment; this.startupTimeout = startupTimeout; - this.timeUnit = timeUnit; this.url = new URL(String.format(URL_MASK, ipAddress, nodeJSPort)); } @@ -114,7 +110,7 @@ public boolean isRunning() { } try { - ping(1500, TimeUnit.MILLISECONDS); + ping(Duration.ofMillis(1500)); return true; } catch (UrlChecker.TimeoutException e) { return false; @@ -127,10 +123,10 @@ public boolean isRunning() { } - private void ping(long time, TimeUnit timeUnit) throws UrlChecker.TimeoutException, MalformedURLException { + private void ping(Duration timeout) throws UrlChecker.TimeoutException, MalformedURLException { // The operating system might block direct access to the universal broadcast IP address URL status = new URL(url.toString().replace(BROADCAST_IP_ADDRESS, "127.0.0.1") + "/status"); - new UrlChecker().waitUntilAvailable(time, timeUnit, status); + new UrlChecker().waitUntilAvailable(timeout.toMillis(), TimeUnit.MILLISECONDS, status); } /** @@ -152,7 +148,7 @@ public void start() throws AppiumServerHasNotBeenStartedLocallyException { process.setEnvironmentVariables(nodeJSEnvironment); process.copyOutputTo(stream); process.executeAsync(); - ping(startupTimeout, timeUnit); + ping(startupTimeout); } catch (Throwable e) { destroyProcess(); String msgTxt = "The local appium server has not been started. " diff --git a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java index dc9b669be..30147838e 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java @@ -21,7 +21,6 @@ import static org.openqa.selenium.remote.CapabilityType.PLATFORM_NAME; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -36,6 +35,7 @@ import org.openqa.selenium.Capabilities; import org.openqa.selenium.Platform; import org.openqa.selenium.os.ExecutableFinder; +import org.openqa.selenium.remote.Browser; import org.openqa.selenium.remote.BrowserType; import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.remote.service.DriverService; @@ -47,6 +47,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; +import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -87,9 +88,6 @@ public final class AppiumServiceBuilder private static final Function NODE_JS_NOT_EXIST_ERROR = (fullPath) -> String.format("The main NodeJS executable does not exist at '%s'", fullPath.getAbsolutePath()); - // The first starting is slow sometimes on some environment - private long startupTimeout = 120; - private TimeUnit timeUnit = TimeUnit.SECONDS; private static final List PATH_CAPABILITIES = ImmutableList.of(AndroidMobileCapabilityType.KEYSTORE_PATH, AndroidMobileCapabilityType.CHROMEDRIVER_EXECUTABLE, MobileCapabilityType.APP); @@ -116,8 +114,8 @@ public int score(Capabilities capabilities) { } String browserName = capabilities.getBrowserName(); - if (browserName.equals(BrowserType.CHROME) || browserName.equals(BrowserType.ANDROID) - || browserName.equals(BrowserType.SAFARI)) { + if (Browser.CHROME.is(browserName) || browserName.equals(BrowserType.ANDROID) + || Browser.SAFARI.is(browserName)) { score++; } @@ -277,21 +275,6 @@ public AppiumServiceBuilder withIPAddress(String ipAddress) { return this; } - /** - * Sets start up timeout. - * - * @param time a time value for the service starting up. - * @param timeUnit a time unit for the service starting up. - * @return self-reference. - */ - public AppiumServiceBuilder withStartUpTimeOut(long time, TimeUnit timeUnit) { - checkNotNull(timeUnit); - checkArgument(time > 0, "Time value should be greater than zero", time); - this.startupTimeout = time; - this.timeUnit = timeUnit; - return this; - } - @Nullable private static File loadPathFromEnv(String envVarName) { String fullPath = System.getProperty(envVarName); @@ -474,11 +457,12 @@ public AppiumServiceBuilder withLogFile(File logFile) { @Override protected AppiumDriverLocalService createDriverService(File nodeJSExecutable, int nodeJSPort, - ImmutableList nodeArguments, - ImmutableMap nodeEnvironment) { + Duration startupTimeout, + List nodeArguments, + Map nodeEnvironment) { try { - return new AppiumDriverLocalService(ipAddress, nodeJSExecutable, nodeJSPort, - nodeArguments, nodeEnvironment, startupTimeout, timeUnit); + return new AppiumDriverLocalService(ipAddress, nodeJSExecutable, nodeJSPort, startupTimeout, nodeArguments, + nodeEnvironment); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/src/main/java/io/appium/java_client/touch/offset/ElementOption.java b/src/main/java/io/appium/java_client/touch/offset/ElementOption.java index ede90103c..775b067d1 100644 --- a/src/main/java/io/appium/java_client/touch/offset/ElementOption.java +++ b/src/main/java/io/appium/java_client/touch/offset/ElementOption.java @@ -6,7 +6,7 @@ import org.openqa.selenium.Point; import org.openqa.selenium.WebElement; -import org.openqa.selenium.internal.HasIdentity; +import org.openqa.selenium.remote.RemoteWebElement; import java.util.HashMap; import java.util.Map; @@ -84,9 +84,9 @@ public ElementOption withCoordinates(int xOffset, int yOffset) { public ElementOption withElement(WebElement element) { checkNotNull(element); checkArgument(true, "Element should be an instance of the class which " - + "implements org.openqa.selenium.internal.HasIdentity", - element instanceof HasIdentity); - elementId = ((HasIdentity) element).getId(); + + "extends org.openqa.selenium.remote.RemoteWebElement", + element instanceof RemoteWebElement); + elementId = ((RemoteWebElement) element).getId(); return this; } diff --git a/src/main/java/io/appium/java_client/windows/WindowsDriver.java b/src/main/java/io/appium/java_client/windows/WindowsDriver.java index 3c8126ac1..cf89449de 100644 --- a/src/main/java/io/appium/java_client/windows/WindowsDriver.java +++ b/src/main/java/io/appium/java_client/windows/WindowsDriver.java @@ -19,7 +19,6 @@ import static io.appium.java_client.remote.MobilePlatform.WINDOWS; import io.appium.java_client.AppiumDriver; -import io.appium.java_client.FindsByWindowsAutomation; import io.appium.java_client.HidesKeyboardWithKeyName; import io.appium.java_client.screenrecording.CanRecordScreen; import io.appium.java_client.service.local.AppiumDriverLocalService; @@ -32,8 +31,7 @@ import java.net.URL; public class WindowsDriver - extends AppiumDriver implements PressesKeyCode, HidesKeyboardWithKeyName, - FindsByWindowsAutomation, CanRecordScreen { + extends AppiumDriver implements PressesKeyCode, HidesKeyboardWithKeyName, CanRecordScreen { public WindowsDriver(HttpCommandExecutor executor, Capabilities capabilities) { super(executor, updateDefaultPlatformName(capabilities, WINDOWS)); diff --git a/src/main/java/io/appium/java_client/windows/WindowsElement.java b/src/main/java/io/appium/java_client/windows/WindowsElement.java index 4f7ec7ba2..ad5d3a5d8 100644 --- a/src/main/java/io/appium/java_client/windows/WindowsElement.java +++ b/src/main/java/io/appium/java_client/windows/WindowsElement.java @@ -16,8 +16,7 @@ package io.appium.java_client.windows; -import io.appium.java_client.FindsByWindowsAutomation; import io.appium.java_client.MobileElement; -public class WindowsElement extends MobileElement implements FindsByWindowsAutomation { +public class WindowsElement extends MobileElement { } diff --git a/src/main/java/io/appium/java_client/ws/StringWebSocketClient.java b/src/main/java/io/appium/java_client/ws/StringWebSocketClient.java index d7ebe559e..6a3148aa2 100644 --- a/src/main/java/io/appium/java_client/ws/StringWebSocketClient.java +++ b/src/main/java/io/appium/java_client/ws/StringWebSocketClient.java @@ -16,21 +16,21 @@ package io.appium.java_client.ws; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import okhttp3.WebSocket; -import okhttp3.WebSocketListener; - import java.net.URI; +import java.time.Duration; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import javax.annotation.Nullable; -public class StringWebSocketClient extends WebSocketListener implements +import org.openqa.selenium.remote.http.ClientConfig; +import org.openqa.selenium.remote.http.HttpClient; +import org.openqa.selenium.remote.http.HttpMethod; +import org.openqa.selenium.remote.http.HttpRequest; +import org.openqa.selenium.remote.http.WebSocket; + +public class StringWebSocketClient implements WebSocket.Listener, CanHandleMessages, CanHandleErrors, CanHandleConnects, CanHandleDisconnects { private final List> messageHandlers = new CopyOnWriteArrayList<>(); private final List> errorHandlers = new CopyOnWriteArrayList<>(); @@ -65,37 +65,36 @@ public void connect(URI endpoint) { return; } - OkHttpClient client = new OkHttpClient.Builder() - .readTimeout(0, TimeUnit.MILLISECONDS) - .build(); - Request request = new Request.Builder() - .url(endpoint.toString()) - .build(); - client.newWebSocket(request, this); - client.dispatcher().executorService().shutdown(); + ClientConfig clientConfig = ClientConfig.defaultConfig() + .readTimeout(Duration.ZERO) + .baseUri(endpoint); // To avoid NPE in org.openqa.selenium.remote.http.netty.NettyMessages (line 78) + HttpClient client = HttpClient.Factory.createDefault().createClient(clientConfig); + HttpRequest request = new HttpRequest(HttpMethod.GET, endpoint.toString()); + client.openSocket(request, this); + onOpen(); setEndpoint(endpoint); } - @Override - public void onOpen(WebSocket webSocket, Response response) { + public void onOpen() { getConnectionHandlers().forEach(Runnable::run); isListening = true; } @Override - public void onClosing(WebSocket webSocket, int code, String reason) { + public void onClose(int code, String reason) { getDisconnectionHandlers().forEach(Runnable::run); isListening = false; } @Override - public void onFailure(WebSocket webSocket, Throwable t, Response response) { + public void onError(Throwable t) { getErrorHandlers().forEach(x -> x.accept(t)); } @Override - public void onMessage(WebSocket webSocket, String text) { + public void onText(CharSequence data) { + String text = data.toString(); getMessageHandlers().forEach(x -> x.accept(text)); } diff --git a/src/main/java/org/openqa/selenium/WebDriver.java b/src/main/java/org/openqa/selenium/WebDriver.java index 08de94859..c8f990896 100644 --- a/src/main/java/org/openqa/selenium/WebDriver.java +++ b/src/main/java/org/openqa/selenium/WebDriver.java @@ -21,14 +21,15 @@ import org.openqa.selenium.logging.Logs; import java.net.URL; +import java.time.Duration; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; /** - * The main interface to use for testing, which represents an idealised web browser. The methods in - * this class fall into three categories: + * WebDriver is a remote control interface that enables introspection and control of user agents + * (browsers). The methods in this interface fall into three categories: *