selenium简介
Selenium是一个用于Web应用程序自动化测试工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera等。
主要功能包括:测试与浏览器的兼容性——测试你的应用程序看是否能够很好得工作在不同浏览器和操作系统之上。
测试系统功能——创建回归测试检验软件功能和用户需求。支持自动录制动作和自动生成 .Net、Java、Perl等不同语言的测试脚本(这里主要是针对selenium ide)
selenium历程
04年,诞生了Selenium Core,Selenium Core是基于浏览器并且采用JavaScript编程语言的测试工具,运行在浏览器的安全沙箱中,设计理念是将待测试产品、Selenium Core和测试脚本均部署到同一台服务器上来完成自动化测试的工作。
05年,Selenium RC诞生,就是selenium1 ,这个时候,Selenium Core其实是Selenium RC的核心。
Selenium RC让待测试产品、Selenium Core和测试脚本三者分散在不同的服务器上。(测试脚本只关心将HTTP请求发送到指定的URL上,selenium本身不需要关心HTTP请求由于什么程序编程语言编写而成)
Selenium RC包括两部分:一个是Selenium RC Server,一个是提供各种编程语言的客户端驱动来编写测试脚本
07年,Webdriver诞生,WebDriver的设计理念是将端到端测试与底层具体的测试工具分隔离,并采用设计模式Adapter适配器来达到目标。WebDriver的API组织更多的是面向对象。
08/09年,selenium2诞生,selenium2其实是selenium rc和webdriver的合并,合并的根本原因是相互补充各自的缺点
09年,selenium3诞生,这个版本剔除了selenium rc , 主要由 selenium webdriver和selenium Grid组成, 我们日常使用的其实就是selenium webdriver,至于selenium grid是一个分布式实现自动化测试的工具
那么今天我们就要说说selenium3(selenium webdriver)的工作原理,下面简称selenium(以上具体时间可能不太准确,我也是通过网络资料了解到的,抛砖引玉^-^)
selenium原理
我们使用Selenium实现自动化测试,主要需要3个东西
1.测试脚本,可以是python,java编写的脚本程序(也可以叫做client端)
2.浏览器驱动, 这个驱动是根据不同的浏览器开发的,不同的浏览器使用不同的webdriver驱动程序且需要对应相应的浏览器版本,比如:geckodriver.exe(chrome)
3.浏览器,目前selenium支持市面上大多数浏览器,如:火狐,谷歌,IE等
selenium脚本
先看一个简单的代码
""" ------------------------------------ @Time : 2019/6/29 8:16 @Auth : linux超 @File : seleniumWebdriver.py @IDE : PyCharm @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! @QQ : 28174043@qq.com @GROUP: 878565760 ------------------------------------ """ from selenium import webdriver dr = webdriver.Chrome() # 打开浏览器 |
执行上述代码,我们会发现程序打开了Chrome浏览器(前提:你已经正确配置了chrome的驱动和对应版本)
那么selenium是如何实现这个过程的呢?ok,我们今天就通过分析源码的方式来理解selenium的工作原理
源码分析
查看weddriver源码(按住Ctrl键,鼠标点击Chrome)
C:\Python36\Lib\site-packages\selenium\webdriver\chrome\webdriver.py
1 class WebDriver(RemoteWebDriver): 2 """ 3 Controls the ChromeDriver and allows you to drive the browser. 4 5 You will need to download the ChromeDriver executable from 6 http://chromedriver.storage.googleapis.com/index.html 7 """ 8 9 def __init__(self, executable_path="chromedriver", port=0, 10 options=None, service_args=None, 11 desired_capabilities=None, service_log_path=None, 12 chrome_options=None, keep_alive=True): 13 """ 14 Creates a new instance of the chrome driver. 15 16 Starts the service and then creates new instance of chrome driver. 17 18 :Args: 19 - executable_path - path to the executable. If the default is used it assumes the executable is in the $PATH 20 - port - port you would like the service to run, if left as 0, a free port will be found. 21 - options - this takes an instance of ChromeOptions 22 - service_args - List of args to pass to the driver service 23 - desired_capabilities - Dictionary object with non-browser specific 24 capabilities only, such as "proxy" or "loggingPref". 25 - service_log_path - Where to log information from the driver. 26 - chrome_options - Deprecated argument for options 27 - keep_alive - Whether to configure ChromeRemoteConnection to use HTTP keep-alive. 28 """ 29 if chrome_options: 30 warnings.warn('use options instead of chrome_options', 31 DeprecationWarning, stacklevel=2) 32 options = chrome_options 33 34 if options is None: 35 # desired_capabilities stays as passed in 36 if desired_capabilities is None: 37 desired_capabilities = self.create_options().to_capabilities() 38 else: 39 if desired_capabilities is None: 40 desired_capabilities = options.to_capabilities() 41 else: 42 desired_capabilities.update(options.to_capabilities()) 43 44 self.service = Service( 45 executable_path, 46 port=port, 47 service_args=service_args, 48 log_path=service_log_path) 49 self.service.start() 50 51 try: 52 RemoteWebDriver.__init__( 53 self, 54 command_executor=ChromeRemoteConnection( 55 remote_server_addr=self.service.service_url, 56 keep_alive=keep_alive), 57 desired_capabilities=desired_capabilities) 58 except Exception: 59 self.quit() 60 raise 61 self._is_remote = False |
通过源码中的44-49行发现,初始化了一个service对象,然后调用了start()方法,那么我们继续看下一49行的start()方法到底实现了什么功能?
C:\Python36\Lib\site-packages\selenium\webdriver\common\service.py
1 def start(self): 2 """ 3 Starts the Service. 4 5 :Exceptions: 6 - WebDriverException : Raised either when it can't start the service 7 or when it can't connect to the service 8 """ 9 try: 10 cmd = [self.path] 11 cmd.extend(self.command_line_args()) 12 self.process = subprocess.Popen(cmd, env=self.env, 13 close_fds=platform.system() != 'Windows', 14 stdout=self.log_file, 15 stderr=self.log_file, 16 stdin=PIPE) 17 except TypeError: 18 raise 19 except OSError as err: 20 if err.errno == errno.ENOENT: 21 raise WebDriverException( 22 "'%s' executable needs to be in PATH. %s" % ( 23 os.path.basename(self.path), self.start_error_message) 24 ) 25 elif err.errno == errno.EACCES: 26 raise WebDriverException( 27 "'%s' executable may have wrong permissions. %s" % ( 28 os.path.basename(self.path), self.start_error_message) 29 ) 30 else: 31 raise 32 except Exception as e: 33 raise WebDriverException( 34 "The executable %s needs to be available in the path. %s\n%s" % 35 (os.path.basename(self.path), self.start_error_message, str(e))) 36 count = 0 37 while True: 38 self.assert_process_still_running() 39 if self.is_connectable(): 40 break 41 count += 1 42 time.sleep(1) 43 if count == 30: 44 raise WebDriverException("Can not connect to the Service %s" % self.path) |
我们发现9-16行其实就是执行了一个cmd命令,命令的作用就是启动了chromedriver.exeChrome浏览器的驱动程序
这里我们需要注意一点: 下载的浏览器驱动一定要配置到环境变量中,或者放到python的根目录下,便于程序在执行驱动的时候查找
这个过程和我们手动启动浏览器驱动是一样的效果,类似下面的结果
启动驱动程序后,绑定端口号9515,且只允许本地访问这个服务,其实我们可以查看一下我们本地电脑任务管理器,确实开启了一个服务进程程序
第一步工作我们已经知道了执行测试脚本webdriver.Chrome()会自动执行chromedriver.exe驱动程序,然后开启一个进程
如何打开浏览器
我们继续看源码 C:\Python36\Lib\site-packages\selenium\webdriver\chrome\webdriver.py 的51-57行代码,调用了父类RemoteWebDriver 的初始化方法,我们看这个方法做了什么事?
C:\Python36\Lib\site-packages\selenium\webdriver\remote\webdriver.py
1 class WebDriver(object): 2 """ 3 Controls a browser by sending commands to a remote server. 4 This server is expected to be running the WebDriver wire protocol 5 as defined at 6 https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol 7 8 :Attributes: 9 - session_id - String ID of the browser session started and controlled by this WebDriver. 10 - capabilities - Dictionaty of effective capabilities of this browser session as returned 11 by the remote server. See https://github.com/SeleniumHQ/selenium/wiki/DesiredCapabilities 12 - command_executor - remote_connection.RemoteConnection object used to execute commands. 13 - error_handler - errorhandler.ErrorHandler object used to handle errors. 14 """ 15 16 _web_element_cls = WebElement 17 18 def __init__(self, command_executor='http://127.0.0.1:4444/wd/hub', 19 desired_capabilities=None, browser_profile=None, proxy=None, 20 keep_alive=False, file_detector=None, options=None): 21 """ 22 Create a new driver that will issue commands using the wire protocol. 23 24 :Args: 25 - command_executor - Either a string representing URL of the remote server or a custom 26 remote_connection.RemoteConnection object. Defaults to 'http://127.0.0.1:4444/wd/hub'. 27 - desired_capabilities - A dictionary of capabilities to request when 28 starting the browser session. Required parameter. 29 - browser_profile - A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object. 30 Only used if Firefox is requested. Optional. 31 - proxy - A selenium.webdriver.common.proxy.Proxy object. The browser session will 32 be started with given proxy settings, if possible. Optional. 33 - keep_alive - Whether to configure remote_connection.RemoteConnection to use 34 HTTP keep-alive. Defaults to False. 35 - file_detector - Pass custom file detector object during instantiation. If None, 36 then default LocalFileDetector() will be used. 37 - options - instance of a driver options.Options class 38 """ 39 capabilities = {} 40 if options is not None: 41 capabilities = options.to_capabilities() 42 if desired_capabilities is not None: 43 if not isinstance(desired_capabilities, dict): 44 raise WebDriverException("Desired Capabilities must be a dictionary") 45 else: 46 capabilities.update(desired_capabilities) 47 if proxy is not None: 48 warnings.warn("Please use FirefoxOptions to set proxy", 49 DeprecationWarning, stacklevel=2) 50 proxy.add_to_capabilities(capabilities) 51 self.command_executor = command_executor 52 if type(self.command_executor) is bytes or isinstance(self.command_executor, str): 53 self.command_executor = RemoteConnection(command_executor, keep_alive=keep_alive) 54 self._is_remote = True 55 self.session_id = None 56 self.capabilities = {} 57 self.error_handler = ErrorHandler() 58 self.start_client() 59 if browser_profile is not None: 60 warnings.warn("Please use FirefoxOptions to set browser profile", 61 DeprecationWarning, stacklevel=2) 62 self.start_session(capabilities, browser_profile) 63 self._switch_to = SwitchTo(self) 64 self._mobile = Mobile(self) 65 self.file_detector = file_detector or LocalFileDetector() |
这里有一行最重要的代码,62行self.start_session(capabilities, browser_profile) 这个方法,继续看一下这个方法的源码做了什么工作
1 def start_session(self, capabilities, browser_profile=None): 2 """ 3 Creates a new session with the desired capabilities. 4 5 :Args: 6 - browser_name - The name of the browser to request. 7 - version - Which browser version to request. 8 - platform - Which platform to request the browser on. 9 - javascript_enabled - Whether the new session should support JavaScript. 10 - browser_profile - A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object. Only used if Firefox is requested. 11 """ 12 if not isinstance(capabilities, dict): 13 raise InvalidArgumentException("Capabilities must be a dictionary") 14 if browser_profile: 15 if "moz:firefoxOptions" in capabilities: 16 capabilities["moz:firefoxOptions"]["profile"] = browser_profile.encoded 17 else: 18 capabilities.update({'firefox_profile': browser_profile.encoded}) 19 w3c_caps = _make_w3c_caps(capabilities) 20 parameters = {"capabilities": w3c_caps, 21 "desiredCapabilities": capabilities} 22 response = self.execute(Command.NEW_SESSION, parameters) 23 if 'sessionId' not in response: 24 response = response['value'] 25 self.session_id = response['sessionId'] 26 self.capabilities = response.get('value') 27 28 # if capabilities is none we are probably speaking to 29 # a W3C endpoint 30 if self.capabilities is None: 31 self.capabilities = response.get('capabilities') 32 33 # Double check to see if we have a W3C Compliant browser 34 self.w3c = response.get('status') is None 35 self.command_executor.w3c = self.w3c |
分析这部分源码可以发现22行是向地址localhost:9515/session发送了一个post请求,参数是json格式的,然后返回特定的响应信息给程序(这里主要就是新建了一个sessionid),最终打开了浏览器
ok,打开浏览器的操作完成了
如何执行对应操作
查看C:\Python36\Lib\site-packages\selenium\webdriver\chrome\webdriver.py源码(第一个源码中的51-57行)
51 try: 52 RemoteWebDriver.__init__( 53 self, 54 command_executor=ChromeRemoteConnection( 55 remote_server_addr=self.service.service_url, 56 keep_alive=keep_alive), 57 desired_capabilities=desired_capabilities) |
点击ChromeRemoteConnection查看一下源码
1 from selenium.webdriver.remote.remote_connection import RemoteConnection 2 3 4 class ChromeRemoteConnection(RemoteConnection): 5 6 def __init__(self, remote_server_addr, keep_alive=True): 7 RemoteConnection.__init__(self, remote_server_addr, keep_alive) 8 self._commands["launchApp"] = ('POST', '/session/$sessionId/chromium/launch_app') 9 self._commands["setNetworkConditions"] = ('POST', '/session/$sessionId/chromium/network_conditions') 10 self._commands["getNetworkConditions"] = ('GET', '/session/$sessionId/chromium/network_conditions') 11 self._commands['executeCdpCommand'] = ('POST', '/session/$sessionId/goog/cdp/execute') |
第7行访问的是localhost:9515/session地址,第8-11行,定义了一些和我们使用的浏览器(chrome)特有的接口地址,我们再看一下父类RemoteConnection里面源码
C:\Python36\Lib\site-packages\selenium\webdriver\remote\remote_connection.py:RemoteConnection
1 self._commands = { 2 Command.STATUS: ('GET', '/status'), 3 Command.NEW_SESSION: ('POST', '/session'), 4 Command.GET_ALL_SESSIONS: ('GET', '/sessions'), 5 Command.QUIT: ('DELETE', '/session/$sessionId'), 6 Command.GET_CURRENT_WINDOW_HANDLE: 7 ('GET', '/session/$sessionId/window_handle'), 8 Command.W3C_GET_CURRENT_WINDOW_HANDLE: 9 ('GET', '/session/$sessionId/window'), 10 Command.GET_WINDOW_HANDLES: 11 ('GET', '/session/$sessionId/window_handles'), 12 Command.W3C_GET_WINDOW_HANDLES: 13 ('GET', '/session/$sessionId/window/handles'), 14 Command.GET: ('POST', '/session/$sessionId/url'), 15 Command.GO_FORWARD: ('POST', '/session/$sessionId/forward'), 16 Command.GO_BACK: ('POST', '/session/$sessionId/back'), 17 Command.REFRESH: ('POST', '/session/$sessionId/refresh'), 18 Command.EXECUTE_SCRIPT: ('POST', '/session/$sessionId/execute'), 19 Command.W3C_EXECUTE_SCRIPT: 20 ('POST', '/session/$sessionId/execute/sync'), 21 Command.W3C_EXECUTE_SCRIPT_ASYNC: 22 ('POST', '/session/$sessionId/execute/async'), 23 Command.GET_CURRENT_URL: ('GET', '/session/$sessionId/url'), 24 Command.GET_TITLE: ('GET', '/session/$sessionId/title'), 25 Command.GET_PAGE_SOURCE: ('GET', '/session/$sessionId/source'), 26 Command.SCREENSHOT: ('GET', '/session/$sessionId/screenshot'), 27 Command.ELEMENT_SCREENSHOT: ('GET', '/session/$sessionId/element/$id/screenshot'), 28 Command.FIND_ELEMENT: ('POST', '/session/$sessionId/element'), 29 Command.FIND_ELEMENTS: ('POST', '/session/$sessionId/elements'), 30 Command.W3C_GET_ACTIVE_ELEMENT: ('GET', '/session/$sessionId/element/active'), 31 Command.GET_ACTIVE_ELEMENT: 32 ('POST', '/session/$sessionId/element/active'), 33 Command.FIND_CHILD_ELEMENT: 34 ('POST', '/session/$sessionId/element/$id/element'), 35 Command.FIND_CHILD_ELEMENTS: 36 ('POST', '/session/$sessionId/element/$id/elements'), 37 Command.CLICK_ELEMENT: ('POST', '/session/$sessionId/element/$id/click'), 38 Command.CLEAR_ELEMENT: ('POST', '/session/$sessionId/element/$id/clear'), 39 Command.SUBMIT_ELEMENT: ('POST', '/session/$sessionId/element/$id/submit'), 40 Command.GET_ELEMENT_TEXT: ('GET', '/session/$sessionId/element/$id/text'), 41 Command.SEND_KEYS_TO_ELEMENT: 42 ('POST', '/session/$sessionId/element/$id/value'), 43 Command.SEND_KEYS_TO_ACTIVE_ELEMENT: 44 ('POST', '/session/$sessionId/keys'), 45 Command.UPLOAD_FILE: ('POST', "/session/$sessionId/file"), 46 Command.GET_ELEMENT_VALUE: 47 ('GET', '/session/$sessionId/element/$id/value'), 48 Command.GET_ELEMENT_TAG_NAME: 49 ('GET', '/session/$sessionId/element/$id/name'), 50 Command.IS_ELEMENT_SELECTED: 51 ('GET', '/session/$sessionId/element/$id/selected'), 52 Command.SET_ELEMENT_SELECTED: 53 ('POST', '/session/$sessionId/element/$id/selected'), 54 Command.IS_ELEMENT_ENABLED: 55 ('GET', '/session/$sessionId/element/$id/enabled'), 56 Command.IS_ELEMENT_DISPLAYED: 57 ('GET', '/session/$sessionId/element/$id/displayed'), 58 Command.GET_ELEMENT_LOCATION: 59 ('GET', '/session/$sessionId/element/$id/location'), 60 Command.GET_ELEMENT_LOCATION_ONCE_SCROLLED_INTO_VIEW: 61 ('GET', '/session/$sessionId/element/$id/location_in_view'), 62 Command.GET_ELEMENT_SIZE: 63 ('GET', '/session/$sessionId/element/$id/size'), 64 Command.GET_ELEMENT_RECT: 65 ('GET', '/session/$sessionId/element/$id/rect'), 66 Command.GET_ELEMENT_ATTRIBUTE: 67 ('GET', '/session/$sessionId/element/$id/attribute/$name'), 68 Command.GET_ELEMENT_PROPERTY: 69 ('GET', '/session/$sessionId/element/$id/property/$name'), 70 Command.GET_ALL_COOKIES: ('GET', '/session/$sessionId/cookie'), 71 Command.ADD_COOKIE: ('POST', '/session/$sessionId/cookie'), 72 Command.GET_COOKIE: ('GET', '/session/$sessionId/cookie/$name'), 73 Command.DELETE_ALL_COOKIES: 74 ('DELETE', '/session/$sessionId/cookie'), 75 Command.DELETE_COOKIE: 76 ('DELETE', '/session/$sessionId/cookie/$name'), 77 Command.SWITCH_TO_FRAME: ('POST', '/session/$sessionId/frame'), 78 Command.SWITCH_TO_PARENT_FRAME: ('POST', '/session/$sessionId/frame/parent'), 79 Command.SWITCH_TO_WINDOW: ('POST', '/session/$sessionId/window'), 80 Command.CLOSE: ('DELETE', '/session/$sessionId/window'), 81 Command.GET_ELEMENT_VALUE_OF_CSS_PROPERTY: 82 ('GET', '/session/$sessionId/element/$id/css/$propertyName'), 83 Command.IMPLICIT_WAIT: 84 ('POST', '/session/$sessionId/timeouts/implicit_wait'), 85 Command.EXECUTE_ASYNC_SCRIPT: ('POST', '/session/$sessionId/execute_async'), 86 Command.SET_SCRIPT_TIMEOUT: 87 ('POST', '/session/$sessionId/timeouts/async_script'), 88 Command.SET_TIMEOUTS: 89 ('POST', '/session/$sessionId/timeouts'), 90 Command.DISMISS_ALERT: 91 ('POST', '/session/$sessionId/dismiss_alert'), 92 Command.W3C_DISMISS_ALERT: 93 ('POST', '/session/$sessionId/alert/dismiss'), 94 Command.ACCEPT_ALERT: 95 ('POST', '/session/$sessionId/accept_alert'), 96 Command.W3C_ACCEPT_ALERT: 97 ('POST', '/session/$sessionId/alert/accept'), 98 Command.SET_ALERT_VALUE: 99 ('POST', '/session/$sessionId/alert_text'), 100 Command.W3C_SET_ALERT_VALUE: 101 ('POST', '/session/$sessionId/alert/text'), 102 Command.GET_ALERT_TEXT: 103 ('GET', '/session/$sessionId/alert_text'), 104 Command.W3C_GET_ALERT_TEXT: 105 ('GET', '/session/$sessionId/alert/text'), 106 Command.SET_ALERT_CREDENTIALS: 107 ('POST', '/session/$sessionId/alert/credentials'), 108 Command.CLICK: 109 ('POST', '/session/$sessionId/click'), 110 Command.W3C_ACTIONS: 111 ('POST', '/session/$sessionId/actions'), 112 Command.W3C_CLEAR_ACTIONS: 113 ('DELETE', '/session/$sessionId/actions'), 114 Command.DOUBLE_CLICK: 115 ('POST', '/session/$sessionId/doubleclick'), 116 Command.MOUSE_DOWN: 117 ('POST', '/session/$sessionId/buttondown'), 118 Command.MOUSE_UP: 119 ('POST', '/session/$sessionId/buttonup'), 120 Command.MOVE_TO: 121 ('POST', '/session/$sessionId/moveto'), 122 Command.GET_WINDOW_SIZE: 123 ('GET', '/session/$sessionId/window/$windowHandle/size'), 124 Command.SET_WINDOW_SIZE: 125 ('POST', '/session/$sessionId/window/$windowHandle/size'), 126 Command.GET_WINDOW_POSITION: 127 ('GET', '/session/$sessionId/window/$windowHandle/position'), 128 Command.SET_WINDOW_POSITION: 129 ('POST', '/session/$sessionId/window/$windowHandle/position'), 130 Command.SET_WINDOW_RECT: 131 ('POST', '/session/$sessionId/window/rect'), 132 Command.GET_WINDOW_RECT: 133 ('GET', '/session/$sessionId/window/rect'), 134 Command.MAXIMIZE_WINDOW: 135 ('POST', '/session/$sessionId/window/$windowHandle/maximize'), 136 Command.W3C_MAXIMIZE_WINDOW: 137 ('POST', '/session/$sessionId/window/maximize'), 138 Command.SET_SCREEN_ORIENTATION: 139 ('POST', '/session/$sessionId/orientation'), 140 Command.GET_SCREEN_ORIENTATION: 141 ('GET', '/session/$sessionId/orientation'), 142 Command.SINGLE_TAP: 143 ('POST', '/session/$sessionId/touch/click'), 144 Command.TOUCH_DOWN: 145 ('POST', '/session/$sessionId/touch/down'), 146 Command.TOUCH_UP: 147 ('POST', '/session/$sessionId/touch/up'), 148 Command.TOUCH_MOVE: 149 ('POST', '/session/$sessionId/touch/move'), 150 Command.TOUCH_SCROLL: 151 ('POST', '/session/$sessionId/touch/scroll'), 152 Command.DOUBLE_TAP: 153 ('POST', '/session/$sessionId/touch/doubleclick'), 154 Command.LONG_PRESS: 155 ('POST', '/session/$sessionId/touch/longclick'), 156 Command.FLICK: 157 ('POST', '/session/$sessionId/touch/flick'), 158 Command.EXECUTE_SQL: 159 ('POST', '/session/$sessionId/execute_sql'), 160 Command.GET_LOCATION: 161 ('GET', '/session/$sessionId/location'), 162 Command.SET_LOCATION: 163 ('POST', '/session/$sessionId/location'), 164 Command.GET_APP_CACHE: 165 ('GET', '/session/$sessionId/application_cache'), 166 Command.GET_APP_CACHE_STATUS: 167 ('GET', '/session/$sessionId/application_cache/status'), 168 Command.CLEAR_APP_CACHE: 169 ('DELETE', '/session/$sessionId/application_cache/clear'), 170 Command.GET_NETWORK_CONNECTION: 171 ('GET', '/session/$sessionId/network_connection'), 172 Command.SET_NETWORK_CONNECTION: 173 ('POST', '/session/$sessionId/network_connection'), 174 Command.GET_LOCAL_STORAGE_ITEM: 175 ('GET', '/session/$sessionId/local_storage/key/$key'), 176 Command.REMOVE_LOCAL_STORAGE_ITEM: 177 ('DELETE', '/session/$sessionId/local_storage/key/$key'), 178 Command.GET_LOCAL_STORAGE_KEYS: 179 ('GET', '/session/$sessionId/local_storage'), 180 Command.SET_LOCAL_STORAGE_ITEM: 181 ('POST', '/session/$sessionId/local_storage'), 182 Command.CLEAR_LOCAL_STORAGE: 183 ('DELETE', '/session/$sessionId/local_storage'), 184 Command.GET_LOCAL_STORAGE_SIZE: 185 ('GET', '/session/$sessionId/local_storage/size'), 186 Command.GET_SESSION_STORAGE_ITEM: 187 ('GET', '/session/$sessionId/session_storage/key/$key'), 188 Command.REMOVE_SESSION_STORAGE_ITEM: 189 ('DELETE', '/session/$sessionId/session_storage/key/$key'), 190 Command.GET_SESSION_STORAGE_KEYS: 191 ('GET', '/session/$sessionId/session_storage'), 192 Command.SET_SESSION_STORAGE_ITEM: 193 ('POST', '/session/$sessionId/session_storage'), 194 Command.CLEAR_SESSION_STORAGE: 195 ('DELETE', '/session/$sessionId/session_storage'), 196 Command.GET_SESSION_STORAGE_SIZE: 197 ('GET', '/session/$sessionId/session_storage/size'), 198 Command.GET_LOG: 199 ('POST', '/session/$sessionId/log'), 200 Command.GET_AVAILABLE_LOG_TYPES: 201 ('GET', '/session/$sessionId/log/types'), 202 Command.CURRENT_CONTEXT_HANDLE: 203 ('GET', '/session/$sessionId/context'), 204 Command.CONTEXT_HANDLES: 205 ('GET', '/session/$sessionId/contexts'), 206 Command.SWITCH_TO_CONTEXT: 207 ('POST', '/session/$sessionId/context'), 208 Command.FULLSCREEN_WINDOW: 209 ('POST', '/session/$sessionId/window/fullscreen'), 210 Command.MINIMIZE_WINDOW: 211 ('POST', '/session/$sessionId/window/minimize') 212 } |
上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理