From 1c83dfb6ac78cb43fdea02c3c40f34dc03653aee Mon Sep 17 00:00:00 2001 From: Jonathan Lipps Date: Tue, 16 Oct 2018 21:46:51 -0700 Subject: [PATCH 1/4] add custom locator strategy --- .../io/appium/java_client/AppiumDriver.java | 2 +- .../io/appium/java_client/FindsByCustom.java | 50 ++++++++++++++ .../java/io/appium/java_client/MobileBy.java | 66 +++++++++++++++++++ .../io/appium/java_client/MobileSelector.java | 3 +- 4 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 src/main/java/io/appium/java_client/FindsByCustom.java diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index 97b05d27b..854d76239 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -64,7 +64,7 @@ */ @SuppressWarnings("unchecked") public class AppiumDriver - extends DefaultGenericMobileDriver implements ComparesImages, FindsByImage { + extends DefaultGenericMobileDriver implements ComparesImages, FindsByImage, FindsByCustom { private static final ErrorHandler errorHandler = new ErrorHandler(new ErrorCodesMobile(), true); // frequently used command parameters diff --git a/src/main/java/io/appium/java_client/FindsByCustom.java b/src/main/java/io/appium/java_client/FindsByCustom.java new file mode 100644 index 000000000..663f0ec5e --- /dev/null +++ b/src/main/java/io/appium/java_client/FindsByCustom.java @@ -0,0 +1,50 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appium.java_client; + +import java.util.List; +import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.WebElement; + +public interface FindsByCustom extends FindsByFluentSelector { + /** + * Performs the lookup for a single element by sending a selector to a custom element finding + * plugin. This type of locator requires the use of the 'customFindModules' capability and a + * separately-installed element finding plugin. + * + * @param selector selector to pass to the custom element finding plugin + * @return The first element that matches the given selector + * @throws NoSuchElementException when no element is found + * @since Appium 1.9.2 + */ + default T findElementByCustom(String selector) { + return findElement(MobileSelector.IMAGE.toString(), selector); + } + + /** + * Performs the lookup for a single element by sending a selector to a custom element finding + * plugin. This type of locator requires the use of the 'customFindModules' capability and a + * separately-installed element finding plugin. + * + * @param selector selector to pass to the custom element finding plugin + * @return a list of elements that match the given selector or an empty list + * @since Appium 1.9.2 + */ + default List findElementsByCustom(String selector) { + return findElements(MobileSelector.IMAGE.toString(), selector); + } +} \ No newline at end of file diff --git a/src/main/java/io/appium/java_client/MobileBy.java b/src/main/java/io/appium/java_client/MobileBy.java index 6a65034a3..92c2f815a 100644 --- a/src/main/java/io/appium/java_client/MobileBy.java +++ b/src/main/java/io/appium/java_client/MobileBy.java @@ -147,6 +147,16 @@ public static By AndroidViewTag(final String tag) { public static By image(final String b64Template) { return new ByImage(b64Template); } + + /** + * This type of locator requires the use of the 'customFindModules' capability and a + * separately-installed element finding plugin. + * + * @param selector selector to pass to the custom element finding plugin + * @return an instance of {@link ByCustom} + * @since Appium 1.9.2 + */ + public static By custom(final String selector) { return new ByCustom(selector); } public static class ByIosUIAutomation extends MobileBy implements Serializable { @@ -572,6 +582,62 @@ protected ByImage(String b64Template) { } } + public static class ByCustom extends MobileBy implements Serializable { + + protected ByCustom(String selector) { + super(MobileSelector.CUSTOM, selector); + } + + /** + * {@inheritDoc} + * + * @throws WebDriverException when current session doesn't support the given selector or when + * value of the selector is not consistent. + * @throws IllegalArgumentException when it is impossible to find something on the given + * {@link SearchContext} instance + */ + @SuppressWarnings("unchecked") + @Override public List findElements(SearchContext context) { + Class contextClass = context.getClass(); + + if (FindsByCustom.class.isAssignableFrom(contextClass)) { + return FindsByCustom.class.cast(context).findElementsByCustom(getLocatorString()); + } + + if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { + return super.findElements(context); + } + + throw formIllegalArgumentException(contextClass, FindsByCustom.class, FindsByFluentSelector.class); + } + + /** + * {@inheritDoc} + * + * @throws WebDriverException when current session doesn't support the given selector or when + * value of the selector is not consistent. + * @throws IllegalArgumentException when it is impossible to find something on the given + * {@link SearchContext} instance + */ + @Override public WebElement findElement(SearchContext context) { + Class contextClass = context.getClass(); + + if (FindsByCustom.class.isAssignableFrom(contextClass)) { + return FindsByCustom.class.cast(context).findElementByCustom(getLocatorString()); + } + + if (FindsByFluentSelector.class.isAssignableFrom(contextClass)) { + return super.findElement(context); + } + + throw formIllegalArgumentException(contextClass, FindsByCustom.class, FindsByFluentSelector.class); + } + + @Override public String toString() { + return "By.Custom: " + getLocatorString(); + } + } + public static class ByAndroidViewTag extends MobileBy implements Serializable { public ByAndroidViewTag(String tag) { diff --git a/src/main/java/io/appium/java_client/MobileSelector.java b/src/main/java/io/appium/java_client/MobileSelector.java index f7d7bbb49..3ecb28461 100644 --- a/src/main/java/io/appium/java_client/MobileSelector.java +++ b/src/main/java/io/appium/java_client/MobileSelector.java @@ -24,7 +24,8 @@ public enum MobileSelector { IOS_CLASS_CHAIN("-ios class chain"), WINDOWS_UI_AUTOMATION("-windows uiautomation"), IMAGE("-image"), - ANDROID_VIEWTAG("-android viewtag"); + ANDROID_VIEWTAG("-android viewtag"), + CUSTOM("-custom"); private final String selector; From 6af8d74b1f5f143bb94c976ec5adab6a21953bf6 Mon Sep 17 00:00:00 2001 From: Jonathan Lipps Date: Wed, 17 Oct 2018 12:03:06 -0700 Subject: [PATCH 2/4] use correct strategy constant --- src/main/java/io/appium/java_client/FindsByCustom.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/appium/java_client/FindsByCustom.java b/src/main/java/io/appium/java_client/FindsByCustom.java index 663f0ec5e..63d87e743 100644 --- a/src/main/java/io/appium/java_client/FindsByCustom.java +++ b/src/main/java/io/appium/java_client/FindsByCustom.java @@ -32,7 +32,7 @@ public interface FindsByCustom extends FindsByFluentSelect * @since Appium 1.9.2 */ default T findElementByCustom(String selector) { - return findElement(MobileSelector.IMAGE.toString(), selector); + return findElement(MobileSelector.CUSTOM.toString(), selector); } /** @@ -45,6 +45,6 @@ default T findElementByCustom(String selector) { * @since Appium 1.9.2 */ default List findElementsByCustom(String selector) { - return findElements(MobileSelector.IMAGE.toString(), selector); + return findElements(MobileSelector.CUSTOM.toString(), selector); } } \ No newline at end of file From 01f1380040c6ef5a18e3166bc679b578fb1a64c6 Mon Sep 17 00:00:00 2001 From: Jonathan Lipps Date: Wed, 17 Oct 2018 12:10:18 -0700 Subject: [PATCH 3/4] fix lint issues --- src/main/java/io/appium/java_client/FindsByCustom.java | 3 ++- src/main/java/io/appium/java_client/MobileBy.java | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/appium/java_client/FindsByCustom.java b/src/main/java/io/appium/java_client/FindsByCustom.java index 63d87e743..93285562d 100644 --- a/src/main/java/io/appium/java_client/FindsByCustom.java +++ b/src/main/java/io/appium/java_client/FindsByCustom.java @@ -16,10 +16,11 @@ package io.appium.java_client; -import java.util.List; import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.WebElement; +import java.util.List; + public interface FindsByCustom extends FindsByFluentSelector { /** * Performs the lookup for a single element by sending a selector to a custom element finding diff --git a/src/main/java/io/appium/java_client/MobileBy.java b/src/main/java/io/appium/java_client/MobileBy.java index 92c2f815a..1fd80ea15 100644 --- a/src/main/java/io/appium/java_client/MobileBy.java +++ b/src/main/java/io/appium/java_client/MobileBy.java @@ -156,7 +156,9 @@ public static By image(final String b64Template) { * @return an instance of {@link ByCustom} * @since Appium 1.9.2 */ - public static By custom(final String selector) { return new ByCustom(selector); } + public static By custom(final String selector) { + return new ByCustom(selector); + } public static class ByIosUIAutomation extends MobileBy implements Serializable { From 969fac6a1c6dd229bdefb02ff10e71c812701e0c Mon Sep 17 00:00:00 2001 From: Jonathan Lipps Date: Wed, 17 Oct 2018 21:16:05 -0700 Subject: [PATCH 4/4] add doc links --- src/main/java/io/appium/java_client/FindsByCustom.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/io/appium/java_client/FindsByCustom.java b/src/main/java/io/appium/java_client/FindsByCustom.java index 93285562d..f908fc424 100644 --- a/src/main/java/io/appium/java_client/FindsByCustom.java +++ b/src/main/java/io/appium/java_client/FindsByCustom.java @@ -29,6 +29,8 @@ public interface FindsByCustom extends FindsByFluentSelect * * @param selector selector to pass to the custom element finding plugin * @return The first element that matches the given selector + * @see + * The documentation on custom element finding plugins and their use * @throws NoSuchElementException when no element is found * @since Appium 1.9.2 */ @@ -43,6 +45,8 @@ default T findElementByCustom(String selector) { * * @param selector selector to pass to the custom element finding plugin * @return a list of elements that match the given selector or an empty list + * @see + * The documentation on custom element finding plugins and their use * @since Appium 1.9.2 */ default List findElementsByCustom(String selector) {