44import io .appium .java_client .MobileBy ;
55
66import java .lang .annotation .Annotation ;
7+ import java .lang .reflect .Constructor ;
78import java .lang .reflect .Field ;
89import java .lang .reflect .InvocationTargetException ;
910import java .lang .reflect .Method ;
1213
1314import org .openqa .selenium .By ;
1415import org .openqa .selenium .support .pagefactory .Annotations ;
16+ import org .openqa .selenium .support .pagefactory .ByAll ;
1517import org .openqa .selenium .support .pagefactory .ByChained ;
1618
1719class AppiumAnnotations extends Annotations {
@@ -143,26 +145,34 @@ By getBy(Annotation annotation) {
143145toUpperCase ().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+
146157private void assertValidAnnotations () {
147158AndroidFindBy androidBy = mobileField
148159.getAnnotation (AndroidFindBy .class );
149160AndroidFindBys androidBys = mobileField
150161.getAnnotation (AndroidFindBys .class );
162+ AndroidFindAll androidFindAll = mobileField .
163+ getAnnotation (AndroidFindAll .class );
151164
152165iOSFindBy iOSBy = mobileField .getAnnotation (iOSFindBy .class );
153166iOSFindBys 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
168178private 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;
222233By [] byArray = new By [annotations .length ];
223234for (int i = 0 ; i < annotations .length ; i ++) {
224235byArray [i ] = getMobileBy (annotations [i ],
225236getFilledValue (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() {
240257AndroidFindBys androidBys = mobileField
241258.getAnnotation (AndroidFindBys .class );
242259if (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
246268iOSFindBy iOSBy = mobileField .getAnnotation (iOSFindBy .class );
@@ -250,8 +272,13 @@ public By buildBy() {
250272
251273iOSFindBys iOSBys = mobileField .getAnnotation (iOSFindBys .class );
252274if (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
256283return super .buildBy ();
257284}
0 commit comments