Skip to content
63 changes: 62 additions & 1 deletion docs/Page-objects.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ RemoteWebElement someElement;
List<RemoteWebElement> someElements;
```

## Also possible combined variants:
## Also possible combined variants for target platforms:

```java
import org.openqa.selenium.remote.RemoteWebElement;
Expand Down Expand Up @@ -194,6 +194,67 @@ RemoteWebElement someElement;
List<RemoteWebElement> someElements;
```

## Mixed chain/any locator strategy

Some locator-element could not be defined certainly sometimes. It may be defined as one of possible variants/chained locator.
If the using of _xpath_ is not convenient for some reasons so there are possible use cases

### the chained searching

```java
import org.openqa.selenium.remote.RemoteWebElement;
import io.appium.java_client.pagefactory.*;
import org.openqa.selenium.support.FindBys;
import org.openqa.selenium.support.FindBy;

//it is necessary to define priorities at this case. The lower number means the higher priority.
//The default value is 0 (the highest priority)
@iOSFindBy(someStrategy1)
@iOSFindAll(value = {@iOSBy(subloctor1), @iOSBy(subloctor1)}, priority = 1) //it means that the chained searching contains
//the searching by all possible locators as the element of the chain
@iOSFindBy(someStrategy2, priority = 2)
@iOSFindBy(someStrategy3, priority = 3)
RemoteWebElement someElement;


@iOSFindBy(someStrategy1)
@iOSFindAll(value = {@iOSBy(subloctor1), @iOSBy(subloctor1)}, priority = 1) //it means that the chained searching contains
//the searching by all possible locators as the element of the chain
@iOSFindBy(someStrategy2, priority = 2)
@iOSFindBy(someStrategy3, priority = 3)
List<RemoteWebElement> someElements;
```

### all possible

```java
import org.openqa.selenium.remote.RemoteWebElement;
import io.appium.java_client.pagefactory.*;
import org.openqa.selenium.support.FindBys;
import org.openqa.selenium.support.FindBy;

//it is not necessary to define priorities at this case. But it can manage the searching.
//The lower number means the higher priority.
//The default value is 0 (the highest priority)
@HowToUseLocators(iOSAutomation = ALL_POSSIBLE)
@iOSFindBy(someStrategy1)
@iOSFindBys(value = {@iOSBy(subloctor1), @iOSBy(subloctor1)}, priority = 1) //it means that the searching by all possible locators
// contains the searching by chained locator as one of all possible variants
@iOSFindBy(someStrategy2, priority = 2)
@iOSFindBy(someStrategy3, priority = 3)
RemoteWebElement someElement;



@HowToUseLocators(iOSAutomation = ALL_POSSIBLE)
@iOSFindBy(someStrategy1)
@iOSFindBys(value = {@iOSBy(subloctor1), @iOSBy(subloctor1)}, priority = 1) //it means that the searching by all possible locators
// contains the searching by chained locator as one of all possible variants
@iOSFindBy(someStrategy2, priority = 2)
@iOSFindBy(someStrategy3, priority = 3)
List<RemoteWebElement> someElements;
```

# Appium Java client is integrated with Selenium PageFactory by AppiumFieldDecorator.

Object fields are populated as below:
Expand Down
2 changes: 1 addition & 1 deletion google-style.xml
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
value="Package name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="TypeName">
<property name="format" value="^([iOSFindBys]||[iOSFindBy]||[iOSFindAll])||([A-Z][a-zA-Z0-9])*$"/>
<property name="format" value="^([*iOSFindBy*]||[*iOSXCUITFind*])||([A-Z][a-zA-Z0-9])*$"/>
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
</module>
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/io/appium/java_client/ScreenshotState.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package io.appium.java_client;

import static nu.pattern.OpenCV.loadShared;

import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
Expand All @@ -32,8 +34,6 @@
import java.util.function.Function;
import java.util.function.Supplier;

import static nu.pattern.OpenCV.loadShared;

public class ScreenshotState {
private static final Duration DEFAULT_INTERVAL_MS = Duration.ofMillis(500);

Expand Down
61 changes: 61 additions & 0 deletions src/main/java/io/appium/java_client/pagefactory/AndroidBy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* 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.pagefactory;

/**
* Used to build a complex android automator locator.
*/
public @interface AndroidBy {
/**
* It is an is Android UIAutomator string.
* Read http://developer.android.com/intl/ru/tools/testing-support-library/
* index.html#uia-apis
*/
String uiAutomator() default "";

/**
* It an UI automation accessibility Id which is a convenient to Android.
* About Android accessibility
* https://developer.android.com/intl/ru/training/accessibility/accessible-app.html
*/
String accessibility() default "";

/**
* It is an id of the target element.
*/
String id() default "";

/**
* It is a className of the target element.
*/
String className() default "";

/**
* It is a desired element tag.
*/
String tagName() default "";

/**
* It is a xpath to the target element.
*/
String xpath() default "";

/**
* @return priority of the searching. Higher number means lower priority.
*/
int priority() default 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,31 @@

package io.appium.java_client.pagefactory;

import java.lang.annotation.ElementType;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Used to mark a field on a Page/Screen Object to indicate that lookup should use a
* series of {@link io.appium.java_client.pagefactory.AndroidFindBy} tags
* series of {@link io.appium.java_client.pagefactory.AndroidBy} tags
* It will then search for all elements that match any criteria. Note that elements
* are not guaranteed to be in document order.
* It is deprecated. Set of {@link io.appium.java_client.pagefactory.AndroidFindBy}
* can be defined without this annotation. To define the correct way how to use
* the defined set please take a look at {@link HowToUseLocators}. The article.
* https://docs.oracle.com/javase/tutorial/java/annotations/repeating.html.
*/
@Deprecated
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RUNTIME) @Target({FIELD, TYPE})
@Repeatable(AndroidFindByAllSet.class)
public @interface AndroidFindAll {
/**
* It is a set of {@link io.appium.java_client.pagefactory.AndroidFindBy} strategies which may
* It is a set of {@link io.appium.java_client.pagefactory.AndroidBy} strategies which may
* be used to find the target element.
*/
AndroidFindBy[] value();
AndroidBy[] value();

/**
* @return priority of the searching. Higher number means lower priority.
*/
int priority() default 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@

package io.appium.java_client.pagefactory;

import java.lang.annotation.ElementType;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


Expand All @@ -30,7 +32,7 @@
* this allows users to quickly and easily create PageObjects.
* using Android UI selectors, accessibility, id, name, class name, tag and xpath
*/
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RUNTIME) @Target({FIELD, TYPE})
@Repeatable(AndroidFindBySet.class)
public @interface AndroidFindBy {
/**
Expand Down Expand Up @@ -66,4 +68,9 @@
* It is a xpath to the target element.
*/
String xpath() default "";

/**
* @return priority of the searching. Higher number means lower priority.
*/
int priority() default 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.appium.java_client.pagefactory;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

/**
* Defines set of chained/possible locators. Each one locator
* should be defined with {@link AndroidFindAll}
*/
@Target(value = {TYPE, FIELD})
@Retention(value = RUNTIME)
public @interface AndroidFindByAllSet {
/**
* @return an array of {@link AndroidFindAll} which builds a sequence of
* the chained searching for elements or a set of possible locators
*/
AndroidFindAll[] value();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.appium.java_client.pagefactory;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

/**
* Defines set of chained/possible locators. Each one locator
* should be defined with {@link io.appium.java_client.pagefactory.AndroidFindBys}
*/
@Target(value = {TYPE, FIELD})
@Retention(value = RUNTIME)
public @interface AndroidFindByChainSet {
/**
* @return an array of {@link io.appium.java_client.pagefactory.AndroidFindBys} which builds a sequence of
* the chained searching for elements or a set of possible locators
*/
AndroidFindBys[] value();
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,19 @@

package io.appium.java_client.pagefactory;

import java.lang.annotation.ElementType;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Defines set of chained/possible locators. Each one locator
* should be defined with {@link io.appium.java_client.pagefactory.AndroidFindBy}
*/
@Target(value = {ElementType.TYPE, ElementType.FIELD})
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = {TYPE, FIELD})
@Retention(value = RUNTIME)
public @interface AndroidFindBySet {
/**
* @return an array of {@link io.appium.java_client.pagefactory.AndroidFindBy} which builds a sequence of
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,29 @@

package io.appium.java_client.pagefactory;

import java.lang.annotation.ElementType;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Used to mark a field on a Page Object to indicate that lookup should use
* a series of {@link io.appium.java_client.pagefactory.AndroidFindBy} tags.
* It is deprecated. Set of {@link io.appium.java_client.pagefactory.AndroidFindBy}
* can be defined without this annotation. To define the correct way how to use
* the defined set please take a look at {@link HowToUseLocators}. The article.
* https://docs.oracle.com/javase/tutorial/java/annotations/repeating.html.
* a series of {@link io.appium.java_client.pagefactory.AndroidBy} tags.
*/
@Deprecated
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RUNTIME) @Target({FIELD, TYPE})
@Repeatable(AndroidFindByChainSet.class)
public @interface AndroidFindBys {
/**
* It is a set of {@link io.appium.java_client.pagefactory.AndroidFindBy} strategies which build
* It is a set of {@link io.appium.java_client.pagefactory.AndroidBy} strategies which build
* the chain of the searching for the target element.
*/
AndroidFindBy[] value();
AndroidBy[] value();

/**
* @return priority of the searching. Higher number means lower priority.
*/
int priority() default 0;
}
Loading