Appium-Python-Client 5.2.0__py3-none-any.whl

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.
Files changed (324) hide show
  1. appium/__init__.py +17 -0
  2. appium/common/__init__.py +17 -0
  3. appium/common/exceptions.py +26 -0
  4. appium/common/helper.py +42 -0
  5. appium/common/logger.py +28 -0
  6. appium/options/__init__.py +0 -0
  7. appium/options/android/__init__.py +2 -0
  8. appium/options/android/common/__init__.py +0 -0
  9. appium/options/android/common/adb/__init__.py +0 -0
  10. appium/options/android/common/adb/adb_exec_timeout_option.py +41 -0
  11. appium/options/android/common/adb/adb_port_option.py +38 -0
  12. appium/options/android/common/adb/allow_delay_adb_option.py +39 -0
  13. appium/options/android/common/adb/build_tools_version_option.py +42 -0
  14. appium/options/android/common/adb/clear_device_logs_on_start_option.py +40 -0
  15. appium/options/android/common/adb/ignore_hidden_api_policy_error_option.py +40 -0
  16. appium/options/android/common/adb/logcat_filter_specs_option.py +42 -0
  17. appium/options/android/common/adb/logcat_format_option.py +39 -0
  18. appium/options/android/common/adb/mock_location_app_option.py +42 -0
  19. appium/options/android/common/adb/remote_adb_host_option.py +39 -0
  20. appium/options/android/common/adb/skip_logcat_capture_option.py +40 -0
  21. appium/options/android/common/adb/suppress_kill_server_option.py +39 -0
  22. appium/options/android/common/app/__init__.py +0 -0
  23. appium/options/android/common/app/allow_test_packages_option.py +40 -0
  24. appium/options/android/common/app/android_install_timeout_option.py +43 -0
  25. appium/options/android/common/app/app_activity_option.py +39 -0
  26. appium/options/android/common/app/app_package_option.py +39 -0
  27. appium/options/android/common/app/app_wait_activity_option.py +40 -0
  28. appium/options/android/common/app/app_wait_duration_option.py +41 -0
  29. appium/options/android/common/app/app_wait_for_launch_option.py +41 -0
  30. appium/options/android/common/app/app_wait_package_option.py +40 -0
  31. appium/options/android/common/app/auto_grant_premissions_option.py +40 -0
  32. appium/options/android/common/app/enforce_app_install_option.py +40 -0
  33. appium/options/android/common/app/intent_action_option.py +40 -0
  34. appium/options/android/common/app/intent_category_option.py +40 -0
  35. appium/options/android/common/app/intent_flags_option.py +40 -0
  36. appium/options/android/common/app/optional_intent_arguments_option.py +40 -0
  37. appium/options/android/common/app/remote_apps_cache_limit_option.py +42 -0
  38. appium/options/android/common/app/uninstall_other_packages_option.py +39 -0
  39. appium/options/android/common/avd/__init__.py +0 -0
  40. appium/options/android/common/avd/avd_args_option.py +38 -0
  41. appium/options/android/common/avd/avd_env_option.py +38 -0
  42. appium/options/android/common/avd/avd_launch_timeout_option.py +41 -0
  43. appium/options/android/common/avd/avd_option.py +41 -0
  44. appium/options/android/common/avd/avd_ready_timeout_option.py +41 -0
  45. appium/options/android/common/avd/gps_enabled_option.py +39 -0
  46. appium/options/android/common/avd/network_speed_option.py +41 -0
  47. appium/options/android/common/context/__init__.py +0 -0
  48. appium/options/android/common/context/auto_webview_timeout_option.py +41 -0
  49. appium/options/android/common/context/chrome_logging_prefs_option.py +41 -0
  50. appium/options/android/common/context/chrome_options_option.py +40 -0
  51. appium/options/android/common/context/chromedriver_args_option.py +41 -0
  52. appium/options/android/common/context/chromedriver_chrome_mapping_file_option.py +43 -0
  53. appium/options/android/common/context/chromedriver_disable_build_check_option.py +41 -0
  54. appium/options/android/common/context/chromedriver_executable_dir_option.py +43 -0
  55. appium/options/android/common/context/chromedriver_executable_option.py +38 -0
  56. appium/options/android/common/context/chromedriver_port_option.py +39 -0
  57. appium/options/android/common/context/chromedriver_ports_option.py +39 -0
  58. appium/options/android/common/context/chromedriver_use_system_executable_option.py +40 -0
  59. appium/options/android/common/context/ensure_webviews_have_pages_option.py +40 -0
  60. appium/options/android/common/context/extract_chrome_android_package_from_context_name_option.py +40 -0
  61. appium/options/android/common/context/native_web_screenshot_option.py +40 -0
  62. appium/options/android/common/context/recreate_chrome_driver_sessions_option.py +41 -0
  63. appium/options/android/common/context/show_chromedriver_log_option.py +39 -0
  64. appium/options/android/common/context/webview_devtools_port_option.py +40 -0
  65. appium/options/android/common/localization/__init__.py +0 -0
  66. appium/options/android/common/localization/locale_script_option.py +40 -0
  67. appium/options/android/common/locking/__init__.py +0 -0
  68. appium/options/android/common/locking/skip_unlock_option.py +42 -0
  69. appium/options/android/common/locking/unlock_key_option.py +40 -0
  70. appium/options/android/common/locking/unlock_strategy_option.py +40 -0
  71. appium/options/android/common/locking/unlock_success_timeout_option.py +43 -0
  72. appium/options/android/common/locking/unlock_type_option.py +40 -0
  73. appium/options/android/common/mjpeg/__init__.py +0 -0
  74. appium/options/android/common/mjpeg/mjpeg_screenshot_url_option.py +40 -0
  75. appium/options/android/common/other/__init__.py +0 -0
  76. appium/options/android/common/other/disable_suppress_accessibility_service_option.py +40 -0
  77. appium/options/android/common/other/user_profile_option.py +42 -0
  78. appium/options/android/common/signing/__init__.py +0 -0
  79. appium/options/android/common/signing/key_alias_option.py +40 -0
  80. appium/options/android/common/signing/key_password_option.py +40 -0
  81. appium/options/android/common/signing/keystore_password_option.py +40 -0
  82. appium/options/android/common/signing/keystore_path_option.py +40 -0
  83. appium/options/android/common/signing/no_sign_option.py +42 -0
  84. appium/options/android/common/signing/use_keystore_option.py +42 -0
  85. appium/options/android/espresso/__init__.py +0 -0
  86. appium/options/android/espresso/activity_options_option.py +41 -0
  87. appium/options/android/espresso/app_locale_option.py +44 -0
  88. appium/options/android/espresso/base.py +221 -0
  89. appium/options/android/espresso/espresso_build_config_option.py +46 -0
  90. appium/options/android/espresso/espresso_server_launch_timeout_option.py +43 -0
  91. appium/options/android/espresso/force_espresso_rebuild_option.py +41 -0
  92. appium/options/android/espresso/intent_options_option.py +41 -0
  93. appium/options/android/espresso/show_gradle_log_option.py +39 -0
  94. appium/options/android/uiautomator2/__init__.py +0 -0
  95. appium/options/android/uiautomator2/base.py +221 -0
  96. appium/options/android/uiautomator2/disable_window_animation_option.py +40 -0
  97. appium/options/android/uiautomator2/mjpeg_server_port_option.py +41 -0
  98. appium/options/android/uiautomator2/skip_device_initialization_option.py +40 -0
  99. appium/options/android/uiautomator2/skip_server_installation_option.py +44 -0
  100. appium/options/android/uiautomator2/uiautomator2_server_install_timeout_option.py +44 -0
  101. appium/options/android/uiautomator2/uiautomator2_server_launch_timeout_option.py +44 -0
  102. appium/options/android/uiautomator2/uiautomator2_server_read_timeout_option.py +46 -0
  103. appium/options/common/__init__.py +1 -0
  104. appium/options/common/app_option.py +41 -0
  105. appium/options/common/auto_web_view_option.py +40 -0
  106. appium/options/common/automation_name_option.py +38 -0
  107. appium/options/common/base.py +125 -0
  108. appium/options/common/browser_name_option.py +38 -0
  109. appium/options/common/bundle_id_option.py +38 -0
  110. appium/options/common/clear_system_files_option.py +38 -0
  111. appium/options/common/device_name_option.py +38 -0
  112. appium/options/common/enable_performance_logging_option.py +38 -0
  113. appium/options/common/event_timings_option.py +40 -0
  114. appium/options/common/full_reset_option.py +38 -0
  115. appium/options/common/is_headless_option.py +39 -0
  116. appium/options/common/language_option.py +38 -0
  117. appium/options/common/locale_option.py +38 -0
  118. appium/options/common/new_command_timeout_option.py +41 -0
  119. appium/options/common/no_reset_option.py +38 -0
  120. appium/options/common/orientation_option.py +40 -0
  121. appium/options/common/other_apps_option.py +39 -0
  122. appium/options/common/platform_version_option.py +40 -0
  123. appium/options/common/postrun_option.py +39 -0
  124. appium/options/common/prerun_option.py +40 -0
  125. appium/options/common/print_page_source_on_find_failure_option.py +40 -0
  126. appium/options/common/skip_log_capture_option.py +38 -0
  127. appium/options/common/supports_capabilities.py +26 -0
  128. appium/options/common/system_host_option.py +38 -0
  129. appium/options/common/system_port_option.py +38 -0
  130. appium/options/common/udid_option.py +38 -0
  131. appium/options/flutter_integration/__init__.py +15 -0
  132. appium/options/flutter_integration/base.py +39 -0
  133. appium/options/flutter_integration/flutter_element_wait_timeout_option.py +50 -0
  134. appium/options/flutter_integration/flutter_enable_mock_camera_option.py +44 -0
  135. appium/options/flutter_integration/flutter_server_launch_timeout_option.py +51 -0
  136. appium/options/flutter_integration/flutter_system_port_option.py +45 -0
  137. appium/options/gecko/__init__.py +1 -0
  138. appium/options/gecko/android_storage_option.py +39 -0
  139. appium/options/gecko/base.py +51 -0
  140. appium/options/gecko/firefox_options_option.py +38 -0
  141. appium/options/gecko/marionette_port_option.py +43 -0
  142. appium/options/gecko/verbosity_option.py +40 -0
  143. appium/options/ios/__init__.py +2 -0
  144. appium/options/ios/safari/__init__.py +0 -0
  145. appium/options/ios/safari/automatic_inspection_option.py +41 -0
  146. appium/options/ios/safari/automatic_profiling_option.py +41 -0
  147. appium/options/ios/safari/base.py +51 -0
  148. appium/options/ios/safari/device_name_option.py +43 -0
  149. appium/options/ios/safari/device_type_option.py +41 -0
  150. appium/options/ios/safari/device_udid_option.py +43 -0
  151. appium/options/ios/safari/platform_build_version_option.py +41 -0
  152. appium/options/ios/safari/platform_version_option.py +41 -0
  153. appium/options/ios/safari/use_simulator_option.py +41 -0
  154. appium/options/ios/safari/webkit_webrtc_option.py +52 -0
  155. appium/options/ios/xcuitest/__init__.py +0 -0
  156. appium/options/ios/xcuitest/app/__init__.py +0 -0
  157. appium/options/ios/xcuitest/app/app_install_strategy_option.py +46 -0
  158. appium/options/ios/xcuitest/app/app_push_timeout_option.py +42 -0
  159. appium/options/ios/xcuitest/app/localizable_strings_dir_option.py +39 -0
  160. appium/options/ios/xcuitest/base.py +223 -0
  161. appium/options/ios/xcuitest/general/__init__.py +0 -0
  162. appium/options/ios/xcuitest/general/include_device_caps_to_session_info_option.py +41 -0
  163. appium/options/ios/xcuitest/general/reset_location_service_option.py +39 -0
  164. appium/options/ios/xcuitest/other/__init__.py +0 -0
  165. appium/options/ios/xcuitest/other/command_timeouts_option.py +57 -0
  166. appium/options/ios/xcuitest/other/launch_with_idb_option.py +42 -0
  167. appium/options/ios/xcuitest/other/show_ios_log_option.py +39 -0
  168. appium/options/ios/xcuitest/other/use_json_source_option.py +39 -0
  169. appium/options/ios/xcuitest/simulator/__init__.py +0 -0
  170. appium/options/ios/xcuitest/simulator/calendar_access_authorized_option.py +41 -0
  171. appium/options/ios/xcuitest/simulator/calendar_format_option.py +38 -0
  172. appium/options/ios/xcuitest/simulator/connect_hardware_keyboard_option.py +43 -0
  173. appium/options/ios/xcuitest/simulator/custom_ssl_cert_option.py +39 -0
  174. appium/options/ios/xcuitest/simulator/enforce_fresh_simulator_creation_option.py +39 -0
  175. appium/options/ios/xcuitest/simulator/force_simulator_software_keyboard_presence_option.py +45 -0
  176. appium/options/ios/xcuitest/simulator/ios_simulator_logs_predicate_option.py +38 -0
  177. appium/options/ios/xcuitest/simulator/keep_key_chains_option.py +39 -0
  178. appium/options/ios/xcuitest/simulator/keychains_exclude_patterns_option.py +44 -0
  179. appium/options/ios/xcuitest/simulator/permissions_option.py +50 -0
  180. appium/options/ios/xcuitest/simulator/reduce_motion_option.py +40 -0
  181. appium/options/ios/xcuitest/simulator/reset_on_session_start_only_option.py +41 -0
  182. appium/options/ios/xcuitest/simulator/scale_factor_option.py +44 -0
  183. appium/options/ios/xcuitest/simulator/shutdown_other_simulators_option.py +44 -0
  184. appium/options/ios/xcuitest/simulator/simulator_devices_set_path_option.py +41 -0
  185. appium/options/ios/xcuitest/simulator/simulator_pasteboard_automatic_sync_option.py +42 -0
  186. appium/options/ios/xcuitest/simulator/simulator_startup_timeout_option.py +46 -0
  187. appium/options/ios/xcuitest/simulator/simulator_trace_pointer_option.py +41 -0
  188. appium/options/ios/xcuitest/simulator/simulator_window_center_option.py +41 -0
  189. appium/options/ios/xcuitest/wda/__init__.py +0 -0
  190. appium/options/ios/xcuitest/wda/allow_provisioning_device_regitration_option.py +40 -0
  191. appium/options/ios/xcuitest/wda/auto_accept_alerts_option.py +39 -0
  192. appium/options/ios/xcuitest/wda/auto_disimiss_alerts_option.py +39 -0
  193. appium/options/ios/xcuitest/wda/derived_data_path_option.py +41 -0
  194. appium/options/ios/xcuitest/wda/disable_automatic_screenshots_option.py +40 -0
  195. appium/options/ios/xcuitest/wda/force_app_launch_option.py +42 -0
  196. appium/options/ios/xcuitest/wda/keychain_password_option.py +39 -0
  197. appium/options/ios/xcuitest/wda/keychain_path_option.py +39 -0
  198. appium/options/ios/xcuitest/wda/max_typing_frequency_option.py +40 -0
  199. appium/options/ios/xcuitest/wda/mjpeg_server_port_option.py +42 -0
  200. appium/options/ios/xcuitest/wda/process_arguments_option.py +42 -0
  201. appium/options/ios/xcuitest/wda/result_bundle_path_option.py +42 -0
  202. appium/options/ios/xcuitest/wda/screenshot_quality_option.py +42 -0
  203. appium/options/ios/xcuitest/wda/should_terminate_app_option.py +42 -0
  204. appium/options/ios/xcuitest/wda/should_use_singleton_test_manager_option.py +39 -0
  205. appium/options/ios/xcuitest/wda/show_xcode_log_option.py +40 -0
  206. appium/options/ios/xcuitest/wda/simple_is_visible_check_option.py +42 -0
  207. appium/options/ios/xcuitest/wda/updated_wda_bundle_id_option.py +39 -0
  208. appium/options/ios/xcuitest/wda/use_native_caching_strategy_option.py +41 -0
  209. appium/options/ios/xcuitest/wda/use_new_wda_option.py +51 -0
  210. appium/options/ios/xcuitest/wda/use_prebuilt_wda_option.py +39 -0
  211. appium/options/ios/xcuitest/wda/use_simple_build_test_option.py +40 -0
  212. appium/options/ios/xcuitest/wda/use_xctestrun_file_option.py +49 -0
  213. appium/options/ios/xcuitest/wda/wait_for_idle_timeout_option.py +45 -0
  214. appium/options/ios/xcuitest/wda/wait_for_quiescence_option.py +42 -0
  215. appium/options/ios/xcuitest/wda/wda_base_url_option.py +41 -0
  216. appium/options/ios/xcuitest/wda/wda_connection_timeout_option.py +43 -0
  217. appium/options/ios/xcuitest/wda/wda_eventloop_idle_delay_option.py +46 -0
  218. appium/options/ios/xcuitest/wda/wda_launch_timeout_option.py +41 -0
  219. appium/options/ios/xcuitest/wda/wda_local_port_option.py +41 -0
  220. appium/options/ios/xcuitest/wda/wda_startup_retries_option.py +39 -0
  221. appium/options/ios/xcuitest/wda/wda_startup_retry_interval_option.py +43 -0
  222. appium/options/ios/xcuitest/wda/web_driver_agent_url_option.py +39 -0
  223. appium/options/ios/xcuitest/wda/xcode_org_id_option.py +39 -0
  224. appium/options/ios/xcuitest/wda/xcode_signing_id_option.py +39 -0
  225. appium/options/ios/xcuitest/webview/__init__.py +0 -0
  226. appium/options/ios/xcuitest/webview/absolute_web_locations_option.py +42 -0
  227. appium/options/ios/xcuitest/webview/additional_webview_bundle_ids_option.py +40 -0
  228. appium/options/ios/xcuitest/webview/enable_async_execute_from_https_option.py +39 -0
  229. appium/options/ios/xcuitest/webview/full_context_list_option.py +42 -0
  230. appium/options/ios/xcuitest/webview/include_safari_in_webviews_option.py +41 -0
  231. appium/options/ios/xcuitest/webview/native_web_tap_option.py +40 -0
  232. appium/options/ios/xcuitest/webview/safari_garbage_collect_option.py +39 -0
  233. appium/options/ios/xcuitest/webview/safari_ignore_fraud_warning_option.py +39 -0
  234. appium/options/ios/xcuitest/webview/safari_ignore_web_hostnames_option.py +42 -0
  235. appium/options/ios/xcuitest/webview/safari_initial_url_option.py +38 -0
  236. appium/options/ios/xcuitest/webview/safari_log_all_communication_hex_dump_option.py +43 -0
  237. appium/options/ios/xcuitest/webview/safari_log_all_communication_option.py +40 -0
  238. appium/options/ios/xcuitest/webview/safari_open_links_in_background_option.py +39 -0
  239. appium/options/ios/xcuitest/webview/safari_socket_chunk_size_option.py +41 -0
  240. appium/options/ios/xcuitest/webview/safari_web_inspector_max_frame_length_option.py +41 -0
  241. appium/options/ios/xcuitest/webview/webkit_response_timeout_option.py +43 -0
  242. appium/options/ios/xcuitest/webview/webview_connect_retries_option.py +40 -0
  243. appium/options/ios/xcuitest/webview/webview_connect_timeout_option.py +43 -0
  244. appium/options/mac/__init__.py +1 -0
  245. appium/options/mac/mac2/__init__.py +0 -0
  246. appium/options/mac/mac2/app_path_option.py +39 -0
  247. appium/options/mac/mac2/arguments_option.py +39 -0
  248. appium/options/mac/mac2/base.py +113 -0
  249. appium/options/mac/mac2/bootstrap_root_option.py +41 -0
  250. appium/options/mac/mac2/environment_option.py +41 -0
  251. appium/options/mac/mac2/server_startup_timeout_option.py +44 -0
  252. appium/options/mac/mac2/show_server_logs_option.py +39 -0
  253. appium/options/mac/mac2/skip_app_kill_option.py +40 -0
  254. appium/options/mac/mac2/web_driver_agent_mac_url_option.py +39 -0
  255. appium/options/windows/__init__.py +1 -0
  256. appium/options/windows/windows/__init__.py +0 -0
  257. appium/options/windows/windows/app_arguments_option.py +40 -0
  258. appium/options/windows/windows/app_top_level_window_option.py +40 -0
  259. appium/options/windows/windows/app_working_dir_option.py +40 -0
  260. appium/options/windows/windows/base.py +97 -0
  261. appium/options/windows/windows/create_session_timeout_option.py +45 -0
  262. appium/options/windows/windows/expreimental_web_driver_option.py +39 -0
  263. appium/options/windows/windows/wait_for_app_launch_option.py +43 -0
  264. appium/protocols/__init__.py +13 -0
  265. appium/protocols/webdriver/__init__.py +13 -0
  266. appium/protocols/webdriver/can_execute_commands.py +23 -0
  267. appium/protocols/webdriver/can_execute_scripts.py +27 -0
  268. appium/protocols/webdriver/can_find_elements.py +32 -0
  269. appium/protocols/webdriver/can_remember_extension_presence.py +23 -0
  270. appium/py.typed +0 -0
  271. appium/version.py +22 -0
  272. appium/webdriver/__init__.py +20 -0
  273. appium/webdriver/appium_connection.py +65 -0
  274. appium/webdriver/appium_service.py +330 -0
  275. appium/webdriver/applicationstate.py +21 -0
  276. appium/webdriver/client_config.py +38 -0
  277. appium/webdriver/clipboard_content_type.py +19 -0
  278. appium/webdriver/command_method.py +27 -0
  279. appium/webdriver/common/__init__.py +17 -0
  280. appium/webdriver/common/appiumby.py +54 -0
  281. appium/webdriver/connectiontype.py +42 -0
  282. appium/webdriver/errorhandler.py +125 -0
  283. appium/webdriver/extensions/__init__.py +13 -0
  284. appium/webdriver/extensions/action_helpers.py +188 -0
  285. appium/webdriver/extensions/android/__init__.py +0 -0
  286. appium/webdriver/extensions/android/activities.py +65 -0
  287. appium/webdriver/extensions/android/common.py +59 -0
  288. appium/webdriver/extensions/android/display.py +48 -0
  289. appium/webdriver/extensions/android/gsm.py +147 -0
  290. appium/webdriver/extensions/android/nativekey.py +1119 -0
  291. appium/webdriver/extensions/android/network.py +175 -0
  292. appium/webdriver/extensions/android/performance.py +85 -0
  293. appium/webdriver/extensions/android/power.py +80 -0
  294. appium/webdriver/extensions/android/sms.py +50 -0
  295. appium/webdriver/extensions/android/system_bars.py +58 -0
  296. appium/webdriver/extensions/applications.py +274 -0
  297. appium/webdriver/extensions/clipboard.py +107 -0
  298. appium/webdriver/extensions/context.py +63 -0
  299. appium/webdriver/extensions/device_time.py +75 -0
  300. appium/webdriver/extensions/execute_driver.py +60 -0
  301. appium/webdriver/extensions/execute_mobile_command.py +62 -0
  302. appium/webdriver/extensions/flutter_integration/__init__.py +13 -0
  303. appium/webdriver/extensions/flutter_integration/flutter_commands.py +296 -0
  304. appium/webdriver/extensions/flutter_integration/flutter_finder.py +55 -0
  305. appium/webdriver/extensions/flutter_integration/scroll_directions.py +6 -0
  306. appium/webdriver/extensions/hw_actions.py +149 -0
  307. appium/webdriver/extensions/images_comparison.py +132 -0
  308. appium/webdriver/extensions/keyboard.py +168 -0
  309. appium/webdriver/extensions/location.py +98 -0
  310. appium/webdriver/extensions/log_event.py +68 -0
  311. appium/webdriver/extensions/logs.py +53 -0
  312. appium/webdriver/extensions/remote_fs.py +110 -0
  313. appium/webdriver/extensions/screen_record.py +207 -0
  314. appium/webdriver/extensions/session.py +41 -0
  315. appium/webdriver/extensions/settings.py +49 -0
  316. appium/webdriver/locator_converter.py +29 -0
  317. appium/webdriver/mobilecommand.py +104 -0
  318. appium/webdriver/switch_to.py +35 -0
  319. appium/webdriver/webdriver.py +495 -0
  320. appium/webdriver/webelement.py +130 -0
  321. appium_python_client-5.2.0.dist-info/METADATA +573 -0
  322. appium_python_client-5.2.0.dist-info/RECORD +324 -0
  323. appium_python_client-5.2.0.dist-info/WHEEL +4 -0
  324. appium_python_client-5.2.0.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,296 @@
1
+ #!/usr/bin/env python
2
+
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import os
16
+ from typing import Any, Dict, List, Optional, Tuple, Union
17
+
18
+ from appium.common.helper import encode_file_to_base64
19
+ from appium.webdriver.extensions.flutter_integration.flutter_finder import FlutterFinder
20
+ from appium.webdriver.extensions.flutter_integration.scroll_directions import ScrollDirection
21
+ from appium.webdriver.webdriver import WebDriver
22
+ from appium.webdriver.webelement import WebElement
23
+
24
+
25
+ class FlutterCommand:
26
+ def __init__(self, driver: WebDriver) -> None:
27
+ self.driver = driver
28
+
29
+ # wait commands
30
+
31
+ def wait_for_visible(
32
+ self,
33
+ locator: Union[WebElement, FlutterFinder],
34
+ timeout: Optional[float] = None,
35
+ ) -> None:
36
+ """
37
+ Waits for a element to become visible.
38
+
39
+ Args:
40
+ locator (Union[WebElement, FlutterFinder]): The element to wait for; can be a WebElement or a FlutterFinder.
41
+ timeout (Optional[float]): Maximum wait time in seconds. Defaults to a predefined timeout if not specified.
42
+
43
+ Returns:
44
+ None
45
+ """
46
+ opts: Dict[str, Any] = self.__get_locator_options(locator)
47
+ if timeout is not None:
48
+ opts['timeout'] = timeout
49
+
50
+ self.execute_flutter_command('waitForVisible', opts)
51
+
52
+ def wait_for_invisible(
53
+ self,
54
+ locator: Union[WebElement, FlutterFinder],
55
+ timeout: Optional[float] = None,
56
+ ) -> None:
57
+ """
58
+ Waits for a element to become invisible.
59
+
60
+ Args:
61
+ locator (Union[WebElement, FlutterFinder]): The element to wait for; can be a WebElement or a FlutterFinder.
62
+ timeout (Optional[float]): Maximum wait time in seconds. Defaults to a predefined timeout if not specified.
63
+
64
+ Returns:
65
+ None:
66
+ """
67
+ opts: Dict[str, Any] = self.__get_locator_options(locator)
68
+ if timeout is not None:
69
+ opts['timeout'] = timeout
70
+
71
+ self.execute_flutter_command('waitForAbsent', opts)
72
+
73
+ # flutter action commands
74
+
75
+ def perform_double_click(self, element: WebElement, offset: Optional[Tuple[int, int]] = None) -> None:
76
+ """
77
+ Performs a double-click on the given element, with an optional offset.
78
+
79
+ Args:
80
+ element (WebElement): The element to double-click on. This parameter is required.
81
+ offset (Optional[Tuple[int, int]]): The x and y offsets from the element to click at. If not specified, the click is performed at the element's center.
82
+
83
+ Returns:
84
+ None:
85
+ """
86
+ opts: Dict[str, Union[WebElement, Dict[str, int]]] = {'origin': element}
87
+ if offset is not None:
88
+ opts['offset'] = {'x': offset[0], 'y': offset[1]}
89
+ self.execute_flutter_command('doubleClick', opts)
90
+
91
+ def perform_long_press(self, element: WebElement, offset: Optional[Tuple[int, int]] = None) -> None:
92
+ """
93
+ Performs a long press on the given element, with an optional offset.
94
+
95
+ Args:
96
+ element (WebElement): The element to perform the long press on. This parameter is required.
97
+ offset (Optional[Tuple[int, int]]): The x and y offsets from the element to perform the long press at. If not specified, the long press is performed at the element's center.
98
+
99
+ Returns:
100
+ None:
101
+ """
102
+ opts: Dict[str, Union[WebElement, Dict[str, int]]] = {'origin': element}
103
+ if offset is not None:
104
+ opts['offset'] = {'x': offset[0], 'y': offset[1]}
105
+ self.execute_flutter_command('longPress', opts)
106
+
107
+ def perform_drag_and_drop(self, source: WebElement, target: WebElement) -> None:
108
+ """
109
+ Performs a drag-and-drop operation from a source element to a target element.
110
+
111
+ Args:
112
+ source (WebElement): The element to drag from.
113
+ target (WebElement): The element to drop onto.
114
+
115
+ Returns:
116
+ None:
117
+ """
118
+ self.execute_flutter_command('dragAndDrop', {'source': source, 'target': target})
119
+
120
+ def scroll_till_visible(
121
+ self,
122
+ scroll_to: FlutterFinder,
123
+ scroll_direction: ScrollDirection = ScrollDirection.DOWN,
124
+ **opts: Any,
125
+ ) -> WebElement:
126
+ """
127
+ Scrolls until the specified element becomes visible.
128
+
129
+ Args:
130
+ scroll_to (FlutterFinder): The Flutter element to scroll to.
131
+ scroll_direction (ScrollDirection): The direction to scroll up or down. Defaults to `ScrollDirection.DOWN`.
132
+
133
+ KeywordArgs:
134
+ scrollView (str): The view of the scroll. Default value is 'Scrollable'
135
+ delta (int): delta for the scroll. Default value is 64
136
+ maxScrolls (int): Max times to scroll. Default value is 15
137
+ settleBetweenScrollsTimeout (float): settle timeout in milliseconds. Default value is 5000
138
+ dragDuration (float): time gap between each scroll in milliseconds. Default value is 100
139
+
140
+ Returns:
141
+ Webelement: scrolled element
142
+ """
143
+ opts['finder'] = scroll_to.to_dict()
144
+ opts['scrollDirection'] = scroll_direction.value
145
+ return self.execute_flutter_command('scrollTillVisible', opts)
146
+
147
+ def inject_mock_image(self, value: str) -> str:
148
+ """
149
+ Injects a mock image to the device. The input can be a file path or a base64-encoded string.
150
+
151
+ Args:
152
+ value (str): The file path of the image or a base64-encoded string.
153
+
154
+ Returns:
155
+ str: Image ID of the injected image.
156
+ """
157
+ if os.path.isfile(value):
158
+ base64_encoded_image = encode_file_to_base64(value)
159
+ else:
160
+ base64_encoded_image = value
161
+ return self.execute_flutter_command('injectImage', {'base64Image': base64_encoded_image})
162
+
163
+ def activate_injected_image(self, image_id: str) -> None:
164
+ """
165
+ Activates an injected image with image ID.
166
+
167
+ Args:
168
+ image_id (str): The ID of the injected image to activate.
169
+
170
+ Returns:
171
+ None:
172
+ """
173
+ self.execute_flutter_command('activateInjectedImage', {'imageId': image_id})
174
+
175
+ def get_render_tree(
176
+ self,
177
+ widget_type: Optional[str] = None,
178
+ key: Optional[str] = None,
179
+ text: Optional[str] = None,
180
+ ) -> List[Optional[Dict]]:
181
+ """
182
+ Returns the render tree of the root widget.
183
+
184
+ Args:
185
+ widget_type (Optional[str]): The type of the widget to primary filter by.
186
+ key (Optional[str]): The key of the widget to filter by.
187
+ text (Optional[str]): The text of the widget to filter by.
188
+
189
+ Returns:
190
+ List[Optional[Dict]]: A list of dictionaries or None values representing the render tree.
191
+
192
+ The result is a nested list of dictionaries representing each widget and its properties,
193
+ such as type, key, size, attribute, state, visual information, and hierarchy.
194
+
195
+ The example widget includes the following code, which is rendered as part of the widget tree:
196
+
197
+ .. code-block:: dart
198
+
199
+ Semantics(
200
+ key: const Key('add_activity_semantics'),
201
+ label: 'add_activity_button',
202
+ button: true,
203
+ child: FloatingActionButton.small(
204
+ key: const Key('add_activity_button'),
205
+ tooltip: 'add_activity_button',
206
+ heroTag: 'add',
207
+ backgroundColor: const Color(0xFF2E2E3A),
208
+ onPressed: null,
209
+ child: Icon(
210
+ Icons.add,
211
+ size: 16,
212
+ color: Colors.amber.shade200.withOpacity(0.5),
213
+ semanticLabel: 'Add icon',
214
+ ),
215
+ ),
216
+ )
217
+
218
+ Example execute command:
219
+
220
+ .. code-block:: python
221
+
222
+ >>> flutter_command = FlutterCommand(driver) # noqa
223
+ >>> flutter_command.get_render_tree(widget_type='Semantics', key='add_activity_semantics')
224
+ output >> [
225
+ {
226
+ "type": "Semantics",
227
+ "elementType": "SingleChildRenderObjectElement",
228
+ "description": "Semantics-[<'add_activity_semantics'>]",
229
+ "depth": 0,
230
+ "key": "[<'add_activity_semantics'>]",
231
+ "attributes": {
232
+ "semanticsLabel": "add_activity_button"
233
+ },
234
+ "visual": {},
235
+ "state": {},
236
+ "rect": {
237
+ "x": 0,
238
+ "y": 0,
239
+ "width": 48,
240
+ "height": 48
241
+ },
242
+ "children": [
243
+ {
244
+ "type": "FloatingActionButton",
245
+ "elementType": "StatelessElement",
246
+ "description": "FloatingActionButton-[<'add_activity_button'>]",
247
+ "depth": 1,
248
+ "key": "[<'add_activity_button'>]",
249
+ "attributes": {},
250
+ "visual": {},
251
+ "state": {},
252
+ "rect": {
253
+ "x": 0,
254
+ "y": 0,
255
+ "width": 48,
256
+ "height": 48
257
+ },
258
+ "children": [
259
+ {...},
260
+ "children": [...]
261
+ }
262
+ ]
263
+ }
264
+ ]
265
+ }
266
+ ]
267
+ """
268
+ opts = {}
269
+ if widget_type is not None:
270
+ opts['widgetType'] = widget_type
271
+ if key is not None:
272
+ opts['key'] = key
273
+ if text is not None:
274
+ opts['text'] = text
275
+
276
+ return self.execute_flutter_command('renderTree', opts)
277
+
278
+ def execute_flutter_command(self, scriptName: str, params: dict) -> Any:
279
+ """
280
+ Executes a Flutter command by sending a script and parameters to the flutter integration driver.
281
+
282
+ Args:
283
+ scriptName (str): The name of the Flutter command to execute.
284
+ This will be prefixed with 'flutter:' when passed to the driver.
285
+ params (dict): A dictionary of parameters to be passed along with the Flutter command.
286
+
287
+ Returns:
288
+ Any: The result of the command execution. The return value depends on the
289
+ specific Flutter command being executed.
290
+ """
291
+ return self.driver.execute_script(f'flutter: {scriptName}', params)
292
+
293
+ def __get_locator_options(self, locator: Union[WebElement, 'FlutterFinder']) -> Dict[str, Union[dict, WebElement]]:
294
+ if isinstance(locator, WebElement):
295
+ return {'element': locator}
296
+ return {'locator': locator.to_dict()}
@@ -0,0 +1,55 @@
1
+ # Licensed to the Software Freedom Conservancy (SFC) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The SFC licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ from typing import Tuple, Union, cast
19
+
20
+ from selenium.webdriver.common.by import ByType as SeleniumByType
21
+
22
+ from appium.webdriver.common.appiumby import AppiumBy
23
+ from appium.webdriver.common.appiumby import ByType as AppiumByType
24
+
25
+
26
+ class FlutterFinder:
27
+ def __init__(self, using: Union[SeleniumByType, AppiumByType], value: str) -> None:
28
+ self.using = using
29
+ self.value = value
30
+
31
+ @staticmethod
32
+ def by_key(value: str) -> 'FlutterFinder':
33
+ return FlutterFinder(cast(AppiumByType, AppiumBy.FLUTTER_INTEGRATION_KEY), value)
34
+
35
+ @staticmethod
36
+ def by_text(value: str) -> 'FlutterFinder':
37
+ return FlutterFinder(cast(AppiumByType, AppiumBy.FLUTTER_INTEGRATION_TEXT), value)
38
+
39
+ @staticmethod
40
+ def by_semantics_label(value: str) -> 'FlutterFinder':
41
+ return FlutterFinder(cast(AppiumByType, AppiumBy.FLUTTER_INTEGRATION_SEMANTICS_LABEL), value)
42
+
43
+ @staticmethod
44
+ def by_type(value: str) -> 'FlutterFinder':
45
+ return FlutterFinder(cast(AppiumByType, AppiumBy.FLUTTER_INTEGRATION_TYPE), value)
46
+
47
+ @staticmethod
48
+ def by_text_containing(value: str) -> 'FlutterFinder':
49
+ return FlutterFinder(cast(AppiumByType, AppiumBy.FLUTTER_INTEGRATION_TEXT_CONTAINING), value)
50
+
51
+ def to_dict(self) -> dict:
52
+ return {'using': self.using, 'value': self.value}
53
+
54
+ def as_args(self) -> Tuple[str, str]:
55
+ return self.using, self.value
@@ -0,0 +1,6 @@
1
+ from enum import Enum
2
+
3
+
4
+ class ScrollDirection(Enum):
5
+ UP = 'up'
6
+ DOWN = 'down'
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/env python
2
+
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from typing import Optional
16
+
17
+ from selenium.common.exceptions import UnknownMethodException
18
+ from typing_extensions import Self
19
+
20
+ from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands
21
+ from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts
22
+ from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence
23
+
24
+ from ..mobilecommand import MobileCommand as Command
25
+
26
+
27
+ class HardwareActions(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence):
28
+ def lock(self, seconds: Optional[int] = None) -> Self:
29
+ """Lock the device. No changes are made if the device is already unlocked.
30
+
31
+ Args:
32
+ seconds: The duration to lock the device, in seconds.
33
+ The device is going to be locked forever until `unlock` is called
34
+ if it equals or is less than zero, otherwise this call blocks until
35
+ the timeout expires and unlocks the screen automatically.
36
+
37
+ Returns:
38
+ Union['WebDriver', 'HardwareActions']: Self instance
39
+ """
40
+ ext_name = 'mobile: lock'
41
+ args = {'seconds': seconds or 0}
42
+ try:
43
+ self.assert_extension_exists(ext_name).execute_script(ext_name, args)
44
+ except UnknownMethodException:
45
+ # TODO: Remove the fallback
46
+ self.mark_extension_absence(ext_name).execute(Command.LOCK, args)
47
+ return self
48
+
49
+ def unlock(self) -> Self:
50
+ """Unlock the device. No changes are made if the device is already locked.
51
+
52
+ Returns:
53
+ Union['WebDriver', 'HardwareActions']: Self instance
54
+ """
55
+ ext_name = 'mobile: unlock'
56
+ try:
57
+ if not self.assert_extension_exists(ext_name).execute_script('mobile: isLocked'):
58
+ return self
59
+ self.execute_script(ext_name)
60
+ except UnknownMethodException:
61
+ # TODO: Remove the fallback
62
+ self.mark_extension_absence(ext_name).execute(Command.UNLOCK)
63
+ return self
64
+
65
+ def is_locked(self) -> bool:
66
+ """Checks whether the device is locked.
67
+
68
+ Returns:
69
+ `True` if the device is locked
70
+ """
71
+ ext_name = 'mobile: isLocked'
72
+ try:
73
+ return self.assert_extension_exists(ext_name).execute_script('mobile: isLocked')
74
+ except UnknownMethodException:
75
+ # TODO: Remove the fallback
76
+ return self.mark_extension_absence(ext_name).execute(Command.IS_LOCKED)['value']
77
+
78
+ def shake(self) -> Self:
79
+ """Shake the device.
80
+
81
+ Returns:
82
+ Union['WebDriver', 'HardwareActions']: Self instance
83
+ """
84
+ ext_name = 'mobile: shake'
85
+ try:
86
+ self.assert_extension_exists(ext_name).execute_script(ext_name)
87
+ except UnknownMethodException:
88
+ # TODO: Remove the fallback
89
+ self.mark_extension_absence(ext_name).execute(Command.SHAKE)
90
+ return self
91
+
92
+ def touch_id(self, match: bool) -> Self:
93
+ """Simulate touchId on iOS Simulator
94
+
95
+ Args:
96
+ match: Simulates a successful touch (`True`) or a failed touch (`False`)
97
+
98
+ Returns:
99
+ Union['WebDriver', 'HardwareActions']: Self instance
100
+ """
101
+ self.execute_script(
102
+ 'mobile: sendBiometricMatch',
103
+ {
104
+ 'type': 'touchId',
105
+ 'match': match,
106
+ },
107
+ )
108
+ return self
109
+
110
+ def toggle_touch_id_enrollment(self) -> Self:
111
+ """Toggle enroll touchId on iOS Simulator
112
+
113
+ Returns:
114
+ Union['WebDriver', 'HardwareActions']: Self instance
115
+ """
116
+ is_enrolled = self.execute_script('mobile: isBiometricEnrolled')
117
+ self.execute_script('mobile: enrollBiometric', {'isEnabled': not is_enrolled})
118
+ return self
119
+
120
+ def finger_print(self, finger_id: int) -> Self:
121
+ """Authenticate users by using their finger print scans on supported Android emulators.
122
+
123
+ Args:
124
+ finger_id: Finger prints stored in Android Keystore system (from 1 to 10)
125
+ """
126
+ ext_name = 'mobile: fingerprint'
127
+ args = {'fingerprintId': finger_id}
128
+ try:
129
+ self.assert_extension_exists(ext_name).execute_script(ext_name, args)
130
+ except UnknownMethodException:
131
+ self.mark_extension_absence(ext_name).execute(Command.FINGER_PRINT, args)
132
+ return self
133
+
134
+ def _add_commands(self) -> None:
135
+ self.command_executor.add_command(Command.LOCK, 'POST', '/session/$sessionId/appium/device/lock')
136
+ self.command_executor.add_command(Command.UNLOCK, 'POST', '/session/$sessionId/appium/device/unlock')
137
+ self.command_executor.add_command(Command.IS_LOCKED, 'POST', '/session/$sessionId/appium/device/is_locked')
138
+ self.command_executor.add_command(Command.SHAKE, 'POST', '/session/$sessionId/appium/device/shake')
139
+ self.command_executor.add_command(Command.TOUCH_ID, 'POST', '/session/$sessionId/appium/simulator/touch_id')
140
+ self.command_executor.add_command(
141
+ Command.TOGGLE_TOUCH_ID_ENROLLMENT,
142
+ 'POST',
143
+ '/session/$sessionId/appium/simulator/toggle_touch_id_enrollment',
144
+ )
145
+ self.command_executor.add_command(
146
+ Command.FINGER_PRINT,
147
+ 'POST',
148
+ '/session/$sessionId/appium/device/finger_print',
149
+ )
@@ -0,0 +1,132 @@
1
+ #!/usr/bin/env python
2
+
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from typing import Any, Dict, Union
16
+
17
+ from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands
18
+
19
+ from ..mobilecommand import MobileCommand as Command
20
+
21
+
22
+ class ImagesComparison(CanExecuteCommands):
23
+ def match_images_features(self, base64_image1: bytes, base64_image2: bytes, **opts: Any) -> Dict[str, Any]:
24
+ """Performs images matching by features.
25
+
26
+ Read
27
+ https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_feature2d/py_matcher/py_matcher.html
28
+ for more details on this topic.
29
+ The method supports all image formats, which are supported by OpenCV itself.
30
+
31
+ Args:
32
+ base64_image1: base64-encoded content of the first image
33
+ base64_image2: base64-encoded content of the second image
34
+
35
+ Keyword Args:
36
+ visualize (bool): Set it to True in order to return the visualization of the matching operation.
37
+ matching visualization. False by default
38
+ detectorName (str): One of possible feature detector names:
39
+ 'AKAZE', 'AGAST', 'BRISK', 'FAST', 'GFTT', 'KAZE', 'MSER', 'SIFT', 'ORB'
40
+ Some of these detectors are not enabled in the default OpenCV deployment.
41
+ 'ORB' By default.
42
+ matchFunc (str): One of supported matching functions names:
43
+ 'FlannBased', 'BruteForce', 'BruteForceL1', 'BruteForceHamming',
44
+ 'BruteForceHammingLut', 'BruteForceSL2'
45
+ 'BruteForce' by default
46
+ goodMatchesFactor (int): The maximum count of "good" matches (e. g. with minimal distances).
47
+ This count is unlimited by default.
48
+
49
+ Returns:
50
+ The dictionary containing the following entries:
51
+
52
+ visualization (bytes): base64-encoded content of PNG visualization of the current comparison
53
+ operation. This entry is only present if `visualize` option is enabled
54
+ count (int): The count of matched edges on both images.
55
+ The more matching edges there are no both images the more similar they are.
56
+ totalCount (int): The total count of matched edges on both images.
57
+ It is equal to `count` if `goodMatchesFactor` does not limit the matches,
58
+ otherwise it contains the total count of matches before `goodMatchesFactor` is
59
+ applied.
60
+ points1 (dict): The array of matching points on the first image. Each point is a dictionary
61
+ with 'x' and 'y' keys
62
+ rect1 (dict): The bounding rect for the `points1` array or a zero rect if not enough matching points
63
+ were found. The rect is represented by a dictionary with 'x', 'y', 'width' and 'height' keys
64
+ points2 (dict): The array of matching points on the second image. Each point is a dictionary
65
+ with 'x' and 'y' keys
66
+ rect2 (dict): The bounding rect for the `points2` array or a zero rect if not enough matching points
67
+ were found. The rect is represented by a dictionary with 'x', 'y', 'width' and 'height' keys
68
+ """
69
+ options = {'mode': 'matchFeatures', 'firstImage': base64_image1, 'secondImage': base64_image2, 'options': opts}
70
+ return self.execute(Command.COMPARE_IMAGES, options)['value']
71
+
72
+ def find_image_occurrence(
73
+ self, base64_full_image: bytes, base64_partial_image: bytes, **opts: Any
74
+ ) -> Dict[str, Union[bytes, Dict]]:
75
+ """Performs images matching by template to find possible occurrence of the partial image
76
+ in the full image.
77
+
78
+ Read
79
+ https://docs.opencv.org/2.4/doc/tutorials/imgproc/histograms/template_matching/template_matching.html
80
+ for more details on this topic.
81
+ The method supports all image formats, which are supported by OpenCV itself.
82
+
83
+ Args:
84
+ base64_full_image: base64-encoded content of the full image
85
+ base64_partial_image: base64-encoded content of the partial image
86
+
87
+ Keyword Args:
88
+ visualize (bool): Set it to True in order to return the visualization of the matching operation.
89
+ False by default
90
+
91
+ Returns:
92
+ The dictionary containing the following entries:
93
+ visualization (bytes): base64-encoded content of PNG visualization of the current comparison
94
+ operation. This entry is only present if `visualize` option is enabled
95
+ rect (dict): The region of the partial image occurrence on the full image.
96
+ The rect is represented by a dictionary with 'x', 'y', 'width' and 'height' keys
97
+ """
98
+ options = {
99
+ 'mode': 'matchTemplate',
100
+ 'firstImage': base64_full_image,
101
+ 'secondImage': base64_partial_image,
102
+ 'options': opts,
103
+ }
104
+ return self.execute(Command.COMPARE_IMAGES, options)['value']
105
+
106
+ def get_images_similarity(self, base64_image1: bytes, base64_image2: bytes, **opts: Any) -> Dict[str, Union[bytes, Dict]]:
107
+ """Performs images matching to calculate the similarity score between them.
108
+
109
+ The flow there is similar to the one used in
110
+ `find_image_occurrence`, but it is mandatory that both images are of equal resolution.
111
+ The method supports all image formats, which are supported by OpenCV itself.
112
+
113
+ Args:
114
+ base64_image1: base64-encoded content of the first image
115
+ base64_image2: base64-encoded content of the second image
116
+
117
+ Keyword Args:
118
+ visualize (boo): Set it to True in order to return the visualization of the matching operation.
119
+ False by default
120
+
121
+ Returns:
122
+ The dictionary containing the following entries:
123
+ visualization (bytes): base64-encoded content of PNG visualization of the current comparison
124
+ operation. This entry is only present if `visualize` option is enabled
125
+ score (float): The similarity score as a float number in range [0.0, 1.0].
126
+ 1.0 is the highest score (means both images are totally equal).
127
+ """
128
+ options = {'mode': 'getSimilarity', 'firstImage': base64_image1, 'secondImage': base64_image2, 'options': opts}
129
+ return self.execute(Command.COMPARE_IMAGES, options)['value']
130
+
131
+ def _add_commands(self) -> None:
132
+ self.command_executor.add_command(Command.COMPARE_IMAGES, 'POST', '/session/$sessionId/appium/compare_images')