From d207f351d358a382ac4b66562a35c85dba89a974 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 27 Oct 2021 08:36:31 +0200 Subject: [PATCH 1/7] refactor!: Remove selenium package override --- .../io/appium/java_client/AppiumDriver.java | 146 +--- .../java_client/AppiumExecutionMethod.java | 4 +- .../DefaultGenericMobileDriver.java | 61 -- .../DefaultGenericMobileElement.java | 49 -- .../appium/java_client/HasBrowserCheck.java | 44 + .../appium/java_client/HasSessionDetails.java | 104 --- .../io/appium/java_client/MobileElement.java | 57 -- .../java_client/android/AndroidDriver.java | 58 +- .../java_client/android/AndroidElement.java | 32 - .../java_client/internal/ElementMap.java | 90 --- .../JsonToMobileElementConverter.java | 84 -- .../io/appium/java_client/ios/IOSDriver.java | 48 +- .../io/appium/java_client/ios/IOSElement.java | 22 - .../io/appium/java_client/mac/Mac2Driver.java | 2 +- .../appium/java_client/mac/Mac2Element.java | 22 - .../pagefactory/AppiumFieldDecorator.java | 13 +- .../utils/WebDriverUnpackUtility.java | 12 +- .../remote/SupportsContextSwitching.java | 81 ++ .../SupportsLocation.java} | 23 +- .../java_client/remote/SupportsRotation.java | 73 ++ .../java_client/windows/WindowsDriver.java | 6 +- .../java_client/windows/WindowsElement.java | 22 - .../org/openqa/selenium/SearchContext.java | 43 - .../java/org/openqa/selenium/WebDriver.java | 757 ------------------ .../java/org/openqa/selenium/WebElement.java | 338 -------- .../java/io/appium/java_client/TestUtils.java | 25 + .../AndroidAbilityToUseSupplierTest.java | 13 +- .../android/AndroidDriverTest.java | 20 - .../android/AndroidElementTest.java | 90 --- .../android/AndroidSearchingTest.java | 4 +- .../java_client/android/AndroidTouchTest.java | 30 +- .../java_client/android/BaseAndroidTest.java | 4 +- .../java_client/android/BaseEspressoTest.java | 4 +- .../android/ExecuteCDPCommandTest.java | 2 +- .../java_client/android/FingerPrintTest.java | 12 +- .../java_client/android/IntentTest.java | 4 +- .../android/OpenNotificationsTest.java | 3 +- .../java_client/android/UIAutomator2Test.java | 5 +- .../java_client/appium/AndroidTest.java | 146 ---- .../appium/AppiumFluentWaitTest.java | 97 --- .../generation/BaseElementGenerationTest.java | 42 - .../android/AndroidElementGeneratingTest.java | 81 -- .../ios/IOSElementGenerationTest.java | 166 ---- .../events/stubs/EmptyWebDriver.java | 2 +- .../io/appium/java_client/ios/AppIOSTest.java | 4 +- .../appium/java_client/ios/BaseIOSTest.java | 2 +- .../java_client/ios/BaseIOSWebViewTest.java | 4 +- .../java_client/ios/BaseSafariTest.java | 2 +- .../appium/java_client/ios/IOSDriverTest.java | 13 +- .../java_client/ios/IOSElementTest.java | 14 +- .../appium/java_client/ios/IOSTouchTest.java | 22 +- .../AndroidPageObjectTest.java | 35 +- .../DesktopBrowserCompatibilityTest.java | 2 +- .../pagefactory_tests/GenericTest.java | 300 ------- .../MobileBrowserCompatibilityTest.java | 2 +- .../pagefactory_tests/XCUITModeTest.java | 29 +- .../widget/tests/AbstractStubWebDriver.java | 23 +- .../widget/tests/StubWebElement.java | 2 +- .../service/local/StartingAppLocallyTest.java | 12 +- 59 files changed, 476 insertions(+), 2931 deletions(-) delete mode 100644 src/main/java/io/appium/java_client/DefaultGenericMobileDriver.java delete mode 100644 src/main/java/io/appium/java_client/DefaultGenericMobileElement.java create mode 100644 src/main/java/io/appium/java_client/HasBrowserCheck.java delete mode 100644 src/main/java/io/appium/java_client/HasSessionDetails.java delete mode 100644 src/main/java/io/appium/java_client/MobileElement.java delete mode 100644 src/main/java/io/appium/java_client/android/AndroidElement.java delete mode 100644 src/main/java/io/appium/java_client/internal/ElementMap.java delete mode 100644 src/main/java/io/appium/java_client/internal/JsonToMobileElementConverter.java delete mode 100644 src/main/java/io/appium/java_client/ios/IOSElement.java delete mode 100644 src/main/java/io/appium/java_client/mac/Mac2Element.java create mode 100644 src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java rename src/main/java/io/appium/java_client/{MobileDriver.java => remote/SupportsLocation.java} (59%) create mode 100644 src/main/java/io/appium/java_client/remote/SupportsRotation.java delete mode 100644 src/main/java/io/appium/java_client/windows/WindowsElement.java delete mode 100644 src/main/java/org/openqa/selenium/SearchContext.java delete mode 100644 src/main/java/org/openqa/selenium/WebDriver.java delete mode 100644 src/main/java/org/openqa/selenium/WebElement.java delete mode 100644 src/test/java/io/appium/java_client/android/AndroidElementTest.java delete mode 100644 src/test/java/io/appium/java_client/appium/AndroidTest.java delete mode 100644 src/test/java/io/appium/java_client/appium/AppiumFluentWaitTest.java delete mode 100644 src/test/java/io/appium/java_client/appium/element/generation/BaseElementGenerationTest.java delete mode 100644 src/test/java/io/appium/java_client/appium/element/generation/android/AndroidElementGeneratingTest.java delete mode 100644 src/test/java/io/appium/java_client/appium/element/generation/ios/IOSElementGenerationTest.java delete mode 100644 src/test/java/io/appium/java_client/pagefactory_tests/GenericTest.java diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index b2fdf10d5..c85cb147c 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -16,31 +16,20 @@ package io.appium.java_client; -import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.remote.MobileCapabilityType.PLATFORM_NAME; -import static org.apache.commons.lang3.StringUtils.containsIgnoreCase; -import static org.apache.commons.lang3.StringUtils.isBlank; import com.google.common.collect.ImmutableMap; -import io.appium.java_client.internal.CapabilityHelpers; -import io.appium.java_client.internal.JsonToMobileElementConverter; import io.appium.java_client.remote.AppiumCommandExecutor; import io.appium.java_client.remote.AppiumNewSessionCommandPayload; 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; import org.openqa.selenium.MutableCapabilities; -import org.openqa.selenium.ScreenOrientation; import org.openqa.selenium.SessionNotCreatedException; import org.openqa.selenium.WebDriver; 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; import org.openqa.selenium.remote.ErrorHandler; @@ -55,29 +44,26 @@ import java.lang.reflect.Field; import java.net.URL; import java.util.Arrays; -import java.util.LinkedHashSet; -import java.util.List; import java.util.Map; -import java.util.Set; /** * Default Appium driver implementation. * - * @param the required type of class which implement {@link WebElement}. - * Instances of the defined type will be returned via findElement* and findElements* - * Warning (!!!). Allowed types: - * {@link WebElement}, {@link org.openqa.selenium.remote.RemoteWebElement}, - * {@link MobileElement} and its subclasses that designed - * specifically for each target mobile OS (still Android and iOS) */ @SuppressWarnings("unchecked") -public class AppiumDriver - extends DefaultGenericMobileDriver implements ComparesImages, ExecutesDriverScript, LogsEvents, HasSettings { +public class AppiumDriver extends RemoteWebDriver implements + WebDriver, + ExecutesMethod, + ComparesImages, + ExecutesDriverScript, + LogsEvents, + HasBrowserCheck, + HasSettings { private static final ErrorHandler errorHandler = new ErrorHandler(new ErrorCodesMobile(), true); // frequently used command parameters private final URL remoteAddress; - private final RemoteLocationContext locationContext; + protected final RemoteLocationContext locationContext; private final ExecuteMethod executeMethod; /** @@ -94,7 +80,6 @@ public AppiumDriver(HttpCommandExecutor executor, Capabilities capabilities) { locationContext = new RemoteLocationContext(executeMethod); super.setErrorHandler(errorHandler); this.remoteAddress = executor.getAddressOfRemoteServer(); - this.setElementConverter(new JsonToMobileElementConverter(this)); } public AppiumDriver(URL remoteAddress, Capabilities desiredCapabilities) { @@ -155,50 +140,11 @@ protected static Capabilities updateDefaultPlatformName(Capabilities originalCap return originalCapabilities; } - @Override - public List findElements(By by) { - return super.findElements(by); - } - @Override public ExecuteMethod getExecuteMethod() { return executeMethod; } - @Override - public WebDriver context(String name) { - checkNotNull(name, "Must supply a context name"); - try { - execute(DriverCommand.SWITCH_TO_CONTEXT, ImmutableMap.of("name", name)); - return this; - } catch (WebDriverException e) { - throw new NoSuchContextException(e.getMessage(), e); - } - } - - @Override - public Set getContextHandles() { - Response response = execute(DriverCommand.GET_CONTEXT_HANDLES); - Object value = response.getValue(); - try { - List returnedValues = (List) value; - return new LinkedHashSet<>(returnedValues); - } catch (ClassCastException ex) { - throw new WebDriverException( - "Returned value cannot be converted to List: " + value, ex); - } - } - - @Override - public String getContext() { - String contextName = - String.valueOf(execute(DriverCommand.GET_CURRENT_CONTEXT_HANDLE).getValue()); - if ("null".equalsIgnoreCase(contextName)) { - return null; - } - return contextName; - } - /** * This method is used to get build version status of running Appium server. * @@ -208,29 +154,6 @@ public Map getStatus() { return (Map) execute(DriverCommand.STATUS).getValue(); } - @Override - public DeviceRotation rotation() { - Response response = execute(DriverCommand.GET_SCREEN_ROTATION); - DeviceRotation deviceRotation = - new DeviceRotation((Map) response.getValue()); - if (deviceRotation.getX() < 0 || deviceRotation.getY() < 0 || deviceRotation.getZ() < 0) { - throw new WebDriverException("Unexpected orientation returned: " + deviceRotation); - } - return deviceRotation; - } - - @Override - public void rotate(DeviceRotation rotation) { - execute(DriverCommand.SET_SCREEN_ROTATION, rotation.parameters()); - } - - - @Override - public void rotate(ScreenOrientation orientation) { - execute(DriverCommand.SET_SCREEN_ORIENTATION, - ImmutableMap.of("orientation", orientation.value().toUpperCase())); - } - /** * This method is used to add custom appium commands in Appium 2.0. * @@ -257,51 +180,10 @@ public void addCommand(HttpMethod httpMethod, String url, String methodName) { ((AppiumCommandExecutor) getCommandExecutor()).refreshAdditionalCommands(); } - @Override - public ScreenOrientation getOrientation() { - Response response = execute(DriverCommand.GET_SCREEN_ORIENTATION); - String orientation = response.getValue().toString().toLowerCase(); - if (orientation.equals(ScreenOrientation.LANDSCAPE.value())) { - return ScreenOrientation.LANDSCAPE; - } else if (orientation.equals(ScreenOrientation.PORTRAIT.value())) { - return ScreenOrientation.PORTRAIT; - } else { - throw new WebDriverException("Unexpected orientation returned: " + orientation); - } - } - - @Override - public Location location() { - return locationContext.location(); - } - - @Override - public void setLocation(Location location) { - locationContext.setLocation(location); - } - public URL getRemoteAddress() { return remoteAddress; } - @Override - public boolean isBrowser() { - String browserName = CapabilityHelpers.getCapability(getCapabilities(), - CapabilityType.BROWSER_NAME, String.class); - if (!isBlank(browserName)) { - try { - return (boolean) executeScript("return !!window.navigator;"); - } catch (WebDriverException ign) { - // ignore - } - } - try { - return !containsIgnoreCase(getContext(), "NATIVE_APP"); - } catch (WebDriverException e) { - return false; - } - } - @Override protected void startSession(Capabilities capabilities) { Response response = execute(new AppiumNewSessionCommandPayload(capabilities)); @@ -333,4 +215,14 @@ protected void startSession(Capabilities capabilities) { } setSessionId(response.getSessionId()); } + + @Override + public Response execute(String driverCommand, Map parameters) { + return super.execute(driverCommand, parameters); + } + + @Override + public Response execute(String command) { + return super.execute(command, ImmutableMap.of()); + } } diff --git a/src/main/java/io/appium/java_client/AppiumExecutionMethod.java b/src/main/java/io/appium/java_client/AppiumExecutionMethod.java index 3bab7980c..3abe1ef4f 100644 --- a/src/main/java/io/appium/java_client/AppiumExecutionMethod.java +++ b/src/main/java/io/appium/java_client/AppiumExecutionMethod.java @@ -24,9 +24,9 @@ import java.util.Map; public class AppiumExecutionMethod implements ExecuteMethod { - private final AppiumDriver driver; + private final AppiumDriver driver; - public AppiumExecutionMethod(AppiumDriver driver) { + public AppiumExecutionMethod(AppiumDriver driver) { this.driver = driver; } diff --git a/src/main/java/io/appium/java_client/DefaultGenericMobileDriver.java b/src/main/java/io/appium/java_client/DefaultGenericMobileDriver.java deleted file mode 100644 index e6d45f5f8..000000000 --- a/src/main/java/io/appium/java_client/DefaultGenericMobileDriver.java +++ /dev/null @@ -1,61 +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 com.google.common.collect.ImmutableMap; - -import org.openqa.selenium.By; -import org.openqa.selenium.Capabilities; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.CommandExecutor; -import org.openqa.selenium.remote.RemoteWebDriver; -import org.openqa.selenium.remote.Response; - -import java.util.List; -import java.util.Map; - -@SuppressWarnings({"unchecked", "rawtypes"}) -abstract class DefaultGenericMobileDriver extends RemoteWebDriver - implements MobileDriver { - - public DefaultGenericMobileDriver(CommandExecutor executor, Capabilities desiredCapabilities) { - super(executor, desiredCapabilities); - } - - @Override public Response execute(String driverCommand, Map parameters) { - return super.execute(driverCommand, parameters); - } - - @Override public Response execute(String command) { - return super.execute(command, ImmutableMap.of()); - } - - @Override public List findElements(By by) { - return super.findElements(by); - } - - @Override public T findElement(By by) { - return (T) super.findElement(by); - } - - @Override - public String toString() { - Capabilities capabilities = getCapabilities(); - return String.format("%s, Capabilities: %s", getClass().getCanonicalName(), - capabilities != null ? capabilities.asMap().toString() : "null"); - } -} diff --git a/src/main/java/io/appium/java_client/DefaultGenericMobileElement.java b/src/main/java/io/appium/java_client/DefaultGenericMobileElement.java deleted file mode 100644 index 6e1bfc64a..000000000 --- a/src/main/java/io/appium/java_client/DefaultGenericMobileElement.java +++ /dev/null @@ -1,49 +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 com.google.common.collect.ImmutableMap; - -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriverException; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.RemoteWebElement; -import org.openqa.selenium.remote.Response; - -import java.util.List; -import java.util.Map; - -@SuppressWarnings({"unchecked", "rawtypes"}) -abstract class DefaultGenericMobileElement extends RemoteWebElement implements ExecutesMethod { - - @Override public Response execute(String driverCommand, Map parameters) { - return super.execute(driverCommand, parameters); - } - - @Override public Response execute(String command) { - return super.execute(command, ImmutableMap.of()); - } - - @Override public List findElements(By by) { - return super.findElements(by); - } - - @Override public T findElement(By by) { - return (T) super.findElement(by); - } - -} diff --git a/src/main/java/io/appium/java_client/HasBrowserCheck.java b/src/main/java/io/appium/java_client/HasBrowserCheck.java new file mode 100644 index 000000000..efa5c6c62 --- /dev/null +++ b/src/main/java/io/appium/java_client/HasBrowserCheck.java @@ -0,0 +1,44 @@ +package io.appium.java_client; + +import com.google.common.collect.ImmutableMap; +import io.appium.java_client.internal.CapabilityHelpers; +import org.openqa.selenium.ContextAware; +import org.openqa.selenium.HasCapabilities; +import org.openqa.selenium.WebDriverException; +import org.openqa.selenium.remote.CapabilityType; + +import java.util.Collections; + +import static org.apache.commons.lang3.StringUtils.containsIgnoreCase; +import static org.apache.commons.lang3.StringUtils.isBlank; +import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT; + +public interface HasBrowserCheck extends ExecutesMethod, HasCapabilities { + /** + * Validates if the driver is currently in a web browser context. + * + * @return true or false. + */ + default boolean isBrowser() { + String browserName = CapabilityHelpers.getCapability(getCapabilities(), + CapabilityType.BROWSER_NAME, String.class); + if (!isBlank(browserName)) { + try { + return (boolean) execute(EXECUTE_SCRIPT, ImmutableMap.of( + "script", "return !!window.navigator;", + "args", Collections.emptyList() + )).getValue(); + } catch (WebDriverException ign) { + // ignore + } + } + if (!(this instanceof ContextAware)) { + return false; + } + try { + return !containsIgnoreCase(((ContextAware) this).getContext(), "NATIVE_APP"); + } catch (WebDriverException e) { + return false; + } + } +} diff --git a/src/main/java/io/appium/java_client/HasSessionDetails.java b/src/main/java/io/appium/java_client/HasSessionDetails.java deleted file mode 100644 index 1ae3f9f80..000000000 --- a/src/main/java/io/appium/java_client/HasSessionDetails.java +++ /dev/null @@ -1,104 +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 static io.appium.java_client.MobileCommand.GET_ALLSESSION; -import static io.appium.java_client.MobileCommand.GET_SESSION; -import static java.util.Optional.ofNullable; -import static java.util.stream.Collectors.toMap; -import static org.apache.commons.lang3.StringUtils.isBlank; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; - -import org.openqa.selenium.remote.Response; - -import java.util.List; -import java.util.Map; -import javax.annotation.Nullable; - -public interface HasSessionDetails extends ExecutesMethod { - /** - * The current session details. - * - * @return a map with values that hold session details. - */ - @SuppressWarnings("unchecked") - default Map getSessionDetails() { - Response response = execute(GET_SESSION); - Map resultMap = Map.class.cast(response.getValue()); - - //this filtering was added to clear returned result. - //results of further operations should be simply interpreted by users - return ImmutableMap.builder() - .putAll(resultMap.entrySet() - .stream().filter(entry -> { - String key = entry.getKey(); - Object value = entry.getValue(); - return !isBlank(key) - && value != null - && !isBlank(String.valueOf(value)); - }).collect(toMap(Map.Entry::getKey, Map.Entry::getValue))).build(); - } - - default @Nullable Object getSessionDetail(String detail) { - return getSessionDetails().get(detail); - } - - /** - * The current mobile platform. - * - * @return name of the current mobile platform. - */ - default @Nullable String getPlatformName() { - Object platformName = ofNullable(getSessionDetail("platformName")) - .orElseGet(() -> getSessionDetail("platform")); - return ofNullable(platformName).map(String::valueOf).orElse(null); - } - - /** - * The current automation name. - * - * @return current automation name. - */ - default @Nullable String getAutomationName() { - return ofNullable(getSessionDetail("automationName")) - .map(String::valueOf).orElse(null); - } - - /** - * Checks if focus is on browser. - * - * @return is focus on browser or on native content. - */ - default boolean isBrowser() { - return ofNullable(getSessionDetail("browserName")) - .orElse(null) != null; - } - - /** - * Get All Sessions details. - * - * @return List of Map objects with All Session Details. - */ - @SuppressWarnings("unchecked") - default List> getAllSessionDetails() { - Response response = execute(GET_ALLSESSION); - List> resultSet = List.class.cast(response.getValue()); - return ImmutableList.>builder().addAll(resultSet).build(); - } -} diff --git a/src/main/java/io/appium/java_client/MobileElement.java b/src/main/java/io/appium/java_client/MobileElement.java deleted file mode 100644 index 45c932b12..000000000 --- a/src/main/java/io/appium/java_client/MobileElement.java +++ /dev/null @@ -1,57 +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 com.google.common.collect.ImmutableMap; - -import org.openqa.selenium.By; -import org.openqa.selenium.Dimension; -import org.openqa.selenium.Point; -import org.openqa.selenium.remote.FileDetector; - -import java.util.List; - -@SuppressWarnings({"unchecked"}) -public abstract class MobileElement - extends DefaultGenericMobileElement { - - /** - * Method returns central coordinates of an element. - * @return The instance of the {@link org.openqa.selenium.Point} - */ - public Point getCenter() { - Point upperLeft = this.getLocation(); - Dimension dimensions = this.getSize(); - return new Point(upperLeft.getX() + dimensions.getWidth() / 2, - upperLeft.getY() + dimensions.getHeight() / 2); - } - - @Override public List findElements(By by) { - return super.findElements(by); - } - - /** - * This method sets the new value of the attribute "value". - * - * @param value is the new value which should be set - */ - public void setValue(String value) { - ImmutableMap.Builder builder = ImmutableMap.builder(); - builder.put("id", id).put("value", value); - execute(MobileCommand.SET_VALUE, builder.build()); - } -} 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 be4bd8e3d..a570e2832 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -26,20 +26,29 @@ import io.appium.java_client.AppiumDriver; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecuteCDPCommand; +import io.appium.java_client.HasAppStrings; +import io.appium.java_client.HasDeviceTime; import io.appium.java_client.HasOnScreenKeyboard; +import io.appium.java_client.HidesKeyboard; +import io.appium.java_client.InteractsWithApps; +import io.appium.java_client.InteractsWithFiles; import io.appium.java_client.LocksDevice; +import io.appium.java_client.PerformsTouchActions; 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; +import io.appium.java_client.remote.SupportsContextSwitching; +import io.appium.java_client.remote.SupportsLocation; +import io.appium.java_client.remote.SupportsRotation; import io.appium.java_client.screenrecording.CanRecordScreen; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; import io.appium.java_client.ws.StringWebSocketClient; import org.openqa.selenium.Capabilities; -import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.HttpCommandExecutor; +import org.openqa.selenium.remote.html5.RemoteLocationContext; import org.openqa.selenium.remote.http.HttpClient; import java.net.URL; @@ -48,21 +57,35 @@ /** * Android driver implementation. - * - * @param the required type of class which implement {@link org.openqa.selenium.WebElement}. - * Instances of the defined type will be returned via findElement* and findElements*. - * Warning (!!!). Allowed types: - * {@link org.openqa.selenium.WebElement} - * {@link org.openqa.selenium.remote.RemoteWebElement} - * {@link io.appium.java_client.MobileElement} - * {@link io.appium.java_client.android.AndroidElement} */ -public class AndroidDriver - extends AppiumDriver - implements PressesKey, HasNetworkConnection, PushesFiles, StartsActivity,LocksDevice, HasAndroidSettings, - HasAndroidDeviceDetails, HasSupportedPerformanceDataType, AuthenticatesByFinger, HasOnScreenKeyboard, - CanRecordScreen, SupportsSpecialEmulatorCommands, SupportsNetworkStateManagement, ListensToLogcatMessages, - HasAndroidClipboard, HasBattery, ExecuteCDPCommand, SupportsExtendedGeolocationCommands { +public class AndroidDriver extends AppiumDriver + implements PressesKey, + SupportsRotation, + SupportsContextSwitching, + SupportsLocation, + PerformsTouchActions, + HidesKeyboard, + HasDeviceTime, + InteractsWithFiles, + InteractsWithApps, + HasAppStrings, + 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; @@ -196,6 +219,11 @@ public AndroidBatteryInfo getBatteryInfo() { "script", "mobile: batteryInfo", "args", Collections.emptyList())).getValue()); } + @Override + public RemoteLocationContext getLocationContext() { + return locationContext; + } + @Override public synchronized StringWebSocketClient getLogcatClient() { if (logcatClient == null) { diff --git a/src/main/java/io/appium/java_client/android/AndroidElement.java b/src/main/java/io/appium/java_client/android/AndroidElement.java deleted file mode 100644 index 5c1231c24..000000000 --- a/src/main/java/io/appium/java_client/android/AndroidElement.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.android; - -import static io.appium.java_client.android.AndroidMobileCommandHelper.replaceElementValueCommand; - -import io.appium.java_client.CommandExecutionHelper; -import io.appium.java_client.MobileElement; - -public class AndroidElement extends MobileElement { - /** - * This method replace current text value. - * @param value a new value - */ - public void replaceValue(String value) { - CommandExecutionHelper.execute(this, replaceElementValueCommand(this, value)); - } -} diff --git a/src/main/java/io/appium/java_client/internal/ElementMap.java b/src/main/java/io/appium/java_client/internal/ElementMap.java deleted file mode 100644 index d2f056c5d..000000000 --- a/src/main/java/io/appium/java_client/internal/ElementMap.java +++ /dev/null @@ -1,90 +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.internal; - -import static org.apache.commons.lang3.StringUtils.isBlank; - -import com.google.common.collect.ImmutableMap; - -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; -import org.openqa.selenium.remote.RemoteWebElement; - -import java.util.Map; -import java.util.Optional; - -public enum ElementMap { - ANDROID_UIAUTOMATOR2(AutomationName.ANDROID_UIAUTOMATOR2.toLowerCase(), AndroidElement.class), - SELENDROID(AutomationName.SELENDROID.toLowerCase(), AndroidElement.class), - 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), - MAC(MobilePlatform.MAC.toLowerCase(), Mac2Element.class); - - private static final Map mobileElementMap; - - static { - ImmutableMap.Builder builder = ImmutableMap.builder(); - for (ElementMap e:values()) { - builder.put(e.getPlatformOrAutomation(), e); - } - mobileElementMap = builder.build(); - } - - private final String platformOrAutomation; - private final Class elementClass; - - ElementMap(String platformOrAutomation, Class elementClass) { - this.platformOrAutomation = platformOrAutomation; - this.elementClass = elementClass; - } - - public String getPlatformOrAutomation() { - return platformOrAutomation; - } - - public Class getElementClass() { - return elementClass; - } - - /** - * Gets element class by {@code platform} and mobile {@code automation} type. - * - * @param platform is the mobile platform. See {@link MobilePlatform}. - * @param automation is the mobile automation type. See {@link AutomationName} - * @return subclass of {@link RemoteWebElement} that convenient to current session details. - */ - public static Class getElementClass(String platform, String automation) { - if (isBlank(platform) && isBlank(automation)) { - return RemoteWebElement.class; - } - ElementMap element = Optional.ofNullable(mobileElementMap.get( - String.valueOf(platform).toLowerCase().trim())) - .orElseGet(() -> mobileElementMap - .get(String.valueOf(automation).toLowerCase().trim())); - if (element == null) { - return RemoteWebElement.class; - } - return element.getElementClass(); - } -} diff --git a/src/main/java/io/appium/java_client/internal/JsonToMobileElementConverter.java b/src/main/java/io/appium/java_client/internal/JsonToMobileElementConverter.java deleted file mode 100644 index d69e39312..000000000 --- a/src/main/java/io/appium/java_client/internal/JsonToMobileElementConverter.java +++ /dev/null @@ -1,84 +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.internal; - -import static io.appium.java_client.internal.ElementMap.getElementClass; - -import io.appium.java_client.remote.MobileCapabilityType; -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 java.lang.reflect.Constructor; - -/** - * Reconstitutes {@link org.openqa.selenium.WebElement}s from their JSON representation. Will recursively convert Lists - * and Maps to catch nested references. All other values pass through the converter unchanged. - */ -public class JsonToMobileElementConverter extends JsonToWebElementConverter { - - protected final RemoteWebDriver driver; - - private final String platform; - private final String automation; - - /** - * Creates a new instance based on {@code driver} and object with session details. - * - * @param driver an instance of {@link RemoteWebDriver} subclass - */ - public JsonToMobileElementConverter(RemoteWebDriver driver) { - super(driver); - this.driver = driver; - Capabilities caps = driver.getCapabilities(); - this.platform = CapabilityHelpers.getCapability(caps, CapabilityType.PLATFORM_NAME, String.class); - this.automation = CapabilityHelpers.getCapability(caps, MobileCapabilityType.AUTOMATION_NAME, String.class); - } - - @Override - public Object apply(Object result) { - Object toBeReturned = result; - if (toBeReturned instanceof RemoteWebElement) { - toBeReturned = newRemoteWebElement(); - ((RemoteWebElement) toBeReturned).setId(((RemoteWebElement) result).getId()); - } - - return super.apply(toBeReturned); - } - - @Override - protected RemoteWebElement newRemoteWebElement() { - Class target; - target = getElementClass(platform, automation); - - try { - Constructor constructor = target.getDeclaredConstructor(); - constructor.setAccessible(true); - RemoteWebElement result = constructor.newInstance(); - - result.setParent(driver); - result.setFileDetector(driver.getFileDetector()); - - return result; - } catch (Exception e) { - throw new WebDriverException(e); - } - } -} 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 ffd4a8a0c..70fe3c46d 100644 --- a/src/main/java/io/appium/java_client/ios/IOSDriver.java +++ b/src/main/java/io/appium/java_client/ios/IOSDriver.java @@ -22,21 +22,30 @@ import com.google.common.collect.ImmutableMap; import io.appium.java_client.AppiumDriver; +import io.appium.java_client.HasAppStrings; +import io.appium.java_client.HasDeviceTime; import io.appium.java_client.HasOnScreenKeyboard; +import io.appium.java_client.HidesKeyboard; import io.appium.java_client.HidesKeyboardWithKeyName; +import io.appium.java_client.InteractsWithApps; +import io.appium.java_client.InteractsWithFiles; import io.appium.java_client.LocksDevice; +import io.appium.java_client.PerformsTouchActions; import io.appium.java_client.battery.HasBattery; import io.appium.java_client.remote.MobilePlatform; +import io.appium.java_client.remote.SupportsContextSwitching; +import io.appium.java_client.remote.SupportsLocation; +import io.appium.java_client.remote.SupportsRotation; import io.appium.java_client.screenrecording.CanRecordScreen; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; import io.appium.java_client.ws.StringWebSocketClient; import org.openqa.selenium.Alert; import org.openqa.selenium.Capabilities; -import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.DriverCommand; import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.Response; +import org.openqa.selenium.remote.html5.RemoteLocationContext; import org.openqa.selenium.remote.http.HttpClient; import java.net.URL; @@ -46,19 +55,27 @@ /** * iOS driver implementation. * - * @param the required type of class which implement - * {@link org.openqa.selenium.WebElement}. - * Instances of the defined type will be returned via findElement* and findElements*. - * Warning (!!!). Allowed types: - * {@link org.openqa.selenium.WebElement} - * {@link org.openqa.selenium.remote.RemoteWebElement} - * {@link io.appium.java_client.MobileElement} - * {@link io.appium.java_client.ios.IOSElement} */ -public class IOSDriver - extends AppiumDriver - implements HidesKeyboardWithKeyName, ShakesDevice, HasIOSSettings, HasOnScreenKeyboard, LocksDevice, - PerformsTouchID, PushesFiles, CanRecordScreen, HasIOSClipboard, ListensToSyslogMessages, +public class IOSDriver extends AppiumDriver implements + SupportsContextSwitching, + SupportsRotation, + SupportsLocation, + HidesKeyboard, + HasDeviceTime, + InteractsWithFiles, + InteractsWithApps, + HasAppStrings, + PerformsTouchActions, + HidesKeyboardWithKeyName, + ShakesDevice, + HasIOSSettings, + HasOnScreenKeyboard, + LocksDevice, + PerformsTouchID, + PushesFiles, + CanRecordScreen, + HasIOSClipboard, + ListensToSyslogMessages, HasBattery { private static final String IOS_DEFAULT_PLATFORM = MobilePlatform.IOS; @@ -208,6 +225,11 @@ class IOSAlert implements Alert { } + @Override + public RemoteLocationContext getLocationContext() { + return locationContext; + } + @Override public synchronized StringWebSocketClient getSyslogClient() { if (syslogClient == null) { diff --git a/src/main/java/io/appium/java_client/ios/IOSElement.java b/src/main/java/io/appium/java_client/ios/IOSElement.java deleted file mode 100644 index 55aa47110..000000000 --- a/src/main/java/io/appium/java_client/ios/IOSElement.java +++ /dev/null @@ -1,22 +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.ios; - -import io.appium.java_client.MobileElement; - -public class IOSElement extends MobileElement { -} 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 215c28971..4808f8f5e 100644 --- a/src/main/java/io/appium/java_client/mac/Mac2Driver.java +++ b/src/main/java/io/appium/java_client/mac/Mac2Driver.java @@ -44,7 +44,7 @@ * * @since Appium 1.20.0 */ -public class Mac2Driver extends AppiumDriver implements CanRecordScreen, 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 deleted file mode 100644 index e41042e8d..000000000 --- a/src/main/java/io/appium/java_client/mac/Mac2Element.java +++ /dev/null @@ -1,22 +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.MobileElement; - -public class Mac2Element extends MobileElement { -} diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java index 1d2b9caa0..ea3b35e5a 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java @@ -16,21 +16,16 @@ package io.appium.java_client.pagefactory; -import static io.appium.java_client.internal.ElementMap.getElementClass; import static io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy; import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.unpackWebDriverFromSearchContext; import static java.time.Duration.ofSeconds; import com.google.common.collect.ImmutableList; -import io.appium.java_client.MobileElement; -import io.appium.java_client.android.AndroidElement; import io.appium.java_client.internal.CapabilityHelpers; -import io.appium.java_client.ios.IOSElement; import io.appium.java_client.pagefactory.bys.ContentType; import io.appium.java_client.pagefactory.locator.CacheableLocator; import io.appium.java_client.remote.MobileCapabilityType; -import io.appium.java_client.windows.WindowsElement; import org.openqa.selenium.Capabilities; import org.openqa.selenium.HasCapabilities; import org.openqa.selenium.SearchContext; @@ -60,15 +55,13 @@ * {@literal @AndroidFindBy}, {@literal @AndroidFindBys}, or * {@literal @iOSFindBy/@iOSFindBys} annotation with a proxy that locates the * elements using the passed in ElementLocatorFactory. - * Please pay attention: fields of {@link WebElement}, {@link RemoteWebElement}, - * {@link MobileElement}, {@link AndroidElement} and {@link IOSElement} are allowed + * Please pay attention: fields of {@link WebElement} or {@link RemoteWebElement} * to use with this decorator */ public class AppiumFieldDecorator implements FieldDecorator { private static final List> availableElementClasses = ImmutableList.of(WebElement.class, - RemoteWebElement.class, MobileElement.class, AndroidElement.class, - IOSElement.class, WindowsElement.class); + RemoteWebElement.class); public static final Duration DEFAULT_WAITING_TIMEOUT = ofSeconds(1); private final WebDriver webDriver; private final DefaultFieldDecorator defaultElementFieldDecoracor; @@ -213,6 +206,6 @@ private Object decorateWidget(Field field) { private WebElement proxyForAnElement(ElementLocator locator) { ElementInterceptor elementInterceptor = new ElementInterceptor(locator, webDriver); - return getEnhancedProxy(getElementClass(platform, automation), elementInterceptor); + return getEnhancedProxy(RemoteWebElement.class, elementInterceptor); } } diff --git a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java index b15ee6775..e11aa2e4d 100644 --- a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java +++ b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java @@ -21,7 +21,7 @@ import static java.util.Optional.ofNullable; import static org.apache.commons.lang3.StringUtils.containsIgnoreCase; -import io.appium.java_client.HasSessionDetails; +import io.appium.java_client.HasBrowserCheck; import io.appium.java_client.pagefactory.bys.ContentType; import org.openqa.selenium.ContextAware; import org.openqa.selenium.SearchContext; @@ -72,7 +72,7 @@ public static WebDriver unpackWebDriverFromSearchContext(SearchContext searchCon * {@link WebDriver} or {@link org.openqa.selenium.WebElement} or some other * user's extension/implementation. * Note: if you want to use your own implementation then it should - * implement {@link ContextAware} or {@link WrapsDriver} or {@link HasSessionDetails} + * implement {@link ContextAware} or {@link WrapsDriver} or {@link HasBrowserCheck} * @return current content type. It depends on current context. If current context is * NATIVE_APP it will return {@link ContentType#NATIVE_MOBILE_SPECIFIC}. * {@link ContentType#HTML_OR_DEFAULT} will be returned if the current context is WEB_VIEW. @@ -81,12 +81,8 @@ public static WebDriver unpackWebDriverFromSearchContext(SearchContext searchCon */ public static ContentType getCurrentContentType(SearchContext context) { return ofNullable(unpackWebDriverFromSearchContext(context)).map(driver -> { - if (HasSessionDetails.class.isAssignableFrom(driver.getClass())) { - HasSessionDetails hasSessionDetails = (HasSessionDetails) driver; - - if (!hasSessionDetails.isBrowser()) { - return NATIVE_MOBILE_SPECIFIC; - } + if (driver instanceof HasBrowserCheck && !((HasBrowserCheck) driver).isBrowser()) { + return NATIVE_MOBILE_SPECIFIC; } if (ContextAware.class.isAssignableFrom(driver.getClass())) { //it is desktop browser diff --git a/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java b/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java new file mode 100644 index 000000000..7f5f79956 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java @@ -0,0 +1,81 @@ +/* + * 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.remote; + +import com.google.common.collect.ImmutableMap; +import io.appium.java_client.ExecutesMethod; +import io.appium.java_client.NoSuchContextException; +import org.openqa.selenium.ContextAware; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebDriverException; +import org.openqa.selenium.remote.DriverCommand; +import org.openqa.selenium.remote.Response; + +import javax.annotation.Nullable; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import static com.google.common.base.Preconditions.checkNotNull; + +public interface SupportsContextSwitching extends WebDriver, ContextAware, ExecutesMethod { + /** + * Switches to the given context. + * + * @param name The name of the context to switch to. + * @return self instance for chaining. + */ + default WebDriver context(String name) { + checkNotNull(name, "Must supply a context name"); + try { + execute(DriverCommand.SWITCH_TO_CONTEXT, ImmutableMap.of("name", name)); + return this; + } catch (WebDriverException e) { + throw new NoSuchContextException(e.getMessage(), e); + } + } + + /** + * Get the names of available contexts. + * + * @return List list of context names. + */ + default Set getContextHandles() { + Response response = execute(DriverCommand.GET_CONTEXT_HANDLES, ImmutableMap.of()); + Object value = response.getValue(); + try { + //noinspection unchecked + List returnedValues = (List) value; + return new LinkedHashSet<>(returnedValues); + } catch (ClassCastException ex) { + throw new WebDriverException( + "Returned value cannot be converted to List: " + value, ex); + } + } + + /** + * Get the name of the current context. + * + * @return Context name or null if it cannot be determined. + */ + @Nullable + default String getContext() { + String contextName = + String.valueOf(execute(DriverCommand.GET_CURRENT_CONTEXT_HANDLE).getValue()); + return "null".equalsIgnoreCase(contextName) ? null : contextName; + } +} diff --git a/src/main/java/io/appium/java_client/MobileDriver.java b/src/main/java/io/appium/java_client/remote/SupportsLocation.java similarity index 59% rename from src/main/java/io/appium/java_client/MobileDriver.java rename to src/main/java/io/appium/java_client/remote/SupportsLocation.java index 708f3b8f0..b2211dfda 100644 --- a/src/main/java/io/appium/java_client/MobileDriver.java +++ b/src/main/java/io/appium/java_client/remote/SupportsLocation.java @@ -14,22 +14,21 @@ * limitations under the License. */ -package io.appium.java_client; +package io.appium.java_client.remote; -import org.openqa.selenium.By; -import org.openqa.selenium.ContextAware; -import org.openqa.selenium.Rotatable; import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; +import org.openqa.selenium.html5.Location; import org.openqa.selenium.html5.LocationContext; +import org.openqa.selenium.remote.html5.RemoteLocationContext; -import java.util.List; +public interface SupportsLocation extends WebDriver, LocationContext { + public RemoteLocationContext getLocationContext(); -public interface MobileDriver extends WebDriver, PerformsTouchActions, ContextAware, Rotatable, - LocationContext, HidesKeyboard, HasDeviceTime, InteractsWithFiles, InteractsWithApps, HasAppStrings, ExecutesMethod, - HasSessionDetails { + default Location location() { + return getLocationContext().location(); + } - List findElements(By by); - - T findElement(By by); + default void setLocation(Location location) { + getLocationContext().setLocation(location); + } } diff --git a/src/main/java/io/appium/java_client/remote/SupportsRotation.java b/src/main/java/io/appium/java_client/remote/SupportsRotation.java new file mode 100644 index 000000000..8cccb8f16 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/SupportsRotation.java @@ -0,0 +1,73 @@ +/* + * 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.remote; + +import com.google.common.collect.ImmutableMap; +import io.appium.java_client.ExecutesMethod; +import org.openqa.selenium.DeviceRotation; +import org.openqa.selenium.Rotatable; +import org.openqa.selenium.ScreenOrientation; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebDriverException; +import org.openqa.selenium.remote.DriverCommand; +import org.openqa.selenium.remote.Response; + +import java.util.Map; + +public interface SupportsRotation extends WebDriver, ExecutesMethod, Rotatable { + /** + * Get device rotation. + * + * @return The rotation value. + */ + default DeviceRotation rotation() { + Response response = execute(DriverCommand.GET_SCREEN_ROTATION); + //noinspection unchecked + DeviceRotation deviceRotation = + new DeviceRotation((Map) response.getValue()); + if (deviceRotation.getX() < 0 || deviceRotation.getY() < 0 || deviceRotation.getZ() < 0) { + throw new WebDriverException("Unexpected orientation returned: " + deviceRotation); + } + return deviceRotation; + } + + default void rotate(DeviceRotation rotation) { + execute(DriverCommand.SET_SCREEN_ROTATION, rotation.parameters()); + } + + default void rotate(ScreenOrientation orientation) { + execute(DriverCommand.SET_SCREEN_ORIENTATION, + ImmutableMap.of("orientation", orientation.value().toUpperCase())); + } + + /** + * Get device orientation. + * + * @return The orientation value. + */ + default ScreenOrientation getOrientation() { + Response response = execute(DriverCommand.GET_SCREEN_ORIENTATION); + String orientation = response.getValue().toString().toLowerCase(); + if (orientation.equals(ScreenOrientation.LANDSCAPE.value())) { + return ScreenOrientation.LANDSCAPE; + } else if (orientation.equals(ScreenOrientation.PORTRAIT.value())) { + return ScreenOrientation.PORTRAIT; + } else { + throw new WebDriverException("Unexpected orientation returned: " + orientation); + } + } +} 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 cf89449de..e96bd4121 100644 --- a/src/main/java/io/appium/java_client/windows/WindowsDriver.java +++ b/src/main/java/io/appium/java_client/windows/WindowsDriver.java @@ -30,8 +30,10 @@ import java.net.URL; -public class WindowsDriver - extends AppiumDriver implements PressesKeyCode, HidesKeyboardWithKeyName, CanRecordScreen { +public class WindowsDriver 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 deleted file mode 100644 index ad5d3a5d8..000000000 --- a/src/main/java/io/appium/java_client/windows/WindowsElement.java +++ /dev/null @@ -1,22 +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.windows; - -import io.appium.java_client.MobileElement; - -public class WindowsElement extends MobileElement { -} diff --git a/src/main/java/org/openqa/selenium/SearchContext.java b/src/main/java/org/openqa/selenium/SearchContext.java deleted file mode 100644 index d6498972e..000000000 --- a/src/main/java/org/openqa/selenium/SearchContext.java +++ /dev/null @@ -1,43 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. 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 org.openqa.selenium; - -import java.util.List; - -public interface SearchContext { - /** - * Find all elements within the current context using the given mechanism. - * - * @param The type of the resulting elements. - * @param by The locating mechanism to use - * @return A list of all {@link WebElement}s, or an empty list if nothing matches - * @see org.openqa.selenium.By - */ - List findElements(By by); - - - /** - * Find the first {@link WebElement} using the given method. - * - * @param The type of the resulting element. - * @param by The locating mechanism - * @return The first matching element on the current context - * @throws NoSuchElementException If no matching elements are found - */ - T findElement(By by); -} diff --git a/src/main/java/org/openqa/selenium/WebDriver.java b/src/main/java/org/openqa/selenium/WebDriver.java deleted file mode 100644 index c8f990896..000000000 --- a/src/main/java/org/openqa/selenium/WebDriver.java +++ /dev/null @@ -1,757 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. 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 org.openqa.selenium; - -import org.openqa.selenium.logging.LoggingPreferences; -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; - - -/** - * WebDriver is a remote control interface that enables introspection and control of user agents - * (browsers). The methods in this interface fall into three categories: - *
    - *
  • Control of the browser itself
  • - *
  • Selection of {@link WebElement}s
  • - *
  • Debugging aids
  • - *
- *

- * Key methods are {@link WebDriver#get(String)}, which is used to load a new web page, and the - * various methods similar to {@link WebDriver#findElement(By)}, which is used to find - * {@link WebElement}s. - *

- * Currently, you will need to instantiate implementations of this interface directly. It is hoped - * that you write your tests against this interface so that you may "swap in" a more fully featured - * browser when there is a requirement for one. - *

- * Most implementations of this interface follow - * W3C WebDriver specification - */ -public interface WebDriver extends SearchContext { - // Navigation - - /** - * Load a new web page in the current browser window. This is done using an HTTP POST operation, - * and the method will block until the load is complete (with the default 'page load strategy'. - * This will follow redirects issued either by the server or as a meta-redirect from within the - * returned HTML. Should a meta-redirect "rest" for any duration of time, it is best to wait until - * this timeout is over, since should the underlying page change whilst your test is executing the - * results of future calls against this interface will be against the freshly loaded page. Synonym - * for {@link org.openqa.selenium.WebDriver.Navigation#to(String)}. - *

- * See W3C WebDriver specification - * for more details. - * - * @param url The URL to load. Must be a fully qualified URL - * @see org.openqa.selenium.PageLoadStrategy - */ - void get(String url); - - /** - * Get a string representing the current URL that the browser is looking at. - *

- * See W3C WebDriver specification - * for more details. - * - * @return The URL of the page currently loaded in the browser - */ - String getCurrentUrl(); - - // General properties - - /** - * Get the title of the current page. - *

- * See W3C WebDriver specification - * for more details. - * - * @return The title of the current page, with leading and trailing whitespace stripped, or null - * if one is not already set - */ - String getTitle(); - - /** - * Find all elements within the current page using the given mechanism. - * This method is affected by the 'implicit wait' times in force at the time of execution. When - * implicitly waiting, this method will return as soon as there are more than 0 items in the - * found collection, or will return an empty list if the timeout is reached. - *

- * See W3C WebDriver specification - * for more details. - * - * @param by The locating mechanism to use - * @return A list of all matching {@link WebElement}s, or an empty list if nothing matches - * @see org.openqa.selenium.By - * @see org.openqa.selenium.WebDriver.Timeouts - */ - @Override - List findElements(By by); - - - /** - * Find the first {@link WebElement} using the given method. - * This method is affected by the 'implicit wait' times in force at the time of execution. - * The findElement(..) invocation will return a matching row, or try again repeatedly until - * the configured timeout is reached. - *

- * findElement should not be used to look for non-present elements, use {@link #findElements(By)} - * and assert zero length response instead. - *

- * See W3C WebDriver specification - * for more details. - * - * @param by The locating mechanism to use - * @return The first matching element on the current page - * @throws NoSuchElementException If no matching elements are found - * @see org.openqa.selenium.By - * @see org.openqa.selenium.WebDriver.Timeouts - */ - @Override - T findElement(By by); - - // Misc - - /** - * Get the source of the last loaded page. If the page has been modified after loading (for - * example, by Javascript) there is no guarantee that the returned text is that of the modified - * page. Please consult the documentation of the particular driver being used to determine whether - * the returned text reflects the current state of the page or the text last sent by the web - * server. The page source returned is a representation of the underlying DOM: do not expect it to - * be formatted or escaped in the same way as the response sent from the web server. Think of it - * as an artist's impression. - *

- * See W3C WebDriver specification - * for more details. - * - * @return The source of the current page - */ - String getPageSource(); - - /** - * Close the current window, quitting the browser if it's the last window currently open. - *

- * See W3C WebDriver specification - * for more details. - */ - void close(); - - /** - * Quits this driver, closing every associated window. - */ - void quit(); - - /** - * Return a set of window handles which can be used to iterate over all open windows of this - * WebDriver instance by passing them to {@link #switchTo()}.{@link Options#window()} - *

- * See W3C WebDriver specification - * for more details. - * - * @return A set of window handles which can be used to iterate over all open windows. - */ - Set getWindowHandles(); - - /** - * Return an opaque handle to this window that uniquely identifies it within this driver instance. - * This can be used to switch to this window at a later date - *

- * See W3C WebDriver specification - * for more details. - * - * @return the current window handle - */ - String getWindowHandle(); - - /** - * Send future commands to a different frame or window. - * - * @return A TargetLocator which can be used to select a frame or window - * @see org.openqa.selenium.WebDriver.TargetLocator - */ - TargetLocator switchTo(); - - /** - * An abstraction allowing the driver to access the browser's history and to navigate to a given - * URL. - * - * @return A {@link org.openqa.selenium.WebDriver.Navigation} that allows the selection of what to - * do next - */ - Navigation navigate(); - - /** - * Gets the Option interface - * - * @return An option interface - * @see org.openqa.selenium.WebDriver.Options - */ - Options manage(); - - /** - * An interface for managing stuff you would do in a browser menu - */ - interface Options { - - /** - * Add a specific cookie. If the cookie's domain name is left blank, it is assumed that the - * cookie is meant for the domain of the current document. - *

- * See W3C WebDriver specification - * for more details. - * - * @param cookie The cookie to add. - */ - void addCookie(Cookie cookie); - - /** - * Delete the named cookie from the current domain. This is equivalent to setting the named - * cookie's expiry date to some time in the past. - *

- * See W3C WebDriver specification - * for more details. - * - * @param name The name of the cookie to delete - */ - void deleteCookieNamed(String name); - - /** - * Delete a cookie from the browser's "cookie jar". The domain of the cookie will be ignored. - * - * @param cookie nom nom nom - */ - void deleteCookie(Cookie cookie); - - /** - * Delete all the cookies for the current domain. - *

- * See W3C WebDriver specification - * for more details. - */ - void deleteAllCookies(); - - /** - * Get all the cookies for the current domain. - *

- * See W3C WebDriver specification - * for more details. - * - * @return A Set of cookies for the current domain. - */ - Set getCookies(); - - /** - * Get a cookie with a given name. - *

- * See W3C WebDriver specification - * for more details. - * - * @param name the name of the cookie - * @return the cookie, or null if no cookie with the given name is present - */ - Cookie getCookieNamed(String name); - - /** - * @return the interface for managing driver timeouts. - */ - Timeouts timeouts(); - - /** - * @return the interface for controlling IME engines to generate complex-script input. - */ - ImeHandler ime(); - - /** - * @return the interface for managing the current window. - */ - Window window(); - - /** - * Gets the {@link Logs} interface used to fetch different types of logs. - *

- * To set the logging preferences {@link LoggingPreferences}. - * - * @return A Logs interface. - */ - @Beta - Logs logs(); - } - - /** - * An interface for managing timeout behavior for WebDriver instances. - *

- * See W3C WebDriver specification - * for more details. - */ - interface Timeouts { - - /** - * @deprecated Use {@link #implicitlyWait(Duration)} - * - * Specifies the amount of time the driver should wait when searching for an element if it is - * not immediately present. - *

- * When searching for a single element, the driver should poll the page until the element has - * been found, or this timeout expires before throwing a {@link NoSuchElementException}. When - * searching for multiple elements, the driver should poll the page until at least one element - * has been found or this timeout has expired. - *

- * Increasing the implicit wait timeout should be used judiciously as it will have an adverse - * effect on test run time, especially when used with slower location strategies like XPath. - *

- * If the timeout is negative, not null, or greater than 2e16 - 1, an error code with invalid - * argument will be returned. - * - * @param time The amount of time to wait. - * @param unit The unit of measure for {@code time}. - * @return A self reference. - */ - @Deprecated - Timeouts implicitlyWait(long time, TimeUnit unit); - - /** - * Specifies the amount of time the driver should wait when searching for an element if it is - * not immediately present. - *

- * When searching for a single element, the driver should poll the page until the element has - * been found, or this timeout expires before throwing a {@link NoSuchElementException}. When - * searching for multiple elements, the driver should poll the page until at least one element - * has been found or this timeout has expired. - *

- * Increasing the implicit wait timeout should be used judiciously as it will have an adverse - * effect on test run time, especially when used with slower location strategies like XPath. - *

- * If the timeout is negative, not null, or greater than 2e16 - 1, an error code with invalid - * argument will be returned. - * - * @param duration The duration to wait. - * @return A self reference. - */ - default Timeouts implicitlyWait(Duration duration) { - return implicitlyWait(duration.toMillis(), TimeUnit.MILLISECONDS); - } - - /** - * Gets the amount of time the driver should wait when searching for an element if it is - * not immediately present. - * - * @return The amount of time the driver should wait when searching for an element. - * @see W3C WebDriver - */ - default Duration getImplicitWaitTimeout() { - throw new UnsupportedCommandException(); - } - - /** - * @deprecated Use {@link #setScriptTimeout(Duration)} - * - * Sets the amount of time to wait for an asynchronous script to finish execution before - * throwing an error. If the timeout is negative, not null, or greater than 2e16 - 1, an - * error code with invalid argument will be returned. - * - * @param time The timeout value. - * @param unit The unit of time. - * @return A self reference. - * @see JavascriptExecutor#executeAsyncScript(String, Object...) - * @see W3C WebDriver - * @see W3C WebDriver - */ - @Deprecated - Timeouts setScriptTimeout(long time, TimeUnit unit); - - /** - * Sets the amount of time to wait for an asynchronous script to finish execution before - * throwing an error. If the timeout is negative, not null, or greater than 2e16 - 1, an - * error code with invalid argument will be returned. - * - * @param duration The timeout value. - * @deprecated Use {@link #scriptTimeout(Duration)} - * @return A self reference. - * @see JavascriptExecutor#executeAsyncScript(String, Object...) - * @see W3C WebDriver - * @see W3C WebDriver - */ - @Deprecated - default Timeouts setScriptTimeout(Duration duration) { - return setScriptTimeout(duration.toMillis(), TimeUnit.MILLISECONDS); - } - - /** - * Sets the amount of time to wait for an asynchronous script to finish execution before - * throwing an error. If the timeout is negative, not null, or greater than 2e16 - 1, an - * error code with invalid argument will be returned. - * - * @param duration The timeout value. - * @return A self reference. - * @see JavascriptExecutor#executeAsyncScript(String, Object...) - * @see W3C WebDriver - * @see W3C WebDriver - */ - default Timeouts scriptTimeout(Duration duration) { - return setScriptTimeout(duration); - } - - /** - * Gets the amount of time to wait for an asynchronous script to finish execution before - * throwing an error. If the timeout is negative, not null, or greater than 2e16 - 1, an - * error code with invalid argument will be returned. - * - * @return The amount of time to wait for an asynchronous script to finish execution. - * @see W3C WebDriver - * @see W3C WebDriver - */ - default Duration getScriptTimeout() { - throw new UnsupportedCommandException(); - } - - /** - * @param time The timeout value. - * @param unit The unit of time. - * @return A Timeouts interface. - * @see W3C WebDriver - * @see W3C WebDriver - * @deprecated Use {@link #pageLoadTimeout(Duration)} - * - * Sets the amount of time to wait for a page load to complete before throwing an error. - * If the timeout is negative, not null, or greater than 2e16 - 1, an error code with - * invalid argument will be returned. - */ - @Deprecated - Timeouts pageLoadTimeout(long time, TimeUnit unit); - - /** - * Sets the amount of time to wait for a page load to complete before throwing an error. - * If the timeout is negative, not null, or greater than 2e16 - 1, an error code with - * invalid argument will be returned. - * - * @param duration The timeout value. - * @return A Timeouts interface. - * @see W3C WebDriver - * @see W3C WebDriver - */ - default Timeouts pageLoadTimeout(Duration duration) { - return pageLoadTimeout(duration.toMillis(), TimeUnit.MILLISECONDS); - } - - /** - * Gets the amount of time to wait for a page load to complete before throwing an error. - * If the timeout is negative, not null, or greater than 2e16 - 1, an error code with - * invalid argument will be returned. - * - * @return The amount of time to wait for a page load to complete. - * @see W3C WebDriver - * @see W3C WebDriver - */ - default Duration getPageLoadTimeout() { - throw new UnsupportedCommandException(); - } - } - - /** - * Used to locate a given frame or window. - */ - interface TargetLocator { - /** - * Select a frame by its (zero-based) index. Selecting a frame by index is equivalent to the - * JS expression window.frames[index] where "window" is the DOM window represented by the - * current context. Once the frame has been selected, all subsequent calls on the WebDriver - * interface are made to that frame. - *

- * See W3C WebDriver specification - * for more details. - * - * @param index (zero-based) index - * @return This driver focused on the given frame - * @throws NoSuchFrameException If the frame cannot be found - */ - WebDriver frame(int index); - - /** - * Select a frame by its name or ID. Frames located by matching name attributes are always given - * precedence over those matched by ID. - * - * @param nameOrId the name of the frame window, the id of the <frame> or <iframe> - * element, or the (zero-based) index - * @return This driver focused on the given frame - * @throws NoSuchFrameException If the frame cannot be found - */ - WebDriver frame(String nameOrId); - - /** - * Select a frame using its previously located {@link WebElement}. - *

- * See W3C WebDriver specification - * for more details. - * - * @param frameElement The frame element to switch to. - * @return This driver focused on the given frame. - * @throws NoSuchFrameException If the given element is neither an IFRAME nor a FRAME element. - * @throws StaleElementReferenceException If the WebElement has gone stale. - * @see WebDriver#findElement(By) - */ - WebDriver frame(WebElement frameElement); - - /** - * Change focus to the parent context. If the current context is the top level browsing context, - * the context remains unchanged. - *

- * See W3C WebDriver specification - * for more details. - * - * @return This driver focused on the parent frame - */ - WebDriver parentFrame(); - - /** - * Switch the focus of future commands for this driver to the window with the given name/handle. - *

- * See W3C WebDriver specification - * for more details. - * - * @param nameOrHandle The name of the window or the handle as returned by - * {@link WebDriver#getWindowHandle()} - * @return This driver focused on the given window - * @throws NoSuchWindowException If the window cannot be found - */ - WebDriver window(String nameOrHandle); - - /** - * Creates a new browser window and switches the focus for future commands of this driver - * to the new window. - *

- * See W3C WebDriver specification - * for more details. - * - * @param typeHint The type of new browser window to be created. The created window is not - * guaranteed to be of the requested type; if the driver does not support - * the requested type, a new browser window will be created of whatever type - * the driver does support. - * @return This driver focused on the given window - */ - WebDriver newWindow(WindowType typeHint); - - /** - * Selects either the first frame on the page, or the main document when a page contains - * iframes. - *

- * See W3C WebDriver specification - * for more details. - * - * @return This driver focused on the top window/first frame. - */ - WebDriver defaultContent(); - - /** - * Switches to the element that currently has focus within the document currently "switched to", - * or the body element if this cannot be detected. This matches the semantics of calling - * "document.activeElement" in Javascript. - *

- * See W3C WebDriver specification - * for more details. - * - * @return The WebElement with focus, or the body element if no element with focus can be - * detected. - */ - WebElement activeElement(); - - /** - * Switches to the currently active modal dialog for this particular driver instance. - * - * @return A handle to the dialog. - * @throws NoAlertPresentException If the dialog cannot be found - */ - Alert alert(); - } - - interface Navigation { - /** - * Move back a single "item" in the browser's history. - *

- * See W3C WebDriver specification - * for more details. - */ - void back(); - - /** - * Move a single "item" forward in the browser's history. Does nothing if we are on the latest - * page viewed. - *

- * See W3C WebDriver specification - * for more details. - */ - void forward(); - - - /** - * Load a new web page in the current browser window. This is done using an HTTP POST operation, - * and the method will block until the load is complete. This will follow redirects issued - * either by the server or as a meta-redirect from within the returned HTML. Should a - * meta-redirect "rest" for any duration of time, it is best to wait until this timeout is over, - * since should the underlying page change whilst your test is executing the results of future - * calls against this interface will be against the freshly loaded page. - *

- * See W3C WebDriver specification - * for more details. - * - * @param url The URL to load. Must be a fully qualified URL - */ - void to(String url); - - /** - * Overloaded version of {@link #to(String)} that makes it easy to pass in a URL. - * - * @param url URL - */ - void to(URL url); - - /** - * Refresh the current page - *

- * See W3C WebDriver specification - * for more details. - */ - void refresh(); - } - - /** - * An interface for managing input methods. - */ - interface ImeHandler { - /** - * All available engines on the machine. To use an engine, it has to be activated. - * - * @return list of available IME engines. - * @throws ImeNotAvailableException if the host does not support IME. - */ - List getAvailableEngines(); - - /** - * Get the name of the active IME engine. The name string is platform-specific. - * - * @return name of the active IME engine. - * @throws ImeNotAvailableException if the host does not support IME. - */ - String getActiveEngine(); - - /** - * Indicates whether IME input active at the moment (not if it's available). - * - * @return true if IME input is available and currently active, false otherwise. - * @throws ImeNotAvailableException if the host does not support IME. - */ - boolean isActivated(); - - /** - * De-activate IME input (turns off the currently activated engine). Note that getActiveEngine - * may still return the name of the engine but isActivated will return false. - * - * @throws ImeNotAvailableException if the host does not support IME. - */ - void deactivate(); - - /** - * Make an engines that is available (appears on the list returned by getAvailableEngines) - * active. After this call, the only loaded engine on the IME daemon will be this one and the - * input sent using sendKeys will be converted by the engine. Note that this is a - * platform-independent method of activating IME (the platform-specific way being using keyboard - * shortcuts). - * - * - * @param engine name of engine to activate. - * @throws ImeNotAvailableException if the host does not support IME. - * @throws ImeActivationFailedException if the engine is not available or if activation failed - * for other reasons. - */ - void activateEngine(String engine); - } - - @Beta - interface Window { - - /** - * Get the size of the current window. This will return the outer window dimension, not just - * the view port. - *

- * See W3C WebDriver specification - * for more details. - * - * @return The current window size. - */ - Dimension getSize(); - - /** - * Set the size of the current window. This will change the outer window dimension, - * not just the view port, synonymous to window.resizeTo() in JS. - *

- * See W3C WebDriver specification - * for more details. - * - * @param targetSize The target size. - */ - void setSize(Dimension targetSize); - - /** - * Get the position of the current window, relative to the upper left corner of the screen. - *

- * See W3C WebDriver specification - * for more details. - * - * @return The current window position. - */ - Point getPosition(); - - /** - * Set the position of the current window. This is relative to the upper left corner of the - * screen, synonymous to window.moveTo() in JS. - *

- * See W3C WebDriver specification - * for more details. - * - * @param targetPosition The target position of the window. - */ - void setPosition(Point targetPosition); - - /** - * Maximizes the current window if it is not already maximized - *

- * See W3C WebDriver specification - * for more details. - */ - void maximize(); - - /** - * Minimizes the current window if it is not already minimized - *

- * See W3C WebDriver specification - * for more details. - */ - void minimize(); - - /** - * Fullscreen the current window if it is not already fullscreen - *

- * See W3C WebDriver specification - * for more details. - */ - void fullscreen(); - } -} diff --git a/src/main/java/org/openqa/selenium/WebElement.java b/src/main/java/org/openqa/selenium/WebElement.java deleted file mode 100644 index ba2e441b7..000000000 --- a/src/main/java/org/openqa/selenium/WebElement.java +++ /dev/null @@ -1,338 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. 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 org.openqa.selenium; - -import java.util.List; - -/** - * Represents an HTML element. Generally, all interesting operations to do with interacting with a - * page will be performed through this interface. - *

- * All method calls will do a freshness check to ensure that the element reference is still valid. - * This essentially determines whether or not the element is still attached to the DOM. If this test - * fails, then an {@link org.openqa.selenium.StaleElementReferenceException} is thrown, and all - * future calls to this instance will fail. - */ -public interface WebElement extends SearchContext, TakesScreenshot { - /** - * Click this element. If this causes a new page to load, you - * should discard all references to this element and any further - * operations performed on this element will throw a - * StaleElementReferenceException. - *

- * Note that if click() is done by sending a native event (which is - * the default on most browsers/platforms) then the method will - * _not_ wait for the next page to load and the caller should verify - * that themselves. - *

- * There are some preconditions for an element to be clicked. The - * element must be visible and it must have a height and width - * greater then 0. - *

- * See W3C WebDriver specification - * for more details. - * - * @throws StaleElementReferenceException If the element no - * longer exists as initially defined - */ - void click(); - - /** - * If this current element is a form, or an element within a form, then this will be submitted to - * the remote server. If this causes the current page to change, then this method will block until - * the new page is loaded. - * - * @throws NoSuchElementException If the given element is not within a form - */ - void submit(); - - /** - * Use this method to simulate typing into an element, which may set its value. - *

- * See W3C WebDriver specification - * for more details. - * - * @param keysToSend character sequence to send to the element - * - * @throws IllegalArgumentException if keysToSend is null - */ - void sendKeys(CharSequence... keysToSend); - - /** - * If this element is a form entry element, this will reset its value. - *

- * See W3C WebDriver specification - * and HTML specification - * for more details. - */ - void clear(); - - /** - * Get the tag name of this element. Not the value of the name attribute: will return - * "input" for the element <input name="foo" />. - *

- * See W3C WebDriver specification - * for more details. - * - * @return The tag name of this element. - */ - String getTagName(); - - /** - * Get the value of the given property of the element. Will return the current value, even if - * this has been modified after the page has been loaded. - *

- * See W3C WebDriver specification - * for more details. - * - * @param name The name of the property. - * @return The property's current value or null if the value is not set. - */ - default String getDomProperty(String name) { - throw new UnsupportedOperationException("getDomProperty"); - } - - /** - * Get the value of the given attribute of the element. - *

- * This method, unlike {@link #getAttribute(String)}, returns the value of the attribute with the - * given name but not the property with the same name. - *

- * The following are deemed to be "boolean" attributes, and will return either "true" or null: - *

- * async, autofocus, autoplay, checked, compact, complete, controls, declare, defaultchecked, - * defaultselected, defer, disabled, draggable, ended, formnovalidate, hidden, indeterminate, - * iscontenteditable, ismap, itemscope, loop, multiple, muted, nohref, noresize, noshade, - * novalidate, nowrap, open, paused, pubdate, readonly, required, reversed, scoped, seamless, - * seeking, selected, truespeed, willvalidate - *

- * See W3C WebDriver specification - * for more details. - * - * @param name The name of the attribute. - * @return The attribute's value or null if the value is not set. - */ - default String getDomAttribute(String name) { - throw new UnsupportedOperationException("getDomAttribute"); - } - - /** - * Get the value of the given attribute of the element. Will return the current value, even if - * this has been modified after the page has been loaded. - *

- * More exactly, this method will return the value of the property with the given name, if it - * exists. If it does not, then the value of the attribute with the given name is returned. If - * neither exists, null is returned. - *

- * The "style" attribute is converted as best can be to a text representation with a trailing - * semi-colon. - *

- * The following are deemed to be "boolean" attributes, and will return either "true" or null: - *

- * async, autofocus, autoplay, checked, compact, complete, controls, declare, defaultchecked, - * defaultselected, defer, disabled, draggable, ended, formnovalidate, hidden, indeterminate, - * iscontenteditable, ismap, itemscope, loop, multiple, muted, nohref, noresize, noshade, - * novalidate, nowrap, open, paused, pubdate, readonly, required, reversed, scoped, seamless, - * seeking, selected, truespeed, willvalidate - *

- * Finally, the following commonly mis-capitalized attribute/property names are evaluated as - * expected: - *

    - *
  • If the given name is "class", the "className" property is returned. - *
  • If the given name is "readonly", the "readOnly" property is returned. - *
- * Note: The reason for this behavior is that users frequently confuse attributes and - * properties. If you need to do something more precise, use {@link #getDomAttribute(String)} - * or {@link #getDomProperty(String)} to obtain the result you desire. - *

- * See W3C WebDriver specification - * for more details. - * - * @param name The name of the attribute. - * @return The attribute/property's current value or null if the value is not set. - */ - String getAttribute(String name); - - /** - * Gets result of computing the WAI-ARIA role of element. - *

- * See W3C WebDriver specification - * for more details. - * - * @return the WAI-ARIA role of the element. - */ - default String getAriaRole() { - throw new UnsupportedOperationException("getAriaRole"); - } - - /** - * Gets result of a Accessible Name and Description Computation for the Accessible Name of the element. - *

- * See W3C WebDriver specification - * for more details. - * - * @return the accessible name of the element. - */ - default String getAccessibleName() { - throw new UnsupportedOperationException("getAccessibleName"); - } - - /** - * Determine whether or not this element is selected or not. This operation only applies to input - * elements such as checkboxes, options in a select and radio buttons. - * For more information on which elements this method supports, - * refer to the specification. - *

- * See W3C WebDriver specification - * for more details. - * - * @return True if the element is currently selected or checked, false otherwise. - */ - boolean isSelected(); - - /** - * Is the element currently enabled or not? This will generally return true for everything but - * disabled input elements. - *

- * See W3C WebDriver specification - * for more details. - * - * @return True if the element is enabled, false otherwise. - */ - boolean isEnabled(); - - /** - * Get the visible (i.e. not hidden by CSS) text of this element, including sub-elements. - *

- * See W3C WebDriver specification - * for more details. - * - * @return The visible text of this element. - */ - String getText(); - - /** - * Find all elements within the current context using the given mechanism. When using xpath be - * aware that webdriver follows standard conventions: a search prefixed with "//" will search the - * entire document, not just the children of this current node. Use ".//" to limit your search to - * the children of this WebElement. - * This method is affected by the 'implicit wait' times in force at the time of execution. When - * implicitly waiting, this method will return as soon as there are more than 0 items in the - * found collection, or will return an empty list if the timeout is reached. - *

- * See W3C WebDriver specification - * for more details. - * - * @param by The locating mechanism to use - * @return A list of all {@link WebElement}s, or an empty list if nothing matches. - * @see org.openqa.selenium.By - * @see org.openqa.selenium.WebDriver.Timeouts - */ - @Override - List findElements(By by); - - /** - * Find the first {@link WebElement} using the given method. See the note in - * {@link #findElements(By)} about finding via XPath. - * This method is affected by the 'implicit wait' times in force at the time of execution. - * The findElement(..) invocation will return a matching row, or try again repeatedly until - * the configured timeout is reached. - *

- * findElement should not be used to look for non-present elements, use {@link #findElements(By)} - * and assert zero length response instead. - *

- * See W3C WebDriver specification - * for more details. - * - * @param by The locating mechanism - * @return The first matching element on the current context. - * @throws NoSuchElementException If no matching elements are found - * @see org.openqa.selenium.By - * @see org.openqa.selenium.WebDriver.Timeouts - */ - @Override - T findElement(By by); - - /** - * @return A representation of an element's shadow root for accessing the shadow DOM of a web component. - * @throws NoSuchShadowRootException If no shadow root is found - */ - default SearchContext getShadowRoot() { - throw new UnsupportedOperationException("getShadowRoot"); - } - - /** - * Is this element displayed or not? This method avoids the problem of having to parse an - * element's "style" attribute. - * - * @return Whether or not the element is displayed - */ - boolean isDisplayed(); - - /** - * Where on the page is the top left-hand corner of the rendered element? - *

- * See W3C WebDriver specification - * for more details. - * - * @return A point, containing the location of the top left-hand corner of the element - */ - Point getLocation(); - - /** - * What is the width and height of the rendered element? - *

- * See W3C WebDriver specification - * for more details. - * - * @return The size of the element on the page. - */ - Dimension getSize(); - - /** - * @return The location and size of the rendered element - *

- * See W3C WebDriver specification - * for more details. - */ - Rectangle getRect(); - - /** - * Get the value of a given CSS property. - * Color values could be returned as rgba or rgb strings. - * This depends on whether the browser omits the implicit opacity value or not. - * - * For example if the "background-color" property is set as "green" in the - * HTML source, the returned value could be "rgba(0, 255, 0, 1)" if implicit opacity value is - * preserved or "rgb(0, 255, 0)" if it is omitted. - * - * Note that shorthand CSS properties (e.g. background, font, border, border-top, margin, - * margin-top, padding, padding-top, list-style, outline, pause, cue) are not returned, - * in accordance with the - * DOM CSS2 specification - * - you should directly access the longhand properties (e.g. background-color) to access the - * desired values. - *

- * See W3C WebDriver specification - * for more details. - * - * @param propertyName the css property name of the element - * @return The current, computed value of the property. - */ - String getCssValue(String propertyName); -} diff --git a/src/test/java/io/appium/java_client/TestUtils.java b/src/test/java/io/appium/java_client/TestUtils.java index c0b55e5f0..6b7b616c5 100644 --- a/src/test/java/io/appium/java_client/TestUtils.java +++ b/src/test/java/io/appium/java_client/TestUtils.java @@ -1,7 +1,13 @@ package io.appium.java_client; +import com.google.common.collect.ImmutableMap; +import org.openqa.selenium.Dimension; +import org.openqa.selenium.Point; import org.openqa.selenium.TimeoutException; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.remote.RemoteWebElement; +import javax.annotation.Nullable; import java.io.IOException; import java.net.DatagramSocket; import java.net.InetAddress; @@ -64,4 +70,23 @@ public static void waitUntilTrue(Supplier func, Duration timeout, Durat } throw new TimeoutException(String.format("Condition unmet after %sms timeout", timeout.toMillis())); } + + public static Point getCenter(WebElement webElement) { + return getCenter(webElement, null); + } + + public static Point getCenter(WebElement webElement, @Nullable Point location) { + Dimension dim = webElement.getSize(); + if (location == null) { + location = webElement.getLocation(); + } + return new Point(location.x + dim.width / 2, location.y + dim.height / 2); + } + + public static void setElementValue(ExecutesMethod driver, RemoteWebElement webElement, String value) { + driver.execute(MobileCommand.SET_VALUE, ImmutableMap.of( + "id", webElement.getId(), + "value", value + )); + } } diff --git a/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java b/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java index 198056e5d..281fb2fdc 100644 --- a/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java @@ -1,17 +1,18 @@ package io.appium.java_client.android; +import static io.appium.java_client.TestUtils.getCenter; import static io.appium.java_client.touch.WaitOptions.waitOptions; import static io.appium.java_client.touch.offset.ElementOption.element; import static java.time.Duration.ofSeconds; import static org.junit.Assert.assertNotEquals; import io.appium.java_client.MobileBy; -import io.appium.java_client.MobileElement; import io.appium.java_client.functions.ActionSupplier; import io.appium.java_client.touch.offset.ElementOption; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.Point; +import org.openqa.selenium.WebElement; import java.util.List; @@ -20,10 +21,10 @@ public class AndroidAbilityToUseSupplierTest extends BaseAndroidTest { private final ActionSupplier horizontalSwipe = () -> { driver.findElement(By.id("io.appium.android.apis:id/gallery")); - AndroidElement gallery = driver.findElement(By.id("io.appium.android.apis:id/gallery")); - List images = gallery.findElements(MobileBy.className("android.widget.ImageView")); + WebElement gallery = driver.findElement(By.id("io.appium.android.apis:id/gallery")); + List images = gallery.findElements(MobileBy.className("android.widget.ImageView")); Point location = gallery.getLocation(); - Point center = gallery.getCenter(); + Point center = getCenter(gallery, location); ElementOption pressOption = element(images.get(2),-10,center.y - location.y); ElementOption moveOption = element(gallery, 10,center.y - location.y); @@ -47,8 +48,8 @@ public class AndroidAbilityToUseSupplierTest extends BaseAndroidTest { @Test public void horizontalSwipingWithSupplier() { Activity activity = new Activity("io.appium.android.apis", ".view.Gallery1"); driver.startActivity(activity); - AndroidElement gallery = driver.findElement(By.id("io.appium.android.apis:id/gallery")); - List images = gallery.findElements(MobileBy.className("android.widget.ImageView")); + WebElement gallery = driver.findElement(By.id("io.appium.android.apis:id/gallery")); + List images = gallery.findElements(MobileBy.className("android.widget.ImageView")); int originalImageCount = images.size(); horizontalSwipe.get().perform(); diff --git a/src/test/java/io/appium/java_client/android/AndroidDriverTest.java b/src/test/java/io/appium/java_client/android/AndroidDriverTest.java index 1f3c0ae00..c94669138 100644 --- a/src/test/java/io/appium/java_client/android/AndroidDriverTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidDriverTest.java @@ -38,8 +38,6 @@ import java.time.Duration; import java.util.ArrayList; import java.util.List; -import java.util.Map; - public class AndroidDriverTest extends BaseAndroidTest { @@ -253,18 +251,6 @@ public void endTestCoverage() { driver.endTestCoverage("android.intent.action.MAIN", ""); } - @Test - public void getDeviceUDIDTest() { - String deviceSerial = driver.getSessionDetail("deviceUDID").toString(); - assertNotNull(deviceSerial); - } - - @Test - public void getSessionMapData() { - Map map = (Map) driver.getSessionDetail("desired"); - assertNotEquals(map.size(), 0); - } - @Test public void deviceDetailsAndKeyboardTest() { assertFalse(driver.isKeyboardShown()); @@ -314,10 +300,4 @@ public void getPerformanceDataTest() { public void getCurrentPackageTest() { assertEquals(APP_ID, driver.getCurrentPackage()); } - - @Test public void validateAllSessions() { - List> jsonMap = driver.getAllSessionDetails(); - assertNotNull(jsonMap); - } - } diff --git a/src/test/java/io/appium/java_client/android/AndroidElementTest.java b/src/test/java/io/appium/java_client/android/AndroidElementTest.java deleted file mode 100644 index cb89f258f..000000000 --- a/src/test/java/io/appium/java_client/android/AndroidElementTest.java +++ /dev/null @@ -1,90 +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.android; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; - -import io.appium.java_client.MobileBy; -import io.appium.java_client.MobileElement; -import org.junit.Before; -import org.junit.Test; -import org.openqa.selenium.By; - -public class AndroidElementTest extends BaseAndroidTest { - - @Before public void setup() { - Activity activity = new Activity("io.appium.android.apis", ".ApiDemos"); - driver.startActivity(activity); - } - - - @Test public void findByAccessibilityIdTest() { - assertNotEquals(driver.findElement(By.id("android:id/content")) - .findElement(MobileBy.AccessibilityId("Graphics")).getText(), null); - assertEquals(driver.findElement(By.id("android:id/content")) - .findElements(MobileBy.AccessibilityId("Graphics")).size(), 1); - } - - @Test public void findByAndroidUIAutomatorTest() { - assertNotEquals(driver.findElement(By.id("android:id/content")) - .findElement(MobileBy - .AndroidUIAutomator("new UiSelector().clickable(true)")).getText(), null); - assertNotEquals(driver.findElement(By.id("android:id/content")) - .findElements(MobileBy - .AndroidUIAutomator("new UiSelector().clickable(true)")).size(), 0); - assertNotEquals(driver.findElement(By.id("android:id/content")) - .findElements(MobileBy - .AndroidUIAutomator("new UiSelector().clickable(true)")).size(), 1); - } - - @Test public void replaceValueTest() { - String originalValue = "original value"; - - Activity activity = new Activity("io.appium.android.apis", ".view.Controls1"); - driver.startActivity(activity); - AndroidElement editElement = driver - .findElement(MobileBy.AndroidUIAutomator("resourceId(\"io.appium.android.apis:id/edit\")")); - editElement.sendKeys(originalValue); - assertEquals(originalValue, editElement.getText()); - String replacedValue = "replaced value"; - editElement.replaceValue(replacedValue); - assertEquals(replacedValue, editElement.getText()); - } - - @Test public void scrollingToSubElement() { - driver.findElement(MobileBy.AccessibilityId("Views")).click(); - AndroidElement list = driver.findElement(By.id("android:id/list")); - MobileElement radioGroup = list - .findElement(MobileBy - .AndroidUIAutomator("new UiScrollable(new UiSelector()).scrollIntoView(" - + "new UiSelector().text(\"Radio Group\"));")); - assertNotNull(radioGroup.getLocation()); - } - - @Test public void setValueTest() { - String value = "new value"; - - Activity activity = new Activity("io.appium.android.apis", ".view.Controls1"); - driver.startActivity(activity); - AndroidElement editElement = driver - .findElement(MobileBy.AndroidUIAutomator("resourceId(\"io.appium.android.apis:id/edit\")")); - editElement.setValue(value); - assertEquals(value, editElement.getText()); - } -} diff --git a/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java b/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java index 4564899f4..4313868dc 100644 --- a/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java @@ -21,10 +21,10 @@ import static org.junit.Assert.assertNotNull; import io.appium.java_client.MobileBy; -import io.appium.java_client.MobileElement; import org.junit.Before; import org.junit.Test; import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; public class AndroidSearchingTest extends BaseAndroidTest { @@ -59,7 +59,7 @@ public void setup() { @Test public void findScrollable() { driver.findElement(MobileBy.AccessibilityId("Views")).click(); - MobileElement radioGroup = driver + WebElement radioGroup = driver .findElement(MobileBy.AndroidUIAutomator("new UiScrollable(new UiSelector()" + ".resourceId(\"android:id/list\")).scrollIntoView(" + "new UiSelector().text(\"Radio Group\"));")); diff --git a/src/test/java/io/appium/java_client/android/AndroidTouchTest.java b/src/test/java/io/appium/java_client/android/AndroidTouchTest.java index 341b8d40b..ae1c3a9ff 100644 --- a/src/test/java/io/appium/java_client/android/AndroidTouchTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidTouchTest.java @@ -1,5 +1,6 @@ package io.appium.java_client.android; +import static io.appium.java_client.TestUtils.getCenter; import static io.appium.java_client.touch.LongPressOptions.longPressOptions; import static io.appium.java_client.touch.TapOptions.tapOptions; import static io.appium.java_client.touch.WaitOptions.waitOptions; @@ -10,7 +11,6 @@ import static org.junit.Assert.assertNotEquals; import io.appium.java_client.MobileBy; -import io.appium.java_client.MobileElement; import io.appium.java_client.MultiTouchAction; import io.appium.java_client.TouchAction; @@ -68,14 +68,14 @@ public void setUp() { @Test public void dragNDropByCoordinatesTest() { Activity activity = new Activity("io.appium.android.apis", ".view.DragAndDropDemo"); driver.startActivity(activity); - AndroidElement dragDot1 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_1")); - AndroidElement dragDot3 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_3")); + WebElement dragDot1 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_1")); + WebElement dragDot3 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_3")); WebElement dragText = driver.findElement(By.id("io.appium.android.apis:id/drag_text")); assertEquals("Drag text not empty", "", dragText.getText()); - Point center1 = dragDot1.getCenter(); - Point center2 = dragDot3.getCenter(); + Point center1 = getCenter(dragDot1); + Point center2 = getCenter(dragDot3); TouchAction dragNDrop = new TouchAction(driver) .longPress(point(center1.x, center1.y)) @@ -88,14 +88,14 @@ public void setUp() { @Test public void dragNDropByCoordinatesAndDurationTest() { Activity activity = new Activity("io.appium.android.apis", ".view.DragAndDropDemo"); driver.startActivity(activity); - AndroidElement dragDot1 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_1")); - AndroidElement dragDot3 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_3")); + WebElement dragDot1 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_1")); + WebElement dragDot3 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_3")); WebElement dragText = driver.findElement(By.id("io.appium.android.apis:id/drag_text")); assertEquals("Drag text not empty", "", dragText.getText()); - Point center1 = dragDot1.getCenter(); - Point center2 = dragDot3.getCenter(); + Point center1 = getCenter(dragDot1); + Point center2 = getCenter(dragDot3); TouchAction dragNDrop = new TouchAction(driver) .longPress(longPressOptions() @@ -133,7 +133,7 @@ public void setUp() { @Test public void tapActionTestByElement() throws Exception { Activity activity = new Activity("io.appium.android.apis", ".view.ChronometerDemo"); driver.startActivity(activity); - AndroidElement chronometer = driver.findElement(By.id("io.appium.android.apis:id/chronometer")); + WebElement chronometer = driver.findElement(By.id("io.appium.android.apis:id/chronometer")); TouchAction startStop = new TouchAction(driver) .tap(tapOptions().withElement(element(driver.findElement(By.id("io.appium.android.apis:id/start"))))) @@ -151,9 +151,9 @@ public void setUp() { @Test public void tapActionTestByCoordinates() throws Exception { Activity activity = new Activity("io.appium.android.apis", ".view.ChronometerDemo"); driver.startActivity(activity); - AndroidElement chronometer = driver.findElement(By.id("io.appium.android.apis:id/chronometer")); + WebElement chronometer = driver.findElement(By.id("io.appium.android.apis:id/chronometer")); - Point center1 = driver.findElement(By.id("io.appium.android.apis:id/start")).getCenter(); + Point center1 = getCenter(driver.findElement(By.id("io.appium.android.apis:id/start"))); TouchAction startStop = new TouchAction(driver) .tap(point(center1.x, center1.y)) @@ -170,11 +170,11 @@ public void setUp() { Activity activity = new Activity("io.appium.android.apis", ".view.Gallery1"); driver.startActivity(activity); - AndroidElement gallery = driver.findElement(By.id("io.appium.android.apis:id/gallery")); - List images = gallery.findElements(MobileBy.className("android.widget.ImageView")); + WebElement gallery = driver.findElement(By.id("io.appium.android.apis:id/gallery")); + List images = gallery.findElements(MobileBy.className("android.widget.ImageView")); int originalImageCount = images.size(); Point location = gallery.getLocation(); - Point center = gallery.getCenter(); + Point center = getCenter(gallery); TouchAction swipe = new TouchAction(driver) .press(element(images.get(2),-10, center.y - location.y)) 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 5108c98ac..065794566 100644 --- a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java +++ b/src/test/java/io/appium/java_client/android/BaseAndroidTest.java @@ -28,7 +28,7 @@ public class BaseAndroidTest { public static final String APP_ID = "io.appium.android.apis"; private static AppiumDriverLocalService service; - protected static AndroidDriver driver; + protected static AndroidDriver driver; /** * initialization. @@ -45,7 +45,7 @@ public class BaseAndroidTest { .setDeviceName("Android Emulator") .setApp(apiDemosApk().toAbsolutePath().toString()) .setEventTimings(); - driver = new AndroidDriver<>(service.getUrl(), options); + driver = new AndroidDriver(service.getUrl(), options); } /** diff --git a/src/test/java/io/appium/java_client/android/BaseEspressoTest.java b/src/test/java/io/appium/java_client/android/BaseEspressoTest.java index cbea1e064..6d9cd7671 100644 --- a/src/test/java/io/appium/java_client/android/BaseEspressoTest.java +++ b/src/test/java/io/appium/java_client/android/BaseEspressoTest.java @@ -29,7 +29,7 @@ public class BaseEspressoTest { private static AppiumDriverLocalService service; - protected static AndroidDriver driver; + protected static AndroidDriver driver; /** * initialization. @@ -48,7 +48,7 @@ public class BaseEspressoTest { capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); capabilities.setCapability(MobileCapabilityType.APP, apiDemosApk().toAbsolutePath().toString()); capabilities.setCapability("eventTimings", true); - driver = new AndroidDriver<>(service.getUrl(), capabilities); + driver = new AndroidDriver(service.getUrl(), capabilities); } /** diff --git a/src/test/java/io/appium/java_client/android/ExecuteCDPCommandTest.java b/src/test/java/io/appium/java_client/android/ExecuteCDPCommandTest.java index 3637d0360..634a9a516 100644 --- a/src/test/java/io/appium/java_client/android/ExecuteCDPCommandTest.java +++ b/src/test/java/io/appium/java_client/android/ExecuteCDPCommandTest.java @@ -58,7 +58,7 @@ public void setUp() { capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, MobileBrowserType.CHROME); capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, "UiAutomator2"); - driver = new AndroidDriver(service.getUrl(), capabilities); + driver = new AndroidDriver(service.getUrl(), capabilities); //This time out is set because test can be run on slow Android SDK emulator PageFactory.initElements(new AppiumFieldDecorator(driver, ofSeconds(5)), this); } diff --git a/src/test/java/io/appium/java_client/android/FingerPrintTest.java b/src/test/java/io/appium/java_client/android/FingerPrintTest.java index 02cf7dba4..e372669ca 100644 --- a/src/test/java/io/appium/java_client/android/FingerPrintTest.java +++ b/src/test/java/io/appium/java_client/android/FingerPrintTest.java @@ -17,7 +17,6 @@ package io.appium.java_client.android; import static io.appium.java_client.MobileBy.AndroidUIAutomator; -import static java.util.concurrent.TimeUnit.SECONDS; import io.appium.java_client.remote.MobileCapabilityType; import io.appium.java_client.service.local.AppiumDriverLocalService; @@ -29,19 +28,22 @@ import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.DesiredCapabilities; +import java.time.Duration; + public class FingerPrintTest { private static AppiumDriverLocalService service; - private static AndroidDriver driver; + private static AndroidDriver driver; private static void initDriver() { DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); capabilities.setCapability("appPackage", "com.android.settings"); capabilities.setCapability("appActivity", "Settings"); - driver = new AndroidDriver<>(service.getUrl(), capabilities); - driver.manage().timeouts().implicitlyWait(15, SECONDS); + driver = new AndroidDriver(service.getUrl(), capabilities); + driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(15)); } /** @@ -65,7 +67,7 @@ private static void initDriver() { } } - private AndroidElement findElementByText(String text) { + private WebElement findElementByText(String text) { return driver.findElements(By.id("android:id/title")).stream().filter(androidElement -> text.equals(androidElement.getText())).findFirst() .orElseThrow(() -> diff --git a/src/test/java/io/appium/java_client/android/IntentTest.java b/src/test/java/io/appium/java_client/android/IntentTest.java index ed82dee0c..441af2a4e 100644 --- a/src/test/java/io/appium/java_client/android/IntentTest.java +++ b/src/test/java/io/appium/java_client/android/IntentTest.java @@ -16,7 +16,7 @@ public class IntentTest { private static AppiumDriverLocalService service; - protected static AndroidDriver driver; + protected static AndroidDriver driver; /** * initialization. @@ -32,7 +32,7 @@ public class IntentTest { DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); capabilities.setCapability(MobileCapabilityType.APP, intentExampleApk().toAbsolutePath().toString()); - driver = new AndroidDriver<>(service.getUrl(), capabilities); + driver = new AndroidDriver(service.getUrl(), capabilities); } /** diff --git a/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java b/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java index 7806ecc14..db055c305 100644 --- a/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java +++ b/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java @@ -5,6 +5,7 @@ import org.junit.Test; +import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.WebDriverWait; import java.util.List; @@ -16,7 +17,7 @@ public void openNotification() { driver.openNotifications(); WebDriverWait wait = new WebDriverWait(driver, 20); assertNotEquals(0, wait.until(input -> { - List result = input + List result = input .findElements(id("com.android.systemui:id/settings_button")); return result.isEmpty() ? null : result; diff --git a/src/test/java/io/appium/java_client/android/UIAutomator2Test.java b/src/test/java/io/appium/java_client/android/UIAutomator2Test.java index 8b18bcce6..e9d110661 100644 --- a/src/test/java/io/appium/java_client/android/UIAutomator2Test.java +++ b/src/test/java/io/appium/java_client/android/UIAutomator2Test.java @@ -4,16 +4,15 @@ import static org.junit.Assert.assertNotNull; import io.appium.java_client.MobileBy; -import io.appium.java_client.MobileElement; import org.junit.After; import org.junit.Ignore; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.DeviceRotation; +import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; - public class UIAutomator2Test extends BaseAndroidTest { @After @@ -62,7 +61,7 @@ public void testToastMSGIsDisplayed() { wait.until(ExpectedConditions.presenceOfElementLocated(MobileBy .AccessibilityId("Make a Popup!"))); - MobileElement popUpElement = driver.findElement(MobileBy.AccessibilityId("Make a Popup!")); + WebElement popUpElement = driver.findElement(MobileBy.AccessibilityId("Make a Popup!")); wait.until(ExpectedConditions.elementToBeClickable(popUpElement)).click(); wait.until(ExpectedConditions.visibilityOfElementLocated( By.xpath(".//*[@text='Search']"))).click(); diff --git a/src/test/java/io/appium/java_client/appium/AndroidTest.java b/src/test/java/io/appium/java_client/appium/AndroidTest.java deleted file mode 100644 index 47e2475e4..000000000 --- a/src/test/java/io/appium/java_client/appium/AndroidTest.java +++ /dev/null @@ -1,146 +0,0 @@ -package io.appium.java_client.appium; - -import static io.appium.java_client.TestResources.apiDemosApk; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; - -import io.appium.java_client.AppiumDriver; -import io.appium.java_client.MobileBy; -import io.appium.java_client.MobileElement; -import io.appium.java_client.android.Activity; -import io.appium.java_client.android.AndroidElement; -import io.appium.java_client.android.StartsActivity; -import io.appium.java_client.remote.MobileCapabilityType; -import io.appium.java_client.remote.MobilePlatform; -import io.appium.java_client.service.local.AppiumDriverLocalService; -import io.appium.java_client.service.local.AppiumServerHasNotBeenStartedLocallyException; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.openqa.selenium.By; -import org.openqa.selenium.remote.DesiredCapabilities; -import org.openqa.selenium.remote.Response; - -import java.util.Map; - -public class AndroidTest { - - private static AppiumDriverLocalService service; - private static AppiumDriver driver; - private StartsActivity startsActivity; - - /** - * initialization. - */ - @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!"); - } - - DesiredCapabilities capabilities = new DesiredCapabilities(); - capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.ANDROID); - capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); - capabilities.setCapability(MobileCapabilityType.APP, apiDemosApk().toAbsolutePath().toString()); - driver = new AppiumDriver<>(service.getUrl(), capabilities); - } - - /** - * finishing. - */ - @AfterClass - public static void afterClass() { - if (driver != null) { - driver.quit(); - } - if (service != null) { - service.stop(); - } - } - - @Before - public void setUp() { - startsActivity = new StartsActivity() { - @Override - public Response execute(String driverCommand, Map parameters) { - return driver.execute(driverCommand, parameters); - } - - @Override - public Response execute(String driverCommand) { - return driver.execute(driverCommand); - } - }; - Activity activity = new Activity("io.appium.android.apis", ".ApiDemos"); - startsActivity.startActivity(activity); - } - - @Test - public void findByAccessibilityIdFromDriverTest() { - assertNotEquals(driver.findElement(MobileBy.AccessibilityId("Graphics")).getText(), null); - assertEquals(driver.findElements(MobileBy.AccessibilityId("Graphics")).size(), 1); - } - - @Test public void findByAndroidUIAutomatorFromDriverTest() { - assertNotEquals(driver - .findElement(MobileBy - .AndroidUIAutomator("new UiSelector().clickable(true)")).getText(), null); - assertNotEquals(driver - .findElements(MobileBy - .AndroidUIAutomator("new UiSelector().clickable(true)")).size(), 0); - assertNotEquals(driver - .findElements(MobileBy - .AndroidUIAutomator("new UiSelector().clickable(true)")).size(), 1); - } - - @Test public void findByAccessibilityIdFromElementTest() { - assertNotEquals(driver.findElement(By.id("android:id/content")) - .findElement(MobileBy.AccessibilityId("Graphics")).getText(), null); - assertEquals(driver.findElement(By.id("android:id/content")) - .findElements(MobileBy.AccessibilityId("Graphics")).size(), 1); - } - - @Test public void findByAndroidUIAutomatorFromElementTest() { - assertNotEquals(driver.findElement(By.id("android:id/content")) - .findElement(MobileBy - .AndroidUIAutomator("new UiSelector().clickable(true)")).getText(), null); - assertNotEquals(driver.findElement(By.id("android:id/content")) - .findElements(MobileBy - .AndroidUIAutomator("new UiSelector().clickable(true)")).size(), 0); - assertNotEquals(driver.findElement(By.id("android:id/content")) - .findElements(MobileBy - .AndroidUIAutomator("new UiSelector().clickable(true)")).size(), 1); - } - - @Test public void replaceValueTest() { - String originalValue = "original value"; - - Activity activity = new Activity("io.appium.android.apis", ".view.Controls1"); - startsActivity.startActivity(activity); - AndroidElement editElement = driver - .findElement(MobileBy - .AndroidUIAutomator("resourceId(\"io.appium.android.apis:id/edit\")")); - editElement.sendKeys(originalValue); - assertEquals(originalValue, editElement.getText()); - String replacedValue = "replaced value"; - editElement.replaceValue(replacedValue); - assertEquals(replacedValue, editElement.getText()); - } - - @Test public void scrollingToSubElement() { - driver.findElement(MobileBy.AccessibilityId("Views")).click(); - AndroidElement list = driver.findElement(By.id("android:id/list")); - MobileElement radioGroup = list - .findElement(MobileBy - .AndroidUIAutomator("new UiScrollable(new UiSelector()).scrollIntoView(" - + "new UiSelector().text(\"Radio Group\"));")); - assertNotNull(radioGroup.getLocation()); - } - -} diff --git a/src/test/java/io/appium/java_client/appium/AppiumFluentWaitTest.java b/src/test/java/io/appium/java_client/appium/AppiumFluentWaitTest.java deleted file mode 100644 index ead5bff7d..000000000 --- a/src/test/java/io/appium/java_client/appium/AppiumFluentWaitTest.java +++ /dev/null @@ -1,97 +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.appium; - -import static java.time.Duration.ofSeconds; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.Is.is; -import static org.hamcrest.core.IsEqual.equalTo; - -import io.appium.java_client.AppiumFluentWait; - -import org.junit.Assert; -import org.junit.Test; -import org.openqa.selenium.TimeoutException; -import org.openqa.selenium.support.ui.Wait; - -import java.time.Clock; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Function; - -public class AppiumFluentWaitTest { - - private static class FakeElement { - public boolean isDisplayed() { - return false; - } - } - - @Test(expected = TimeoutException.class) - public void testDefaultStrategy() { - final FakeElement el = new FakeElement(); - final Wait wait = new AppiumFluentWait<>(el, Clock.systemDefaultZone(), duration -> { - assertThat(duration.getSeconds(), is(equalTo(1L))); - Thread.sleep(duration.toMillis()); - }).withPollingStrategy(AppiumFluentWait.IterationInfo::getInterval) - .withTimeout(ofSeconds(3)) - .pollingEvery(ofSeconds(1)); - wait.until(FakeElement::isDisplayed); - Assert.fail("TimeoutException is expected"); - } - - @Test - public void testCustomStrategyOverridesDefaultInterval() { - final FakeElement el = new FakeElement(); - final AtomicInteger callsCounter = new AtomicInteger(0); - final Wait wait = new AppiumFluentWait<>(el, Clock.systemDefaultZone(), duration -> { - callsCounter.incrementAndGet(); - assertThat(duration.getSeconds(), is(equalTo(2L))); - Thread.sleep(duration.toMillis()); - }).withPollingStrategy(info -> ofSeconds(2)) - .withTimeout(ofSeconds(3)) - .pollingEvery(ofSeconds(1)); - try { - wait.until(FakeElement::isDisplayed); - Assert.fail("TimeoutException is expected"); - } catch (TimeoutException e) { - // this is expected - assertThat(callsCounter.get(), is(equalTo(2))); - } - } - - @Test - public void testIntervalCalculationForCustomStrategy() { - final FakeElement el = new FakeElement(); - final AtomicInteger callsCounter = new AtomicInteger(0); - // Linear dependency - final Function pollingStrategy = x -> x * 2; - final Wait wait = new AppiumFluentWait<>(el, Clock.systemDefaultZone(), duration -> { - int callNumber = callsCounter.incrementAndGet(); - assertThat(duration.getSeconds(), is(equalTo(pollingStrategy.apply((long) callNumber)))); - Thread.sleep(duration.toMillis()); - }).withPollingStrategy(info -> ofSeconds(pollingStrategy.apply(info.getNumber()))) - .withTimeout(ofSeconds(4)) - .pollingEvery(ofSeconds(1)); - try { - wait.until(FakeElement::isDisplayed); - Assert.fail("TimeoutException is expected"); - } catch (TimeoutException e) { - // this is expected - assertThat(callsCounter.get(), is(equalTo(2))); - } - } -} diff --git a/src/test/java/io/appium/java_client/appium/element/generation/BaseElementGenerationTest.java b/src/test/java/io/appium/java_client/appium/element/generation/BaseElementGenerationTest.java deleted file mode 100644 index 83271f229..000000000 --- a/src/test/java/io/appium/java_client/appium/element/generation/BaseElementGenerationTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.appium.java_client.appium.element.generation; - -import static org.junit.Assert.assertEquals; - -import io.appium.java_client.AppiumDriver; -import io.appium.java_client.service.local.AppiumDriverLocalService; -import org.junit.After; -import org.openqa.selenium.By; -import org.openqa.selenium.Capabilities; -import org.openqa.selenium.SessionNotCreatedException; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.DesiredCapabilities; - -import java.util.function.BiPredicate; -import java.util.function.Supplier; - -public class BaseElementGenerationTest { - protected AppiumDriver driver; - protected AppiumDriverLocalService service; - - protected final BiPredicate> commonPredicate = (by, aClass) -> { - WebElement element = driver.findElement(by); - assertEquals(element.getClass(), aClass); - return true; - }; - - @After - public void tearDown() { - try { - if (driver != null) { - driver.quit(); - } - if (service != null) { - service.stop(); - } - } finally { - driver = null; - service = null; - } - } - -} diff --git a/src/test/java/io/appium/java_client/appium/element/generation/android/AndroidElementGeneratingTest.java b/src/test/java/io/appium/java_client/appium/element/generation/android/AndroidElementGeneratingTest.java deleted file mode 100644 index 1582c7b18..000000000 --- a/src/test/java/io/appium/java_client/appium/element/generation/android/AndroidElementGeneratingTest.java +++ /dev/null @@ -1,81 +0,0 @@ -package io.appium.java_client.appium.element.generation.android; - -import static io.appium.java_client.MobileBy.AndroidUIAutomator; -import static io.appium.java_client.TestResources.apiDemosApk; -import static org.junit.Assert.assertTrue; -import static org.openqa.selenium.By.name; -import static org.openqa.selenium.By.tagName; - -import io.appium.java_client.AppiumDriver; -import io.appium.java_client.android.AndroidElement; -import io.appium.java_client.appium.element.generation.BaseElementGenerationTest; -import io.appium.java_client.remote.AndroidMobileCapabilityType; -import io.appium.java_client.remote.MobileBrowserType; -import io.appium.java_client.remote.MobileCapabilityType; -import io.appium.java_client.remote.MobilePlatform; -import io.appium.java_client.service.local.AppiumDriverLocalService; -import org.junit.Test; -import org.openqa.selenium.By; -import org.openqa.selenium.Capabilities; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.DesiredCapabilities; - -import java.util.function.BiPredicate; -import java.util.function.Supplier; - -public class AndroidElementGeneratingTest extends BaseElementGenerationTest { - - private final Supplier commonCapabilitiesSupplier = () -> { - DesiredCapabilities serverCapabilities = new DesiredCapabilities(); - serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.ANDROID); - serverCapabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); - serverCapabilities.setCapability(MobileCapabilityType.APP, apiDemosApk().toAbsolutePath().toString()); - return serverCapabilities; - }; - - @Test - public void whenAndroidNativeAppIsLaunched() { - assertTrue(check(() -> { - DesiredCapabilities clientCapabilities = commonCapabilitiesSupplier.get(); - clientCapabilities.setCapability(MobileCapabilityType.FULL_RESET, true); - clientCapabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 60); - return clientCapabilities; - }, commonPredicate, AndroidUIAutomator("new UiSelector().clickable(true)") - )); - } - - @Test - public void whenAndroidHybridAppIsLaunched() { - assertTrue(check(() -> { - DesiredCapabilities clientCapabilities = commonCapabilitiesSupplier.get(); - clientCapabilities.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, "io.appium.android.apis"); - clientCapabilities.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, ".view.WebView1"); - return clientCapabilities; - }, (by, aClass) -> { - driver.context("WEBVIEW_io.appium.android.apis"); - return commonPredicate.test(by, aClass); - }, tagName("a"))); - } - - @Test - public void whenAndroidBrowserIsLaunched() { - assertTrue(check(() -> { - DesiredCapabilities clientCapabilities = commonCapabilitiesSupplier.get(); - clientCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.ANDROID); - clientCapabilities.setCapability(MobileCapabilityType.BROWSER_NAME, MobileBrowserType.BROWSER); - clientCapabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); - return clientCapabilities; - }, (by, aClass) -> { - driver.get("https://www.google.com"); - return commonPredicate.test(by, aClass); - }, name("q"))); - } - - private boolean check(Supplier capabilitiesSupplier, - BiPredicate> filter, - By by) { - service = AppiumDriverLocalService.buildDefaultService(); - driver = new AppiumDriver<>(service, capabilitiesSupplier.get()); - return filter.test(by, AndroidElement.class); - } -} diff --git a/src/test/java/io/appium/java_client/appium/element/generation/ios/IOSElementGenerationTest.java b/src/test/java/io/appium/java_client/appium/element/generation/ios/IOSElementGenerationTest.java deleted file mode 100644 index 2a1cc2dfa..000000000 --- a/src/test/java/io/appium/java_client/appium/element/generation/ios/IOSElementGenerationTest.java +++ /dev/null @@ -1,166 +0,0 @@ -package io.appium.java_client.appium.element.generation.ios; - -import static io.appium.java_client.TestResources.testAppZip; -import static io.appium.java_client.TestResources.vodQaAppZip; -import static org.junit.Assert.assertTrue; -import static org.openqa.selenium.By.id; -import static org.openqa.selenium.By.name; -import static org.openqa.selenium.By.partialLinkText; - -import io.appium.java_client.AppiumDriver; -import io.appium.java_client.MobileBy; -import io.appium.java_client.appium.element.generation.BaseElementGenerationTest; -import io.appium.java_client.ios.BaseIOSTest; -import io.appium.java_client.ios.IOSElement; -import io.appium.java_client.remote.AutomationName; -import io.appium.java_client.remote.IOSMobileCapabilityType; -import io.appium.java_client.remote.MobileBrowserType; -import io.appium.java_client.remote.MobileCapabilityType; -import io.appium.java_client.remote.MobilePlatform; -import io.appium.java_client.service.local.AppiumDriverLocalService; -import org.junit.Ignore; -import org.junit.Test; -import org.openqa.selenium.By; -import org.openqa.selenium.Capabilities; -import org.openqa.selenium.SessionNotCreatedException; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.DesiredCapabilities; -import org.openqa.selenium.support.ui.ExpectedConditions; -import org.openqa.selenium.support.ui.WebDriverWait; - -import java.io.File; -import java.time.Duration; -import java.util.function.BiPredicate; -import java.util.function.Function; -import java.util.function.Supplier; - -public class IOSElementGenerationTest extends BaseElementGenerationTest { - - private static final File testApp = testAppZip().toFile(); - - private static final File webViewApp = vodQaAppZip().toFile(); - - private final Supplier commonAppCapabilitiesSupplier = () -> { - DesiredCapabilities serverCapabilities = new DesiredCapabilities(); - serverCapabilities.setCapability(MobileCapabilityType.DEVICE_NAME, BaseIOSTest.DEVICE_NAME); - serverCapabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST); - serverCapabilities.setCapability(IOSMobileCapabilityType.WDA_LAUNCH_TIMEOUT, - BaseIOSTest.WDA_LAUNCH_TIMEOUT.toMillis()); - serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, BaseIOSTest.PLATFORM_VERSION); - serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.IOS); - return serverCapabilities; - }; - - private final Function> appFileSupplierFunction = file -> { - final DesiredCapabilities clientCapabilities = new DesiredCapabilities(); - return () -> { - clientCapabilities.setCapability(MobileCapabilityType.APP, file.getAbsolutePath()); - return clientCapabilities; - }; - }; - - private final Supplier serverBrowserCapabilitiesSupplier = () -> { - DesiredCapabilities serverCapabilities = new DesiredCapabilities(); - serverCapabilities.setCapability(MobileCapabilityType.BROWSER_NAME, MobileBrowserType.SAFARI); - serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, BaseIOSTest.PLATFORM_VERSION); - serverCapabilities.setCapability(MobileCapabilityType.DEVICE_NAME, BaseIOSTest.DEVICE_NAME); - serverCapabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST); - serverCapabilities.setCapability(IOSMobileCapabilityType.WDA_LAUNCH_TIMEOUT, - BaseIOSTest.WDA_LAUNCH_TIMEOUT.toMillis()); - return serverCapabilities; - }; - - private final Supplier clientBrowserCapabilitiesSupplier = () -> { - DesiredCapabilities clientCapabilities = new DesiredCapabilities(); - clientCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.IOS); - return clientCapabilities; - }; - - @Test - public void whenIOSNativeAppIsLaunched() { - assertTrue(check(() -> { - Capabilities caps = commonAppCapabilitiesSupplier.get(); - return caps.merge(appFileSupplierFunction.apply(testApp).get()); - }, commonPredicate, - MobileBy.AccessibilityId("Answer") - )); - } - - @Ignore - @Test - public void whenIOSHybridAppIsLaunched() { - assertTrue(check(() -> { - Capabilities caps = commonAppCapabilitiesSupplier.get(); - return caps.merge(appFileSupplierFunction.apply(webViewApp).get()); - }, (by, aClass) -> { - new WebDriverWait(driver, Duration.ofSeconds(30)) - .until(ExpectedConditions.presenceOfElementLocated(id("login"))) - .click(); - driver.findElement(MobileBy.AccessibilityId("webView")).click(); - new WebDriverWait(driver, Duration.ofSeconds(30)) - .until(ExpectedConditions - .presenceOfElementLocated(MobileBy.AccessibilityId("Webview"))); - try { - Thread.sleep(10000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - driver.getContextHandles().forEach((handle) -> { - if (handle.contains("WEBVIEW")) { - driver.context(handle); - } - }); - return commonPredicate.test(by, aClass); - }, partialLinkText("login"))); - } - - @Test - public void whenIOSBrowserIsLaunched() { - assertTrue(check(() -> { - Capabilities caps = serverBrowserCapabilitiesSupplier.get(); - return caps.merge(clientBrowserCapabilitiesSupplier.get()); - }, (by, aClass) -> { - driver.get("https://www.google.com"); - return commonPredicate.test(by, aClass); - }, name("q"))); - } - - @Test - public void whenIOSNativeAppIsLaunched2() { - assertTrue(check(() -> { - DesiredCapabilities serverCapabilities = commonAppCapabilitiesSupplier.get(); - serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, BaseIOSTest.PLATFORM_VERSION); - serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.IOS); - return serverCapabilities.merge(appFileSupplierFunction.apply(testApp).get()); - }, commonPredicate, id("IntegerA"))); - } - - @Test - public void whenIOSBrowserIsLaunched2() { - assertTrue(check(() -> { - DesiredCapabilities serverCapabilities = serverBrowserCapabilitiesSupplier.get(); - serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, BaseIOSTest.PLATFORM_VERSION); - serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.IOS); - return serverCapabilities.merge(clientBrowserCapabilitiesSupplier.get()); - }, (by, aClass) -> { - driver.get("https://www.google.com"); - return commonPredicate.test(by, aClass); - }, name("q"))); - } - - private boolean check(Supplier capabilitiesSupplier, - BiPredicate> filter, - By by) { - service = AppiumDriverLocalService.buildDefaultService(); - Capabilities caps = capabilitiesSupplier.get(); - DesiredCapabilities fixedCaps = new DesiredCapabilities(caps); - fixedCaps.setCapability("commandTimeouts", "120000"); - try { - driver = new AppiumDriver<>(service, fixedCaps); - } catch (SessionNotCreatedException e) { - fixedCaps.setCapability("useNewWDA", true); - driver = new AppiumDriver<>(service, fixedCaps); - } - return filter.test(by, IOSElement.class); - } -} diff --git a/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java b/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java index ae2e0df64..5316f56e4 100644 --- a/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java +++ b/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java @@ -97,7 +97,7 @@ public StubWebElement findElement(String by, String using) throws WebDriverExcep return new StubWebElement(); } - public List findElements(By by) { + public List findElements(By by) { return createStubList(); } 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 28a911ca2..26551d91b 100644 --- a/src/test/java/io/appium/java_client/ios/AppIOSTest.java +++ b/src/test/java/io/appium/java_client/ios/AppIOSTest.java @@ -34,10 +34,10 @@ public static void beforeClass() throws Exception { capabilities.setCapability("commandTimeouts", "240000"); capabilities.setCapability(MobileCapabilityType.APP, testAppZip().toAbsolutePath().toString()); try { - driver = new IOSDriver<>(new URL("http://" + ip + ":" + PORT + "/wd/hub"), capabilities); + driver = new IOSDriver(new URL("http://" + ip + ":" + PORT + "/wd/hub"), capabilities); } catch (SessionNotCreatedException e) { capabilities.setCapability("useNewWDA", true); - driver = new IOSDriver<>(new URL("http://" + ip + ":" + PORT + "/wd/hub"), capabilities); + 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 68097c7cc..c887ab6f8 100644 --- a/src/test/java/io/appium/java_client/ios/BaseIOSTest.java +++ b/src/test/java/io/appium/java_client/ios/BaseIOSTest.java @@ -29,7 +29,7 @@ public class BaseIOSTest { protected static AppiumDriverLocalService service; - protected static IOSDriver driver; + 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 12"; diff --git a/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java b/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java index 445e37033..999719551 100644 --- a/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java +++ b/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java @@ -51,9 +51,9 @@ public static void beforeClass() throws IOException { capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST); capabilities.setCapability("commandTimeouts", "240000"); capabilities.setCapability(MobileCapabilityType.APP, vodQaAppZip().toAbsolutePath().toString()); - Supplier> createDriver = () -> { + Supplier createDriver = () -> { try { - return new IOSDriver<>(new URL("http://" + ip + ":" + PORT + "/wd/hub"), capabilities); + return new IOSDriver(new URL("http://" + ip + ":" + PORT + "/wd/hub"), capabilities); } catch (MalformedURLException e) { throw new RuntimeException(e); } diff --git a/src/test/java/io/appium/java_client/ios/BaseSafariTest.java b/src/test/java/io/appium/java_client/ios/BaseSafariTest.java index cc4a7d05d..122d30257 100644 --- a/src/test/java/io/appium/java_client/ios/BaseSafariTest.java +++ b/src/test/java/io/appium/java_client/ios/BaseSafariTest.java @@ -44,6 +44,6 @@ public class BaseSafariTest extends BaseIOSTest { capabilities.setCapability(IOSMobileCapabilityType.WDA_LAUNCH_TIMEOUT, WDA_LAUNCH_TIMEOUT.toMillis()); capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, DEVICE_NAME); - driver = new IOSDriver<>(new URL("http://" + ip + ":" + PORT + "/wd/hub"), capabilities); + driver = new IOSDriver(new URL("http://" + ip + ":" + PORT + "/wd/hub"), capabilities); } } 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 345a7186b..f06e5b882 100644 --- a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSDriverTest.java @@ -26,7 +26,6 @@ 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.Before; @@ -34,7 +33,9 @@ import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.ScreenOrientation; +import org.openqa.selenium.WebElement; import org.openqa.selenium.html5.Location; +import org.openqa.selenium.remote.RemoteWebElement; import org.openqa.selenium.remote.Response; import org.openqa.selenium.remote.http.HttpMethod; import org.openqa.selenium.support.ui.ExpectedConditions; @@ -66,11 +67,13 @@ public void addCustomCommandWithSessionIdTest() { @Test public void addCustomCommandWithElementIdTest() { - IOSElement intA = driver.findElement(By.id("IntegerA")); + WebElement intA = driver.findElement(By.id("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")); + String.format("/session/%s/appium/element/%s/value", driver.getSessionId(), + ((RemoteWebElement) intA).getId()), "setNewValue"); + final Response setNewValue = driver.execute("setNewValue", + ImmutableMap.of("id", ((RemoteWebElement) intA).getId(), "value", "8")); assertNotNull(setNewValue.getSessionId()); } @@ -124,7 +127,7 @@ public void getDeviceTimeTest() { } @Test public void keyboardTest() { - MobileElement element = driver.findElement(By.id("IntegerA")); + WebElement element = driver.findElement(By.id("IntegerA")); element.click(); assertTrue(driver.isKeyboardShown()); } diff --git a/src/test/java/io/appium/java_client/ios/IOSElementTest.java b/src/test/java/io/appium/java_client/ios/IOSElementTest.java index 582e9f97c..121e2b7d0 100644 --- a/src/test/java/io/appium/java_client/ios/IOSElementTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSElementTest.java @@ -1,19 +1,23 @@ package io.appium.java_client.ios; +import static io.appium.java_client.TestUtils.setElementValue; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; import org.junit.FixMethodOrder; import org.junit.Ignore; import org.junit.Test; import org.junit.runners.MethodSorters; -import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.remote.RemoteWebElement; import org.openqa.selenium.support.ui.WebDriverWait; import io.appium.java_client.MobileBy; +import java.time.Duration; + @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class IOSElementTest extends AppIOSTest { @@ -26,11 +30,11 @@ public void findByAccessibilityIdTest() { @Ignore @Test public void setValueTest() { - WebDriverWait wait = new WebDriverWait(driver, 20); + WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20)); - IOSElement slider = wait.until( + WebElement slider = wait.until( driver1 -> driver1.findElement(MobileBy.className("XCUIElementTypeSlider"))); - slider.setValue("0%"); + setElementValue(driver, (RemoteWebElement) slider, "0%"); assertEquals("0%", slider.getAttribute("value")); } } diff --git a/src/test/java/io/appium/java_client/ios/IOSTouchTest.java b/src/test/java/io/appium/java_client/ios/IOSTouchTest.java index faf2ab98b..4364696ba 100644 --- a/src/test/java/io/appium/java_client/ios/IOSTouchTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSTouchTest.java @@ -10,12 +10,12 @@ import static org.openqa.selenium.support.ui.ExpectedConditions.alertIsPresent; import io.appium.java_client.MobileBy; -import io.appium.java_client.MobileElement; import io.appium.java_client.MultiTouchAction; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.WebDriverWait; @FixMethodOrder(MethodSorters.NAME_ASCENDING) @@ -23,28 +23,28 @@ public class IOSTouchTest extends AppIOSTest { @Test public void tapTest() { - IOSElement intA = driver.findElement(By.id("IntegerA")); - IOSElement intB = driver.findElement(By.id("IntegerB")); + WebElement intA = driver.findElement(By.id("IntegerA")); + WebElement intB = driver.findElement(By.id("IntegerB")); intA.clear(); intB.clear(); intA.sendKeys("2"); intB.sendKeys("4"); - MobileElement e = driver.findElement(MobileBy.AccessibilityId("ComputeSumButton")); + WebElement e = driver.findElement(MobileBy.AccessibilityId("ComputeSumButton")); new IOSTouchAction(driver).tap(tapOptions().withElement(element(e))).perform(); assertEquals(driver.findElement(By.xpath("//*[@name = \"Answer\"]")).getText(), "6"); } @Test public void touchWithPressureTest() { - IOSElement intA = driver.findElement(By.id("IntegerA")); - IOSElement intB = driver.findElement(By.id("IntegerB")); + WebElement intA = driver.findElement(By.id("IntegerA")); + WebElement intB = driver.findElement(By.id("IntegerB")); intA.clear(); intB.clear(); intA.sendKeys("2"); intB.sendKeys("4"); - MobileElement e = driver.findElement(MobileBy.AccessibilityId("ComputeSumButton")); + WebElement e = driver.findElement(MobileBy.AccessibilityId("ComputeSumButton")); new IOSTouchAction(driver) .press(iosPressOptions() .withElement(element(e)) @@ -56,8 +56,8 @@ public void touchWithPressureTest() { } @Test public void multiTouchTest() { - MobileElement e = driver.findElement(MobileBy.AccessibilityId("ComputeSumButton")); - MobileElement e2 = driver.findElement(MobileBy.AccessibilityId("show alert")); + WebElement e = driver.findElement(MobileBy.AccessibilityId("ComputeSumButton")); + WebElement e2 = driver.findElement(MobileBy.AccessibilityId("show alert")); IOSTouchAction tap1 = new IOSTouchAction(driver).tap(tapOptions().withElement(element(e))); IOSTouchAction tap2 = new IOSTouchAction(driver).tap(tapOptions().withElement(element(e2))); @@ -70,12 +70,12 @@ public void touchWithPressureTest() { } @Test public void doubleTapTest() { - IOSElement firstField = driver.findElement(By.id("IntegerA")); + WebElement firstField = driver.findElement(By.id("IntegerA")); firstField.sendKeys("2"); IOSTouchAction iosTouchAction = new IOSTouchAction(driver); iosTouchAction.doubleTap(element(firstField)); - IOSElement editingMenu = driver.findElement(MobileBy.className("XCUIElementTypeTextField")); + WebElement editingMenu = driver.findElement(MobileBy.className("XCUIElementTypeTextField")); assertNotNull(editingMenu); } } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java index 99121e990..56c423ab4 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java @@ -23,9 +23,6 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; -import io.appium.java_client.MobileElement; -import io.appium.java_client.android.AndroidElement; - import io.appium.java_client.android.BaseAndroidTest; import io.appium.java_client.pagefactory.AndroidBy; @@ -64,10 +61,10 @@ public class AndroidPageObjectTest extends BaseAndroidTest { private List androidUIAutomatorViews; @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/text1\")") - private List mobileElementViews; + private List mobileElementViews; @FindBy(className = "android.widget.TextView") - private List mobiletextVieWs; + private List mobiletextVieWs; @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/text1\")") private List remoteElementViews; @@ -94,10 +91,10 @@ public class AndroidPageObjectTest extends BaseAndroidTest { private WebElement androidUIAutomatorView; @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/text1\")") - private MobileElement mobileElementView; + private WebElement mobileElementView; @FindBy(className = "android.widget.TextView") - private MobileElement mobiletextVieW; + private WebElement mobiletextVieW; @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/text1\")") private RemoteWebElement remotetextVieW; @@ -114,12 +111,12 @@ public class AndroidPageObjectTest extends BaseAndroidTest { @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")") @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")") @AndroidFindBy(id = "android:id/text1") - private AndroidElement androidElementView; + private WebElement androidElementView; @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")") @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")") @AndroidFindBy(id = "android:id/text1") - private List androidElementViews; + private List androidElementViews; @HowToUseLocators(androidAutomation = ALL_POSSIBLE) @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/Fakecontent\")") @@ -154,7 +151,7 @@ public class AndroidPageObjectTest extends BaseAndroidTest { @CacheLookup @FindBy(className = "android.widget.TextView") - private MobileElement cached; + private WebElement cached; @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")") @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")") @@ -173,21 +170,21 @@ public class AndroidPageObjectTest extends BaseAndroidTest { @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")"), @AndroidBy(id = "android:id/fakeId")}, priority = 1) @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")") - private AndroidElement androidElementViewFoundByMixedSearching; + private WebElement androidElementViewFoundByMixedSearching; @AndroidFindBy(id = "android:id/text1", priority = 2) @AndroidFindAll(value = { @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")"), @AndroidBy(id = "android:id/fakeId")}, priority = 1) @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")") - private List androidElementsViewFoundByMixedSearching; + private List androidElementsViewFoundByMixedSearching; @AndroidFindBys({ @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")", priority = 1), @AndroidBy(className = "android.widget.FrameLayout")}) @AndroidFindBys({@AndroidBy(id = "android:id/text1", priority = 1), @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")")}) - private AndroidElement androidElementViewFoundByMixedSearching2; + private WebElement androidElementViewFoundByMixedSearching2; @AndroidFindBys({ @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")", priority = 1), @@ -195,7 +192,7 @@ public class AndroidPageObjectTest extends BaseAndroidTest { @AndroidFindBys({ @AndroidBy(id = "android:id/text1", priority = 1), @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")")}) - private List androidElementsViewFoundByMixedSearching2; + private List androidElementsViewFoundByMixedSearching2; @HowToUseLocators(androidAutomation = ALL_POSSIBLE) @AndroidFindBy(id = "android:id/fakeId1") @@ -207,7 +204,7 @@ public class AndroidPageObjectTest extends BaseAndroidTest { @AndroidBy(className = "android.widget.FrameLayout")}, priority = 2) @AndroidFindBy(id = "android:id/fakeId3", priority = 3) @AndroidFindBy(id = "android:id/fakeId4", priority = 4) - private AndroidElement androidElementViewFoundByMixedSearching3; + private WebElement androidElementViewFoundByMixedSearching3; @HowToUseLocators(androidAutomation = ALL_POSSIBLE) @AndroidFindBy(id = "android:id/fakeId1") @@ -219,7 +216,7 @@ public class AndroidPageObjectTest extends BaseAndroidTest { @AndroidBy(className = "android.widget.FrameLayout")}, priority = 2) @AndroidFindBy(id = "android:id/fakeId3", priority = 3) @AndroidFindBy(id = "android:id/fakeId4", priority = 4) - private List androidElementsViewFoundByMixedSearching3; + private List androidElementsViewFoundByMixedSearching3; /** * The setting up. @@ -336,8 +333,8 @@ public class AndroidPageObjectTest extends BaseAndroidTest { } @Test public void checkThatClassObjectMethodsDoNotInvokeTheSearching() { - assertTrue(AndroidElement.class.isAssignableFrom(fakeElement.getClass())); - assertNotEquals(AndroidElement.class, fakeElement.getClass()); + assertTrue(WebElement.class.isAssignableFrom(fakeElement.getClass())); + assertNotEquals(WebElement.class, fakeElement.getClass()); assertEquals(driver, ((WrapsDriver) fakeElement).getWrappedDriver()); } @@ -347,7 +344,7 @@ public class AndroidPageObjectTest extends BaseAndroidTest { } @Test public void checkCached() { - assertEquals(cached.getId(), cached.getId()); + assertEquals(((RemoteWebElement) cached).getId(), ((RemoteWebElement) cached).getId()); } @Test(expected = NoSuchElementException.class) diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java index 63ff333b5..81b3be1cf 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java @@ -48,7 +48,7 @@ public class DesktopBrowserCompatibilityTest { private List foundLinks; private List main; //this list is located by id="main" private WebDriver trap1; - private List> trap2; + private List trap2; /** * The starting. diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/GenericTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/GenericTest.java deleted file mode 100644 index 16e83e2fe..000000000 --- a/src/test/java/io/appium/java_client/pagefactory_tests/GenericTest.java +++ /dev/null @@ -1,300 +0,0 @@ -package io.appium.java_client.pagefactory_tests; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import io.appium.java_client.pagefactory.AppiumFieldDecorator; -import io.appium.java_client.remote.AutomationName; -import io.appium.java_client.remote.MobileCapabilityType; - -import org.apache.commons.lang3.NotImplementedException; -import org.junit.Test; -import org.openqa.selenium.By; -import org.openqa.selenium.Capabilities; -import org.openqa.selenium.HasCapabilities; -import org.openqa.selenium.Platform; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.CapabilityType; -import org.openqa.selenium.support.PageFactory; -import io.appium.java_client.MobileElement; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -public class GenericTest { - - /** - * The Generic types are null on an unbound page. - */ - private static void assertUnboundGenericsNull(T genericItem, - List genericItems) { - assertNull(genericItem); - assertNull(genericItems); - } - - /** - * The Generic types are not null on a page bound by a WebElement (or WebElement - * sub type). - */ - private static void assertBoundGenericsNotNull(T genericItem, - List genericItems) { - assertNotNull(genericItem); - assertNotNull(genericItems); - } - - /** - * The Element types are never null. - */ - private static void assertElementsNotNull(WebElement elementItem, - List elementItems) { - assertNotNull(elementItem); - assertNotNull(elementItems); - } - - /** - * The Object types are always null. - */ - private static void assertObjectsNull(Object objectItem, List objectItems) { - assertNull(objectItem); - assertNull(objectItems); - } - - /** - * A page with no generic types. The Object types are never initialized. - */ - static class TempNoGenericsPage { - public WebElement webElementItem; - public MobileElement mobileElementItem; - public Object objectItem; - - public List webElementItems; - public List mobileElementItems; - public List objectItems; - - public void assertInit() { - assertElementsNotNull(webElementItem, webElementItems); - assertElementsNotNull(mobileElementItem, mobileElementItems); - assertObjectsNull(objectItem, objectItems); - } - } - - /** - * A page with an unbound generic type. The generic and Object types are never - * initialized. - */ - static class TempUnboundPage { - public T genericItem; - public WebElement webElementItem; - public MobileElement mobileElementItem; - public Object objectItem; - - public List genericItems; - public List webElementItems; - public List mobileElementItems; - public List objectItems; - - public void assertInit() { - assertUnboundGenericsNull(genericItem, genericItems); - assertElementsNotNull(webElementItem, webElementItems); - assertElementsNotNull(mobileElementItem, mobileElementItems); - assertObjectsNull(objectItem, objectItems); - } - } - - /** - * A page with a WebElement bound generic type. The Object types are never - * initialized. - */ - static class TempWebBoundPage { - public T genericItem; - public WebElement webElementItem; - public MobileElement mobileElementItem; - public Object objectItem; - - public List genericItems; - public List webElementItems; - public List mobileElementItems; - public List objectItems; - - public void assertInit() { - assertBoundGenericsNotNull(genericItem, genericItems); - assertElementsNotNull(webElementItem, webElementItems); - assertElementsNotNull(mobileElementItem, mobileElementItems); - assertObjectsNull(objectItem, objectItems); - } - } - - /** - * A page with a MobileElement bound generic type. The Object types are never - * initialized. - */ - static class TempMobileBoundPage { - public T genericItem; - public WebElement webElementItem; - public MobileElement mobileElementItem; - public Object objectItem; - - public List genericItems; - public List webElementItems; - public List mobileElementItems; - public List objectItems; - - public void assertInit() { - assertBoundGenericsNotNull(genericItem, genericItems); - assertElementsNotNull(webElementItem, webElementItems); - assertElementsNotNull(mobileElementItem, mobileElementItems); - assertObjectsNull(objectItem, objectItems); - } - } - - static class MockWebDriver implements WebDriver, HasCapabilities { - - @Override - public void get(String url) { - System.out.print(url); - } - - @Override - public String getCurrentUrl() { - return null; - } - - @Override - public String getTitle() { - return null; - } - - @Override - public List findElements(By by) { - throw new NotImplementedException("MockWebDriver did not expect to findElements"); - } - - @Override - public T findElement(By by) { - throw new NotImplementedException("MockWebDriver did not expect to findElement"); - } - - @Override - public String getPageSource() { - return null; - } - - @Override - public void close() { - System.out.print("Closed"); - } - - @Override - public void quit() { - System.out.print("Died"); - } - - @Override - public Set getWindowHandles() { - return null; - } - - @Override - public String getWindowHandle() { - return null; - } - - @Override - public TargetLocator switchTo() { - return null; - } - - @Override - public Navigation navigate() { - return null; - } - - @Override - public Options manage() { - return null; - } - - @Override - public Capabilities getCapabilities() { - - final Map capabilities = new HashMap<>(); - - // These are needed to map the proxy element to a MobileElement. - capabilities.put(CapabilityType.PLATFORM_NAME, Platform.ANY.toString()); - capabilities.put(MobileCapabilityType.AUTOMATION_NAME, - AutomationName.IOS_XCUI_TEST.toString()); - - return new Capabilities() { - - @Override - public Object getCapability(String capabilityName) { - return capabilities.get(capabilityName); - } - - @Override - public Map asMap() { - return capabilities; - } - }; - } - } - - @Test - public void noGenericsTestCase() { - TempNoGenericsPage page = new TempNoGenericsPage(); - PageFactory.initElements(new AppiumFieldDecorator(new MockWebDriver()), page); - page.assertInit(); - } - - @Test - public void unBoundTestCase() { - TempUnboundPage page = new TempUnboundPage<>(); - PageFactory.initElements(new AppiumFieldDecorator(new MockWebDriver()), page); - page.assertInit(); - } - - @Test - public void unboundWebElementTestCase() { - TempUnboundPage page = new TempUnboundPage<>(); - PageFactory.initElements(new AppiumFieldDecorator(new MockWebDriver()), page); - page.assertInit(); - } - - @Test - public void webBoundUnknownElementTestCase() { - TempWebBoundPage page = new TempWebBoundPage<>(); - PageFactory.initElements(new AppiumFieldDecorator(new MockWebDriver()), page); - page.assertInit(); - } - - @Test - public void webBoundWebElementTestCase() { - TempWebBoundPage page = new TempWebBoundPage<>(); - PageFactory.initElements(new AppiumFieldDecorator(new MockWebDriver()), page); - page.assertInit(); - } - - @Test - public void webBoundMobileElementTestCase() { - TempWebBoundPage page = new TempWebBoundPage<>(); - PageFactory.initElements(new AppiumFieldDecorator(new MockWebDriver()), page); - page.assertInit(); - } - - @Test - public void mobileBoundUnknownElementTestCase() { - TempMobileBoundPage page = new TempMobileBoundPage<>(); - PageFactory.initElements(new AppiumFieldDecorator(new MockWebDriver()), page); - page.assertInit(); - } - - @Test - public void mobileBoundMobileElementTestCase() { - TempMobileBoundPage page = new TempMobileBoundPage<>(); - PageFactory.initElements(new AppiumFieldDecorator(new MockWebDriver()), page); - page.assertInit(); - } -} diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java index 4be99b958..8c4b5cf30 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java @@ -66,7 +66,7 @@ public class MobileBrowserCompatibilityTest { DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, MobileBrowserType.BROWSER); - driver = new AndroidDriver(service.getUrl(), capabilities); + driver = new AndroidDriver(service.getUrl(), capabilities); //This time out is set because test can be run on slow Android SDK emulator PageFactory.initElements(new AppiumFieldDecorator(driver, ofSeconds(5)), this); } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java index ee2324256..547cb4840 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java @@ -17,6 +17,7 @@ package io.appium.java_client.pagefactory_tests; +import static io.appium.java_client.TestUtils.setElementValue; import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE; import static io.appium.java_client.pagefactory.LocatorGroupStrategy.CHAIN; import static org.hamcrest.MatcherAssert.assertThat; @@ -28,7 +29,6 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import io.appium.java_client.MobileElement; import io.appium.java_client.ios.AppIOSTest; import io.appium.java_client.pagefactory.AppiumFieldDecorator; import io.appium.java_client.pagefactory.HowToUseLocators; @@ -38,6 +38,7 @@ import org.junit.Test; import org.junit.runners.MethodSorters; import org.openqa.selenium.WebElement; +import org.openqa.selenium.remote.RemoteWebElement; import org.openqa.selenium.support.PageFactory; import org.openqa.selenium.support.ui.WebDriverWait; @@ -52,45 +53,45 @@ public class XCUITModeTest extends AppIOSTest { @HowToUseLocators(iOSXCUITAutomation = ALL_POSSIBLE) @iOSXCUITFindBy(iOSNsPredicate = "label contains 'Compute'") @iOSXCUITFindBy(className = "XCUIElementTypeButton") - private MobileElement computeButton; + private WebElement computeButton; @HowToUseLocators(iOSXCUITAutomation = CHAIN) @iOSXCUITFindBy(iOSNsPredicate = "name like 'Answer'") private WebElement answer; @iOSXCUITFindBy(iOSNsPredicate = "name = 'IntegerA'") - private MobileElement textField1; + private WebElement textField1; @HowToUseLocators(iOSXCUITAutomation = ALL_POSSIBLE) @iOSXCUITFindBy(iOSNsPredicate = "name = 'IntegerB'") @iOSXCUITFindBy(accessibility = "IntegerB") - private MobileElement textField2; + private WebElement textField2; @iOSXCUITFindBy(iOSNsPredicate = "name ENDSWITH 'Gesture'") - private MobileElement gesture; + private WebElement gesture; @iOSXCUITFindBy(className = "XCUIElementTypeSlider") - private MobileElement slider; + private WebElement slider; @iOSXCUITFindBy(id = "locationStatus") - private MobileElement locationStatus; + private WebElement locationStatus; @HowToUseLocators(iOSXCUITAutomation = CHAIN) @iOSXCUITFindBy(iOSNsPredicate = "name BEGINSWITH 'contact'") - private MobileElement contactAlert; + private WebElement contactAlert; @HowToUseLocators(iOSXCUITAutomation = ALL_POSSIBLE) @iOSXCUITFindBy(iOSNsPredicate = "name BEGINSWITH 'location'") - private MobileElement locationAlert; + private WebElement locationAlert; @iOSXCUITFindBy(iOSClassChain = "XCUIElementTypeWindow/*/XCUIElementTypeTextField[2]") - private MobileElement secondTextField; + private WebElement secondTextField; @iOSXCUITFindBy(iOSClassChain = "XCUIElementTypeWindow/*/XCUIElementTypeButton[-1]") - private MobileElement lastButton; + private WebElement lastButton; @iOSXCUITFindBy(iOSClassChain = "XCUIElementTypeWindow/*/XCUIElementTypeButton") - private List allButtons; + private List allButtons; /** * The setting up. @@ -144,8 +145,8 @@ public class XCUITModeTest extends AppIOSTest { } @Test public void setValueTest() { - textField1.setValue("2"); - textField2.setValue("4"); + setElementValue(driver, (RemoteWebElement) textField1, "2"); + setElementValue(driver, (RemoteWebElement) textField2, "4"); driver.hideKeyboard(); computeButton.click(); assertEquals("6", answer.getText()); diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java index 7e3d5783a..b9b9d097e 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java @@ -8,12 +8,13 @@ import static io.appium.java_client.remote.MobilePlatform.WINDOWS; import static org.apache.commons.lang3.StringUtils.EMPTY; -import io.appium.java_client.HasSessionDetails; +import io.appium.java_client.HasBrowserCheck; import org.openqa.selenium.By; import org.openqa.selenium.Capabilities; import org.openqa.selenium.Cookie; import org.openqa.selenium.HasCapabilities; import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; import org.openqa.selenium.logging.Logs; import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.remote.Response; @@ -25,7 +26,9 @@ import java.util.Set; import java.util.concurrent.TimeUnit; -public abstract class AbstractStubWebDriver implements WebDriver, HasSessionDetails, +public abstract class AbstractStubWebDriver implements + WebDriver, + HasBrowserCheck, HasCapabilities { @Override public Response execute(String driverCommand, Map parameters) { @@ -37,12 +40,6 @@ public Response execute(String driverCommand) { return null; } - @Override - public abstract String getPlatformName(); - - @Override - public abstract String getAutomationName(); - @Override public boolean isBrowser() { return false; @@ -64,7 +61,7 @@ public String getTitle() { } @Override - public List findElements(By by) { + public List findElements(By by) { return of(new StubWebElement(this, by), new StubWebElement(this, by)); } @@ -108,6 +105,14 @@ public Navigation navigate() { return null; } + public String getPlatformName() { + return ""; + } + + public String getAutomationName() { + return ""; + } + @Override public Capabilities getCapabilities() { Map caps = new HashMap<>(); diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/StubWebElement.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/StubWebElement.java index 52aa50807..cffb170fd 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/StubWebElement.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/StubWebElement.java @@ -70,7 +70,7 @@ public String getText() { } @Override - public List findElements(By by) { + public List findElements(By by) { return of(new StubWebElement(driver, by), new StubWebElement(driver, by)); } diff --git a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java index 612db0aed..7f0bdf590 100644 --- a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java +++ b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java @@ -44,7 +44,7 @@ public class StartingAppLocallyTest { @Test public void startingAndroidAppWithCapabilitiesOnlyTest() { - AndroidDriver driver = new AndroidDriver<>(new UiAutomator2Options() + AndroidDriver driver = new AndroidDriver(new UiAutomator2Options() .setDeviceName("Android Emulator") .autoGrantPermissions() .setApp(apiDemosApk().toAbsolutePath().toString())); @@ -68,7 +68,7 @@ public void startingAndroidAppWithCapabilitiesAndServiceTest() { .withArgument(GeneralServerFlag.SESSION_OVERRIDE) .withArgument(GeneralServerFlag.STRICT_CAPS); - AndroidDriver driver = new AndroidDriver<>(builder, new UiAutomator2Options() + AndroidDriver driver = new AndroidDriver(builder, new UiAutomator2Options() .setDeviceName("Android Emulator") .autoGrantPermissions() .setApp(apiDemosApk().toAbsolutePath().toString())); @@ -106,7 +106,7 @@ public void startingAndroidAppWithCapabilitiesAndFlagsOnServerSideTest() { .setAppPackage("io.appium.android.apis") .setAppActivity(".view.WebView1"); - AndroidDriver driver = new AndroidDriver<>(builder, clientOptions); + AndroidDriver driver = new AndroidDriver(builder, clientOptions); try { Capabilities caps = driver.getCapabilities(); @@ -130,7 +130,7 @@ public void startingIOSAppWithCapabilitiesOnlyTest() { capabilities.setCapability(MobileCapabilityType.APP, uiCatalogAppZip().toAbsolutePath().toString()); capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST); - IOSDriver driver = new IOSDriver<>(capabilities); + IOSDriver driver = new IOSDriver(capabilities); try { Capabilities caps = driver.getCapabilities(); @@ -160,7 +160,7 @@ public void startingIOSAppWithCapabilitiesAndServiceTest() { .withArgument(GeneralServerFlag.SESSION_OVERRIDE) .withArgument(GeneralServerFlag.STRICT_CAPS); - IOSDriver driver = new IOSDriver<>(builder, capabilities); + IOSDriver driver = new IOSDriver(builder, capabilities); try { Capabilities caps = driver.getCapabilities(); assertTrue(caps.getCapability(MobileCapabilityType.PLATFORM_NAME) @@ -188,7 +188,7 @@ public void startingIOSAppWithCapabilitiesAndFlagsOnServerSideTest() { .withArgument(GeneralServerFlag.SESSION_OVERRIDE) .withArgument(GeneralServerFlag.STRICT_CAPS).withCapabilities(serverCapabilities); - IOSDriver driver = new IOSDriver<>(builder, clientCapabilities); + IOSDriver driver = new IOSDriver(builder, clientCapabilities); try { Capabilities caps = driver.getCapabilities(); assertTrue(caps.getCapability(MobileCapabilityType.PLATFORM_NAME) From 853cec43d9bbc138b24aa7a220683cf51adfb0f8 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 27 Oct 2021 08:54:02 +0200 Subject: [PATCH 2/7] Do not check rotation --- .../io/appium/java_client/remote/SupportsRotation.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/main/java/io/appium/java_client/remote/SupportsRotation.java b/src/main/java/io/appium/java_client/remote/SupportsRotation.java index 8cccb8f16..c61279856 100644 --- a/src/main/java/io/appium/java_client/remote/SupportsRotation.java +++ b/src/main/java/io/appium/java_client/remote/SupportsRotation.java @@ -37,12 +37,7 @@ public interface SupportsRotation extends WebDriver, ExecutesMethod, Rotatable { default DeviceRotation rotation() { Response response = execute(DriverCommand.GET_SCREEN_ROTATION); //noinspection unchecked - DeviceRotation deviceRotation = - new DeviceRotation((Map) response.getValue()); - if (deviceRotation.getX() < 0 || deviceRotation.getY() < 0 || deviceRotation.getZ() < 0) { - throw new WebDriverException("Unexpected orientation returned: " + deviceRotation); - } - return deviceRotation; + return new DeviceRotation((Map) response.getValue()); } default void rotate(DeviceRotation rotation) { From 7b4fe061eb27698535cf8161bf75a76f46b6ea25 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 27 Oct 2021 08:55:38 +0200 Subject: [PATCH 3/7] Tune orientation retrieval --- .../appium/java_client/remote/SupportsRotation.java | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/main/java/io/appium/java_client/remote/SupportsRotation.java b/src/main/java/io/appium/java_client/remote/SupportsRotation.java index c61279856..8ac22a707 100644 --- a/src/main/java/io/appium/java_client/remote/SupportsRotation.java +++ b/src/main/java/io/appium/java_client/remote/SupportsRotation.java @@ -22,7 +22,6 @@ import org.openqa.selenium.Rotatable; import org.openqa.selenium.ScreenOrientation; import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.DriverCommand; import org.openqa.selenium.remote.Response; @@ -56,13 +55,7 @@ default void rotate(ScreenOrientation orientation) { */ default ScreenOrientation getOrientation() { Response response = execute(DriverCommand.GET_SCREEN_ORIENTATION); - String orientation = response.getValue().toString().toLowerCase(); - if (orientation.equals(ScreenOrientation.LANDSCAPE.value())) { - return ScreenOrientation.LANDSCAPE; - } else if (orientation.equals(ScreenOrientation.PORTRAIT.value())) { - return ScreenOrientation.PORTRAIT; - } else { - throw new WebDriverException("Unexpected orientation returned: " + orientation); - } + String orientation = String.valueOf(response.getValue()); + return ScreenOrientation.valueOf(orientation.toUpperCase()); } } From 4045c205e71f007e27ffc3723989b31832b27ee4 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 27 Oct 2021 11:19:48 +0200 Subject: [PATCH 4/7] Add a helper to set element value --- .../io/appium/java_client/AppiumDriver.java | 7 ++-- .../java_client/CanSetElementValue.java | 35 +++++++++++++++++++ .../io/appium/java_client/ExecutesMethod.java | 8 ++--- .../io/appium/java_client/MobileCommand.java | 2 +- .../java_client/android/AndroidDriver.java | 4 +-- .../io/appium/java_client/mac/Mac2Driver.java | 3 +- .../java_client/windows/WindowsDriver.java | 1 - .../java/io/appium/java_client/TestUtils.java | 9 ----- .../java_client/ios/IOSElementTest.java | 3 +- .../pagefactory_tests/XCUITModeTest.java | 8 ++--- 10 files changed, 50 insertions(+), 30 deletions(-) create mode 100644 src/main/java/io/appium/java_client/CanSetElementValue.java diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index c85cb147c..0ed7c7fd3 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -18,8 +18,6 @@ import static io.appium.java_client.remote.MobileCapabilityType.PLATFORM_NAME; -import com.google.common.collect.ImmutableMap; - import io.appium.java_client.remote.AppiumCommandExecutor; import io.appium.java_client.remote.AppiumNewSessionCommandPayload; import io.appium.java_client.remote.MobileCapabilityType; @@ -44,19 +42,20 @@ import java.lang.reflect.Field; import java.net.URL; import java.util.Arrays; +import java.util.Collections; import java.util.Map; /** * Default Appium driver implementation. * */ -@SuppressWarnings("unchecked") public class AppiumDriver extends RemoteWebDriver implements WebDriver, ExecutesMethod, ComparesImages, ExecutesDriverScript, LogsEvents, + CanSetElementValue, HasBrowserCheck, HasSettings { @@ -223,6 +222,6 @@ public Response execute(String driverCommand, Map parameters) { @Override public Response execute(String command) { - return super.execute(command, ImmutableMap.of()); + return super.execute(command, Collections.emptyMap()); } } diff --git a/src/main/java/io/appium/java_client/CanSetElementValue.java b/src/main/java/io/appium/java_client/CanSetElementValue.java new file mode 100644 index 000000000..45a7916b3 --- /dev/null +++ b/src/main/java/io/appium/java_client/CanSetElementValue.java @@ -0,0 +1,35 @@ +/* + * 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 com.google.common.collect.ImmutableMap; +import org.openqa.selenium.remote.RemoteWebElement; + +public interface CanSetElementValue extends ExecutesMethod { + /** + * Set a value to an element. + * + * @param webElement Web element instance. + * @param value Value to set. + */ + default void setElementValue(RemoteWebElement webElement, String value) { + this.execute(MobileCommand.SET_VALUE, ImmutableMap.of( + "id", webElement.getId(), + "value", value + )); + } +} diff --git a/src/main/java/io/appium/java_client/ExecutesMethod.java b/src/main/java/io/appium/java_client/ExecutesMethod.java index 1f49276bc..f0bd981ca 100644 --- a/src/main/java/io/appium/java_client/ExecutesMethod.java +++ b/src/main/java/io/appium/java_client/ExecutesMethod.java @@ -22,18 +22,18 @@ public interface ExecutesMethod { /** - * Executes JSONWP command and returns a response. + * Executes the given command and returns a response. * - * @param driverCommand a JSONWP command + * @param driverCommand a command to execute * @param parameters map of command parameters * @return a result response */ Response execute(String driverCommand, Map parameters); /** - * Executes JSONWP command and returns a response. + * Executes the given command and returns a response. * - * @param driverCommand a JSONWP command + * @param driverCommand a command to execute * @return a result response */ Response execute(String driverCommand); diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index f601aaab7..8442d7da4 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -41,7 +41,7 @@ public class MobileCommand { //General protected static final String RESET; protected static final String GET_STRINGS; - protected static final String SET_VALUE; + public static final String SET_VALUE; protected static final String PULL_FILE; protected static final String PULL_FOLDER; public static final String RUN_APP_IN_BACKGROUND; 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 a570e2832..a57ad8880 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -58,8 +58,8 @@ /** * Android driver implementation. */ -public class AndroidDriver extends AppiumDriver - implements PressesKey, +public class AndroidDriver extends AppiumDriver implements + PressesKey, SupportsRotation, SupportsContextSwitching, SupportsLocation, 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 4808f8f5e..3df534092 100644 --- a/src/main/java/io/appium/java_client/mac/Mac2Driver.java +++ b/src/main/java/io/appium/java_client/mac/Mac2Driver.java @@ -44,7 +44,8 @@ * * @since Appium 1.20.0 */ -public class Mac2Driver extends AppiumDriver implements CanRecordScreen, HasSettings { +public class Mac2Driver extends AppiumDriver implements + CanRecordScreen { public Mac2Driver(HttpCommandExecutor executor, Capabilities capabilities) { super(executor, prepareCaps(capabilities)); } 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 e96bd4121..032ce91cd 100644 --- a/src/main/java/io/appium/java_client/windows/WindowsDriver.java +++ b/src/main/java/io/appium/java_client/windows/WindowsDriver.java @@ -24,7 +24,6 @@ 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.HttpCommandExecutor; import org.openqa.selenium.remote.http.HttpClient; diff --git a/src/test/java/io/appium/java_client/TestUtils.java b/src/test/java/io/appium/java_client/TestUtils.java index 6b7b616c5..f2ed2792e 100644 --- a/src/test/java/io/appium/java_client/TestUtils.java +++ b/src/test/java/io/appium/java_client/TestUtils.java @@ -1,11 +1,9 @@ package io.appium.java_client; -import com.google.common.collect.ImmutableMap; import org.openqa.selenium.Dimension; import org.openqa.selenium.Point; import org.openqa.selenium.TimeoutException; import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.RemoteWebElement; import javax.annotation.Nullable; import java.io.IOException; @@ -82,11 +80,4 @@ public static Point getCenter(WebElement webElement, @Nullable Point location) { } return new Point(location.x + dim.width / 2, location.y + dim.height / 2); } - - public static void setElementValue(ExecutesMethod driver, RemoteWebElement webElement, String value) { - driver.execute(MobileCommand.SET_VALUE, ImmutableMap.of( - "id", webElement.getId(), - "value", value - )); - } } diff --git a/src/test/java/io/appium/java_client/ios/IOSElementTest.java b/src/test/java/io/appium/java_client/ios/IOSElementTest.java index 121e2b7d0..e1c013217 100644 --- a/src/test/java/io/appium/java_client/ios/IOSElementTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSElementTest.java @@ -1,6 +1,5 @@ package io.appium.java_client.ios; -import static io.appium.java_client.TestUtils.setElementValue; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; @@ -34,7 +33,7 @@ public void setValueTest() { WebElement slider = wait.until( driver1 -> driver1.findElement(MobileBy.className("XCUIElementTypeSlider"))); - setElementValue(driver, (RemoteWebElement) slider, "0%"); + driver.setElementValue((RemoteWebElement) slider, "0%"); assertEquals("0%", slider.getAttribute("value")); } } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java index 547cb4840..aa72d203e 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java @@ -14,10 +14,8 @@ * limitations under the License. */ - package io.appium.java_client.pagefactory_tests; -import static io.appium.java_client.TestUtils.setElementValue; import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE; import static io.appium.java_client.pagefactory.LocatorGroupStrategy.CHAIN; import static org.hamcrest.MatcherAssert.assertThat; @@ -40,7 +38,6 @@ import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.RemoteWebElement; import org.openqa.selenium.support.PageFactory; -import org.openqa.selenium.support.ui.WebDriverWait; import java.util.List; @@ -48,7 +45,6 @@ public class XCUITModeTest extends AppIOSTest { private boolean populated = false; - private WebDriverWait waiting = new WebDriverWait(driver, 10); @HowToUseLocators(iOSXCUITAutomation = ALL_POSSIBLE) @iOSXCUITFindBy(iOSNsPredicate = "label contains 'Compute'") @@ -145,8 +141,8 @@ public class XCUITModeTest extends AppIOSTest { } @Test public void setValueTest() { - setElementValue(driver, (RemoteWebElement) textField1, "2"); - setElementValue(driver, (RemoteWebElement) textField2, "4"); + driver.setElementValue((RemoteWebElement) textField1, "2"); + driver.setElementValue((RemoteWebElement) textField2, "4"); driver.hideKeyboard(); computeButton.click(); assertEquals("6", answer.getText()); From aafc93847fa14f3769da18362f4db9a7671c489b Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 27 Oct 2021 11:34:23 +0200 Subject: [PATCH 5/7] Tune caps merging --- .../io/appium/java_client/AppiumDriver.java | 15 ++++++-------- .../io/appium/java_client/mac/Mac2Driver.java | 20 ++++++++----------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index 0ed7c7fd3..0fc29c020 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -24,11 +24,11 @@ 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.ImmutableCapabilities; import org.openqa.selenium.MutableCapabilities; import org.openqa.selenium.SessionNotCreatedException; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriverException; -import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.remote.DriverCommand; import org.openqa.selenium.remote.ErrorHandler; import org.openqa.selenium.remote.ExecuteMethod; @@ -47,7 +47,6 @@ /** * Default Appium driver implementation. - * */ public class AppiumDriver extends RemoteWebDriver implements WebDriver, @@ -131,12 +130,9 @@ public AppiumDriver(Capabilities desiredCapabilities) { */ protected static Capabilities updateDefaultPlatformName(Capabilities originalCapabilities, String defaultName) { - if (originalCapabilities.getCapability(PLATFORM_NAME) == null) { - DesiredCapabilities dc = new DesiredCapabilities(originalCapabilities); - dc.setCapability(PLATFORM_NAME, defaultName); - return dc; - } - return originalCapabilities; + return originalCapabilities.getCapability(PLATFORM_NAME) == null + ? originalCapabilities.merge(new ImmutableCapabilities(PLATFORM_NAME, defaultName)) + : originalCapabilities; } @Override @@ -150,6 +146,7 @@ public ExecuteMethod getExecuteMethod() { * @return map containing version details */ public Map getStatus() { + //noinspection unchecked return (Map) execute(DriverCommand.STATUS).getValue(); } @@ -157,7 +154,7 @@ public Map getStatus() { * 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 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) { 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 3df534092..9ad2b368c 100644 --- a/src/main/java/io/appium/java_client/mac/Mac2Driver.java +++ b/src/main/java/io/appium/java_client/mac/Mac2Driver.java @@ -17,7 +17,6 @@ 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; @@ -25,8 +24,7 @@ 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.ImmutableCapabilities; import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.http.HttpClient; @@ -85,16 +83,14 @@ public Mac2Driver(Capabilities 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; + return (originalCaps.getCapability(PLATFORM_NAME) == null + || !AutomationName.MAC2.equalsIgnoreCase(automationName)) + ? originalCaps.merge(new ImmutableCapabilities( + PLATFORM_NAME, MAC, + MobileCapabilityType.AUTOMATION_NAME, AutomationName.MAC2 + )) + : originalCaps; } } From 16da49e6971d29bba7ceb49865808a89ecbbdd5e Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 27 Oct 2021 12:03:04 +0200 Subject: [PATCH 6/7] Add docstring --- .../appium/java_client/android/CanReplaceElementValue.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java b/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java index 5b620ac64..72a170f32 100644 --- a/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java +++ b/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java @@ -6,6 +6,12 @@ import org.openqa.selenium.remote.RemoteWebElement; public interface CanReplaceElementValue extends ExecutesMethod { + /** + * Replaces element value with the given one. + * + * @param element The destination element. + * @param value The value to set. + */ default void replaceElementValue(RemoteWebElement element, String value) { this.execute(MobileCommand.REPLACE_VALUE, ImmutableMap.of( "id", element.getId(), From c57b51b41836b964a5b36fdc53e04917acb61908 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 27 Oct 2021 12:04:16 +0200 Subject: [PATCH 7/7] Remove extra interface --- src/main/java/io/appium/java_client/AppiumDriver.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index 0fc29c020..cd987ca94 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -27,7 +27,6 @@ import org.openqa.selenium.ImmutableCapabilities; import org.openqa.selenium.MutableCapabilities; import org.openqa.selenium.SessionNotCreatedException; -import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.DriverCommand; import org.openqa.selenium.remote.ErrorHandler; @@ -49,7 +48,6 @@ * Default Appium driver implementation. */ public class AppiumDriver extends RemoteWebDriver implements - WebDriver, ExecutesMethod, ComparesImages, ExecutesDriverScript,