Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Functions #543

Merged
merged 7 commits into from
Dec 22, 2016
Merged

Functions #543

merged 7 commits into from
Dec 22, 2016

Conversation

TikhomirovSergey
Copy link
Contributor

@TikhomirovSergey TikhomirovSergey commented Dec 21, 2016

Change list

  • new functional interface io.appium.java_client.functions.AppiumFunction was designed. It extends 'java.util.function.Function' and com.google.common.base.Function. It was designed in order to provide compatibility with the org.openqa.selenium.support.ui.Wait.

  • new functional interface io.appium.java_client.functions.ExpectedCondition was designed. It extends 'io.appium.java_client.functions.AppiumFunction' and org.openqa.selenium.support.ui.ExpectedCondition.

  • the new interface io.appium.java_client.PerformsActions was added. It unifies TouchAction and MultiTouchAction now.

  • io.appium.java_client.functions.ActionSupplier was designed. It extends java.util.function.Supplier.

  • source code cleaning up.

Types of changes

  • No changes in production code.
  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Details

1) io.appium.java_client.functions.AppiumFunction and io.appium.java_client.functions.ExpectedCondition provide chained waitings. Samples are below.

  • with precondition:
//firstly it is needed to wait for some context using regular expression pattern
//and switch to this context
AppiumFunction<Pattern, WebDriver> contextFunction = input -> {
        Set<String> contexts = driver.getContextHandles();
        String current = driver.getContext();
        contexts.forEach(context -> {
            Matcher m = input.matcher(context);
            if (m.find()) {
                driver.context(context);
            }
        });
       if (!current.equals(driver.getContext())) {
            return driver;
       }
        return null;
 };

//and then fetch some elements by tag. The rendering can take some time
private final AppiumFunction<WebDriver, List<WebElement>> searchingFunction = input -> {
        List<WebElement> result = input.findElements(By.tagName("a"));
       if (result.size() > 0) {
           return result;
        }
        return null;
};

import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;

@Test public void tezt() {
    ....
    Wait<Pattern> wait = new FluentWait<>(Pattern.compile("WEBVIEW"))
               .withTimeout(30, TimeUnit.SECONDS);
    List<WebElement> elements = wait.until(searchingFunction.compose(contextFunction));    
    ....
}
  • the same with post-condition:
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;

@Test public void tezt() {
    ....
    Wait<Pattern> wait = new FluentWait<>(Pattern.compile("WEBVIEW"))
               .withTimeout(30, TimeUnit.SECONDS);
    List<WebElement> elements = wait.until(contextFunction.andThen(searchingFunction));    
    ....
}

All this is NullPointerException-safe.

2) We are going to remove old gesture methods because they doesn't work as expected for many cases, they force users to use only way defined by them (but it is possible to perform some action in many ways. For example, it is possible to perform the swiping in aboit 6-8 similar ways). But end users should be able to customize TouchAction/MultipleTouchAction up to them. So I decided to propose the supplier. Possible options:

  • it is possible to define certain actions in functional way. For some screen/test, or test framework - it doesn't matter.
private final ActionSupplier<TouchAction> horizontalSwipe = () -> {
    driver.findElementById("io.appium.android.apis:id/gallery");

    AndroidElement gallery = driver.findElementById("io.appium.android.apis:id/gallery");
    List<MobileElement> images = gallery
                .findElementsByClassName("android.widget.ImageView");
    Point location = gallery.getLocation();
    Point center = gallery.getCenter();

    return new TouchAction(driver).press(images.get(2), -10, center.y - location.y)
                .waitAction(2000).moveTo(gallery, 10, center.y - location.y).release();
};

private final ActionSupplier<TouchAction> verticalSwiping = () ->
        new TouchAction(driver).press(driver.findElementByAccessibilityId("Gallery"))
                .waitAction(2000).moveTo(driver.findElementByAccessibilityId("Auto Complete")).release();

@Test public void tezt() {
    ...
    horizontalSwipe.get().perform();
    ...
    verticalSwiping.get().perform();   
    ...
}
  • it is possiple to organize chaines of touch actions using common Java 8 tools or tools made up by end users.

The new ExpectedCondition was added. It combines org.openqa.selenium.support.ui.ExpectedCondition and java.util.function.Function.
Methods `compose` and `andThen` were overridden the way to prevent NPE occurence.
It was added to allow user to customize gestures in more agile way.
Also:
- the new interface PerformsActions was added. It is implemented by TouchAction and MultiTouchAction.
- The feature was covered with test.
@TikhomirovSergey
Copy link
Contributor Author

@jlipps @bootstraponline @saikrishna321 You are invited to review this PR too :)

@TikhomirovSergey
Copy link
Contributor Author

#399

@TikhomirovSergey TikhomirovSergey merged commit c5b9d7b into appium:master Dec 22, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants