├── src
├── main
│ └── java
│ │ └── io
│ │ └── github
│ │ └── ashwith
│ │ └── flutter
│ │ ├── finders
│ │ ├── PageBack.java
│ │ ├── ByText.java
│ │ ├── ByType.java
│ │ ├── ByToolTip.java
│ │ ├── ByValueKey.java
│ │ ├── ByAncestor.java
│ │ ├── ByDescendant.java
│ │ └── BySemanticsLabel.java
│ │ ├── FlutterElement.java
│ │ └── FlutterFinder.java
└── test
│ └── java
│ └── io
│ └── github
│ └── ashwith
│ └── flutter
│ └── example
│ └── FlutterFinderExampleTest.java
├── .github
└── workflows
│ ├── mavenbuild.yml
│ ├── maven-publish.yml
│ └── github-release.yml
├── .gitignore
├── LICENSE
├── README.md
└── pom.xml
/src/main/java/io/github/ashwith/flutter/finders/PageBack.java:
--------------------------------------------------------------------------------
1 | package io.github.ashwith.flutter.finders;
2 |
3 | import io.github.ashwith.flutter.FlutterElement;
4 |
5 | /**
6 | * To navigate back to previous page
7 | *
8 | * @author ashwith
9 | * @version 1.0.0
10 | */
11 | public interface PageBack {
12 |
13 | FlutterElement pageBack();
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/io/github/ashwith/flutter/finders/ByText.java:
--------------------------------------------------------------------------------
1 | package io.github.ashwith.flutter.finders;
2 |
3 | import io.github.ashwith.flutter.FlutterElement;
4 |
5 | /**
6 | * To identify the element using Text
7 | *
8 | * @author ashwith
9 | * @version 1.0.0
10 | */
11 | public interface ByText {
12 |
13 | FlutterElement byText(String input);
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/io/github/ashwith/flutter/finders/ByType.java:
--------------------------------------------------------------------------------
1 | package io.github.ashwith.flutter.finders;
2 |
3 | import io.github.ashwith.flutter.FlutterElement;
4 |
5 | /**
6 | * To identify the element using Type
7 | *
8 | * @author ashwith
9 | * @version 1.0.0
10 | */
11 | public interface ByType {
12 |
13 | FlutterElement byType(String type);
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/io/github/ashwith/flutter/finders/ByToolTip.java:
--------------------------------------------------------------------------------
1 | package io.github.ashwith.flutter.finders;
2 |
3 | import io.github.ashwith.flutter.FlutterElement;
4 |
5 | /**
6 | * To identify the element using ToolTip
7 | *
8 | * @author ashwith
9 | * @version 1.0.0
10 | */
11 | public interface ByToolTip {
12 |
13 | FlutterElement byToolTip(String toolTipText);
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/io/github/ashwith/flutter/finders/ByValueKey.java:
--------------------------------------------------------------------------------
1 | package io.github.ashwith.flutter.finders;
2 |
3 | import io.github.ashwith.flutter.FlutterElement;
4 |
5 | /**
6 | * To identify the element using Value key
7 | *
8 | * @author ashwith
9 | * @version 1.0.0
10 | */
11 | public interface ByValueKey {
12 |
13 |
14 | FlutterElement byValueKey(String key);
15 |
16 | FlutterElement byValueKey(int key);
17 | }
--------------------------------------------------------------------------------
/.github/workflows/mavenbuild.yml:
--------------------------------------------------------------------------------
1 | name: Java CI
2 |
3 | on: [push]
4 |
5 | jobs:
6 | build:
7 | runs-on: ubuntu-latest
8 |
9 | steps:
10 | - uses: actions/checkout@v3
11 | - name: Set up JDK 17
12 | uses: actions/setup-java@v3
13 | with:
14 | java-version: '17'
15 | distribution: 'temurin'
16 | - name: Build with Maven
17 | run: mvn --batch-mode --update-snapshots package
--------------------------------------------------------------------------------
/src/main/java/io/github/ashwith/flutter/finders/ByAncestor.java:
--------------------------------------------------------------------------------
1 | package io.github.ashwith.flutter.finders;
2 |
3 | import io.github.ashwith.flutter.FlutterElement;
4 |
5 | /**
6 | * To identify the element using Ancestor
7 | *
8 | * @author ashwith
9 | * @version 1.0.0
10 | */
11 | public interface ByAncestor {
12 |
13 | FlutterElement byAncestor(FlutterElement of, FlutterElement matching, boolean matchRoot, boolean firstMatchOnly);
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/io/github/ashwith/flutter/finders/ByDescendant.java:
--------------------------------------------------------------------------------
1 | package io.github.ashwith.flutter.finders;
2 |
3 | import io.github.ashwith.flutter.FlutterElement;
4 |
5 | /**
6 | * To identify the element using Descendant
7 | *
8 | * @author ashwith
9 | * @version 1.0.0
10 | */
11 | public interface ByDescendant {
12 |
13 | FlutterElement byDescendant(FlutterElement of, FlutterElement matching, boolean matchRoot, boolean firstMatchOnly);
14 |
15 | }
--------------------------------------------------------------------------------
/src/main/java/io/github/ashwith/flutter/finders/BySemanticsLabel.java:
--------------------------------------------------------------------------------
1 | package io.github.ashwith.flutter.finders;
2 |
3 | import io.github.ashwith.flutter.FlutterElement;
4 |
5 | import java.util.regex.Pattern;
6 |
7 | /**
8 | * To identify the element using SemanticsLabel
9 | * @author ashwith
10 | * @version 1.0.0
11 | */
12 | public interface BySemanticsLabel {
13 |
14 | FlutterElement bySemanticsLabel(String label);
15 |
16 | FlutterElement bySemanticsLabel(Pattern label);
17 | }
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.nar
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 |
25 | #inteliji
26 | .idea
27 |
28 | #maven file
29 | target/
30 | pom.xml.tag
31 | pom.xml.releaseBackup
32 | pom.xml.versionsBackup
33 | pom.xml.next
34 | release.properties
35 | dependency-reduced-pom.xml
36 | buildNumber.properties
37 | .mvn/timing.properties
38 | # https://github.com/takari/maven-wrapper#usage-without-binary-jar
39 | .mvn/wrapper/maven-wrapper.jar
40 | *.iml
41 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 ashwithpoojary98
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.github/workflows/maven-publish.yml:
--------------------------------------------------------------------------------
1 | name: Publish to Maven Central
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | workflow_dispatch:
8 |
9 | jobs:
10 | publish:
11 | runs-on: ubuntu-latest
12 |
13 | steps:
14 | - name: 1. Checkout repository
15 | uses: actions/checkout@v4
16 | with:
17 | fetch-depth: 0
18 |
19 | - name: 2. Set up JDK 11
20 | uses: actions/setup-java@v4
21 | with:
22 | java-version: '11'
23 | distribution: 'temurin'
24 |
25 | - name: 3. Configure GPG
26 | run: |
27 | echo "${{ secrets.GPG_PRIVATE_KEY }}" | gpg --batch --import
28 | echo "allow-loopback-pinentry" >> ~/.gnupg/gpg-agent.conf
29 | echo "pinentry-mode loopback" >> ~/.gnupg/gpg.conf
30 | gpg-connect-agent reloadagent /bye
31 | export GPG_TTY=$(tty)
32 |
33 | - name: 4. Create Maven settings.xml
34 | run: |
35 | mkdir -p ~/.m2
36 | cat > ~/.m2/settings.xml << EOF
37 |
38 |
39 |
40 | central
41 | ${{ secrets.MAVEN_USERNAME }}
42 | ${{ secrets.MAVEN_PASSWORD }}
43 |
44 |
45 |
46 | EOF
47 |
48 | - name: 5. Deploy to Maven Central Portal
49 | run: mvn clean deploy -P release --batch-mode -Dgpg.passphrase="${{ secrets.GPG_PASSPHRASE }}" -Dgpg.pinentry-mode=loopback
--------------------------------------------------------------------------------
/src/test/java/io/github/ashwith/flutter/example/FlutterFinderExampleTest.java:
--------------------------------------------------------------------------------
1 | package io.github.ashwith.flutter.example;
2 |
3 | import io.github.ashwith.flutter.FlutterFinder;
4 | import io.appium.java_client.android.AndroidDriver;
5 | import org.openqa.selenium.WebElement;
6 | import org.openqa.selenium.remote.DesiredCapabilities;
7 | import org.openqa.selenium.remote.RemoteWebDriver;
8 | import org.testng.annotations.AfterMethod;
9 | import org.testng.annotations.BeforeMethod;
10 | import org.testng.annotations.Test;
11 |
12 | import java.net.MalformedURLException;
13 | import java.net.URL;
14 | import java.time.Duration;
15 |
16 |
17 | public class FlutterFinderExampleTest {
18 | RemoteWebDriver driver;
19 |
20 | @BeforeMethod
21 | public void openApp() throws MalformedURLException {
22 | DesiredCapabilities capabilities = new DesiredCapabilities();
23 | capabilities.setCapability("deviceName", "emulator-5554");
24 | capabilities.setCapability("platformName", "Android");
25 | capabilities.setCapability("noReset", true);
26 | capabilities.setCapability("app", "");
27 | capabilities.setCapability("automationName", "Flutter");
28 | driver = new AndroidDriver(new URL("http://0.0.0.0:4723/wd/hub"), capabilities);
29 | driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(30));
30 | }
31 |
32 | @Test
33 | public void appiumFlutterTest() {
34 | FlutterFinder finder = new FlutterFinder(driver);
35 | WebElement element = finder.byToolTip("increment");
36 | element.click();
37 | }
38 |
39 | @AfterMethod
40 | public void tearDown() {
41 | if (driver != null) {
42 | driver.quit();
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/io/github/ashwith/flutter/FlutterElement.java:
--------------------------------------------------------------------------------
1 | package io.github.ashwith.flutter;
2 |
3 |
4 | import com.google.gson.Gson;
5 | import com.google.gson.JsonElement;
6 | import com.google.gson.JsonPrimitive;
7 | import org.openqa.selenium.remote.RemoteWebElement;
8 |
9 | import java.util.Base64;
10 | import java.util.HashMap;
11 | import java.util.Map;
12 | import java.util.Objects;
13 |
14 | /**
15 | * Implement FlutterElement extending RemoteWebElement to enable common Mobile element operations such as click, enter e.t.c on FlutterElement objects
16 | *
17 | * @author ashwith
18 | * @version 1.0.0
19 | */
20 | public class FlutterElement extends RemoteWebElement {
21 |
22 | private final Map rawMap;
23 | private final Gson gson = new Gson();
24 |
25 | protected FlutterElement(final Map rawMap) {
26 | this.rawMap = rawMap;
27 | id = serialize(rawMap);
28 | }
29 |
30 | /**
31 | * To return the raw data map
32 | *
33 | * @return raw data map
34 | */
35 | protected Map getRawMap() {
36 | return rawMap;
37 | }
38 |
39 | /**
40 | * To serialize raw data map
41 | *
42 | * @param rawMap serializing map
43 | * @return Stringify map
44 | */
45 | private String serialize(final Map rawMap) {
46 | final JsonPrimitive localInstance = new JsonPrimitive(String.valueOf(false));
47 | Map tempMap = new HashMap<>();
48 | rawMap.forEach(
49 | (key, value) -> {
50 | if (value instanceof String || value instanceof Integer || value instanceof Boolean) {
51 | tempMap.put(key, new JsonPrimitive(String.valueOf(value)));
52 | } else if (value instanceof JsonElement) {
53 | tempMap.put(key, value);
54 | } else if (value instanceof Map) {
55 | tempMap.put(key, gson.toJson(value));
56 | } else {
57 | tempMap.put(key, localInstance);
58 | }
59 | });
60 | String mapJsonStringify = gson.toJson(tempMap);
61 | return Base64.getEncoder().encodeToString(mapJsonStringify.getBytes());
62 | }
63 |
64 | @Override
65 | public boolean equals(Object o) {
66 | if (this == o) return true;
67 | if (o == null || getClass() != o.getClass()) return false;
68 | if (!super.equals(o)) return false;
69 | FlutterElement that = (FlutterElement) o;
70 | return Objects.equals(rawMap, that.rawMap) && Objects.equals(gson, that.gson);
71 | }
72 |
73 | @Override
74 | public int hashCode() {
75 | return Objects.hash(super.hashCode(), rawMap, gson);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/.github/workflows/github-release.yml:
--------------------------------------------------------------------------------
1 | name: Create Release with Automated Notes
2 |
3 | on:
4 | push:
5 | tags:
6 | - 'v*.*.*' # Triggers on semantic version tags like v1.0.0, v2.1.3
7 |
8 | permissions:
9 | contents: write
10 |
11 | jobs:
12 | release:
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 | - name: Checkout code
17 | uses: actions/checkout@v4
18 | with:
19 | fetch-depth: 0 # Fetch all history for changelog generation
20 |
21 | - name: Get previous tag
22 | id: previoustag
23 | run: |
24 | PREVIOUS_TAG=$(git tag --sort=-creatordate | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sed -n '2p')
25 | if [ -z "$PREVIOUS_TAG" ]; then
26 | echo "No previous tag found, using first commit"
27 | PREVIOUS_TAG=$(git rev-list --max-parents=0 HEAD)
28 | fi
29 | echo "tag=$PREVIOUS_TAG" >> $GITHUB_OUTPUT
30 | echo "Previous tag: $PREVIOUS_TAG"
31 |
32 | - name: Generate changelog
33 | id: changelog
34 | run: |
35 | echo "# What's Changed" > changelog.md
36 | echo "" >> changelog.md
37 |
38 | # Get commits between tags
39 | COMMITS=$(git log ${{ steps.previoustag.outputs.tag }}..HEAD --pretty=format:"%s|%h" --no-merges)
40 |
41 | # Categorize commits
42 | echo "## ✨ Features" >> changelog.md
43 | echo "$COMMITS" | grep -iE "^feat|^feature" | sed 's/\(.*\)|\(.*\)/- \1 (\2)/' >> changelog.md || echo "- No new features" >> changelog.md
44 | echo "" >> changelog.md
45 |
46 | echo "## 🐛 Bug Fixes" >> changelog.md
47 | echo "$COMMITS" | grep -iE "^fix|^bugfix" | sed 's/\(.*\)|\(.*\)/- \1 (\2)/' >> changelog.md || echo "- No bug fixes" >> changelog.md
48 | echo "" >> changelog.md
49 |
50 | echo "## 📚 Documentation" >> changelog.md
51 | echo "$COMMITS" | grep -iE "^docs|^doc" | sed 's/\(.*\)|\(.*\)/- \1 (\2)/' >> changelog.md || echo "- No documentation updates" >> changelog.md
52 | echo "" >> changelog.md
53 |
54 | echo "## 🔧 Other Changes" >> changelog.md
55 | echo "$COMMITS" | grep -viE "^feat|^feature|^fix|^bugfix|^docs|^doc" | sed 's/\(.*\)|\(.*\)/- \1 (\2)/' >> changelog.md || echo "- No other changes" >> changelog.md
56 |
57 | # Output for GitHub
58 | echo "notes<> $GITHUB_OUTPUT
59 | cat changelog.md >> $GITHUB_OUTPUT
60 | echo "EOF" >> $GITHUB_OUTPUT
61 |
62 | - name: Display changelog
63 | run: cat changelog.md
64 |
65 | - name: Create Release
66 | uses: softprops/action-gh-release@v1
67 | with:
68 | body: ${{ steps.changelog.outputs.notes }}
69 | draft: false
70 | prerelease: false
71 | generate_release_notes: true # Also includes GitHub's auto-generated notes
72 | env:
73 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
74 |
75 | - name: Notify release created
76 | run: |
77 | echo "✅ Release ${{ github.ref_name }} created successfully!"
78 | echo "📝 View it at: ${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ github.ref_name }}"
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Appium Flutter Finder Java
2 | Flutter appium driver is automation tool with java implementation.
3 |
4 | [](https://github.com/ashwithpoojary98/javaflutterfinder)
5 | [](https://github.com/ashwithpoojary98/javaflutterfinder/stargazers)
6 | [](https://github.com/ashwithpoojary98/javaflutterfinder/pulls)
7 | [](https://github.com/ashwithpoojary98/javaflutterfinder/network)
8 |
9 | # maven-plugin
10 | [](https://github.com/ashwithpoojary98/javaflutterfinder/actions/workflows/mavenbuild.yml)
11 | ## Setup
12 | Add maven dependency to pom.xml
13 |
14 | ```xml
15 |
16 | io.github.ashwithpoojary98
17 | appium_flutterfinder_java
18 | 1.0.12
19 |
20 | ```
21 |
22 | ## Maven Center Repo link
23 |
24 | https://mvnrepository.com/artifact/io.github.ashwithpoojary98/appium_flutterfinder_java
25 | ## Usage
26 |
27 | ```java
28 |
29 | import io.appium.java_client.AppiumDriver;
30 |
31 | public class FlutterFinderExampleTest {
32 | RemoteWebDriver driver;
33 |
34 | @BeforeMethod
35 | public void openApp() throws MalformedURLException {
36 | DesiredCapabilities capabilities = new DesiredCapabilities();
37 | capabilities.setCapability("deviceName", "emulator-5554");
38 | capabilities.setCapability("platformName", "Android");
39 | capabilities.setCapability("noReset", true);
40 | capabilities.setCapability("app", "");
41 | capabilities.setCapability("automationName", "Flutter");
42 | driver = new AppiumDriver(new URL("http://0.0.0.0:4723/wd/hub"), capabilities);
43 | driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(30));
44 | }
45 |
46 | @Test
47 | public void appiumFlutterTest() {
48 | FlutterFinder finder = new FlutterFinder(driver);
49 | WebElement element = finder.byValueKey("increment");
50 | element.click();
51 | }
52 |
53 | @AfterMethod
54 | public void tearDown() {
55 | if (driver != null) {
56 | driver.quit();
57 | }
58 | }
59 | }
60 | ```
61 | ### Automation setup
62 | https://dev.to/ashwithpoojary98/automating-flutter-app-using-flutter-appium-driver-1cmb
63 |
64 | ### list of finder
65 | 1. byValueKey(String key)
66 | 2. byValueKey(int key)
67 | 3. byToolTip(String toolTipText)
68 | 4. byType(String type)
69 | 5. byText(String input)
70 | 6. byAncestor(FlutterElement of, FlutterElement matching, boolean matchRoot, boolean firstMatchOnly)
71 | 7. byDescendant(FlutterElement of, FlutterElement matching, boolean matchRoot, boolean firstMatchOnly)
72 | 8. bySemanticsLabel(String label)
73 | 9. bySemanticsLabel(Pattern label)
74 |
75 |
76 | ### Flutter Common Finders
77 | https://api.flutter.dev/flutter/flutter_test/CommonFinders-class.html
78 |
79 | ### More about flutter finder
80 | https://github.com/appium-userland/appium-flutter-driver
81 |
82 | ## License
83 |
84 | appium_flutterfinder_java is released under [](https://opensource.org/licenses/MIT)
85 |
86 | Copyright (c) 2025 appium_flutterfinder_java
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 | io.github.ashwithpoojary98
7 | appium_flutterfinder_java
8 | 1.0.14
9 |
10 |
11 |
12 | org.apache.maven.plugins
13 | maven-compiler-plugin
14 |
15 | 11
16 | 11
17 |
18 |
19 |
20 | org.sonatype.central
21 | central-publishing-maven-plugin
22 | 0.9.0
23 | true
24 |
25 | central
26 | true
27 |
28 |
29 |
30 |
31 | jar
32 | ${project.groupId}:${project.artifactId}
33 | Flutter finder plugin for Appium in java
34 | https://github.com/ashwithpoojary98/javaflutterfinder
35 |
36 |
37 | MIT License
38 | http://www.opensource.org/licenses/mit-license.php
39 |
40 |
41 |
42 |
43 |
44 |
45 | ashwith
46 | ashwithpoojary98@gmail.com
47 | ashwithpoojary98
48 | https://github.com/ashwithpoojary98/javaflutterfinder
49 |
50 |
51 |
52 | scm:git:git://github.com/ashwithpoojary98/javaflutterfinder.git
53 | scm:git:ssh://github.com:ashwithpoojary98/javaflutterfinder.git
54 | https://github.com/ashwithpoojary98/javaflutterfinder
55 |
56 |
57 |
58 |
59 | 11
60 | 11
61 | 10.0.0
62 | 2.13.1
63 | 7.11.0
64 | true
65 |
66 |
67 |
68 |
69 | io.appium
70 | java-client
71 | ${appium.version}
72 |
73 |
74 | com.google.code.gson
75 | gson
76 | ${google.gson.version}
77 |
78 |
79 | org.testng
80 | testng
81 | ${testng.version}
82 |
83 |
84 |
85 |
86 | release
87 |
88 |
89 |
90 | org.apache.maven.plugins
91 | maven-source-plugin
92 | 2.2.1
93 |
94 |
95 | attach-sources
96 |
97 | jar-no-fork
98 |
99 |
100 |
101 |
102 |
103 | org.apache.maven.plugins
104 | maven-javadoc-plugin
105 | 2.9.1
106 |
107 |
108 | attach-javadocs
109 |
110 | jar
111 |
112 |
113 |
114 |
115 |
116 | org.apache.maven.plugins
117 | maven-gpg-plugin
118 | 1.5
119 |
120 |
121 | sign-artifacts
122 | verify
123 |
124 | sign
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
--------------------------------------------------------------------------------
/src/main/java/io/github/ashwith/flutter/FlutterFinder.java:
--------------------------------------------------------------------------------
1 | package io.github.ashwith.flutter;
2 |
3 |
4 | import io.github.ashwith.flutter.finders.ByAncestor;
5 | import io.github.ashwith.flutter.finders.ByDescendant;
6 | import io.github.ashwith.flutter.finders.BySemanticsLabel;
7 | import io.github.ashwith.flutter.finders.ByText;
8 | import io.github.ashwith.flutter.finders.ByToolTip;
9 | import io.github.ashwith.flutter.finders.ByType;
10 | import io.github.ashwith.flutter.finders.ByValueKey;
11 | import io.github.ashwith.flutter.finders.PageBack;
12 | import org.openqa.selenium.remote.FileDetector;
13 | import org.openqa.selenium.remote.RemoteWebDriver;
14 |
15 | import java.util.HashMap;
16 | import java.util.Map;
17 | import java.util.regex.Pattern;
18 |
19 | /**
20 | * Flutter finder implementation of different type of flutter element finder
21 | *
22 | * @author ashwith
23 | * @version 1.0.0
24 | */
25 | public class FlutterFinder implements ByValueKey, ByType, ByToolTip, ByText, ByAncestor, ByDescendant,
26 | BySemanticsLabel, PageBack {
27 | RemoteWebDriver driver;
28 | FileDetector fileDetector;
29 | private static final String FINDER_TYPE = "finderType";
30 |
31 | public FlutterFinder(RemoteWebDriver driver) {
32 | this.driver = driver;
33 | this.fileDetector = keys -> null;
34 | }
35 |
36 | @Override
37 | public FlutterElement byValueKey(String key) {
38 | FlutterElement flutterElement = new FlutterElement(Map
39 | .of(FINDER_TYPE, "ByValueKey",
40 | "keyValueType", "String",
41 | "keyValueString", key));
42 | flutterElement.setParent(driver);
43 | flutterElement.setFileDetector(fileDetector);
44 | return flutterElement;
45 | }
46 |
47 | @Override
48 | public FlutterElement byValueKey(int key) {
49 | FlutterElement flutterElement = new FlutterElement(Map
50 | .of(FINDER_TYPE, "ByValueKey",
51 | "keyValueType", "int",
52 | "keyValueString", key));
53 | flutterElement.setParent(driver);
54 | flutterElement.setFileDetector(fileDetector);
55 | return flutterElement;
56 | }
57 |
58 | @Override
59 | public FlutterElement byType(String type) {
60 | FlutterElement flutterElement = new FlutterElement(Map.of(
61 | FINDER_TYPE, "ByType",
62 | "type", type
63 | ));
64 | flutterElement.setParent(driver);
65 | flutterElement.setFileDetector(fileDetector);
66 | return flutterElement;
67 | }
68 |
69 | @Override
70 | public FlutterElement byToolTip(String toolTipText) {
71 | FlutterElement flutterElement = new FlutterElement(Map.of(
72 | FINDER_TYPE, "ByTooltipMessage",
73 | "text", toolTipText
74 | ));
75 | flutterElement.setParent(driver);
76 | flutterElement.setFileDetector(fileDetector);
77 | return flutterElement;
78 | }
79 |
80 | @Override
81 | public FlutterElement byText(String input) {
82 | FlutterElement flutterElement = new FlutterElement(Map.of(
83 | FINDER_TYPE, "ByText",
84 | "text", input
85 | ));
86 | flutterElement.setParent(driver);
87 | flutterElement.setFileDetector(fileDetector);
88 | return flutterElement;
89 | }
90 |
91 | @Override
92 | public FlutterElement byAncestor(FlutterElement of, FlutterElement matching,
93 | boolean matchRoot, boolean firstMatchOnly) {
94 | Map matchIdentifier = new HashMap<>(Map.of(
95 | FINDER_TYPE, "Ancestor",
96 | "matchRoot", matchRoot,
97 | "firstMatchOnly", firstMatchOnly
98 | ));
99 | matchIdentifier.put("of", of.getRawMap());
100 | matchIdentifier.put("matching", matching.getRawMap());
101 | FlutterElement flutterElement = new FlutterElement(matchIdentifier);
102 | flutterElement.setParent(driver);
103 | flutterElement.setFileDetector(fileDetector);
104 | return flutterElement;
105 | }
106 |
107 | @Override
108 | public FlutterElement byDescendant(FlutterElement of, FlutterElement matching,
109 | boolean matchRoot, boolean firstMatchOnly) {
110 | Map matchIdentifier = new HashMap<>(Map.of(
111 | FINDER_TYPE, "Descendant",
112 | "matchRoot", matchRoot,
113 | "firstMatchOnly", firstMatchOnly
114 | ));
115 | matchIdentifier.put("of", of.getRawMap());
116 | matchIdentifier.put("matching", matching.getRawMap());
117 | FlutterElement flutterElement = new FlutterElement(matchIdentifier);
118 | flutterElement.setParent(driver);
119 | flutterElement.setFileDetector(fileDetector);
120 | return flutterElement;
121 | }
122 |
123 | @Override
124 | public FlutterElement bySemanticsLabel(String label) {
125 | FlutterElement flutterElement = new FlutterElement(Map.of(
126 | FINDER_TYPE, "BySemanticsLabel",
127 | "isRegExp", false,
128 | "label", label
129 | ));
130 | flutterElement.setParent(driver);
131 | flutterElement.setFileDetector(fileDetector);
132 | return flutterElement;
133 | }
134 |
135 | @Override
136 | public FlutterElement bySemanticsLabel(Pattern label) {
137 | FlutterElement flutterElement = new FlutterElement(Map.of(
138 | FINDER_TYPE, "BySemanticsLabel",
139 | "isRegExp", true,
140 | "label", label.toString()
141 | ));
142 | flutterElement.setParent(driver);
143 | flutterElement.setFileDetector(fileDetector);
144 | return flutterElement;
145 | }
146 |
147 | @Override
148 | public FlutterElement pageBack() {
149 | return new FlutterElement(Map.of(FINDER_TYPE, "PageBack"));
150 | }
151 | }
--------------------------------------------------------------------------------