Skip to content

Commit 10eba88

Browse files
committed
Merge pull request appium#126 from TikhomirovSergey/master
appium#122 Fix
2 parents cc79c93 + e35e4cb commit 10eba88

File tree

7 files changed

+270
-159
lines changed

7 files changed

+270
-159
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package io.appium.java_client.pagefactory;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
/**
9+
* Used to mark a field on a Page/Screen Object to indicate that lookup should use a series of {@link AndroidFindBy} tags
10+
* It will then search for all elements that match any criteria. Note that elements
11+
* are not guaranteed to be in document order.
12+
*/
13+
@Retention(RetentionPolicy.RUNTIME)
14+
@Target({ElementType.FIELD, ElementType.TYPE})
15+
public @interface AndroidFindAll {
16+
AndroidFindBy[] value();
17+
}

src/main/java/io/appium/java_client/pagefactory/AppiumAnnotations.java

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import io.appium.java_client.MobileBy;
55

66
import java.lang.annotation.Annotation;
7+
import java.lang.reflect.Constructor;
78
import java.lang.reflect.Field;
89
import java.lang.reflect.InvocationTargetException;
910
import java.lang.reflect.Method;
@@ -12,6 +13,7 @@
1213

1314
import org.openqa.selenium.By;
1415
import org.openqa.selenium.support.pagefactory.Annotations;
16+
import org.openqa.selenium.support.pagefactory.ByAll;
1517
import org.openqa.selenium.support.pagefactory.ByChained;
1618

1719
class AppiumAnnotations extends Annotations{
@@ -143,26 +145,34 @@ By getBy(Annotation annotation) {
143145
toUpperCase().trim();
144146
}
145147

148+
private static void checkDisallowedAnnotationPairs(Annotation a1,
149+
Annotation a2) throws IllegalArgumentException {
150+
if (a1 != null && a2 != null) {
151+
throw new IllegalArgumentException(
152+
"If you use a '@" + a1.getClass().getSimpleName() + "' annotation, "
153+
+ "you must not also use a '@" + a2.getClass().getSimpleName() + "' annotation");
154+
}
155+
}
156+
146157
private void assertValidAnnotations() {
147158
AndroidFindBy androidBy = mobileField
148159
.getAnnotation(AndroidFindBy.class);
149160
AndroidFindBys androidBys = mobileField
150161
.getAnnotation(AndroidFindBys.class);
162+
AndroidFindAll androidFindAll = mobileField.
163+
getAnnotation(AndroidFindAll.class);
151164

152165
iOSFindBy iOSBy = mobileField.getAnnotation(iOSFindBy.class);
153166
iOSFindBys iOSBys = mobileField.getAnnotation(iOSFindBys.class);
154-
155-
if (androidBy != null && androidBys != null) {
156-
throw new IllegalArgumentException(
157-
"If you use a '@AndroidFindBy' annotation, "
158-
+ "you must not also use a '@AndroidFindBys' annotation");
159-
}
160-
161-
if (iOSBy != null && iOSBys != null) {
162-
throw new IllegalArgumentException(
163-
"If you use a '@iOSFindBy' annotation, "
164-
+ "you must not also use a '@iOSFindBys' annotation");
165-
}
167+
iOSFindAll iOSFindAll = mobileField.getAnnotation(iOSFindAll.class);
168+
169+
checkDisallowedAnnotationPairs(androidBy, androidBys);
170+
checkDisallowedAnnotationPairs(androidBy, androidFindAll);
171+
checkDisallowedAnnotationPairs(androidBys, androidFindAll);
172+
173+
checkDisallowedAnnotationPairs(iOSBy, iOSBys);
174+
checkDisallowedAnnotationPairs(iOSBy, iOSFindAll);
175+
checkDisallowedAnnotationPairs(iOSBys, iOSFindAll);
166176
}
167177

168178
private static Method[] prepareAnnotationMethods(
@@ -217,14 +227,21 @@ private By getMobileBy(Annotation annotation, String valueName) {
217227
+ ": There is an unknown strategy " + valueName);
218228
}
219229

220-
private By getChainedMobileBy(Annotation[] annotations) {
230+
@SuppressWarnings("unchecked")
231+
private <T extends By> T getComplexMobileBy(Annotation[] annotations, Class<T> requiredByClass) {
221232
;
222233
By[] byArray = new By[annotations.length];
223234
for (int i = 0; i < annotations.length; i++) {
224235
byArray[i] = getMobileBy(annotations[i],
225236
getFilledValue(annotations[i]));
226237
}
227-
return new ByChained(byArray);
238+
try {
239+
Constructor<?> c = requiredByClass.getConstructor(By[].class);
240+
Object[] values = new Object[]{byArray};
241+
return (T) c.newInstance(values);
242+
} catch (Exception e) {
243+
throw new RuntimeException(e);
244+
}
228245
}
229246

230247
@Override
@@ -240,7 +257,12 @@ public By buildBy() {
240257
AndroidFindBys androidBys = mobileField
241258
.getAnnotation(AndroidFindBys.class);
242259
if (androidBys != null && ANDROID.toUpperCase().equals(platform)) {
243-
return getChainedMobileBy(androidBys.value());
260+
return getComplexMobileBy(androidBys.value(), ByChained.class);
261+
}
262+
263+
AndroidFindAll androidFindAll = mobileField.getAnnotation(AndroidFindAll.class);
264+
if (androidFindAll != null && ANDROID.toUpperCase().equals(platform)) {
265+
return getComplexMobileBy(androidFindAll.value(), ByAll.class);
244266
}
245267

246268
iOSFindBy iOSBy = mobileField.getAnnotation(iOSFindBy.class);
@@ -250,8 +272,13 @@ public By buildBy() {
250272

251273
iOSFindBys iOSBys = mobileField.getAnnotation(iOSFindBys.class);
252274
if (iOSBys != null && IOS.toUpperCase().equals(platform)) {
253-
return getChainedMobileBy(iOSBys.value());
275+
return getComplexMobileBy(iOSBys.value(), ByChained.class);
254276
}
277+
278+
iOSFindAll iOSFindAll = mobileField.getAnnotation(iOSFindAll.class);
279+
if (iOSFindAll != null && IOS.toUpperCase().equals(platform)) {
280+
return getComplexMobileBy(iOSFindAll.value(), ByAll.class);
281+
}
255282

256283
return super.buildBy();
257284
}

0 commit comments

Comments
 (0)