Search code examples
androidselenium-webdriverautomated-testsappiumselenide

Why does merging two sequences into a single androidDriver.perform() method result in an InvalidElementStateException in Appium/Selenide?


I am working on automating tests for an Android application using Appium and Selenide. I have a scenario where I need to perform two separate actions on two different buttons. When I use a separate androidDriver.perform() method for each action, everything works fine. However, when I try to perform both actions within a single androidDriver.perform() method by passing both sequences to the method, I encounter an InvalidElementStateException.

if (isAndroid()) {

SelenideElement buttonsKeyBoard1 = $x("//android.widget.Button[contains(@resource-id, 'Keyboard_1Button')]").should(Condition.visible);
SelenideElement buttonsKeyBoard2 = $x("//android.widget.Button[contains(@resource-id, 'Keyboard_2Button')]");

List<SelenideElement> buttonsKeyBoard = new ArrayList<>();
buttonsKeyBoard.add(buttonsKeyBoard1);
buttonsKeyBoard.add(buttonsKeyBoard2);


// Create a list to hold the sequences
List<Sequence> sequences = new ArrayList<>();

// Process the first button
PointerInput finger1 = new PointerInput(PointerInput.Kind.TOUCH, "finger1");
PointerInput finger2 = new PointerInput(PointerInput.Kind.TOUCH, "finger2");

Sequence tap1 = new Sequence(finger1, 1);
Sequence tap2 = new Sequence(finger2, 1);

Point sourceLocation = buttonsKeyBoard1.getLocation();
Point sourceLocation2 = buttonsKeyBoard2.getLocation();

int centerX = sourceLocation.getX() + buttonsKeyBoard1.getSize().getWidth() / 2;
int centerY = sourceLocation.getY() + buttonsKeyBoard1.getSize().getHeight() / 2;
System.out.println("x1 and y1 " + centerX + " " + centerY);
int centerX2 = sourceLocation2.getX() + buttonsKeyBoard2.getSize().getWidth() / 2;
int centerY2= sourceLocation2.getY() + buttonsKeyBoard2.getSize().getHeight() / 2;

System.out.println("x2 and y2 " + centerX2 + " " + centerY2);
tap1.addAction(finger1.createPointerMove(Duration.ofMillis(500), PointerInput.Origin.viewport(), centerX, centerY));
tap1.addAction(finger1.createPointerDown(LEFT.asArg()));
tap1.addAction(finger1.createPointerUp(LEFT.asArg()));
sequences.add(tap1);  // Add the sequence to the list of sequences

tap2.addAction(finger2.createPointerMove(Duration.ofMillis(500), PointerInput.Origin.viewport(), centerX2, centerY2));
tap2.addAction(finger2.createPointerDown(LEFT.asArg()));
tap2.addAction(finger2.createPointerUp(LEFT.asArg()));
sequences.add(tap2);  // Add the sequence to the list of sequences

androidDriver.perform(sequences);
}

The error message that I receive is as follows:

Caused by: org.openqa.selenium.InvalidElementStateException: Unable to perform W3C actions. Check the logcat output for possible error reports and make sure your input actions chain is valid.

But when I change it to the follow, and create 2 seperate sequence and 2 different perform methods. the methode works. But I think that's not the idea, I want to execute as many sequences as possible with the same perform method.

        sequences.add(tap1);  // Add the sequence to the list of sequences

        tap2.addAction(finger2.createPointerMove(Duration.ofMillis(10), PointerInput.Origin.viewport(), centerX2, centerY2));
        tap2.addAction(finger2.createPointerDown(LEFT.asArg()));
        tap2.addAction(finger2.createPointerUp(LEFT.asArg()));
        sequences2.add(tap2);  // Add the sequence to the list of sequences

        androidDriver.perform(sequences);
        androidDriver.perform(sequences2);

Solution

  • I got the solution, I only miss the pause after pointerDown.

    tap1.addAction(finger1.createPointerMove(ofMillis(10),PointerInput.Origin.viewport(), centerX, centerY));
    tap1.addAction(finger1.createPointerDown(LEFT.asArg()));
    tap1.addAction(new Pause(finger1, ofMillis(100)));
    tap1.addAction(finger1.createPointerUp(LEFT.asArg()));
    sequences.add(tap1); // Add the sequence to the list of sequences
    tap2.addAction(finger2.createPointerMove(ofMillis(10), PointerInput.Origin.viewport(), centerX2, centerY2));
    tap2.addAction(finger2.createPointerDown(LEFT.asArg()));
    tap2.addAction(new Pause(finger2, ofMillis(100)));
    tap2.addAction(finger2.createPointerUp(LEFT.asArg()));
    
    sequences.add(tap2);  // Add the sequence to the list of sequences
    
    androidDriver.perform(sequences);`