diff --git a/appium/webdriver/extensions/android/activities.py b/appium/webdriver/extensions/android/activities.py index 5a9f2cc95..e0cb84d59 100644 --- a/appium/webdriver/extensions/android/activities.py +++ b/appium/webdriver/extensions/android/activities.py @@ -12,21 +12,26 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import TypeVar +import warnings +from typing import TYPE_CHECKING, cast -from selenium.common.exceptions import TimeoutException +from selenium.common.exceptions import TimeoutException, UnknownMethodException from selenium.webdriver.support.ui import WebDriverWait from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands +from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts +from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence from appium.webdriver.mobilecommand import MobileCommand as Command -T = TypeVar('T', bound=CanExecuteCommands) +if TYPE_CHECKING: + from appium.webdriver.webdriver import WebDriver -class Activities(CanExecuteCommands): - def start_activity(self: T, app_package: str, app_activity: str, **opts: str) -> T: +class Activities(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): + def start_activity(self, app_package: str, app_activity: str, **opts: str) -> 'WebDriver': """Opens an arbitrary activity during a test. If the activity belongs to another application, that application is started and the activity is opened. + deprecated:: 2.9.0 This is an Android-only method. @@ -43,6 +48,11 @@ def start_activity(self: T, app_package: str, app_activity: str, **opts: str) -> optional_intent_arguments (str): Optional arguments to the intent. dont_stop_app_on_reset (str): Should the app be stopped on reset? """ + warnings.warn( + 'The "session" API is deprecated. Use "mobile: startActivity" extension instead.', + DeprecationWarning, + ) + data = {'appPackage': app_package, 'appActivity': app_activity} arguments = { 'app_wait_package': 'appWaitPackage', @@ -57,7 +67,7 @@ def start_activity(self: T, app_package: str, app_activity: str, **opts: str) -> if key in opts: data[value] = opts[key] self.execute(Command.START_ACTIVITY, data) - return self + return cast('WebDriver', self) @property def current_activity(self) -> str: @@ -66,7 +76,12 @@ def current_activity(self) -> str: Returns: str: The current activity name running on the device """ - return self.execute(Command.GET_CURRENT_ACTIVITY)['value'] + ext_name = 'mobile: getCurrentActivity' + try: + return self.assert_extension_exists(ext_name).execute_script(ext_name) + except UnknownMethodException: + # TODO: Remove the fallback + return self.mark_extension_absence(ext_name).execute(Command.GET_CURRENT_ACTIVITY)['value'] def wait_activity(self, activity: str, timeout: int, interval: int = 1) -> bool: """Wait for an activity: block until target activity presents or time out. diff --git a/appium/webdriver/extensions/android/common.py b/appium/webdriver/extensions/android/common.py index b121d339f..f6aa92708 100644 --- a/appium/webdriver/extensions/android/common.py +++ b/appium/webdriver/extensions/android/common.py @@ -11,18 +11,24 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +import warnings +from typing import TYPE_CHECKING, Any, cast -from typing import Any, TypeVar +from selenium.common.exceptions import UnknownMethodException from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands +from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts +from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence from appium.webdriver.mobilecommand import MobileCommand as Command -T = TypeVar('T', bound=CanExecuteCommands) +if TYPE_CHECKING: + from appium.webdriver.webdriver import WebDriver -class Common(CanExecuteCommands): - def end_test_coverage(self, intent: str, path: str) -> Any: # TODO Check return type +class Common(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): + def end_test_coverage(self, intent: str, path: str) -> Any: """Ends the coverage collection and pull the coverage.ec file from the device. + deprecated:: 2.9.0 Android only. See https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/android/android-coverage.md @@ -34,25 +40,41 @@ def end_test_coverage(self, intent: str, path: str) -> Any: # TODO Check return Returns: TODO """ - data = { - 'intent': intent, - 'path': path, - } - return self.execute(Command.END_TEST_COVERAGE, data)['value'] + warnings.warn( + 'This API is deprecated and will be removed in future versions', + DeprecationWarning, + ) + return self.execute( + Command.END_TEST_COVERAGE, + { + 'intent': intent, + 'path': path, + }, + )['value'] - def open_notifications(self: T) -> T: + def open_notifications(self) -> 'WebDriver': """Open notification shade in Android (API Level 18 and above) Returns: Union['WebDriver', 'Common']: Self instance """ - self.execute(Command.OPEN_NOTIFICATIONS, {}) - return self + ext_name = 'mobile: openNotifications' + try: + self.assert_extension_exists(ext_name).execute_script(ext_name) + except UnknownMethodException: + # TODO: Remove the fallback + self.mark_extension_absence(ext_name).execute(Command.OPEN_NOTIFICATIONS, {}) + return cast('WebDriver', self) @property def current_package(self) -> str: """Retrieves the current package running on the device.""" - return self.execute(Command.GET_CURRENT_PACKAGE)['value'] + ext_name = 'mobile: getCurrentPackage' + try: + return self.assert_extension_exists(ext_name).execute_script(ext_name) + except UnknownMethodException: + # TODO: Remove the fallback + return self.mark_extension_absence(ext_name).execute(Command.GET_CURRENT_PACKAGE)['value'] def _add_commands(self) -> None: # noinspection PyProtectedMember,PyUnresolvedReferences diff --git a/appium/webdriver/extensions/android/display.py b/appium/webdriver/extensions/android/display.py index 9822182aa..e04bd1bef 100644 --- a/appium/webdriver/extensions/android/display.py +++ b/appium/webdriver/extensions/android/display.py @@ -12,11 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. +from selenium.common.exceptions import UnknownMethodException + from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands +from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts +from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence from appium.webdriver.mobilecommand import MobileCommand as Command -class Display(CanExecuteCommands): +class Display(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): def get_display_density(self) -> int: """Get the display density, Android only @@ -29,7 +33,12 @@ def get_display_density(self) -> int: Return: int: The display density """ - return self.execute(Command.GET_DISPLAY_DENSITY)['value'] + ext_name = 'mobile: getDisplayDensity' + try: + return self.assert_extension_exists(ext_name).execute_script(ext_name) + except UnknownMethodException: + # TODO: Remove the fallback + return self.mark_extension_absence(ext_name).execute(Command.GET_DISPLAY_DENSITY)['value'] def _add_commands(self) -> None: # noinspection PyProtectedMember,PyUnresolvedReferences diff --git a/appium/webdriver/extensions/android/gsm.py b/appium/webdriver/extensions/android/gsm.py index 0dae0b4ba..7d97ac2de 100644 --- a/appium/webdriver/extensions/android/gsm.py +++ b/appium/webdriver/extensions/android/gsm.py @@ -12,14 +12,19 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import TypeVar +from typing import TYPE_CHECKING, cast + +from selenium.common.exceptions import UnknownMethodException from appium.common.helper import extract_const_attributes from appium.common.logger import logger from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands +from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts +from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence from appium.webdriver.mobilecommand import MobileCommand as Command -T = TypeVar('T', bound=CanExecuteCommands) +if TYPE_CHECKING: + from appium.webdriver.webdriver import WebDriver class GsmCallActions: @@ -47,8 +52,8 @@ class GsmVoiceState: ON = 'on' -class Gsm(CanExecuteCommands): - def make_gsm_call(self: T, phone_number: str, action: str) -> T: +class Gsm(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): + def make_gsm_call(self, phone_number: str, action: str) -> 'WebDriver': """Make GSM call (Emulator only) Android only. @@ -64,16 +69,22 @@ def make_gsm_call(self: T, phone_number: str, action: str) -> T: Returns: Union['WebDriver', 'Gsm']: Self instance """ + ext_name = 'mobile: gsmCall' constants = extract_const_attributes(GsmCallActions) if action not in constants.values(): logger.warning( f'{action} is unknown. Consider using one of {list(constants.keys())} constants. ' f'(e.g. {GsmCallActions.__name__}.CALL)' ) - self.execute(Command.MAKE_GSM_CALL, {'phoneNumber': phone_number, 'action': action}) - return self - - def set_gsm_signal(self: T, strength: int) -> T: + args = {'phoneNumber': phone_number, 'action': action} + try: + self.assert_extension_exists(ext_name).execute_script(ext_name, args) + except UnknownMethodException: + # TODO: Remove the fallback + self.mark_extension_absence(ext_name).execute(Command.MAKE_GSM_CALL, args) + return cast('WebDriver', self) + + def set_gsm_signal(self, strength: int) -> 'WebDriver': """Set GSM signal strength (Emulator only) Android only. @@ -88,16 +99,23 @@ def set_gsm_signal(self: T, strength: int) -> T: Returns: Union['WebDriver', 'Gsm']: Self instance """ + ext_name = 'mobile: gsmSignal' constants = extract_const_attributes(GsmSignalStrength) if strength not in constants.values(): logger.warning( f'{strength} is out of range. Consider using one of {list(constants.keys())} constants. ' f'(e.g. {GsmSignalStrength.__name__}.GOOD)' ) - self.execute(Command.SET_GSM_SIGNAL, {'signalStrength': strength, 'signalStrengh': strength}) - return self + try: + self.assert_extension_exists(ext_name).execute_script(ext_name, {'strength': strength}) + except UnknownMethodException: + # TODO: Remove the fallback + self.mark_extension_absence(ext_name).execute( + Command.SET_GSM_SIGNAL, {'signalStrength': strength, 'signalStrengh': strength} + ) + return cast('WebDriver', self) - def set_gsm_voice(self: T, state: str) -> T: + def set_gsm_voice(self, state: str) -> 'WebDriver': """Set GSM voice state (Emulator only) Android only. @@ -112,14 +130,20 @@ def set_gsm_voice(self: T, state: str) -> T: Returns: Union['WebDriver', 'Gsm']: Self instance """ + ext_name = 'mobile: gmsVoice' constants = extract_const_attributes(GsmVoiceState) if state not in constants.values(): logger.warning( f'{state} is unknown. Consider using one of {list(constants.keys())} constants. ' f'(e.g. {GsmVoiceState.__name__}.HOME)' ) - self.execute(Command.SET_GSM_VOICE, {'state': state}) - return self + args = {'state': state} + try: + self.assert_extension_exists(ext_name).execute_script(ext_name, args) + except UnknownMethodException: + # TODO: Remove the fallback + self.mark_extension_absence(ext_name).execute(Command.SET_GSM_VOICE, args) + return cast('WebDriver', self) def _add_commands(self) -> None: # noinspection PyProtectedMember,PyUnresolvedReferences diff --git a/appium/webdriver/extensions/android/network.py b/appium/webdriver/extensions/android/network.py index 46bfce8b0..aa6bca3d0 100644 --- a/appium/webdriver/extensions/android/network.py +++ b/appium/webdriver/extensions/android/network.py @@ -12,14 +12,19 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import TypeVar +from typing import TYPE_CHECKING, cast + +from selenium.common.exceptions import UnknownMethodException from appium.common.helper import extract_const_attributes from appium.common.logger import logger from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands +from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts +from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence from appium.webdriver.mobilecommand import MobileCommand as Command -T = TypeVar('T', bound=CanExecuteCommands) +if TYPE_CHECKING: + from appium.webdriver.webdriver import WebDriver class NetSpeed: @@ -34,15 +39,34 @@ class NetSpeed: FULL = 'full' # No limit, the default (up: 0.0, down: 0.0) -class Network(CanExecuteCommands): +class NetworkMask: + WIFI = 0b010 + DATA = 0b100 + AIRPLANE_MODE = 0b001 + + +class Network(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): @property def network_connection(self) -> int: """Returns an integer bitmask specifying the network connection type. Android only. Possible values are available through the enumeration `appium.webdriver.ConnectionType` + + This API only works reliably on emulators (any version) and real devices + since API level 31. """ - return self.execute(Command.GET_NETWORK_CONNECTION, {})['value'] + ext_name = 'mobile: getConnectivity' + try: + result_map = self.assert_extension_exists(ext_name).execute_script(ext_name) + return ( + (NetworkMask.WIFI if result_map['wifi'] else 0) + | (NetworkMask.DATA if result_map['data'] else 0) + | (NetworkMask.AIRPLANE_MODE if result_map['airplaneMode'] else 0) + ) + except UnknownMethodException: + # TODO: Remove the fallback + return self.mark_extension_absence(ext_name).execute(Command.GET_NETWORK_CONNECTION, {})['value'] def set_network_connection(self, connection_type: int) -> int: """Sets the network connection type. Android only. @@ -65,25 +89,49 @@ def set_network_connection(self, connection_type: int) -> int: These are available through the enumeration `appium.webdriver.ConnectionType` + This API only works reliably on emulators (any version) and real devices + since API level 31. + Args: connection_type: a member of the enum `appium.webdriver.ConnectionType` Return: int: Set network connection type """ - data = {'parameters': {'type': connection_type}} - return self.execute(Command.SET_NETWORK_CONNECTION, data)['value'] + ext_name = 'mobile: setConnectivity' + try: + return self.assert_extension_exists(ext_name).execute_script( + ext_name, + { + 'wifi': bool(connection_type & NetworkMask.WIFI), + 'data': bool(connection_type & NetworkMask.DATA), + 'airplaneMode': bool(connection_type & NetworkMask.AIRPLANE_MODE), + }, + ) + except UnknownMethodException: + # TODO: Remove the fallback + return self.mark_extension_absence(ext_name).execute( + Command.SET_NETWORK_CONNECTION, {'parameters': {'type': connection_type}} + )['value'] - def toggle_wifi(self: T) -> T: + def toggle_wifi(self) -> 'WebDriver': """Toggle the wifi on the device, Android only. + This API only works reliably on emulators (any version) and real devices + since API level 31. Returns: Union['WebDriver', 'Network']: Self instance """ - self.execute(Command.TOGGLE_WIFI, {}) - return self + ext_name = 'mobile: setConnectivity' + try: + self.assert_extension_exists(ext_name).execute_script( + ext_name, {'wifi': not (self.network_connection & NetworkMask.WIFI)} + ) + except UnknownMethodException: + self.mark_extension_absence(ext_name).execute(Command.TOGGLE_WIFI, {}) + return cast('WebDriver', self) - def set_network_speed(self: T, speed_type: str) -> T: + def set_network_speed(self, speed_type: str) -> 'WebDriver': """Set the network speed emulation. Android Emulator only. @@ -104,9 +152,13 @@ def set_network_speed(self: T, speed_type: str) -> T: f'{speed_type} is unknown. Consider using one of {list(constants.keys())} constants. ' f'(e.g. {NetSpeed.__name__}.LTE)' ) - - self.execute(Command.SET_NETWORK_SPEED, {'netspeed': speed_type}) - return self + ext_name = 'mobile: networkSpeed' + try: + self.assert_extension_exists(ext_name).execute_script(ext_name, {'speed': speed_type}) + except UnknownMethodException: + # TODO: Remove the fallback + self.mark_extension_absence(ext_name).execute(Command.SET_NETWORK_SPEED, {'netspeed': speed_type}) + return cast('WebDriver', self) def _add_commands(self) -> None: # noinspection PyProtectedMember,PyUnresolvedReferences diff --git a/appium/webdriver/extensions/android/performance.py b/appium/webdriver/extensions/android/performance.py index 2c4f46690..0611c751a 100644 --- a/appium/webdriver/extensions/android/performance.py +++ b/appium/webdriver/extensions/android/performance.py @@ -14,11 +14,15 @@ from typing import Dict, List, Union +from selenium.common.exceptions import UnknownMethodException + from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands +from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts +from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence from appium.webdriver.mobilecommand import MobileCommand as Command -class Performance(CanExecuteCommands): +class Performance(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): def get_performance_data( self, package_name: str, data_type: str, data_read_timeout: Union[int, None] = None ) -> List[List[str]]: @@ -40,12 +44,17 @@ def get_performance_data( Returns: The data along to `data_type` """ - data: Dict[str, Union[str, int]] = {'packageName': package_name, 'dataType': data_type} - if data_read_timeout is not None: - data['dataReadTimeout'] = data_read_timeout - return self.execute(Command.GET_PERFORMANCE_DATA, data)['value'] + ext_name = 'mobile: getPerformanceData' + args: Dict[str, Union[str, int]] = {'packageName': package_name, 'dataType': data_type} + try: + return self.assert_extension_exists(ext_name).execute_script(ext_name, args) + except UnknownMethodException: + # TODO: Remove the fallback + if data_read_timeout is not None: + args['dataReadTimeout'] = data_read_timeout + return self.mark_extension_absence(ext_name).execute(Command.GET_PERFORMANCE_DATA, args)['value'] - def get_performance_data_types(self) -> List: + def get_performance_data_types(self) -> List[str]: """Returns the information types of the system state which is supported to read as like cpu, memory, network traffic, and battery. Android only. @@ -56,7 +65,12 @@ def get_performance_data_types(self) -> List: Returns: Available data types """ - return self.execute(Command.GET_PERFORMANCE_DATA_TYPES)['value'] + ext_name = 'mobile: getPerformanceDataTypes' + try: + return self.assert_extension_exists(ext_name).execute_script(ext_name) + except UnknownMethodException: + # TODO: Remove the fallback + return self.mark_extension_absence(ext_name).execute(Command.GET_PERFORMANCE_DATA_TYPES)['value'] def _add_commands(self) -> None: # noinspection PyProtectedMember,PyUnresolvedReferences diff --git a/appium/webdriver/extensions/android/power.py b/appium/webdriver/extensions/android/power.py index c1b9b2116..8913526a5 100644 --- a/appium/webdriver/extensions/android/power.py +++ b/appium/webdriver/extensions/android/power.py @@ -12,18 +12,23 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import TypeVar +from typing import TYPE_CHECKING, cast + +from selenium.common.exceptions import UnknownMethodException from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands +from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts +from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence from appium.webdriver.mobilecommand import MobileCommand as Command -T = TypeVar('T', bound=CanExecuteCommands) +if TYPE_CHECKING: + from appium.webdriver.webdriver import WebDriver -class Power(CanExecuteCommands): +class Power(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): AC_OFF, AC_ON = 'off', 'on' - def set_power_capacity(self: T, percent: int) -> T: + def set_power_capacity(self, percent: int) -> 'WebDriver': """Emulate power capacity change on the connected emulator. Android only. @@ -37,10 +42,16 @@ def set_power_capacity(self: T, percent: int) -> T: Returns: Union['WebDriver', 'Power']: Self instance """ - self.execute(Command.SET_POWER_CAPACITY, {'percent': percent}) - return self - - def set_power_ac(self: T, ac_state: str) -> T: + ext_name = 'mobile: powerCapacity' + args = {'percent': percent} + try: + self.assert_extension_exists(ext_name).execute_script(ext_name, args) + except UnknownMethodException: + # TODO: Remove the fallback + self.mark_extension_absence(ext_name).execute(Command.SET_POWER_CAPACITY, args) + return cast('WebDriver', self) + + def set_power_ac(self, ac_state: str) -> 'WebDriver': """Emulate power state change on the connected emulator. Android only. @@ -55,8 +66,14 @@ def set_power_ac(self: T, ac_state: str) -> T: Returns: Union['WebDriver', 'Power']: Self instance """ - self.execute(Command.SET_POWER_AC, {'state': ac_state}) - return self + ext_name = 'mobile: powerAC' + args = {'state': ac_state} + try: + self.assert_extension_exists(ext_name).execute_script(ext_name, args) + except UnknownMethodException: + # TODO: Remove the fallback + self.mark_extension_absence(ext_name).execute(Command.SET_POWER_AC, args) + return cast('WebDriver', self) def _add_commands(self) -> None: # noinspection PyProtectedMember,PyUnresolvedReferences diff --git a/appium/webdriver/extensions/android/sms.py b/appium/webdriver/extensions/android/sms.py index 013494dd1..24b76ca6a 100644 --- a/appium/webdriver/extensions/android/sms.py +++ b/appium/webdriver/extensions/android/sms.py @@ -12,16 +12,21 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import TypeVar +from typing import TYPE_CHECKING, cast + +from selenium.common.exceptions import UnknownMethodException from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands +from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts +from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence from appium.webdriver.mobilecommand import MobileCommand as Command -T = TypeVar('T', bound=CanExecuteCommands) +if TYPE_CHECKING: + from appium.webdriver.webdriver import WebDriver -class Sms(CanExecuteCommands): - def send_sms(self: T, phone_number: str, message: str) -> T: +class Sms(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): + def send_sms(self, phone_number: str, message: str) -> 'WebDriver': """Emulate send SMS event on the connected emulator. Android only. @@ -36,8 +41,14 @@ def send_sms(self: T, phone_number: str, message: str) -> T: Returns: Union['WebDriver', 'Sms']: Self instance """ - self.execute(Command.SEND_SMS, {'phoneNumber': phone_number, 'message': message}) - return self + ext_name = 'mobile: sendSms' + args = {'phoneNumber': phone_number, 'message': message} + try: + self.assert_extension_exists(ext_name).execute_script(ext_name, args) + except UnknownMethodException: + # TODO: Remove the fallback + self.mark_extension_absence(ext_name).execute(Command.SEND_SMS, args) + return cast('WebDriver', self) def _add_commands(self) -> None: # noinspection PyProtectedMember,PyUnresolvedReferences diff --git a/appium/webdriver/extensions/android/system_bars.py b/appium/webdriver/extensions/android/system_bars.py index b894fe7c5..d2fed74f4 100644 --- a/appium/webdriver/extensions/android/system_bars.py +++ b/appium/webdriver/extensions/android/system_bars.py @@ -14,11 +14,15 @@ from typing import Dict, Union +from selenium.common.exceptions import UnknownMethodException + from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands +from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts +from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence from appium.webdriver.mobilecommand import MobileCommand as Command -class SystemBars(CanExecuteCommands): +class SystemBars(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): def get_system_bars(self) -> Dict[str, Dict[str, Union[int, bool]]]: """Retrieve visibility and bounds information of the status and navigation bars. @@ -39,7 +43,12 @@ def get_system_bars(self) -> Dict[str, Dict[str, Union[int, bool]]]: - width - height """ - return self.execute(Command.GET_SYSTEM_BARS)['value'] + ext_name = 'mobile: getSystemBars' + try: + return self.assert_extension_exists(ext_name).execute_script(ext_name) + except UnknownMethodException: + # TODO: Remove the fallback + return self.mark_extension_absence(ext_name).execute(Command.GET_SYSTEM_BARS)['value'] def _add_commands(self) -> None: # noinspection PyProtectedMember,PyUnresolvedReferences diff --git a/test/functional/android/common_tests.py b/test/functional/android/common_tests.py index 6fdbd3e1f..66aea810a 100644 --- a/test/functional/android/common_tests.py +++ b/test/functional/android/common_tests.py @@ -29,11 +29,6 @@ class TestCommon(BaseTestCase): def test_current_package(self) -> None: assert APIDEMO_PKG_NAME == self.driver.current_package - @pytest.mark.skip('Not sure how to set this up to run') - def test_end_test_coverage(self) -> None: - self.driver.end_test_coverage(intent='android.intent.action.MAIN', path='') - sleep(5) - # TODO Due to unexpected dialog, "System UI isn't responding" @pytest.mark.skipif(condition=is_ci(), reason='Need to fix flaky test during running on CI.') def test_open_notifications(self) -> None: diff --git a/test/unit/webdriver/device/activities_test.py b/test/unit/webdriver/device/activities_test.py index b64a10d64..2374ba6cc 100644 --- a/test/unit/webdriver/device/activities_test.py +++ b/test/unit/webdriver/device/activities_test.py @@ -14,49 +14,10 @@ import httpretty -from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body +from test.unit.helper.test_helper import android_w3c_driver, appium_command class TestWebDriverActivities(object): - @httpretty.activate - def test_start_activity(self): - driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/appium/device/start_activity'), body='{"value": ""}' - ) - driver.start_activity('com.example.myapp', '.ExampleActivity') - - d = get_httpretty_request_body(httpretty.last_request()) - assert d['appPackage'] == 'com.example.myapp' - assert d['appActivity'] == '.ExampleActivity' - - @httpretty.activate - def test_start_activity_with_opts(self): - driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/appium/device/start_activity'), body='{"value": ""}' - ) - driver.start_activity( - app_package='com.example.myapp', - app_activity='.ExampleActivity', - app_wait_package='com.example.waitapp', - intent_action='android.intent.action.MAIN', - intent_category='android.intent.category.LAUNCHER', - intent_flags='0x10200000', - optional_intent_arguments='--es "activity" ".ExampleActivity"', - dont_stop_app_on_reset=True, - ) - - d = get_httpretty_request_body(httpretty.last_request()) - assert d['appPackage'] == 'com.example.myapp' - assert d['appActivity'] == '.ExampleActivity' - assert d['appWaitPackage'] == 'com.example.waitapp' - assert d['intentAction'] == 'android.intent.action.MAIN' - assert d['intentCategory'] == 'android.intent.category.LAUNCHER' - assert d['intentFlags'] == '0x10200000' - assert d['optionalIntentArguments'] == '--es "activity" ".ExampleActivity"' - assert d['dontStopAppOnReset'] is True - @httpretty.activate def test_current_activity(self): driver = android_w3c_driver() @@ -65,6 +26,11 @@ def test_current_activity(self): appium_command('/session/1234567890/appium/device/current_activity'), body='{"value": ".ExampleActivity"}', ) + httpretty.register_uri( + httpretty.POST, + appium_command('/session/1234567890/execute/sync'), + body='{"value": ".ExampleActivity"}', + ) assert driver.current_activity == '.ExampleActivity' @httpretty.activate @@ -75,4 +41,9 @@ def test_wait_activity(self): appium_command('/session/1234567890/appium/device/current_activity'), body='{"value": ".ExampleActivity"}', ) + httpretty.register_uri( + httpretty.POST, + appium_command('/session/1234567890/execute/sync'), + body='{"value": ".ExampleActivity"}', + ) assert driver.wait_activity('.ExampleActivity', 1) is True diff --git a/test/unit/webdriver/device/common_test.py b/test/unit/webdriver/device/common_test.py index 3d9b22834..c4065e472 100644 --- a/test/unit/webdriver/device/common_test.py +++ b/test/unit/webdriver/device/common_test.py @@ -23,6 +23,7 @@ class TestWebDriverCommon(object): def test_open_notifications(self): driver = android_w3c_driver() httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/appium/device/open_notifications')) + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) assert isinstance(driver.open_notifications(), WebDriver) @httpretty.activate @@ -33,4 +34,9 @@ def test_current_package(self): appium_command('/session/1234567890/appium/device/current_package'), body='{"value": ".ExamplePackage"}', ) + httpretty.register_uri( + httpretty.POST, + appium_command('/session/1234567890/execute/sync'), + body='{"value": ".ExamplePackage"}', + ) assert driver.current_package == '.ExamplePackage' diff --git a/test/unit/webdriver/device/display_test.py b/test/unit/webdriver/device/display_test.py index 927896071..96adab424 100644 --- a/test/unit/webdriver/device/display_test.py +++ b/test/unit/webdriver/device/display_test.py @@ -24,4 +24,7 @@ def test_get_display_density(self): httpretty.register_uri( httpretty.GET, appium_command('/session/1234567890/appium/device/display_density'), body='{"value": 560}' ) + httpretty.register_uri( + httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": 560}' + ) assert driver.get_display_density() == 560 diff --git a/test/unit/webdriver/device/gsm_test.py b/test/unit/webdriver/device/gsm_test.py index f6ad5ee05..cd776a94a 100644 --- a/test/unit/webdriver/device/gsm_test.py +++ b/test/unit/webdriver/device/gsm_test.py @@ -27,11 +27,15 @@ def test_make_gsm_call(self): httpretty.POST, appium_command('/session/1234567890/appium/device/gsm_call'), ) + httpretty.register_uri( + httpretty.POST, + appium_command('/session/1234567890/execute/sync'), + ) assert isinstance(driver.make_gsm_call('5551234567', GsmCallActions.CALL), WebDriver) d = get_httpretty_request_body(httpretty.last_request()) - assert d['phoneNumber'] == '5551234567' - assert d['action'] == GsmCallActions.CALL + assert d['args'][0]['phoneNumber'] == '5551234567' + assert d['args'][0]['action'] == GsmCallActions.CALL @httpretty.activate def test_set_gsm_signal(self): @@ -40,11 +44,14 @@ def test_set_gsm_signal(self): httpretty.POST, appium_command('/session/1234567890/appium/device/gsm_signal'), ) + httpretty.register_uri( + httpretty.POST, + appium_command('/session/1234567890/execute/sync'), + ) assert isinstance(driver.set_gsm_signal(GsmSignalStrength.GREAT), WebDriver) d = get_httpretty_request_body(httpretty.last_request()) - assert d['signalStrength'] == GsmSignalStrength.GREAT - assert d['signalStrengh'] == GsmSignalStrength.GREAT + assert d['args'][0]['strength'] == GsmSignalStrength.GREAT @httpretty.activate def test_set_gsm_voice(self): @@ -53,7 +60,11 @@ def test_set_gsm_voice(self): httpretty.POST, appium_command('/session/1234567890/appium/device/gsm_voice'), ) + httpretty.register_uri( + httpretty.POST, + appium_command('/session/1234567890/execute/sync'), + ) assert isinstance(driver.set_gsm_voice(GsmVoiceState.ROAMING), WebDriver) d = get_httpretty_request_body(httpretty.last_request()) - assert d['state'] == GsmVoiceState.ROAMING + assert d['args'][0]['state'] == GsmVoiceState.ROAMING diff --git a/test/unit/webdriver/device/power_test.py b/test/unit/webdriver/device/power_test.py index 7a5254c40..2d87a8d4c 100644 --- a/test/unit/webdriver/device/power_test.py +++ b/test/unit/webdriver/device/power_test.py @@ -27,10 +27,14 @@ def test_set_power_capacity(self): httpretty.POST, appium_command('/session/1234567890/appium/device/power_capacity'), ) + httpretty.register_uri( + httpretty.POST, + appium_command('/session/1234567890/execute/sync'), + ) assert isinstance(driver.set_power_capacity(50), WebDriver) d = get_httpretty_request_body(httpretty.last_request()) - assert d['percent'] == 50 + assert d['args'][0]['percent'] == 50 @httpretty.activate def test_set_power_ac(self): @@ -39,7 +43,11 @@ def test_set_power_ac(self): httpretty.POST, appium_command('/session/1234567890/appium/device/power_ac'), ) + httpretty.register_uri( + httpretty.POST, + appium_command('/session/1234567890/execute/sync'), + ) assert isinstance(driver.set_power_ac(Power.AC_ON), WebDriver) d = get_httpretty_request_body(httpretty.last_request()) - assert d['state'] == Power.AC_ON + assert d['args'][0]['state'] == Power.AC_ON diff --git a/test/unit/webdriver/device/sms_test.py b/test/unit/webdriver/device/sms_test.py index 5e3fb2001..1323f50c4 100644 --- a/test/unit/webdriver/device/sms_test.py +++ b/test/unit/webdriver/device/sms_test.py @@ -26,8 +26,12 @@ def test_send_sms(self): httpretty.POST, appium_command('/session/1234567890/appium/device/send_sms'), ) + httpretty.register_uri( + httpretty.POST, + appium_command('/session/1234567890/execute/sync'), + ) assert isinstance(driver.send_sms('555-123-4567', 'Hey lol'), WebDriver) d = get_httpretty_request_body(httpretty.last_request()) - assert d['phoneNumber'] == '555-123-4567' - assert d['message'] == 'Hey lol' + assert d['args'][0]['phoneNumber'] == '555-123-4567' + assert d['args'][0]['message'] == 'Hey lol' diff --git a/test/unit/webdriver/device/system_bars_test.py b/test/unit/webdriver/device/system_bars_test.py index 6799733ea..2706be3db 100644 --- a/test/unit/webdriver/device/system_bars_test.py +++ b/test/unit/webdriver/device/system_bars_test.py @@ -21,14 +21,20 @@ class TestWebDriverSystemBars(object): @httpretty.activate def test_get_system_bars(self): driver = android_w3c_driver() + body = '''{"value": + {"statusBar": + {"visible": true, "x": 0, "y": 0, "width": 1080, "height": 1920}, + "navigationBar": + {"visible": true, "x": 0, "y": 0, "width": 1080, "height": 126}}}''' httpretty.register_uri( httpretty.GET, appium_command('/session/1234567890/appium/device/system_bars'), - body=''' {"value": - {"statusBar": - {"visible": true, "x": 0, "y": 0, "width": 1080, "height": 1920}, - "navigationBar": - {"visible": true, "x": 0, "y": 0, "width": 1080, "height": 126}}}''', + body=body, + ) + httpretty.register_uri( + httpretty.POST, + appium_command('/session/1234567890/execute/sync'), + body=body, ) d = driver.get_system_bars() diff --git a/test/unit/webdriver/network_test.py b/test/unit/webdriver/network_test.py index c903db402..d586fcbd4 100644 --- a/test/unit/webdriver/network_test.py +++ b/test/unit/webdriver/network_test.py @@ -27,6 +27,11 @@ def test_network_connection(self): httpretty.register_uri( httpretty.GET, appium_command('/session/1234567890/network_connection'), body='{"value": 2}' ) + httpretty.register_uri( + httpretty.POST, + appium_command('/session/1234567890/execute/sync'), + body='{"value": {"wifi": true, "data": false, "airplaneMode": false}}', + ) assert driver.network_connection == 2 @httpretty.activate @@ -35,10 +40,15 @@ def test_set_network_connection(self): httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/network_connection'), body='{"value": ""}' ) + httpretty.register_uri( + httpretty.POST, + appium_command('/session/1234567890/execute/sync'), + body='{"value": {"wifi": true, "data": false, "airplaneMode": false}}', + ) driver.set_network_connection(2) d = get_httpretty_request_body(httpretty.last_request()) - assert d['parameters']['type'] == 2 + assert d['args'][0]['wifi'] is True @httpretty.activate def test_set_network_speed(self): @@ -47,10 +57,14 @@ def test_set_network_speed(self): httpretty.POST, appium_command('/session/1234567890/appium/device/network_speed'), ) + httpretty.register_uri( + httpretty.POST, + appium_command('/session/1234567890/execute/sync'), + ) assert isinstance(driver.set_network_speed(NetSpeed.LTE), WebDriver) d = get_httpretty_request_body(httpretty.last_request()) - assert d['netspeed'] == NetSpeed.LTE + assert d['args'][0]['speed'] == NetSpeed.LTE @httpretty.activate def test_toggle_wifi(self): @@ -59,4 +73,9 @@ def test_toggle_wifi(self): httpretty.POST, appium_command('/session/1234567890/appium/device/toggle_wifi'), ) + httpretty.register_uri( + httpretty.POST, + appium_command('/session/1234567890/execute/sync'), + body='{"value": {"wifi": true, "data": false, "airplaneMode": false}}', + ) assert isinstance(driver.toggle_wifi(), WebDriver) diff --git a/test/unit/webdriver/performance_test.py b/test/unit/webdriver/performance_test.py index 78d62756f..d4534c903 100644 --- a/test/unit/webdriver/performance_test.py +++ b/test/unit/webdriver/performance_test.py @@ -26,12 +26,16 @@ def test_get_performance_data(self): appium_command('/session/1234567890/appium/getPerformanceData'), body='{"value": [["user", "kernel"], ["2.5", "1.3"]]}', ) + httpretty.register_uri( + httpretty.POST, + appium_command('/session/1234567890/execute/sync'), + body='{"value": [["user", "kernel"], ["2.5", "1.3"]]}', + ) assert driver.get_performance_data('my.app.package', 'cpuinfo', 5) == [['user', 'kernel'], ['2.5', '1.3']] d = get_httpretty_request_body(httpretty.last_request()) - assert d['packageName'] == 'my.app.package' - assert d['dataType'] == 'cpuinfo' - assert d['dataReadTimeout'] == 5 + assert d['args'][0]['packageName'] == 'my.app.package' + assert d['args'][0]['dataType'] == 'cpuinfo' @httpretty.activate def test_get_performance_data_types(self): @@ -41,4 +45,9 @@ def test_get_performance_data_types(self): appium_command('/session/1234567890/appium/performanceData/types'), body='{"value": ["cpuinfo", "memoryinfo", "batteryinfo", "networkinfo"]}', ) + httpretty.register_uri( + httpretty.POST, + appium_command('/session/1234567890/execute/sync'), + body='{"value": ["cpuinfo", "memoryinfo", "batteryinfo", "networkinfo"]}', + ) assert driver.get_performance_data_types() == ['cpuinfo', 'memoryinfo', 'batteryinfo', 'networkinfo']