Skip to content
85 changes: 85 additions & 0 deletions src/main/java/io/appium/java_client/AppiumBy.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Collections;
import java.util.HashMap;

import static com.google.common.base.Strings.isNullOrEmpty;

Expand Down Expand Up @@ -53,6 +56,13 @@ protected AppiumBy(String selector, String locatorString, String locatorName) {
return String.format("%s.%s: %s", AppiumBy.class.getSimpleName(), locatorName, remoteParameters.value());
}

public Map<String, Object> toJson() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure this method is needed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently flutter driver supports custom commands like scrollTillVisble, waitForVisible, waitForVisible etc, which accepts raw locator info(By) as arguments. So users can directly pass the locator info by calling toJson() method instead of constructing the JsonMap manually.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can observe that Remotable.Parameters class already contains toJson method. It's private though. Lets add it to the list in SeleniumHQ/selenium#13949 and leave a TODO there.

Also consider using Map.of() factory instead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you also provide an example of any of the above calls where toJson method may be used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One such example is using flutter: scrollTillVisible method.

  1. Without toJson()
driver.executeScript("flutter: scrollTillVisible", Map.of("finder", Map.of("using", "-flutter key", "value", "login_button")));
  1. With toJson()
driver.executeScript("flutter: scrollTillVisible", Map.of("finder", AppiumBy.flutterKey("login_button").toJson());

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would probably make sense to create FlutterIosDriver and FlutterAndroidDriver inherited from iOSDriver and AndroidDriver, so the above extensions may be implemented as first-class methods, e.g.

flutter. scrollTillVisible(AppiumBy.flutterKey("login_button"))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We initially had a similar idea. After reviewing the implementation, we found that the logic is consistent for both iOS and Android drivers, so we decided to maintain this approach.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sudharsan-selvaraj Agree we wanted to make it consistent but nothing is stopping us implementing the initial approach if everyone is fine. It gets easier to implement the tests.
cc: @mykola-mokhnach

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@saikrishna321 @mykola-mokhnach That sounds good! Let's proceed by creating separate Flutter-specific driver classes to abstract the underlying commands. I'll prepare a patch with the changes and tag for the review.

Map<String, Object> params = new HashMap<String, Object>();
params.put("using", this.remoteParameters.using());
params.put("value", this.remoteParameters.value());
return Collections.unmodifiableMap(params);
}

/**
* About Android accessibility
* https://developer.android.com/intl/ru/training/accessibility/accessible-app.html
Expand Down Expand Up @@ -186,6 +196,51 @@ public static By iOSNsPredicateString(final String iOSNsPredicateString) {
return new ByIosNsPredicate(iOSNsPredicateString);
}

/**
* This locator strategy is available in FlutterIntegration Driver mode.
* @param selector is the value defined to the key attribute of the flutter element
* @return an instance of {@link AppiumBy.ByFlutterKey}
*/
public static By flutterKey(final String selector) {
return new ByFlutterKey(selector);
}

/**
* This locator strategy is available in FlutterIntegration Driver mode.
* @param selector is the Type of widget mounted in the app tree
* @return an instance of {@link AppiumBy.ByFlutterType}
*/
public static By flutterType(final String selector) {
return new ByFlutterType(selector);
}

/**
* This locator strategy is available in FlutterIntegration Driver mode.
* @param selector is the text that is present on the widget
* @return an instance of {@link AppiumBy.ByFlutterText}
*/
public static By flutterText(final String selector) {
return new ByFlutterText(selector);
}

/**
* This locator strategy is available in FlutterIntegration Driver mode.
* @param selector is the text that is partially present on the widget
* @return an instance of {@link AppiumBy.ByFlutterTextContaining}
*/
public static By flutterTextContaining(final String selector) {
return new ByFlutterTextContaining(selector);
}

/**
* This locator strategy is available in FlutterIntegration Driver mode.
* @param semanticsLabel represents the value assigned to the label attribute of semantics element
* @return an instance of {@link AppiumBy.ByFlutterSemanticsLabel}
*/
public static By flutterSemanticsLabel(final String semanticsLabel) {
return new ByFlutterSemanticsLabel(semanticsLabel);
}

public static class ByAccessibilityId extends AppiumBy implements Serializable {
public ByAccessibilityId(String accessibilityId) {
super("accessibility id", accessibilityId, "accessibilityId");
Expand Down Expand Up @@ -257,4 +312,34 @@ protected ByIosNsPredicate(String locatorString) {
super("-ios predicate string", locatorString, "iOSNsPredicate");
}
}

public static class ByFlutterType extends AppiumBy implements Serializable {
protected ByFlutterType(String locatorString) {
super("-flutter type", locatorString, "flutterType");
}
}

public static class ByFlutterKey extends AppiumBy implements Serializable {
protected ByFlutterKey(String locatorString) {
super("-flutter key", locatorString, "flutterKey");
}
}

public static class ByFlutterSemanticsLabel extends AppiumBy implements Serializable {
protected ByFlutterSemanticsLabel(String locatorString) {
super("-flutter semantics label", locatorString, "flutterSemanticsLabel");
}
}

public static class ByFlutterText extends AppiumBy implements Serializable {
protected ByFlutterText(String locatorString) {
super("-flutter text", locatorString, "flutterText");
}
}

public static class ByFlutterTextContaining extends AppiumBy implements Serializable {
protected ByFlutterTextContaining(String locatorString) {
super("-flutter text containing", locatorString, "flutterTextContaining");
}
}
}
Loading