diff --git a/appium/webdriver/mobilecommand.py b/appium/webdriver/mobilecommand.py index b4065be0..824fe1cb 100644 --- a/appium/webdriver/mobilecommand.py +++ b/appium/webdriver/mobilecommand.py @@ -63,3 +63,5 @@ class MobileCommand(object): SET_LOCATION = 'setLocation' GET_DEVICE_TIME = 'getDeviceTime' CLEAR = 'clear' + START_RECORDING_SCREEN = 'startRecordingScreen' + STOP_RECORDING_SCREEN = 'stopRecordingScreen' diff --git a/appium/webdriver/webdriver.py b/appium/webdriver/webdriver.py index 41af0c3f..fbd5432c 100644 --- a/appium/webdriver/webdriver.py +++ b/appium/webdriver/webdriver.py @@ -24,7 +24,6 @@ from appium.webdriver.common.multi_action import MultiAction from selenium.webdriver.common.by import By -from selenium.webdriver.remote.webelement import WebElement from selenium.webdriver.support.ui import WebDriverWait from selenium.common.exceptions import TimeoutException @@ -809,6 +808,87 @@ def set_location(self, latitude, longitude, altitude): self.execute(Command.SET_LOCATION, data) return self + def start_recording_screen(self, **options): + """ + Start asynchronous screen recording process. + + :param options: The following options are supported: + - remotePath: The remotePath upload option is the path to the remote location, + where the resulting video from the previous screen recording should be uploaded. + The following protocols are supported: http/https (multipart), ftp. + Missing value (the default setting) means the content of the resulting + file should be encoded as Base64 and passed as the endpoint response value, but + an exception will be thrown if the generated media file is too big to + fit into the available process memory. + This option only has an effect if there is/was an active screen recording session + and forced restart is not enabled (the default setting). + - user: The name of the user for the remote authentication. + Only has an effect if both `remotePath` and `password` are set. + - password: The password for the remote authentication. + Only has an effect if both `remotePath` and `user` are set. + - method: The HTTP method name ('PUT'/'POST'). PUT method is used by default. + Only has an effect if `remotePath` is set. + - timeLimit: The actual time limit of the recorded video in seconds. + The default value for both iOS and Android is 180 seconds (3 minutes). + The maximum value for Android is 3 minutes. + The maximum value for iOS is 10 minutes. + - forcedRestart: Whether to ignore the result of previous capture and start a new recording + immediately (`True` value). By default (`False`) the endpoint will try to catch and return the result of + the previous capture if it's still available. + + iOS Specific: + - videoQuality: The video encoding quality: 'low', 'medium', 'high', 'photo'. Defaults to 'medium'. + Only works for real devices. + - videoType: The format of the screen capture to be recorded. + Available formats: 'h264', 'mp4' or 'fmp4'. Default is 'mp4'. + Only works for Simulator. + + Android Specific: + - videoSize: The video size of the generated media file. The format is WIDTHxHEIGHT. + The default value is the device's native display resolution (if supported), + 1280x720 if not. For best results, use a size supported by your device's + Advanced Video Coding (AVC) encoder. + - bitRate: The video bit rate for the video, in megabits per second. + The default value is 4. You can increase the bit rate to improve video quality, + but doing so results in larger movie files. + + :return: Base-64 encoded content of the recorded media file or an empty string + if the file has been successfully uploaded to a remote location + (depends on the actual `remotePath` value). + """ + if 'password' in options: + options['pass'] = options['password'] + del options['password'] + return self.execute(Command.START_RECORDING_SCREEN, options)['value'] + + def stop_recording_screen(self, **options): + """ + Gather the output from the previously started screen recording to a media file. + + :param options: The following options are supported: + - remotePath: The remotePath upload option is the path to the remote location, + where the resulting video should be uploaded. + The following protocols are supported: http/https (multipart), ftp. + Missing value (the default setting) means the content of the resulting + file should be encoded as Base64 and passed as the endpoint response value, but + an exception will be thrown if the generated media file is too big to + fit into the available process memory. + - user: The name of the user for the remote authentication. + Only has an effect if both `remotePath` and `password` are set. + - password: The password for the remote authentication. + Only has an effect if both `remotePath` and `user` are set. + - method: The HTTP method name ('PUT'/'POST'). PUT method is used by default. + Only has an effect if `remotePath` is set. + + :return: Base-64 encoded content of the recorded media file or an empty string + if the file has been successfully uploaded to a remote location + (depends on the actual `remotePath` value). + """ + if 'password' in options: + options['pass'] = options['password'] + del options['password'] + return self.execute(Command.STOP_RECORDING_SCREEN, options)['value'] + @property def device_time(self): """Returns the date and time from the device @@ -911,3 +991,7 @@ def _addCommands(self): ('GET', '/session/$sessionId/appium/device/system_time') self.command_executor._commands[Command.CLEAR] = \ ('POST', '/session/$sessionId/element/$id/clear') + self.command_executor._commands[Command.START_RECORDING_SCREEN] = \ + ('POST', '/session/$sessionId/appium/start_recording_screen') + self.command_executor._commands[Command.STOP_RECORDING_SCREEN] = \ + ('POST', '/session/$sessionId/appium/stop_recording_screen') diff --git a/test/functional/android/appium_tests.py b/test/functional/android/appium_tests.py index e7227873..d358c43b 100644 --- a/test/functional/android/appium_tests.py +++ b/test/functional/android/appium_tests.py @@ -43,6 +43,12 @@ def tearDown(self): if hasattr(self, 'zipfilename') and os.path.isfile(self.zipfilename): os.remove(self.zipfilename) + def test_screen_record(self): + self.driver.start_recording_screen(timeLimit=10, forcedRestart=True) + sleep(5) + result = self.driver.stop_recording_screen() + self.assertTrue(len(result) > 0) + def test_lock(self): self.driver.lock(-1) try: diff --git a/test/functional/ios/appium_tests.py b/test/functional/ios/appium_tests.py index 73db5108..ebc6dcf0 100644 --- a/test/functional/ios/appium_tests.py +++ b/test/functional/ios/appium_tests.py @@ -15,8 +15,6 @@ import unittest from time import sleep -from selenium.common.exceptions import NoSuchElementException - from appium import webdriver import desired_capabilities @@ -37,6 +35,12 @@ def test_lock(self): self.driver.unlock() self.assertFalse(self.driver.is_locked()) + def test_screen_record(self): + self.driver.start_recording_screen() + sleep(5) + result = self.driver.stop_recording_screen() + self.assertTrue(len(result) > 0) + def test_shake(self): # what can we assert about this? self.driver.shake()