qaf flutter native app support - additional locator strategies for flutter app using appium-flutter-driver
- Add qaf-support-flutter dependency to your project
- Refer installation and usage for setup appium flutter driver.
- Custom locator stretegies specific to fluter driver
- Auto scroll to view
- Child element support
Flutter Driver API | locator strategy | Example |
---|---|---|
bySemanticsLabel | flutter-label flutter-label-regex |
flutter-label=foo |
byTooltip | flutter-tooltip |
flutter-tooltip=Increment |
byType | flutter-type |
flutter-type=TextField |
byValueKey | flutter-valuekey |
flutter-valuekey=counter |
text | flutter-text |
flutter-text=foo |
rawmap | flutter-rawmap | flutter-rawmap={"finderType":"PageBack"} flutter-rawmap={"finderType":"Descendant","matching":"{\"finderType\":\"ByType\",\"type\": \"ListView\"}","of":"{\"finderType\":\"ByText\",\"text\": \"element text\"}"} |
descendant | 🆗 | using child element (preferred) or flutter-rawmap |
pageBack | 🆗 | pageBack() |
ancestor | :not tested: | Using flutter-rawmap |
Flutter driver doesn't support finding list of elements.
remote.server=localhost
remote.port=4723
driver.name=fluterDriver
fluter.capabilities.driverClass=io.appium.java_client.android.AndroidDriver
fluter.additional.capabilities= {\
"app": "<app>",\
"platformName": "Android",\
"deviceName": "Android Emulator",\
"automationName": "Flutter",\
"retryBackoffTime": 2000,\
"maxRetryCount": 5\
}
import static com.qmetry.qaf.automation.support.flutter.FlutterUtils.*;
import static com.qmetry.qaf.automation.ui.webdriver.ElementFactory.$;
import com.qmetry.qaf.automation.support.flutter.FlutterElement;
@Test
public void testNextRoute() {
waitForFirstFrame();
FlutterElement parent = new FlutterElement("flutter-tooltip=counter_tooltip");
FlutterElement child = new FlutterElement(parent,"flutter-valuekey=counter");
System.out.println("Child text:: " + child.getText());
parent.waitForPresent();
FlutterElement nextRoute = new FlutterElement("flutter-text=Go to next route");
nextRoute.click();
parent.waitForNotPresent();
// nextRoute.verifyNotPresent();
FlutterElement list = new FlutterElement("flutter-type=ListView");
list.verifyPresent("ListView Container");
QAFWebElement entryC = list.findElement("flutter-text=Entry C");
System.out.println(entryC.getText());
QAFWebElement entryD = list.findElement("flutter-text=Entry D");
System.out.println(entryD.getText());
QAFExtendedWebElement textField = new QAFExtendedWebElement(list,"flutter-type=TextField");
textField.sendKeys("flutter test");
entryD = list.findElement("flutter-text=Entry D");
entryD.verifyText("Entry D");
//page back
getPageBackElement().click();
$("flutter-valuekey=counter").verifyPresent();
}
@Test
public void contextTest() throws IOException {
Set<String> contexts = ((AppiumDriver<WebElement>) getDriver().getUnderLayingDriver()).getContextHandles();
System.out.println(contexts);
//default context is FLUTTER
Object res = getDriver().executeScript("flutter:checkHealth");
System.out.println("flutter:checkHealth: " + res);
res = getDriver().executeScript("flutter:getRenderTree");
System.out.println("flutter:getRenderTree: " + res);
res = getDriver().executeScript("flutter:getLayerTree");
System.out.println("flutter:getLayerTree: " + res);
QAFExtendedWebElement increment1 = new QAFExtendedWebElement(
new ByFlutter("{'finderType':'ByTooltipMessage','text':'Increment'}"));
increment1.click();
increment1.click();
increment1.assertPresent("Increment buttton");
QAFExtendedWebElement counter = new QAFExtendedWebElement(
new ByFlutter("{'finderType':'ByValueKey','keyValueString':'counter','keyValueType':'String'}"));
counter.verifyText("2", "counter");
// switch to Native
switchContext("NATIVE_APP");
QAFExtendedWebElement content = new QAFExtendedWebElement("id=android:id/content");
QAFExtendedWebElement increment2 = new QAFExtendedWebElement(content, "accessibility id=Increment");
increment2.click();
increment2.verifyVisible("Increment button");
switchContext("FLUTTER");
counter.verifyText("3", "counter");
switchContext("NATIVE_APP");
QAFExtendedWebElement content1 = new QAFExtendedWebElement("id=android:id/content");
content1.verifyPresent("container");
content1.findElement("accessibility id=Increment").click();
switchContext("FLUTTER");
counter.verifyText("4", "counter");
QAFExtendedWebElement increment3 = new QAFExtendedWebElement("flutter-tooltip=Increment");
increment3.click();
counter.verifyText("5", "counter");
//This will not work because parent is not in flutter context. Both parent and child requied to be from same (native/flutter) context
//QAFExtendedWebElement increment4 = new QAFExtendedWebElement(content1, "flutter-tooltip=Increment");
//increment4.click();
}
public void switchContext(String contextName) {
((AppiumDriver<WebElement>) getDriver().getUnderLayingDriver()).context(contextName);
}
public void waitForFirstFrame() {
getDriver().executeScript("flutter:waitForFirstFrame");
}