appium-mcp 0.0.1 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +37 -0
- package/.github/workflows/pr-title.yml +15 -0
- package/.github/workflows/publish.yml +31 -0
- package/.gitmodules +9 -0
- package/.prettierignore +29 -0
- package/.prettierrc +10 -0
- package/.releaserc +37 -0
- package/CHANGELOG.md +37 -0
- package/LICENSE +21 -0
- package/README.md +153 -0
- package/dist/devicemanager/adb-manager.d.ts +71 -0
- package/dist/devicemanager/adb-manager.js +140 -0
- package/dist/devicemanager/adb-manager.js.map +1 -0
- package/dist/devicemanager/ios-manager.d.ts +58 -0
- package/dist/devicemanager/ios-manager.js +122 -0
- package/dist/devicemanager/ios-manager.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/locators/element-filter.d.ts +13 -0
- package/dist/locators/element-filter.js +79 -0
- package/dist/locators/element-filter.js.map +1 -0
- package/dist/locators/generate-all-locators.d.ts +21 -0
- package/dist/locators/generate-all-locators.js +72 -0
- package/dist/locators/generate-all-locators.js.map +1 -0
- package/dist/locators/locator-generation.d.ts +36 -0
- package/dist/locators/locator-generation.js +501 -0
- package/dist/locators/locator-generation.js.map +1 -0
- package/dist/locators/logger.d.ts +5 -0
- package/dist/locators/logger.js +9 -0
- package/dist/locators/logger.js.map +1 -0
- package/dist/locators/source-parsing.d.ts +43 -0
- package/dist/locators/source-parsing.js +100 -0
- package/dist/locators/source-parsing.js.map +1 -0
- package/dist/resources/index.d.ts +1 -0
- package/dist/resources/index.js +7 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/java/template.d.ts +4 -0
- package/dist/resources/java/template.js +82 -0
- package/dist/resources/java/template.js.map +1 -0
- package/dist/schema.d.ts +2 -0
- package/dist/schema.js +5 -0
- package/dist/schema.js.map +1 -0
- package/dist/scripts/simple-index-documentation.d.ts +20 -0
- package/dist/scripts/simple-index-documentation.js +77 -0
- package/dist/scripts/simple-index-documentation.js.map +1 -0
- package/dist/scripts/simple-query-documentation.d.ts +12 -0
- package/dist/scripts/simple-query-documentation.js +52 -0
- package/dist/scripts/simple-query-documentation.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.js +37 -0
- package/dist/server.js.map +1 -0
- package/dist/tests/__mocks__/@appium/support.d.ts +21 -0
- package/dist/tests/__mocks__/@appium/support.js +30 -0
- package/dist/tests/__mocks__/@appium/support.js.map +1 -0
- package/dist/tests/generate-all-locators.test.d.ts +1 -0
- package/dist/tests/generate-all-locators.test.js +140 -0
- package/dist/tests/generate-all-locators.test.js.map +1 -0
- package/dist/tests/test-setup-wda.d.ts +1 -0
- package/dist/tests/test-setup-wda.js +202 -0
- package/dist/tests/test-setup-wda.js.map +1 -0
- package/dist/tools/answer-appium.d.ts +1 -0
- package/dist/tools/answer-appium.js +71 -0
- package/dist/tools/answer-appium.js.map +1 -0
- package/dist/tools/boot-simulator.d.ts +1 -0
- package/dist/tools/boot-simulator.js +71 -0
- package/dist/tools/boot-simulator.js.map +1 -0
- package/dist/tools/create-session.d.ts +1 -0
- package/dist/tools/create-session.js +192 -0
- package/dist/tools/create-session.js.map +1 -0
- package/dist/tools/delete-session.d.ts +1 -0
- package/dist/tools/delete-session.js +47 -0
- package/dist/tools/delete-session.js.map +1 -0
- package/dist/tools/documentation/index.d.ts +28 -0
- package/dist/tools/documentation/index.js +63 -0
- package/dist/tools/documentation/index.js.map +1 -0
- package/dist/tools/documentation/reasoning-rag.d.ts +88 -0
- package/dist/tools/documentation/reasoning-rag.js +281 -0
- package/dist/tools/documentation/reasoning-rag.js.map +1 -0
- package/dist/tools/documentation/sentence-transformers-embeddings.d.ts +34 -0
- package/dist/tools/documentation/sentence-transformers-embeddings.js +111 -0
- package/dist/tools/documentation/sentence-transformers-embeddings.js.map +1 -0
- package/dist/tools/documentation/simple-pdf-indexer.d.ts +45 -0
- package/dist/tools/documentation/simple-pdf-indexer.js +402 -0
- package/dist/tools/documentation/simple-pdf-indexer.js.map +1 -0
- package/dist/tools/documentation/uploads/documents.json +1 -0
- package/dist/tools/generate-tests.d.ts +2 -0
- package/dist/tools/generate-tests.js +46 -0
- package/dist/tools/generate-tests.js.map +1 -0
- package/dist/tools/index.d.ts +16 -0
- package/dist/tools/index.js +112 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/install-wda.d.ts +1 -0
- package/dist/tools/install-wda.js +219 -0
- package/dist/tools/install-wda.js.map +1 -0
- package/dist/tools/interactions/activate-app.d.ts +2 -0
- package/dist/tools/interactions/activate-app.js +44 -0
- package/dist/tools/interactions/activate-app.js.map +1 -0
- package/dist/tools/interactions/click.d.ts +2 -0
- package/dist/tools/interactions/click.js +45 -0
- package/dist/tools/interactions/click.js.map +1 -0
- package/dist/tools/interactions/double-tap.d.ts +2 -0
- package/dist/tools/interactions/double-tap.js +81 -0
- package/dist/tools/interactions/double-tap.js.map +1 -0
- package/dist/tools/interactions/find.d.ts +13 -0
- package/dist/tools/interactions/find.js +55 -0
- package/dist/tools/interactions/find.js.map +1 -0
- package/dist/tools/interactions/get-text.d.ts +2 -0
- package/dist/tools/interactions/get-text.js +45 -0
- package/dist/tools/interactions/get-text.js.map +1 -0
- package/dist/tools/interactions/install-app.d.ts +2 -0
- package/dist/tools/interactions/install-app.js +43 -0
- package/dist/tools/interactions/install-app.js.map +1 -0
- package/dist/tools/interactions/list-apps.d.ts +2 -0
- package/dist/tools/interactions/list-apps.js +59 -0
- package/dist/tools/interactions/list-apps.js.map +1 -0
- package/dist/tools/interactions/screenshot.d.ts +2 -0
- package/dist/tools/interactions/screenshot.js +49 -0
- package/dist/tools/interactions/screenshot.js.map +1 -0
- package/dist/tools/interactions/set-value.d.ts +2 -0
- package/dist/tools/interactions/set-value.js +46 -0
- package/dist/tools/interactions/set-value.js.map +1 -0
- package/dist/tools/interactions/terminate-app.d.ts +2 -0
- package/dist/tools/interactions/terminate-app.js +45 -0
- package/dist/tools/interactions/terminate-app.js.map +1 -0
- package/dist/tools/interactions/uninstall-app.d.ts +2 -0
- package/dist/tools/interactions/uninstall-app.js +45 -0
- package/dist/tools/interactions/uninstall-app.js.map +1 -0
- package/dist/tools/locators.d.ts +1 -0
- package/dist/tools/locators.js +71 -0
- package/dist/tools/locators.js.map +1 -0
- package/dist/tools/scroll-to-element.d.ts +1 -0
- package/dist/tools/scroll-to-element.js +155 -0
- package/dist/tools/scroll-to-element.js.map +1 -0
- package/dist/tools/scroll.d.ts +1 -0
- package/dist/tools/scroll.js +91 -0
- package/dist/tools/scroll.js.map +1 -0
- package/dist/tools/select-device.d.ts +5 -0
- package/dist/tools/select-device.js +222 -0
- package/dist/tools/select-device.js.map +1 -0
- package/dist/tools/select-platform.d.ts +1 -0
- package/dist/tools/select-platform.js +195 -0
- package/dist/tools/select-platform.js.map +1 -0
- package/dist/tools/session-store.d.ts +7 -0
- package/dist/tools/session-store.js +64 -0
- package/dist/tools/session-store.js.map +1 -0
- package/dist/tools/setup-wda.d.ts +1 -0
- package/dist/tools/setup-wda.js +177 -0
- package/dist/tools/setup-wda.js.map +1 -0
- package/docs/CONTRIBUTING.md +424 -0
- package/eslint.config.js +49 -0
- package/examples/android-gmail.md +7 -0
- package/examples/android-todo-app.md +9 -0
- package/jest.config.js +23 -0
- package/package.json +71 -6
- package/scripts/setup-submodules-sparse.sh +53 -0
- package/scripts/update-submodules.sh +14 -0
- package/src/devicemanager/adb-manager.ts +164 -0
- package/src/devicemanager/ios-manager.ts +145 -0
- package/src/index.ts +47 -0
- package/src/locators/element-filter.ts +134 -0
- package/src/locators/generate-all-locators.ts +149 -0
- package/src/locators/locator-generation.ts +657 -0
- package/src/locators/logger.ts +11 -0
- package/src/locators/source-parsing.ts +149 -0
- package/src/resources/caps.json +697 -0
- package/src/resources/index.ts +7 -0
- package/src/resources/java/template.ts +83 -0
- package/src/resources/submodules/appium/.github/PULL_REQUEST_TEMPLATE.md +28 -0
- package/src/resources/submodules/appium/CHANGELOG.md +45 -0
- package/src/resources/submodules/appium/CONDUCT.md +48 -0
- package/src/resources/submodules/appium/GOVERNANCE.md +185 -0
- package/src/resources/submodules/appium/IDEAS.md +16 -0
- package/src/resources/submodules/appium/README.md +221 -0
- package/src/resources/submodules/appium/ROADMAP.md +30 -0
- package/src/resources/submodules/appium/SPONSORS.md +3 -0
- package/src/resources/submodules/appium/docs/README.md +6 -0
- package/src/resources/submodules/appium/docs/payout.md +35 -0
- package/src/resources/submodules/appium/packages/appium/CHANGELOG.md +1437 -0
- package/src/resources/submodules/appium/packages/appium/README.md +221 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/blog/index.md +2 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/blog/posts/announcing-appiumconf2024.md +45 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/blog/posts/announcing-browserstack-as-strategic-partner.md +46 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/blog/posts/announcing-headspin-as-development-partner.md +47 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/blog/posts/announcing-lambdatest-as-strategic-partner.md +42 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/blog/posts/announcing-sauce-labs-as-strategic-partner.md +36 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/blog/posts/announcing-sponsorship-program.md +48 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/blog/posts/appium3.md +40 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/blog/posts/hello-world.md +15 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/contributing/index.md +150 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/developing/build-docs.md +86 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/developing/build-doctor-checks.md +141 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/developing/build-drivers.md +860 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/developing/build-plugins.md +514 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/developing/config-system.md +451 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/developing/index.md +18 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/developing/sensitive.md +49 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/ecosystem/clients.md +132 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/ecosystem/drivers.md +207 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/ecosystem/index.md +45 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/ecosystem/plugins.md +138 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/ecosystem/tools.md +83 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/guides/branch-testing.md +57 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/guides/caching.md +76 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/guides/caps.md +275 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/guides/config.md +98 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/guides/context.md +44 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/guides/event-timing.md +73 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/guides/execute-methods.md +122 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/guides/grid.md +166 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/guides/headers.md +17 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/guides/log-filters.md +86 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/guides/managing-exts.md +87 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/guides/migrating-1-to-2.md +368 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/guides/migrating-2-to-3.md +464 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/guides/security.md +89 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/guides/settings.md +68 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/guides/tls.md +42 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/index.md +59 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/intro/appium.md +202 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/intro/clients.md +127 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/intro/drivers.md +188 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/intro/history.md +196 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/intro/index.md +39 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/quickstart/index.md +29 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/quickstart/install.md +50 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/quickstart/next-steps.md +23 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/quickstart/requirements.md +29 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/quickstart/test-dotnet.md +105 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/quickstart/test-java.md +23 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/quickstart/test-js.md +75 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/quickstart/test-py.md +60 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/quickstart/test-rb.md +83 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/quickstart/uiauto2-driver.md +144 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/reference/api/appium.md +394 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/reference/api/bidi.md +70 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/reference/api/index.md +30 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/reference/api/jsonwp.md +214 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/reference/api/mjsonwp.md +151 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/reference/api/others.md +671 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/reference/api/plugins.md +289 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/reference/api/webdriver.md +1114 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/reference/cli/env-vars.md +31 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/reference/cli/extensions.md +239 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/reference/cli/index.md +35 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/reference/cli/server.md +76 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/reference/cli/setup.md +76 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/reference/index.md +25 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/resources/index.md +28 -0
- package/src/resources/submodules/appium/packages/appium/docs/en/sponsors/index.md +64 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/blog/index.md +2 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/blog/posts/announcing-appiumconf2024.md +45 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/blog/posts/announcing-browserstack-as-strategic-partner.md +46 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/blog/posts/announcing-headspin-as-development-partner.md +47 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/blog/posts/announcing-lambdatest-as-strategic-partner.md +41 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/blog/posts/announcing-sauce-labs-as-strategic-partner.md +36 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/blog/posts/announcing-sponsorship-program.md +48 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/blog/posts/appium3.md +40 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/blog/posts/hello-world.md +15 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/contributing/index.md +158 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/developing/build-docs.md +86 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/developing/build-doctor-checks.md +141 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/developing/build-drivers.md +866 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/developing/build-plugins.md +520 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/developing/config-system.md +468 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/developing/index.md +18 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/developing/sensitive.md +49 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/ecosystem/clients.md +143 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/ecosystem/drivers.md +219 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/ecosystem/index.md +45 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/ecosystem/plugins.md +140 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/ecosystem/tools.md +87 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/guides/branch-testing.md +57 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/guides/caching.md +78 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/guides/caps.md +259 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/guides/config.md +102 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/guides/context.md +44 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/guides/event-timing.md +75 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/guides/execute-methods.md +142 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/guides/grid.md +166 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/guides/headers.md +17 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/guides/log-filters.md +86 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/guides/managing-exts.md +89 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/guides/migrating-1-to-2.md +402 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/guides/migrating-2-to-3.md +458 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/guides/security.md +89 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/guides/settings.md +70 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/guides/tls.md +43 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/index.md +55 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/intro/appium.md +191 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/intro/clients.md +139 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/intro/drivers.md +188 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/intro/history.md +196 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/intro/index.md +39 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/quickstart/index.md +23 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/quickstart/install.md +47 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/quickstart/next-steps.md +19 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/quickstart/requirements.md +29 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/quickstart/test-dotnet.md +107 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/quickstart/test-java.md +23 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/quickstart/test-js.md +77 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/quickstart/test-py.md +63 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/quickstart/test-rb.md +85 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/quickstart/uiauto2-driver.md +148 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/reference/api/appium.md +395 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/reference/api/bidi.md +71 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/reference/api/index.md +30 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/reference/api/jsonwp.md +215 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/reference/api/mjsonwp.md +152 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/reference/api/others.md +672 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/reference/api/plugins.md +291 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/reference/api/webdriver.md +1114 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/reference/cli/env-vars.md +31 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/reference/cli/extensions.md +240 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/reference/cli/index.md +35 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/reference/cli/server.md +76 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/reference/cli/setup.md +78 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/reference/index.md +25 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/resources/index.md +28 -0
- package/src/resources/submodules/appium/packages/appium/docs/ja/sponsors/index.md +61 -0
- package/src/resources/submodules/appium/packages/appium/docs/overrides/assets/images/appium-logo-horiz-white.png +0 -0
- package/src/resources/submodules/appium/packages/appium/docs/overrides/assets/images/appium-logo-horiz.png +0 -0
- package/src/resources/submodules/appium/packages/appium/docs/overrides/assets/images/appium-logo-white.png +0 -0
- package/src/resources/submodules/appium/packages/appium/docs/overrides/assets/images/appium-logo.png +0 -0
- package/src/resources/submodules/appium/packages/appium/docs/overrides/assets/images/sponsor-logo-browserstack-dark.png +0 -0
- package/src/resources/submodules/appium/packages/appium/docs/overrides/assets/images/sponsor-logo-browserstack-light.png +0 -0
- package/src/resources/submodules/appium/packages/appium/docs/overrides/assets/images/sponsor-logo-lambdatest-dark.png +0 -0
- package/src/resources/submodules/appium/packages/appium/docs/overrides/assets/images/sponsor-logo-lambdatest-light.png +0 -0
- package/src/resources/submodules/appium/packages/appium/docs/overrides/assets/images/sponsor-logo-sauce.png +0 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/blog/index.md +2 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/blog/posts/announcing-appiumconf2024.md +45 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/blog/posts/announcing-browserstack-as-strategic-partner.md +46 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/blog/posts/announcing-headspin-as-development-partner.md +47 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/blog/posts/announcing-lambdatest-as-strategic-partner.md +41 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/blog/posts/announcing-sauce-labs-as-strategic-partner.md +36 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/blog/posts/announcing-sponsorship-program.md +48 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/blog/posts/appium3.md +40 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/blog/posts/hello-world.md +15 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/contributing/index.md +132 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/developing/build-docs.md +86 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/developing/build-doctor-checks.md +141 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/developing/build-drivers.md +866 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/developing/build-plugins.md +520 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/developing/config-system.md +468 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/developing/index.md +18 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/developing/sensitive.md +49 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/ecosystem/clients.md +143 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/ecosystem/drivers.md +219 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/ecosystem/index.md +45 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/ecosystem/plugins.md +140 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/ecosystem/tools.md +87 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/guides/branch-testing.md +57 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/guides/caching.md +78 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/guides/caps.md +284 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/guides/config.md +102 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/guides/context.md +44 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/guides/event-timing.md +75 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/guides/execute-methods.md +142 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/guides/grid.md +166 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/guides/headers.md +17 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/guides/log-filters.md +86 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/guides/managing-exts.md +89 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/guides/migrating-1-to-2.md +410 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/guides/migrating-2-to-3.md +459 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/guides/security.md +89 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/guides/settings.md +70 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/guides/tls.md +43 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/index.md +54 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/intro/appium.md +200 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/intro/clients.md +139 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/intro/drivers.md +188 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/intro/history.md +196 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/intro/index.md +39 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/quickstart/index.md +23 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/quickstart/install.md +47 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/quickstart/next-steps.md +19 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/quickstart/requirements.md +21 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/quickstart/test-dotnet.md +99 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/quickstart/test-java.md +20 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/quickstart/test-js.md +62 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/quickstart/test-py.md +57 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/quickstart/test-rb.md +80 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/quickstart/uiauto2-driver.md +148 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/reference/api/appium.md +395 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/reference/api/bidi.md +71 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/reference/api/index.md +30 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/reference/api/jsonwp.md +215 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/reference/api/mjsonwp.md +152 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/reference/api/others.md +672 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/reference/api/plugins.md +291 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/reference/api/webdriver.md +1114 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/reference/cli/env-vars.md +31 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/reference/cli/extensions.md +240 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/reference/cli/index.md +35 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/reference/cli/server.md +76 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/reference/cli/setup.md +78 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/reference/index.md +25 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/resources/index.md +28 -0
- package/src/resources/submodules/appium/packages/appium/docs/zh/sponsors/index.md +61 -0
- package/src/resources/submodules/appium/packages/appium/types/manifest/README.md +30 -0
- package/src/resources/submodules/appium/packages/base-driver/CHANGELOG.md +1131 -0
- package/src/resources/submodules/appium/packages/base-driver/README.md +15 -0
- package/src/resources/submodules/appium/packages/base-driver/docs/mjsonwp/errors.md +82 -0
- package/src/resources/submodules/appium/packages/base-driver/docs/mjsonwp/protocol-methods.md +182 -0
- package/src/resources/submodules/appium/packages/base-driver/static/appium.png +0 -0
- package/src/resources/submodules/appium/packages/base-plugin/CHANGELOG.md +672 -0
- package/src/resources/submodules/appium/packages/base-plugin/README.md +15 -0
- package/src/resources/submodules/appium/packages/docutils/CHANGELOG.md +948 -0
- package/src/resources/submodules/appium/packages/docutils/README.md +27 -0
- package/src/resources/submodules/appium/packages/driver-test-support/CHANGELOG.md +717 -0
- package/src/resources/submodules/appium/packages/driver-test-support/README.md +112 -0
- package/src/resources/submodules/appium/packages/eslint-config-appium-ts/CHANGELOG.md +168 -0
- package/src/resources/submodules/appium/packages/eslint-config-appium-ts/README.md +33 -0
- package/src/resources/submodules/appium/packages/execute-driver-plugin/CHANGELOG.md +603 -0
- package/src/resources/submodules/appium/packages/execute-driver-plugin/README.md +42 -0
- package/src/resources/submodules/appium/packages/fake-driver/CHANGELOG.md +545 -0
- package/src/resources/submodules/appium/packages/fake-driver/README.md +7 -0
- package/src/resources/submodules/appium/packages/fake-driver/lib/screen.png +0 -0
- package/src/resources/submodules/appium/packages/fake-plugin/CHANGELOG.md +683 -0
- package/src/resources/submodules/appium/packages/fake-plugin/README.md +7 -0
- package/src/resources/submodules/appium/packages/images-plugin/CHANGELOG.md +602 -0
- package/src/resources/submodules/appium/packages/images-plugin/README.md +27 -0
- package/src/resources/submodules/appium/packages/images-plugin/docs/find-by-image.md +65 -0
- package/src/resources/submodules/appium/packages/images-plugin/docs/image-comparison.md +203 -0
- package/src/resources/submodules/appium/packages/images-plugin/test/fixtures/appstore.png +0 -0
- package/src/resources/submodules/appium/packages/images-plugin/test/fixtures/img1.png +0 -0
- package/src/resources/submodules/appium/packages/images-plugin/test/fixtures/img2.png +0 -0
- package/src/resources/submodules/appium/packages/images-plugin/test/fixtures/img2_part.png +0 -0
- package/src/resources/submodules/appium/packages/logger/CHANGELOG.md +162 -0
- package/src/resources/submodules/appium/packages/logger/README.md +31 -0
- package/src/resources/submodules/appium/packages/opencv/CHANGELOG.md +384 -0
- package/src/resources/submodules/appium/packages/opencv/README.md +68 -0
- package/src/resources/submodules/appium/packages/opencv/test/e2e/images/appium-diagram.jpg +0 -0
- package/src/resources/submodules/appium/packages/opencv/test/e2e/images/cc1.png +0 -0
- package/src/resources/submodules/appium/packages/opencv/test/e2e/images/cc2.png +0 -0
- package/src/resources/submodules/appium/packages/opencv/test/e2e/images/cc_rotated.png +0 -0
- package/src/resources/submodules/appium/packages/opencv/test/e2e/images/findwaldo.jpg +0 -0
- package/src/resources/submodules/appium/packages/opencv/test/e2e/images/number5.png +0 -0
- package/src/resources/submodules/appium/packages/opencv/test/e2e/images/waldo.jpg +0 -0
- package/src/resources/submodules/appium/packages/plugin-test-support/CHANGELOG.md +539 -0
- package/src/resources/submodules/appium/packages/plugin-test-support/README.md +49 -0
- package/src/resources/submodules/appium/packages/relaxed-caps-plugin/CHANGELOG.md +154 -0
- package/src/resources/submodules/appium/packages/relaxed-caps-plugin/README.md +35 -0
- package/src/resources/submodules/appium/packages/schema/CHANGELOG.md +271 -0
- package/src/resources/submodules/appium/packages/schema/README.md +50 -0
- package/src/resources/submodules/appium/packages/storage-plugin/CHANGELOG.md +73 -0
- package/src/resources/submodules/appium/packages/storage-plugin/README.md +83 -0
- package/src/resources/submodules/appium/packages/strongbox/CHANGELOG.md +94 -0
- package/src/resources/submodules/appium/packages/strongbox/README.md +96 -0
- package/src/resources/submodules/appium/packages/support/CHANGELOG.md +1054 -0
- package/src/resources/submodules/appium/packages/support/README.md +161 -0
- package/src/resources/submodules/appium/packages/test-support/CHANGELOG.md +712 -0
- package/src/resources/submodules/appium/packages/test-support/README.md +61 -0
- package/src/resources/submodules/appium/packages/tsconfig/CHANGELOG.md +131 -0
- package/src/resources/submodules/appium/packages/tsconfig/README.md +19 -0
- package/src/resources/submodules/appium/packages/types/CHANGELOG.md +793 -0
- package/src/resources/submodules/appium/packages/types/README.md +21 -0
- package/src/resources/submodules/appium/packages/universal-xml-plugin/CHANGELOG.md +435 -0
- package/src/resources/submodules/appium/packages/universal-xml-plugin/README.md +53 -0
- package/src/resources/submodules/appium/renovate/README.md +63 -0
- package/src/resources/submodules/appium-uiautomator2-driver/CHANGELOG.md +1204 -0
- package/src/resources/submodules/appium-uiautomator2-driver/README.md +2077 -0
- package/src/resources/submodules/appium-uiautomator2-driver/docs/actions.md +72 -0
- package/src/resources/submodules/appium-uiautomator2-driver/docs/activity-startup.md +47 -0
- package/src/resources/submodules/appium-uiautomator2-driver/docs/android-appbundle.md +69 -0
- package/src/resources/submodules/appium-uiautomator2-driver/docs/android-mobile-gestures.md +352 -0
- package/src/resources/submodules/appium-uiautomator2-driver/docs/bidi.md +50 -0
- package/src/resources/submodules/appium-uiautomator2-driver/docs/capability-sets.md +136 -0
- package/src/resources/submodules/appium-uiautomator2-driver/docs/scheduled-actions.md +155 -0
- package/src/resources/submodules/appium-uiautomator2-driver/docs/uiautomator-uiselector.md +51 -0
- package/src/resources/submodules/appium-uiautomator2-driver/docs/unlock/main.md +95 -0
- package/src/resources/submodules/appium-uiautomator2-driver/docs/unlock/screen1.png +0 -0
- package/src/resources/submodules/appium-uiautomator2-driver/docs/unlock/screen2.png +0 -0
- package/src/resources/submodules/appium-uiautomator2-driver/test/functional/assets/checkered-squares.png +0 -0
- package/src/resources/submodules/appium-uiautomator2-driver/test/functional/assets/start-button.png +0 -0
- package/src/resources/submodules/appium-uiautomator2-driver/test/functional/assets/stop-button.png +0 -0
- package/src/resources/submodules/appium-xcuitest-driver/.github/ISSUE_TEMPLATE.md +4 -0
- package/src/resources/submodules/appium-xcuitest-driver/CHANGELOG.md +2594 -0
- package/src/resources/submodules/appium-xcuitest-driver/README.md +55 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/assets/images/appium-logo-white.png +0 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/assets/images/appium-logo.png +0 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/assets/images/appium-plus-xctest.png +0 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/contributing.md +45 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/endpoints-wda.md +61 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/endpoints.md +98 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/assets/images/ios-xctest-file-movement/keynote.png +0 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/assets/images/ios-xctest-file-movement/on_my_iphone.png +0 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/assets/images/ios-xctest-file-movement/top_files.png +0 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/attach-to-running-wda.md +43 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/audio-capture.md +78 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/capability-sets.md +169 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/ci-setup.md +47 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/clipboard.md +47 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/elements-lookup-troubleshooting.md +158 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/file-transfer.md +147 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/gestures.md +52 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/hybrid.md +137 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/input-events.md +67 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/install-certificate.md +19 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/multiple-xcode-versions.md +37 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/parallel-tests.md +39 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/run-prebuilt-wda.md +135 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/run-preinstalled-wda.md +178 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/touch-id.md +33 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/troubleshooting.md +191 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/tvos.md +114 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/wda-custom-server.md +283 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/guides/wda-slowness.md +231 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/index.md +36 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/installation/index.md +137 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/overview.md +19 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/preparation/assets/images/check-prov-prof.png +0 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/preparation/assets/images/create-new-project.png +0 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/preparation/assets/images/create-single-page.png +0 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/preparation/assets/images/no-prov-prof.png +0 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/preparation/assets/images/project-prov-prof.png +0 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/preparation/assets/images/set-up-bundle.png +0 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/preparation/assets/images/untrusted-dev.png +0 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/preparation/assets/images/xcode-bundle-id.png +0 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/preparation/assets/images/xcode-config.png +0 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/preparation/assets/images/xcode-facebook-fail.png +0 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/preparation/assets/images/xcode-facebook-succeed.png +0 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/preparation/index.md +51 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/preparation/prov-profile-basic-auto.md +49 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/preparation/prov-profile-basic-manual.md +40 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/preparation/prov-profile-full-manual.md +50 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/preparation/prov-profile-generic-manual.md +49 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/preparation/real-device-config.md +100 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/reference/assets/images/useXctestrunFile.png +0 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/reference/bidi.md +75 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/reference/capabilities.md +165 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/reference/commands.md +490 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/reference/element-attributes.md +27 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/reference/execute-methods.md +2206 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/reference/ios-predicate.md +196 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/reference/locator-strategies.md +19 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/reference/scripts.md +29 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/reference/security-flags.md +22 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/reference/server-args.md +16 -0
- package/src/resources/submodules/appium-xcuitest-driver/docs/reference/settings.md +49 -0
- package/src/resources/submodules/appium-xcuitest-driver/test/assets/TestApp-iphonesimulator.app/Default-568h@2x.png +0 -0
- package/src/resources/submodules/appium-xcuitest-driver/test/assets/test.png +0 -0
- package/src/schema.ts +5 -0
- package/src/scripts/simple-index-documentation.ts +93 -0
- package/src/scripts/simple-query-documentation.ts +61 -0
- package/src/server.ts +40 -0
- package/src/tests/README.md +83 -0
- package/src/tests/__mocks__/@appium/support.ts +31 -0
- package/src/tests/generate-all-locators.test.ts +179 -0
- package/src/tests/test-setup-wda.ts +247 -0
- package/src/tools/README.md +170 -0
- package/src/tools/answer-appium.ts +75 -0
- package/src/tools/boot-simulator.ts +87 -0
- package/src/tools/create-session.ts +270 -0
- package/src/tools/delete-session.ts +46 -0
- package/src/tools/documentation/index.ts +97 -0
- package/src/tools/documentation/reasoning-rag.ts +434 -0
- package/src/tools/documentation/sentence-transformers-embeddings.ts +142 -0
- package/src/tools/documentation/simple-pdf-indexer.ts +509 -0
- package/src/tools/documentation/uploads/documents.json +1 -0
- package/src/tools/generate-tests.ts +50 -0
- package/src/tools/index.ts +133 -0
- package/src/tools/install-wda.ts +277 -0
- package/src/tools/interactions/activate-app.ts +46 -0
- package/src/tools/interactions/click.ts +47 -0
- package/src/tools/interactions/double-tap.ts +87 -0
- package/src/tools/interactions/find.ts +58 -0
- package/src/tools/interactions/get-text.ts +47 -0
- package/src/tools/interactions/install-app.ts +45 -0
- package/src/tools/interactions/list-apps.ts +65 -0
- package/src/tools/interactions/screenshot.ts +56 -0
- package/src/tools/interactions/set-value.ts +48 -0
- package/src/tools/interactions/terminate-app.ts +47 -0
- package/src/tools/interactions/uninstall-app.ts +47 -0
- package/src/tools/locators.ts +83 -0
- package/src/tools/scroll-to-element.ts +188 -0
- package/src/tools/scroll.ts +97 -0
- package/src/tools/select-device.ts +298 -0
- package/src/tools/select-platform.ts +243 -0
- package/src/tools/session-store.ts +72 -0
- package/src/tools/setup-wda.ts +218 -0
- package/src/types/appium-ios-device.d.ts +8 -0
- package/src/types/appium-xcuitest-driver.d.ts +5 -0
- package/tsconfig.json +23 -0
- package/index.js +0 -0
|
@@ -0,0 +1,657 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
import * as XPath from 'xpath';
|
|
3
|
+
const xpathSelect = XPath.select;
|
|
4
|
+
|
|
5
|
+
import log from './logger.js';
|
|
6
|
+
import {
|
|
7
|
+
childNodesOf,
|
|
8
|
+
domToXML,
|
|
9
|
+
findDOMNodeByPath,
|
|
10
|
+
xmlToDOM,
|
|
11
|
+
JSONElement,
|
|
12
|
+
ElementAttributes,
|
|
13
|
+
} from './source-parsing.js';
|
|
14
|
+
import {
|
|
15
|
+
Document as XMLDocument,
|
|
16
|
+
Node as XMLNode,
|
|
17
|
+
Element as XMLElement,
|
|
18
|
+
} from '@xmldom/xmldom';
|
|
19
|
+
|
|
20
|
+
// Attributes on nodes that are likely to be unique to the node so we should consider first when
|
|
21
|
+
// suggesting xpath locators. These are considered IN ORDER.
|
|
22
|
+
const UNIQUE_XPATH_ATTRIBUTES = [
|
|
23
|
+
'name',
|
|
24
|
+
'content-desc',
|
|
25
|
+
'id',
|
|
26
|
+
'resource-id',
|
|
27
|
+
'accessibility-id',
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
// Attributes that we should recommend as a fallback but ideally only in conjunction with other
|
|
31
|
+
// attributes
|
|
32
|
+
const MAYBE_UNIQUE_XPATH_ATTRIBUTES = ['label', 'text', 'value'];
|
|
33
|
+
|
|
34
|
+
const CHECKED_CLASS_CHAIN_ATTRIBUTES = ['name', 'label', 'value'];
|
|
35
|
+
|
|
36
|
+
const CHECKED_PREDICATE_ATTRIBUTES = ['name', 'label', 'value', 'type'];
|
|
37
|
+
|
|
38
|
+
// Map of element attributes to their UiAutomator syntax, ordered by (likely) decreasing uniqueness
|
|
39
|
+
const CHECKED_UIAUTOMATOR_ATTRIBUTES: [string, string][] = [
|
|
40
|
+
['resource-id', 'resourceId'],
|
|
41
|
+
['text', 'text'],
|
|
42
|
+
['content-desc', 'description'],
|
|
43
|
+
['class', 'className'],
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
// Map of element attributes to their matching simple (optimal) locator strategies
|
|
47
|
+
const SIMPLE_STRATEGY_MAPPINGS: [string, string][] = [
|
|
48
|
+
['name', 'accessibility id'],
|
|
49
|
+
['content-desc', 'accessibility id'],
|
|
50
|
+
['id', 'id'],
|
|
51
|
+
['rntestid', 'id'],
|
|
52
|
+
['resource-id', 'id'],
|
|
53
|
+
['class', 'class name'],
|
|
54
|
+
['type', 'class name'],
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Check whether the provided attribute & value are unique in the source
|
|
59
|
+
*/
|
|
60
|
+
export function areAttrAndValueUnique(
|
|
61
|
+
attrName: string,
|
|
62
|
+
attrValue: string,
|
|
63
|
+
sourceDoc: XMLDocument
|
|
64
|
+
): boolean {
|
|
65
|
+
// If no sourceDoc provided, assume it's unique
|
|
66
|
+
if (!sourceDoc || _.isEmpty(sourceDoc)) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
const result = xpathSelect(
|
|
70
|
+
`//*[@${attrName}="${attrValue.replace(/"/g, '')}"]`,
|
|
71
|
+
sourceDoc as any
|
|
72
|
+
);
|
|
73
|
+
return Array.isArray(result) ? result.length < 2 : false;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Get suggested selectors for simple locator strategies (which match a specific attribute)
|
|
78
|
+
*/
|
|
79
|
+
export function getSimpleSuggestedLocators(
|
|
80
|
+
attributes: ElementAttributes,
|
|
81
|
+
sourceDoc: XMLDocument,
|
|
82
|
+
isNative: boolean = true
|
|
83
|
+
): Record<string, string> {
|
|
84
|
+
const res: Record<string, string> = {};
|
|
85
|
+
for (let [strategyAlias, strategy] of SIMPLE_STRATEGY_MAPPINGS) {
|
|
86
|
+
// accessibility id is only supported in native context
|
|
87
|
+
if (!(strategy === 'accessibility id' && !isNative)) {
|
|
88
|
+
const value = attributes[strategyAlias];
|
|
89
|
+
if (value && areAttrAndValueUnique(strategyAlias, value, sourceDoc)) {
|
|
90
|
+
res[strategy] = value;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return res;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Get suggested selectors for complex locator strategies (multiple attributes, axes, etc.)
|
|
99
|
+
*/
|
|
100
|
+
export function getComplexSuggestedLocators(
|
|
101
|
+
path: string,
|
|
102
|
+
sourceDoc: XMLDocument,
|
|
103
|
+
isNative: boolean,
|
|
104
|
+
automationName: string
|
|
105
|
+
): Record<string, string> {
|
|
106
|
+
let complexLocators: Record<string, string | null> = {};
|
|
107
|
+
const domNode = findDOMNodeByPath(path, sourceDoc);
|
|
108
|
+
if (isNative) {
|
|
109
|
+
switch (automationName) {
|
|
110
|
+
case 'xcuitest':
|
|
111
|
+
case 'mac2': {
|
|
112
|
+
const optimalClassChain = getOptimalClassChain(sourceDoc, domNode);
|
|
113
|
+
complexLocators['-ios class chain'] = optimalClassChain
|
|
114
|
+
? '**' + optimalClassChain
|
|
115
|
+
: null;
|
|
116
|
+
complexLocators['-ios predicate string'] = getOptimalPredicateString(
|
|
117
|
+
sourceDoc,
|
|
118
|
+
domNode
|
|
119
|
+
);
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
case 'uiautomator2': {
|
|
123
|
+
complexLocators['-android uiautomator'] = getOptimalUiAutomatorSelector(
|
|
124
|
+
sourceDoc,
|
|
125
|
+
domNode,
|
|
126
|
+
path
|
|
127
|
+
);
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
complexLocators.xpath = getOptimalXPath(sourceDoc, domNode);
|
|
133
|
+
|
|
134
|
+
// Remove entries for locators where the optimal selector could not be found
|
|
135
|
+
return _.omitBy(complexLocators, _.isNil) as Record<string, string>;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Get suggested selectors for all locator strategies
|
|
140
|
+
*/
|
|
141
|
+
export function getSuggestedLocators(
|
|
142
|
+
selectedElement: JSONElement,
|
|
143
|
+
sourceXML: string,
|
|
144
|
+
isNative: boolean,
|
|
145
|
+
automationName: string
|
|
146
|
+
): [string, string][] {
|
|
147
|
+
const sourceDoc = xmlToDOM(sourceXML);
|
|
148
|
+
const simpleLocators = getSimpleSuggestedLocators(
|
|
149
|
+
selectedElement.attributes,
|
|
150
|
+
sourceDoc,
|
|
151
|
+
isNative
|
|
152
|
+
);
|
|
153
|
+
const complexLocators = getComplexSuggestedLocators(
|
|
154
|
+
selectedElement.path,
|
|
155
|
+
sourceDoc,
|
|
156
|
+
isNative,
|
|
157
|
+
automationName
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
// Combine all locators
|
|
161
|
+
const allLocators = { ...simpleLocators, ...complexLocators };
|
|
162
|
+
|
|
163
|
+
// Define priority order based on platform preference
|
|
164
|
+
let priorityOrder: string[];
|
|
165
|
+
|
|
166
|
+
if (
|
|
167
|
+
isNative &&
|
|
168
|
+
(automationName === 'xcuitest' || automationName === 'mac2')
|
|
169
|
+
) {
|
|
170
|
+
// iOS priority: Accessibility Id > Predicate > Class Chain > XPath > Class Name
|
|
171
|
+
priorityOrder = [
|
|
172
|
+
'id',
|
|
173
|
+
'accessibility id',
|
|
174
|
+
'-ios predicate string',
|
|
175
|
+
'-ios class chain',
|
|
176
|
+
'xpath',
|
|
177
|
+
'class name',
|
|
178
|
+
];
|
|
179
|
+
} else if (isNative && automationName === 'uiautomator2') {
|
|
180
|
+
// Android priority: Accessibility Id > UiAutomator > XPath > Class Name
|
|
181
|
+
priorityOrder = [
|
|
182
|
+
'id',
|
|
183
|
+
'accessibility id',
|
|
184
|
+
'xpath',
|
|
185
|
+
'-android uiautomator',
|
|
186
|
+
'class name',
|
|
187
|
+
];
|
|
188
|
+
} else {
|
|
189
|
+
priorityOrder = ['id', 'class name', 'xpath'];
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Sort locators by priority order, keeping only available ones
|
|
193
|
+
const sortedLocators: [string, string][] = [];
|
|
194
|
+
|
|
195
|
+
// Add locators in priority order
|
|
196
|
+
for (const strategy of priorityOrder) {
|
|
197
|
+
if (allLocators[strategy]) {
|
|
198
|
+
sortedLocators.push([strategy, allLocators[strategy]]);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Add any remaining locators that weren't in the priority list (like 'id' for native contexts)
|
|
203
|
+
for (const [strategy, value] of _.toPairs(allLocators)) {
|
|
204
|
+
if (!priorityOrder.includes(strategy)) {
|
|
205
|
+
sortedLocators.push([strategy, value]);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Return all valid locators, or empty array if none found
|
|
210
|
+
// Filter out any undefined entries
|
|
211
|
+
return sortedLocators.filter(
|
|
212
|
+
(locator): locator is [string, string] =>
|
|
213
|
+
Array.isArray(locator) &&
|
|
214
|
+
locator.length === 2 &&
|
|
215
|
+
typeof locator[0] === 'string' &&
|
|
216
|
+
typeof locator[1] === 'string' &&
|
|
217
|
+
locator[0] !== undefined &&
|
|
218
|
+
locator[1] !== undefined
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Return information about whether an xpath query results in a unique element, and the non-unique
|
|
224
|
+
* index of the element in the document if not unique
|
|
225
|
+
*/
|
|
226
|
+
function determineXpathUniqueness(
|
|
227
|
+
xpath: string,
|
|
228
|
+
doc: XMLDocument,
|
|
229
|
+
domNode: XMLNode
|
|
230
|
+
): [boolean, number?] {
|
|
231
|
+
let othersWithAttr: XMLNode[] = [];
|
|
232
|
+
|
|
233
|
+
// If the XPath does not parse, move to the next unique attribute
|
|
234
|
+
try {
|
|
235
|
+
const result = XPath.select(xpath, doc as any);
|
|
236
|
+
othersWithAttr = Array.isArray(result)
|
|
237
|
+
? (result as unknown as XMLNode[])
|
|
238
|
+
: [];
|
|
239
|
+
} catch {
|
|
240
|
+
return [false];
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (othersWithAttr.length > 1) {
|
|
244
|
+
return [false, othersWithAttr.indexOf(domNode)];
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return [true];
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Given an xml doc and a current dom node, try to find a robust xpath selector qualified by
|
|
252
|
+
* key attributes, which is unique in the document (or unique plus index).
|
|
253
|
+
*/
|
|
254
|
+
function getUniqueXPath(
|
|
255
|
+
doc: XMLDocument,
|
|
256
|
+
domNode: XMLNode,
|
|
257
|
+
attrs: string[] | [string, string][]
|
|
258
|
+
): [string | undefined, boolean | undefined] {
|
|
259
|
+
let uniqueXpath: string | undefined, semiUniqueXpath: string | undefined;
|
|
260
|
+
const tagForXpath = domNode.nodeName || '*';
|
|
261
|
+
const isPairs = attrs.length > 0 && _.isArray(attrs[0]);
|
|
262
|
+
const isNodeName = attrs.length === 0;
|
|
263
|
+
|
|
264
|
+
// If we're looking for a unique //<nodetype>, return it only if it's actually unique. No
|
|
265
|
+
// semi-uniqueness here!
|
|
266
|
+
if (isNodeName) {
|
|
267
|
+
let xpath = `//${domNode.nodeName}`;
|
|
268
|
+
const [isUnique] = determineXpathUniqueness(xpath, doc, domNode);
|
|
269
|
+
if (isUnique) {
|
|
270
|
+
// even if this node name is unique, if it's the root node, we don't want to refer to it using
|
|
271
|
+
// '//' but rather '/'
|
|
272
|
+
if (!domNode.parentNode?.nodeName) {
|
|
273
|
+
xpath = `/${domNode.nodeName}`;
|
|
274
|
+
}
|
|
275
|
+
return [xpath, true];
|
|
276
|
+
}
|
|
277
|
+
return [undefined, undefined];
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Otherwise go through our various attributes to look for uniqueness
|
|
281
|
+
for (const attrName of attrs) {
|
|
282
|
+
let xpath: string;
|
|
283
|
+
if (isPairs) {
|
|
284
|
+
const [attr1Name, attr2Name] = attrName as [string, string];
|
|
285
|
+
const attr1Value = (domNode as XMLElement).getAttribute?.(attr1Name);
|
|
286
|
+
const attr2Value = (domNode as XMLElement).getAttribute?.(attr2Name);
|
|
287
|
+
if (!attr1Value || !attr2Value) {
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
xpath = `//${tagForXpath}[@${attr1Name}="${attr1Value}" and @${attr2Name}="${attr2Value}"]`;
|
|
291
|
+
} else {
|
|
292
|
+
const attrValue = (domNode as XMLElement).getAttribute?.(
|
|
293
|
+
attrName as string
|
|
294
|
+
);
|
|
295
|
+
if (!attrValue) {
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
xpath = `//${tagForXpath}[@${attrName}="${attrValue}"]`;
|
|
299
|
+
}
|
|
300
|
+
const [isUnique, indexIfNotUnique] = determineXpathUniqueness(
|
|
301
|
+
xpath,
|
|
302
|
+
doc,
|
|
303
|
+
domNode
|
|
304
|
+
);
|
|
305
|
+
if (isUnique) {
|
|
306
|
+
uniqueXpath = xpath;
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// if the xpath wasn't totally unique it might still be our best bet. Store a less unique
|
|
311
|
+
// version qualified by an index for later in semiUniqueXpath. If we can't find a better
|
|
312
|
+
// unique option down the road, we'll fall back to this
|
|
313
|
+
if (!semiUniqueXpath && !_.isUndefined(indexIfNotUnique)) {
|
|
314
|
+
semiUniqueXpath = `(${xpath})[${indexIfNotUnique + 1}]`;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
if (uniqueXpath) {
|
|
318
|
+
return [uniqueXpath, true];
|
|
319
|
+
}
|
|
320
|
+
if (semiUniqueXpath) {
|
|
321
|
+
return [semiUniqueXpath, false];
|
|
322
|
+
}
|
|
323
|
+
return [undefined, undefined];
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Get an optimal XPath for a Node
|
|
328
|
+
*/
|
|
329
|
+
export function getOptimalXPath(
|
|
330
|
+
doc: XMLDocument,
|
|
331
|
+
domNode: XMLNode
|
|
332
|
+
): string | null {
|
|
333
|
+
try {
|
|
334
|
+
// BASE CASE #1: If this isn't an element, we're above the root, return empty string
|
|
335
|
+
if (!domNode.nodeName || domNode.nodeType !== 1) {
|
|
336
|
+
return '';
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const attrsForPairs = [
|
|
340
|
+
...UNIQUE_XPATH_ATTRIBUTES,
|
|
341
|
+
...MAYBE_UNIQUE_XPATH_ATTRIBUTES,
|
|
342
|
+
];
|
|
343
|
+
const attrPairsPermutations: [string, string][] = attrsForPairs.flatMap(
|
|
344
|
+
(v1, i) =>
|
|
345
|
+
attrsForPairs.slice(i + 1).map(v2 => [v1, v2] as [string, string])
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
const cases = [
|
|
349
|
+
// BASE CASE #2: If this node has a unique attribute or content attribute, return an absolute
|
|
350
|
+
// XPath with that attribute
|
|
351
|
+
UNIQUE_XPATH_ATTRIBUTES,
|
|
352
|
+
|
|
353
|
+
// BASE CASE #3: If this node has a unique pair of attributes including 'maybe' attributes,
|
|
354
|
+
// return an xpath based on that pair
|
|
355
|
+
attrPairsPermutations,
|
|
356
|
+
|
|
357
|
+
// BASE CASE #4: Look for a 'maybe' unique attribute on its own. It's better if we find one
|
|
358
|
+
// of these that's unique in conjunction with another attribute, but if not, that's OK.
|
|
359
|
+
// Better than a hierarchical query.
|
|
360
|
+
MAYBE_UNIQUE_XPATH_ATTRIBUTES,
|
|
361
|
+
|
|
362
|
+
// BASE CASE #5: Look to see if the node type is unique in the document
|
|
363
|
+
[],
|
|
364
|
+
];
|
|
365
|
+
|
|
366
|
+
// It's possible that in all of these cases we don't find a truly unique selector. But
|
|
367
|
+
// a selector qualified by attribute with an index attached like //*[@id="foo"][1] is still
|
|
368
|
+
// better than a fully path-based selector. We call this a 'semi unique xpath'
|
|
369
|
+
let semiUniqueXpath: string | undefined;
|
|
370
|
+
|
|
371
|
+
// Go through each of our cases and look for selectors for each case in order
|
|
372
|
+
for (const attrs of cases) {
|
|
373
|
+
const [xpath, isFullyUnique] = getUniqueXPath(doc, domNode, attrs);
|
|
374
|
+
if (isFullyUnique) {
|
|
375
|
+
// if we ever encounter an actually unique selector, return it straightaway
|
|
376
|
+
return xpath!;
|
|
377
|
+
} else if (!semiUniqueXpath && xpath) {
|
|
378
|
+
// if we have a semin unique selector, and haven't already captured a semi unique selector,
|
|
379
|
+
// hold onto it for later. If we end up without any unique selectors from any of the cases,
|
|
380
|
+
// then we'll return this. But we want to make sure to return our FIRST instance of a semi
|
|
381
|
+
// unique selector, since it might theoretically be the best.
|
|
382
|
+
semiUniqueXpath = xpath;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Once we've gone through all our cases, if we do have a semi unique xpath, send that back
|
|
387
|
+
if (semiUniqueXpath) {
|
|
388
|
+
return semiUniqueXpath;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Otherwise fall back to a purely hierarchical expression of this dom node's position in the
|
|
392
|
+
// document as a last resort.
|
|
393
|
+
// First get the relative xpath of this node using tagName
|
|
394
|
+
let xpath = `/${domNode.nodeName}`;
|
|
395
|
+
|
|
396
|
+
// If this node has siblings of the same tagName, get the index of this node
|
|
397
|
+
if (domNode.parentNode) {
|
|
398
|
+
// Get the siblings
|
|
399
|
+
const childNodes = Array.prototype.slice
|
|
400
|
+
.call(domNode.parentNode.childNodes, 0)
|
|
401
|
+
.filter(
|
|
402
|
+
(childNode: XMLNode) =>
|
|
403
|
+
childNode.nodeType === 1 && childNode.nodeName === domNode.nodeName
|
|
404
|
+
);
|
|
405
|
+
|
|
406
|
+
// If there's more than one sibling, append the index
|
|
407
|
+
if (childNodes.length > 1) {
|
|
408
|
+
let index = childNodes.indexOf(domNode);
|
|
409
|
+
xpath += `[${index + 1}]`;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// Make a recursive call to this nodes parents and prepend it to this xpath
|
|
414
|
+
return getOptimalXPath(doc, domNode.parentNode!) + xpath;
|
|
415
|
+
} catch (error) {
|
|
416
|
+
// If there's an unexpected exception, abort
|
|
417
|
+
logLocatorError('XPath', error);
|
|
418
|
+
return null;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Get an optimal class chain for a Node based on the getOptimalXPath method
|
|
424
|
+
*/
|
|
425
|
+
export function getOptimalClassChain(
|
|
426
|
+
doc: XMLDocument,
|
|
427
|
+
domNode: XMLNode
|
|
428
|
+
): string | null {
|
|
429
|
+
try {
|
|
430
|
+
// BASE CASE #1: If this isn't an element, we're above the root, return empty string
|
|
431
|
+
// Also return empty for 'XCUIElementTypeApplication', which cannot be found via class chain
|
|
432
|
+
if (
|
|
433
|
+
!domNode.nodeName ||
|
|
434
|
+
domNode.nodeType !== 1 ||
|
|
435
|
+
domNode.nodeName === 'XCUIElementTypeApplication'
|
|
436
|
+
) {
|
|
437
|
+
return '';
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// BASE CASE #2: If this node has a unique class chain based on attributes, return it
|
|
441
|
+
let classChain: string, othersWithAttr: XMLNode[];
|
|
442
|
+
|
|
443
|
+
for (let attrName of CHECKED_CLASS_CHAIN_ATTRIBUTES) {
|
|
444
|
+
const attrValue = (domNode as XMLElement).getAttribute?.(attrName);
|
|
445
|
+
if (_.isEmpty(attrValue)) {
|
|
446
|
+
continue;
|
|
447
|
+
}
|
|
448
|
+
const xpath = `//${domNode.nodeName || '*'}[@${attrName}="${attrValue}"]`;
|
|
449
|
+
classChain = `/${
|
|
450
|
+
domNode.nodeName || '*'
|
|
451
|
+
}[\`${attrName} == "${attrValue}"\`]`;
|
|
452
|
+
|
|
453
|
+
// If the XPath does not parse, move to the next unique attribute
|
|
454
|
+
try {
|
|
455
|
+
const result = xpathSelect(xpath, doc as any);
|
|
456
|
+
othersWithAttr = Array.isArray(result)
|
|
457
|
+
? (result as unknown as XMLNode[])
|
|
458
|
+
: [];
|
|
459
|
+
} catch {
|
|
460
|
+
continue;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// If the attribute isn't actually unique, get its index too
|
|
464
|
+
if (othersWithAttr.length > 1) {
|
|
465
|
+
let index = othersWithAttr.indexOf(domNode);
|
|
466
|
+
classChain = `${classChain}[${index + 1}]`;
|
|
467
|
+
}
|
|
468
|
+
return classChain;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// BASE CASE #3: If this node has no unique attributes, repeat checks for its parent
|
|
472
|
+
// Get the relative xpath of this node using tagName
|
|
473
|
+
classChain = `/${domNode.nodeName}`;
|
|
474
|
+
|
|
475
|
+
// If this node has siblings of the same tagName, get the index of this node
|
|
476
|
+
if (domNode.parentNode) {
|
|
477
|
+
// Get the siblings
|
|
478
|
+
const childNodes = Array.prototype.slice
|
|
479
|
+
.call(domNode.parentNode.childNodes, 0)
|
|
480
|
+
.filter(
|
|
481
|
+
(childNode: XMLNode) =>
|
|
482
|
+
childNode.nodeType === 1 && childNode.nodeName === domNode.nodeName
|
|
483
|
+
);
|
|
484
|
+
|
|
485
|
+
// If there's more than one sibling, append the index
|
|
486
|
+
if (childNodes.length > 1) {
|
|
487
|
+
let index = childNodes.indexOf(domNode);
|
|
488
|
+
classChain += `[${index + 1}]`;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// Make a recursive call to this nodes parents and prepend it to this xpath
|
|
493
|
+
return getOptimalClassChain(doc, domNode.parentNode!) + classChain;
|
|
494
|
+
} catch (error) {
|
|
495
|
+
// If there's an unexpected exception, abort
|
|
496
|
+
logLocatorError('class chain', error);
|
|
497
|
+
return null;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Get an optimal predicate string for a Node based on the getOptimalXPath method
|
|
503
|
+
* Only works for a single element - no parent/child scope
|
|
504
|
+
*/
|
|
505
|
+
export function getOptimalPredicateString(
|
|
506
|
+
doc: XMLDocument,
|
|
507
|
+
domNode: XMLNode
|
|
508
|
+
): string | null {
|
|
509
|
+
try {
|
|
510
|
+
// BASE CASE #1: If this isn't an element, or we're above the root, return empty string
|
|
511
|
+
if (!domNode.nodeName || domNode.nodeType !== 1) {
|
|
512
|
+
return '';
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// BASE CASE #2: Check all attributes and try to find the best way
|
|
516
|
+
let xpathAttributes: string[] = [];
|
|
517
|
+
let predicateString: string[] = [];
|
|
518
|
+
let othersWithAttr: XMLNode[];
|
|
519
|
+
|
|
520
|
+
for (let attrName of CHECKED_PREDICATE_ATTRIBUTES) {
|
|
521
|
+
const attrValue = (domNode as XMLElement).getAttribute?.(attrName);
|
|
522
|
+
if (_.isEmpty(attrValue)) {
|
|
523
|
+
continue;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
xpathAttributes.push(`@${attrName}="${attrValue}"`);
|
|
527
|
+
const xpath = `//*[${xpathAttributes.join(' and ')}]`;
|
|
528
|
+
predicateString.push(`${attrName} == "${attrValue}"`);
|
|
529
|
+
|
|
530
|
+
// If the XPath does not parse, move to the next attribute
|
|
531
|
+
try {
|
|
532
|
+
const result = xpathSelect(xpath, doc as any);
|
|
533
|
+
othersWithAttr = Array.isArray(result)
|
|
534
|
+
? (result as unknown as XMLNode[])
|
|
535
|
+
: [];
|
|
536
|
+
} catch {
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// Return as soon as the accumulated attribute combination is unique
|
|
541
|
+
if (othersWithAttr.length === 1) {
|
|
542
|
+
return predicateString.join(' AND ');
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
} catch (error) {
|
|
546
|
+
// If there's an unexpected exception, abort
|
|
547
|
+
logLocatorError('predicate string', error);
|
|
548
|
+
return null;
|
|
549
|
+
}
|
|
550
|
+
return null;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Get an optimal UiAutomator selector for a Node
|
|
555
|
+
* Only works for elements inside the last direct child of the hierarchy (xpath: /hierarchy/*[last()] )
|
|
556
|
+
*/
|
|
557
|
+
export function getOptimalUiAutomatorSelector(
|
|
558
|
+
doc: XMLDocument,
|
|
559
|
+
domNode: XMLNode,
|
|
560
|
+
path: string
|
|
561
|
+
): string | null {
|
|
562
|
+
try {
|
|
563
|
+
// BASE CASE #1: If this isn't an element, or we're above the root, return empty string
|
|
564
|
+
if (!domNode.nodeName || domNode.nodeType !== 1) {
|
|
565
|
+
return '';
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// UiAutomator can only find elements inside the last direct child of the hierarchy.
|
|
569
|
+
// hierarchy is the child of doc (which is <xml/>), so need to get the children of its child
|
|
570
|
+
// BASE CASE #2: If there is no hierarchy or its children, return null
|
|
571
|
+
const docChildren = childNodesOf(doc);
|
|
572
|
+
const hierarchyChildren = _.isEmpty(docChildren)
|
|
573
|
+
? []
|
|
574
|
+
: childNodesOf(docChildren[0]);
|
|
575
|
+
if (_.isEmpty(hierarchyChildren)) {
|
|
576
|
+
return null;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// BASE CASE #3: If looking for an element that is not inside
|
|
580
|
+
// the last direct child of the hierarchy, return null
|
|
581
|
+
const lastHierarchyChildIndex = (hierarchyChildren.length - 1).toString();
|
|
582
|
+
let pathArray = path.split('.');
|
|
583
|
+
const requestedHierarchyChildIndex = pathArray[0];
|
|
584
|
+
if (requestedHierarchyChildIndex !== lastHierarchyChildIndex) {
|
|
585
|
+
return null;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// In order to use only the last direct child of the hierarchy as the new scope,
|
|
589
|
+
// need to recreate it as a Document (Node -> XML -> Document),
|
|
590
|
+
// then modify the path by changing the first index,
|
|
591
|
+
// and finally recreate the domNode, since it still references the original parent
|
|
592
|
+
const lastHierarchyChild =
|
|
593
|
+
hierarchyChildren[parseInt(lastHierarchyChildIndex, 10)];
|
|
594
|
+
const newXml = domToXML(lastHierarchyChild);
|
|
595
|
+
// wrap the new XML in a dummy tag which will have the node type Document
|
|
596
|
+
const newDoc = xmlToDOM(`<dummy>${newXml}</dummy>`);
|
|
597
|
+
pathArray[0] = '0';
|
|
598
|
+
const newPath = pathArray.join('.');
|
|
599
|
+
const newDomNode = findDOMNodeByPath(newPath, newDoc);
|
|
600
|
+
|
|
601
|
+
// BASE CASE #4: Check all attributes and try to find unique ones
|
|
602
|
+
let uiSelector: string,
|
|
603
|
+
othersWithAttr: XMLNode[],
|
|
604
|
+
othersWithAttrMinCount: number | undefined,
|
|
605
|
+
mostUniqueSelector: string | undefined;
|
|
606
|
+
|
|
607
|
+
for (const [attrName, attrTranslation] of CHECKED_UIAUTOMATOR_ATTRIBUTES) {
|
|
608
|
+
const attrValue = (newDomNode as XMLElement).getAttribute?.(attrName);
|
|
609
|
+
if (_.isEmpty(attrValue)) {
|
|
610
|
+
continue;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
const xpath = `//${newDomNode.nodeName}[@${attrName}="${attrValue}"]`;
|
|
614
|
+
uiSelector = `new UiSelector().${attrTranslation}("${attrValue}")`;
|
|
615
|
+
|
|
616
|
+
// If the XPath does not parse, move to the next unique attribute
|
|
617
|
+
try {
|
|
618
|
+
const result = xpathSelect(xpath, newDoc as any);
|
|
619
|
+
othersWithAttr = Array.isArray(result)
|
|
620
|
+
? (result as unknown as XMLNode[])
|
|
621
|
+
: [];
|
|
622
|
+
} catch {
|
|
623
|
+
continue;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
// If the attribute is unique, return it, otherwise save it and add an index,
|
|
627
|
+
// but only if it returns the least number of elements
|
|
628
|
+
if (othersWithAttr.length === 1) {
|
|
629
|
+
return uiSelector;
|
|
630
|
+
} else if (
|
|
631
|
+
!othersWithAttrMinCount ||
|
|
632
|
+
othersWithAttr.length < othersWithAttrMinCount
|
|
633
|
+
) {
|
|
634
|
+
othersWithAttrMinCount = othersWithAttr.length;
|
|
635
|
+
mostUniqueSelector = `${uiSelector}.instance(${othersWithAttr.indexOf(
|
|
636
|
+
newDomNode
|
|
637
|
+
)})`;
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// BASE CASE #5: Did not find any unique attributes - use the 'most unique' selector
|
|
642
|
+
if (mostUniqueSelector) {
|
|
643
|
+
return mostUniqueSelector;
|
|
644
|
+
}
|
|
645
|
+
} catch (error) {
|
|
646
|
+
// If there's an unexpected exception, abort
|
|
647
|
+
logLocatorError('uiautomator selector', error);
|
|
648
|
+
return null;
|
|
649
|
+
}
|
|
650
|
+
return null;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
function logLocatorError(strategy: string, error: any): void {
|
|
654
|
+
log.error(
|
|
655
|
+
`The most optimal ${strategy} could not be determined because an error was thrown: '${error}'`
|
|
656
|
+
);
|
|
657
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { logger } from '@appium/support';
|
|
2
|
+
|
|
3
|
+
const log = logger.getLogger('mcp-appium');
|
|
4
|
+
|
|
5
|
+
export default log;
|
|
6
|
+
export { log };
|
|
7
|
+
|
|
8
|
+
// For backward compatibility, export as named exports
|
|
9
|
+
// Note: @appium/support logger doesn't have trace method, using debug instead
|
|
10
|
+
export const trace = (message: string) => log.debug(message);
|
|
11
|
+
export const error = (message: string) => log.error(message);
|