NỘI DUNG BÀI HỌC
✅Cách xử lý Scroll trên Flutter app
✅Cách xử lý Scroll trên Native app
1. Sử dụng W3C Actions API để thực thi hành động scroll
Sử dụng 2 class chính của Selenium là PointerInput và Sequence. Sử dụng lại chính hàm swipe hôm trước đã chỉ cho các bạn.
public void swipe(int startX, int startY, int endX, int endY, int durationMillis) {
PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
Sequence swipe = new Sequence(finger, 1);
swipe.addAction(finger.createPointerMove(Duration.ofMillis(0), PointerInput.Origin.viewport(), startX, startY));
swipe.addAction(finger.createPointerDown(0));
swipe.addAction(finger.createPointerMove(Duration.ofMillis(durationMillis), PointerInput.Origin.viewport(), endX, endY));
swipe.addAction(finger.createPointerUp(0));
DriverManager.getDriver().perform(Collections.singletonList(swipe));
}
@Test
public void testScrollUsingW3CActions() {
swipe(670, 2442, 670, 1200, 1000);
swipe(670, 2442, 670, 1200, 1000);
swipe(670, 2442, 670, 1200, 1000);
}
2. Sử dụng Gesture mobile command cho Android và iOS
Sử dụng hàm executeScript với thuộc tính "mobile: scrollGesture"
public void scrollGestureCommand() {
// Scroll gesture cho Android
Map<String, Object> scrollParams = new HashMap<> ();
scrollParams.put("left", 670); //vị trí mép trái vùng cuộn cách mép trái màn hình
scrollParams.put("top", 500); //xác định mép trên của vùng cuộn
scrollParams.put("width", 200); //chiều ngang của vùng kéo
scrollParams.put("height", 2000); //chiều dài của vùng kéo
scrollParams.put("direction", "down"); //Scroll theo chiều từ trên xuống dưới (up, down, left, right)
scrollParams.put("percent", 1); //Scroll 100% của vùng kéo được chỉ định (width, height)
// Thực hiện scroll gesture
DriverManager.getDriver().executeScript("mobile: scrollGesture", scrollParams);
}
@Test
public void testScrollUsingMobileCommand() {
scrollGestureCommand();
scrollGestureCommand();
}
Full code demo:
package com.anhtester.Bai12_Scroll;
import com.anhtester.common.BaseTest;
import com.anhtester.drivers.DriverManager;
import org.openqa.selenium.interactions.PointerInput;
import org.openqa.selenium.interactions.Sequence;
import org.testng.annotations.Test;
import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class DemoScrollNativeApp extends BaseTest {
public void swipe(int startX, int startY, int endX, int endY, int durationMillis) {
PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
Sequence swipe = new Sequence(finger, 1);
swipe.addAction(finger.createPointerMove(Duration.ofMillis(0), PointerInput.Origin.viewport(), startX, startY));
swipe.addAction(finger.createPointerDown(0));
swipe.addAction(finger.createPointerMove(Duration.ofMillis(durationMillis), PointerInput.Origin.viewport(), endX, endY));
swipe.addAction(finger.createPointerUp(0));
DriverManager.getDriver().perform(Collections.singletonList(swipe));
}
public void scrollGestureCommand() {
// Scroll gesture cho Android
Map<String, Object> scrollParams = new HashMap<>();
scrollParams.put("left", 670); //vị trí mép trái vùng cuộn cách mép trái màn hình
scrollParams.put("top", 500); //xác định mép trên của vùng cuộn
scrollParams.put("width", 200); //chiều ngang của vùng kéo
scrollParams.put("height", 2000); //chiều dài của vùng kéo
scrollParams.put("direction", "down"); //Scroll theo chiều từ trên xuống dưới (up, down, left, right)
scrollParams.put("percent", 1); //Scroll 100% của vùng kéo được chỉ định (width, height)
// Thực hiện scroll gesture
DriverManager.getDriver().executeScript("mobile: scrollGesture", scrollParams);
}
@Test
public void testScrollUsingW3CActions() {
swipe(670, 2442, 670, 1200, 1000);
swipe(670, 2442, 670, 1200, 1000);
swipe(670, 2442, 670, 1200, 1000);
}
@Test
public void testScrollUsingMobileCommand() {
scrollGestureCommand();
scrollGestureCommand();
}
}
✅Cách xử lý Scroll trên Flutter app
Xử lý giống với Swipe, tuy nhiên tuỳ chỉnh một chút chỗ Element đầu vào tại vị trí có thể cuộn được. (scrollable=true)
// 1. Tìm phần tử có khả năng cuộn (ví dụ: View/ListView)
WebElement scrollableElement = DriverManager.getDriver().findElement(AppiumBy.xpath("//android.widget.FrameLayout[@resource-id=\"android:id/content\"]/android.widget.FrameLayout/android.view.View/android.view.View/android.view.View/android.view.View/android.view.View[2]/android.view.View")); // Thay đổi locator phù hợp
Point elementCenter = scrollableElement.getRect().getPoint().moveBy(scrollableElement.getSize().getWidth() / 2, scrollableElement.getSize().getHeight() / 2);
// 2. Tạo PointerInput
PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
// 3. Tạo Sequence (chuỗi hành động) để cuộn xuống
Sequence scrollDownSequence = new Sequence(finger, 1)
.addAction(finger.createPointerMove(Duration.ofMillis(0), PointerInput.Origin.viewport(), elementCenter.getX(), elementCenter.getY())) // Di chuyển pointer đến tâm phần tử
.addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg())) // Nhấn pointer xuống
.addAction(finger.createPointerMove(Duration.ofMillis(300), PointerInput.Origin.viewport(), elementCenter.getX(), elementCenter.getY() - 1000)) // Di chuyển pointer lên (cuộn xuống) 500 pixels
.addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg())); // Nhấc pointer lên
// 4. Thực hiện Sequence
DriverManager.getDriver().perform(Collections.singletonList(scrollDownSequence));
Demo với app flutter Taurus:
package com.anhtester.Bai12_Scroll;
import com.anhtester.common.BaseTestTaurusApp;
import com.anhtester.drivers.DriverManager;
import com.anhtester.keywords.MobileUI;
import io.appium.java_client.AppiumBy;
import org.openqa.selenium.Point;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.PointerInput;
import org.openqa.selenium.interactions.Sequence;
import org.testng.annotations.Test;
import java.time.Duration;
import java.util.Collections;
public class DemoScrollFlutterApp extends BaseTestTaurusApp {
@Test
public void testScrollInFlutterApp() {
loginTaurusApp();
downloadDataFromServer(1);
DriverManager.getDriver().findElement(AppiumBy.accessibilityId("Back")).click();
MobileUI.sleep(2);
DriverManager.getDriver().findElement(AppiumBy.accessibilityId("Menu")).click();
MobileUI.sleep(4);
// 1. Tìm phần tử có khả năng cuộn (ví dụ: View/ListView)
WebElement scrollableElement = DriverManager.getDriver().findElement(AppiumBy.xpath("//android.widget.FrameLayout[@resource-id=\"android:id/content\"]/android.widget.FrameLayout/android.view.View/android.view.View/android.view.View/android.view.View/android.view.View[2]/android.view.View")); // Thay đổi locator phù hợp
Point elementCenter = scrollableElement.getRect().getPoint().moveBy(scrollableElement.getSize().getWidth() / 2, scrollableElement.getSize().getHeight() / 2);
// 2. Tạo PointerInput
PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
// 3. Tạo Sequence (chuỗi hành động) để cuộn xuống
Sequence scrollDownSequence = new Sequence(finger, 1)
.addAction(finger.createPointerMove(Duration.ofMillis(0), PointerInput.Origin.viewport(), elementCenter.getX(), elementCenter.getY())) // Di chuyển pointer đến tâm phần tử
.addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg())) // Nhấn pointer xuống
.addAction(finger.createPointerMove(Duration.ofMillis(300), PointerInput.Origin.viewport(), elementCenter.getX(), elementCenter.getY() - 1000)) // Di chuyển pointer lên (cuộn xuống) 500 pixels
.addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg())); // Nhấc pointer lên
// 4. Thực hiện Sequence
DriverManager.getDriver().perform(Collections.singletonList(scrollDownSequence));
MobileUI.sleep(2);
}
} 