diff --git a/Rakefile b/Rakefile index 40d23a45..1e508160 100644 --- a/Rakefile +++ b/Rakefile @@ -113,28 +113,7 @@ end desc('Execute RuboCop static code analysis') RuboCop::RakeTask.new(:rubocop) do |t| - t.patterns = %w(lib test script) + t.patterns = %w(lib test) t.options = %w(-D) t.fail_on_error = true end - -desc('print commands which Ruby client has not implemented them yet') -namespace :commands do - require './script/commands' - - desc('Mobile JSON protocol') - task :mjsonwp do |_t, _args| - c = Script::CommandsChecker.new - c.get_mjsonwp_routes - c.get_all_command_path './mjsonwp_routes.js' - c.all_diff_commands_mjsonwp.each { |key, value| puts("command: #{key}, method: #{value}") } - end - - desc('W3C protocol') - task :w3c do |_t, _args| - c = Script::CommandsChecker.new - c.get_mjsonwp_routes - c.get_all_command_path './mjsonwp_routes.js' - c.all_diff_commands_w3c.each { |key, value| puts("command: #{key}, method: #{value}") } - end -end diff --git a/script/commands.rb b/script/commands.rb deleted file mode 100644 index 2af8bebe..00000000 --- a/script/commands.rb +++ /dev/null @@ -1,166 +0,0 @@ -# frozen_string_literal: true - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# 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. - -require 'net/http' -require './lib/appium_lib_core' - -module Script - class CommandsChecker - attr_reader :spec_commands, - :implemented_w3c_commands, :implemented_core_commands, - :webdriver_w3c_commands - - # Set commands implemented in this core library. - # - # - implemented_w3c_commands: All commands include ::Selenium::WebDriver::Remote::Bridge::COMMANDS - # - implemented_core_commands: All commands except for selenium-webdriver's commands - # - def initialize - @spec_commands = nil - - @implemented_core_commands = convert_driver_commands Appium::Core::Commands::COMMANDS - end - - # Get the bellow url's file. - # https://raw.githubusercontent.com/appium/appium-base-driver/master/lib/mjsonwp/routes.js?raw=1 - # - # @param [String] to_path: A file path to routes.js - # @return [String] The file path in which has saved `routes.js`. - # - def get_mjsonwp_routes(to_path = './mjsonwp_routes.js') - uri = URI 'https://raw.githubusercontent.com/appium/appium-base-driver/master/lib/protocol/routes.js?raw=1' - result = Net::HTTP.get uri - - File.delete to_path if File.exist? to_path - File.write to_path, result - to_path - end - - # @private - HTTP_METHOD_MATCH = /GET:|POST:|DELETE:|PUT:|PATCH:/.freeze - # @private - WD_HUB_PREFIX_MATCH = "'/wd/hub/" - - # Read routes.js and set the values in @spec_commands - # - # @param [String] path: A file path to routes.js - # @return [Hash] @spec_commands - # - def get_all_command_path(path = './mjsonwp_routes.js') - raise "No file in #{path}" unless File.exist? path - - current_command = '' - @spec_commands = File.read(path).lines.each_with_object({}) do |line, memo| - if line =~ /#{WD_HUB_PREFIX_MATCH}.+'/ - current_command = gsub_set(line.slice(/#{WD_HUB_PREFIX_MATCH}.+'/)) - memo[current_command] = [] - elsif line =~ HTTP_METHOD_MATCH - memo[current_command] << line.slice(HTTP_METHOD_MATCH).chop.downcase.to_sym - end - memo - end - end - - # All commands which haven't been implemented in ruby core library yet. - # @return [Hash] - # - def all_diff_commands_w3c - result = compare_commands(@spec_commands, @implemented_w3c_commands) - white_list.each { |v| result.delete v } - mjsonwp_spec.each { |v| result.delete v } - result - end - - # Commands, only this core library, which haven't been implemented in ruby core library yet. - # @return [Hash] - # - def diff_except_for_webdriver - result = compare_commands(@spec_commands, @implemented_core_commands) - white_list.each { |v| result.delete v } - result - end - - def compare_commands(command1, with_command2) - return {} if command1.nil? - return command1 if with_command2.nil? - - result = {} - command1.each_key do |key| - if with_command2.key? key - diff = command1[key] - with_command2[key] - result[key] = diff unless diff.empty? - else - result[key] = command1[key] - end - end - result - end - - private - - # rubocop:disable Lint/PercentStringArray - def white_list - %w( - '/wd/hub/session' - '/wd/hub/sessions' - ).map { |v| gsub_set(v) } - end - - # https://raw.githubusercontent.com/appium/appium-base-driver/master/lib/mjsonwp/routes.js - def mjsonwp_spec - %w( - '/wd/hub/session/:sessionId/alert_text' - '/wd/hub/session/:sessionId/accept_alert' - '/wd/hub/session/:sessionId/dismiss_alert' - ).map { |v| gsub_set(v) } - end - - def w3c_spec - %w( - '/wd/hub/session/:sessionId/alert/text' - '/wd/hub/session/:sessionId/alert/accept' - '/wd/hub/session/:sessionId/alert/dismiss' - '/wd/hub/session/:sessionId/element/:elementId/rect' - ).map { |v| gsub_set(v) } - end - # rubocop:enable Lint/PercentStringArray - - def gsub_set(line) - return nil if line.gsub(/(\A#{WD_HUB_PREFIX_MATCH}|'\z)/, '').nil? - - line.gsub(/(\A#{WD_HUB_PREFIX_MATCH}|'\z)/, '') - .sub(':sessionId', ':session_id') - .sub('element/:elementId', 'element/:id') - .sub(':windowhandle', ':window_handle') - .sub('equals/:otherId', 'equals/:other') - .sub('css/:propertyName', 'css/:property_name') - .sub('element/:id/pageIndex', 'element/:id/page_index') - end - - def convert_driver_commands(from) - from.each_with_object({}) do |command, memo| - method = command[1][0] - key = command[1][1] - - if memo[key] - memo[key] << method - else - memo[key] = [method] - end - - memo - end - end - end -end diff --git a/test/unit/script/commands_test.rb b/test/unit/script/commands_test.rb deleted file mode 100644 index 71218d73..00000000 --- a/test/unit/script/commands_test.rb +++ /dev/null @@ -1,62 +0,0 @@ -# frozen_string_literal: true - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# 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. - -require 'test_helper' -require './script/commands' - -class ScriptTest - class CommandsCheckerTest < Minitest::Test - def setup - @c = Script::CommandsChecker.new - end - - def test_get_all_command_path - @c.get_all_command_path AppiumLibCoreTest.path_of('test/unit/script/test_routes.js') - assert_equal 143, @c.spec_commands.length - assert_equal ['status', [:get]], @c.spec_commands.first - assert_equal %i(get post delete), @c.spec_commands['session/:session_id/cookie'] - - assert_equal [:get], @c.spec_commands['session/:session_id/element/:id'] - assert_equal %i(get post), @c.spec_commands['session/:session_id/window/:window_handle/size'] - assert_equal [:get], @c.spec_commands['session/:session_id/element/:id/equals/:other'] - assert_equal [:get], @c.spec_commands['session/:session_id/element/:id/css/:property_name'] - assert_equal [:get], @c.spec_commands['session/:session_id/element/:id/page_index'] - end - - def test_implemented_core_commands - assert_equal ['status', [:get]], @c.implemented_core_commands.first - - # pick up an arbitrary command - assert_equal [:post], @c.implemented_core_commands['session/:session_id/appium/device/pull_folder'] - end - - def test_compare_commands_command1_is_bigger - command1 = { 'session/:session_id/contexts' => [:get] } - command2 = { 'session/:session_id/contexts' => %i(get post) } - - assert_equal({}, @c.compare_commands(command1, command2)) - end - - def test_compare_commands_command2_lack_some_commands - command1 = { 'session/:session_id/contexts' => %i(get post) } - command2 = { 'session/:session_id/contexts' => [:get] } - - assert_equal({ 'session/:session_id/contexts' => [:post] }, @c.compare_commands(command1, command2)) - end - - def test_can_call_diff_methods - assert_equal({}, @c.diff_except_for_webdriver) - end - end -end diff --git a/test/unit/script/test_routes.js b/test/unit/script/test_routes.js deleted file mode 100644 index ca538be0..00000000 --- a/test/unit/script/test_routes.js +++ /dev/null @@ -1,556 +0,0 @@ -import _ from 'lodash'; - - -// define the routes, mapping of HTTP methods to particular driver commands, -// and any parameters that are expected in a request -// parameters can be `required` or `optional` -const METHOD_MAP = { - '/wd/hub/status': { - GET: {command: 'getStatus'} - }, - '/wd/hub/session': { - POST: {command: 'createSession', payloadParams: { - validate: (jsonObj) => (!jsonObj.capabilities && !jsonObj.desiredCapabilities) && 'we require one of "desiredCapabilities" or "capabilities" object', - optional: ['desiredCapabilities', 'requiredCapabilities', 'capabilities']}} - }, - '/wd/hub/sessions': { - GET: {command: 'getSessions'} -}, -'/wd/hub/session/:sessionId': { - GET: {command: 'getSession'}, - DELETE: {command: 'deleteSession'} -}, -'/wd/hub/session/:sessionId/timeouts': { - POST: {command: 'timeouts', payloadParams: {required: ['type', 'ms']}} -}, -'/wd/hub/session/:sessionId/timeouts/async_script': { - POST: {command: 'asyncScriptTimeout', payloadParams: {required: ['ms']}} -}, -'/wd/hub/session/:sessionId/timeouts/implicit_wait': { - POST: {command: 'implicitWait', payloadParams: {required: ['ms']}} -}, -'/wd/hub/session/:sessionId/window_handle': { - GET: {command: 'getWindowHandle'} -}, -'/wd/hub/session/:sessionId/window_handles': { - GET: {command: 'getWindowHandles'} -}, -'/wd/hub/session/:sessionId/url': { - GET: {command: 'getUrl'}, - POST: {command: 'setUrl', payloadParams: {required: ['url']}} -}, -'/wd/hub/session/:sessionId/forward': { - POST: {command: 'forward'} -}, -'/wd/hub/session/:sessionId/back': { - POST: {command: 'back'} -}, -'/wd/hub/session/:sessionId/refresh': { - POST: {command: 'refresh'} -}, -'/wd/hub/session/:sessionId/execute': { - POST: {command: 'execute', payloadParams: {required: ['script', 'args']}} -}, -'/wd/hub/session/:sessionId/execute_async': { - POST: {command: 'executeAsync', payloadParams: {required: ['script', 'args']}} -}, -'/wd/hub/session/:sessionId/screenshot': { - GET: {command: 'getScreenshot'} -}, -'/wd/hub/session/:sessionId/ime/available_engines': { - GET: {command: 'availableIMEEngines'} -}, -'/wd/hub/session/:sessionId/ime/active_engine': { - GET: {command: 'getActiveIMEEngine'} -}, -'/wd/hub/session/:sessionId/ime/activated': { - GET: {command: 'isIMEActivated'} -}, -'/wd/hub/session/:sessionId/ime/deactivate': { - POST: {command: 'deactivateIMEEngine'} -}, -'/wd/hub/session/:sessionId/ime/activate': { - POST: {command: 'activateIMEEngine', payloadParams: {required: ['engine']}} -}, -'/wd/hub/session/:sessionId/frame': { - POST: {command: 'setFrame', payloadParams: {required: ['id']}} -}, -'/wd/hub/session/:sessionId/frame/parent': { - POST: {} -}, -'/wd/hub/session/:sessionId/window': { - POST: {command: 'setWindow', payloadParams: {required: ['name']}}, - DELETE: {command: 'closeWindow'} -}, -'/wd/hub/session/:sessionId/window/:windowhandle/size': { - GET: {command: 'getWindowSize'}, - POST: {} -}, -'/wd/hub/session/:sessionId/window/:windowhandle/position': { - POST: {}, - GET: {} -}, -'/wd/hub/session/:sessionId/window/:windowhandle/maximize': { - POST: {command: 'maximizeWindow'} -}, -'/wd/hub/session/:sessionId/cookie': { - GET: {command: 'getCookies'}, - POST: {command: 'setCookie', payloadParams: {required: ['cookie']}}, - DELETE: {command: 'deleteCookies'} -}, -'/wd/hub/session/:sessionId/cookie/:name': { - DELETE: {command: 'deleteCookie'} -}, -'/wd/hub/session/:sessionId/source': { - GET: {command: 'getPageSource'} -}, -'/wd/hub/session/:sessionId/title': { - GET: {command: 'title'} -}, -'/wd/hub/session/:sessionId/element': { - POST: {command: 'findElement', payloadParams: {required: ['using', 'value']}} -}, -'/wd/hub/session/:sessionId/elements': { - POST: {command: 'findElements', payloadParams: {required: ['using', 'value']}} -}, -'/wd/hub/session/:sessionId/element/active': { - POST: {command: 'active'} -}, -'/wd/hub/session/:sessionId/element/:elementId': { - GET: {} -}, -'/wd/hub/session/:sessionId/element/:elementId/element': { - POST: {command: 'findElementFromElement', payloadParams: {required: ['using', 'value']}} -}, -'/wd/hub/session/:sessionId/element/:elementId/elements': { - POST: {command: 'findElementsFromElement', payloadParams: {required: ['using', 'value']}} -}, -'/wd/hub/session/:sessionId/element/:elementId/click': { - POST: {command: 'click'} -}, -'/wd/hub/session/:sessionId/element/:elementId/submit': { - POST: {command: 'submit'} -}, -'/wd/hub/session/:sessionId/element/:elementId/text': { - GET: {command: 'getText'} -}, -'/wd/hub/session/:sessionId/element/:elementId/value': { - POST: {command: 'setValue', payloadParams: { - validate: (jsonObj) => { - return (!jsonObj.value && !jsonObj.text) && - 'we require one of "text" or "value" params'; - }, - optional: ['value', 'text'], - makeArgs: (jsonObj) => { - // override the default argument constructor because of the special - // logic here. Basically we want to accept either a value (old JSONWP) - // or a text (new W3C) parameter, but only send one of them to the - // command (not both). Prefer 'value' since it's more - // backward-compatible. - return [jsonObj.value || jsonObj.text]; - } - }} -}, -'/wd/hub/session/:sessionId/keys': { - POST: {command: 'keys', payloadParams: {required: ['value']}} -}, -'/wd/hub/session/:sessionId/element/:elementId/name': { - GET: {command: 'getName'} -}, -'/wd/hub/session/:sessionId/element/:elementId/clear': { - POST: {command: 'clear'} -}, -'/wd/hub/session/:sessionId/element/:elementId/selected': { - GET: {command: 'elementSelected'} -}, -'/wd/hub/session/:sessionId/element/:elementId/enabled': { - GET: {command: 'elementEnabled'} -}, -'/wd/hub/session/:sessionId/element/:elementId/attribute/:name': { - GET: {command: 'getAttribute'} -}, -'/wd/hub/session/:sessionId/element/:elementId/equals/:otherId': { - GET: {command: 'equalsElement'} -}, -'/wd/hub/session/:sessionId/element/:elementId/displayed': { - GET: {command: 'elementDisplayed'} -}, -'/wd/hub/session/:sessionId/element/:elementId/location': { - GET: {command: 'getLocation'} -}, -'/wd/hub/session/:sessionId/element/:elementId/location_in_view': { - GET: {command: 'getLocationInView'} -}, -'/wd/hub/session/:sessionId/element/:elementId/size': { - GET: {command: 'getSize'} -}, -'/wd/hub/session/:sessionId/element/:elementId/css/:propertyName': { - GET: {command: 'getCssProperty'} -}, -'/wd/hub/session/:sessionId/orientation': { - GET: {command: 'getOrientation'}, - POST: {command: 'setOrientation', payloadParams: {required: ['orientation']}} -}, -'/wd/hub/session/:sessionId/rotation': { - GET: {command: 'getRotation'}, - POST: {command: 'setRotation', payloadParams: {required: ['x', 'y', 'z']}} -}, -'/wd/hub/session/:sessionId/moveto': { - POST: {command: 'moveTo', payloadParams: {optional: ['element', 'xoffset', 'yoffset']}} -}, -'/wd/hub/session/:sessionId/click': { - POST: {command: 'clickCurrent', payloadParams: {optional: ['button']}} -}, -'/wd/hub/session/:sessionId/buttondown': { - POST: {} -}, -'/wd/hub/session/:sessionId/buttonup': { - POST: {} -}, -'/wd/hub/session/:sessionId/doubleclick': { - POST: {} -}, -'/wd/hub/session/:sessionId/touch/click': { - POST: {command: 'click', payloadParams: {required: ['element']}} -}, -'/wd/hub/session/:sessionId/touch/down': { - POST: {command: 'touchDown', payloadParams: {required: ['x', 'y']}} -}, -'/wd/hub/session/:sessionId/touch/up': { - POST: {command: 'touchUp', payloadParams: {required: ['x', 'y']}} -}, -'/wd/hub/session/:sessionId/touch/move': { - POST: {command: 'touchMove', payloadParams: {required: ['x', 'y']}} -}, -'/wd/hub/session/:sessionId/touch/scroll': { - POST: {} -}, -'/wd/hub/session/:sessionId/touch/doubleclick': { - POST: {} -}, -'/wd/hub/session/:sessionId/touch/longclick': { - POST: {command: 'touchLongClick', payloadParams: {required: ['elements']}} -}, -'/wd/hub/session/:sessionId/touch/flick': { - POST: {command: 'flick', payloadParams: {optional: ['element', 'xspeed', 'yspeed', 'xoffset', 'yoffset', 'speed']}} -}, -'/wd/hub/session/:sessionId/location': { - GET: {command: 'getGeoLocation'}, - POST: {command: 'setGeoLocation', payloadParams: {required: ['location']}} -}, -'/wd/hub/session/:sessionId/local_storage': { - GET: {}, - POST: {}, - DELETE: {} -}, -'/wd/hub/session/:sessionId/local_storage/key/:key': { - GET: {}, - DELETE: {} -}, -'/wd/hub/session/:sessionId/local_storage/size': { - GET: {} -}, -'/wd/hub/session/:sessionId/session_storage': { - GET: {}, - POST: {}, - DELETE: {} -}, -'/wd/hub/session/:sessionId/session_storage/key/:key': { - GET: {}, - DELETE: {} -}, -'/wd/hub/session/:sessionId/session_storage/size': { - GET: {} -}, -'/wd/hub/session/:sessionId/log': { - POST: {command: 'getLog', payloadParams: {required: ['type']}} -}, -'/wd/hub/session/:sessionId/log/types': { - GET: {command: 'getLogTypes'} -}, -'/wd/hub/session/:sessionId/application_cache/status': { - GET: {} -}, - -// -// mjsonwire -// -'/wd/hub/session/:sessionId/context': { - GET: {command: 'getCurrentContext'}, - POST: {command: 'setContext', payloadParams: {required: ['name']}} -}, -'/wd/hub/session/:sessionId/contexts': { - GET: {command: 'getContexts'} -}, -'/wd/hub/session/:sessionId/element/:elementId/pageIndex': { - GET: {command: 'getPageIndex'} -}, -'/wd/hub/session/:sessionId/network_connection': { - GET: {command: 'getNetworkConnection'}, - POST: {command: 'setNetworkConnection', payloadParams: {unwrap: 'parameters', required: ['type']}} -}, -'/wd/hub/session/:sessionId/touch/perform': { - POST: {command: 'performTouch', payloadParams: {wrap: 'actions', required: ['actions']}} -}, -'/wd/hub/session/:sessionId/touch/multi/perform': { - POST: {command: 'performMultiAction', payloadParams: {required: ['actions'], optional: ['elementId']}} -}, -'/wd/hub/session/:sessionId/receive_async_response': { - POST: {command: 'receiveAsyncResponse', payloadParams: {required: ['status', 'value']}} -}, -'/wd/hub/session/:sessionId/appium/device/shake': { - POST: {command: 'mobileShake'} -}, -'/wd/hub/session/:sessionId/appium/device/system_time': { - GET: {command: 'getDeviceTime'} -}, -'/wd/hub/session/:sessionId/appium/device/lock': { - POST: {command: 'lock', payloadParams: {optional: ['seconds']}} -}, -'/wd/hub/session/:sessionId/appium/device/unlock': { - POST: {command: 'unlock'} -}, -'/wd/hub/session/:sessionId/appium/device/is_locked': { - POST: {command: 'isLocked'} -}, -'/wd/hub/session/:sessionId/appium/start_recording_screen': { - POST: {command: 'startRecordingScreen', payloadParams: {required: ['filePath', 'videoSize', 'timeLimit', 'bitRate']}} -}, -'/wd/hub/session/:sessionId/appium/stop_recording_screen': { - POST: {command: 'stopRecordingScreen'} -}, -'/wd/hub/session/:sessionId/appium/performanceData/types': { - POST: {command: 'getPerformanceDataTypes'} -}, -'/wd/hub/session/:sessionId/appium/getPerformanceData': { - POST: {command: 'getPerformanceData', payloadParams: {required: ['packageName', 'dataType'], optional: ['dataReadTimeout']}} -}, -'/wd/hub/session/:sessionId/appium/device/press_keycode': { - POST: {command: 'pressKeyCode', payloadParams: {required: ['keycode'], optional: ['metastate']}} -}, -'/wd/hub/session/:sessionId/appium/device/long_press_keycode': { - POST: {command: 'longPressKeyCode', payloadParams: {required: ['keycode'], optional: ['metastate']}} -}, -'/wd/hub/session/:sessionId/appium/device/finger_print': { - POST: {command: 'fingerprint', payloadParams: {required: ['fingerprintId']}} -}, -'/wd/hub/session/:sessionId/appium/device/send_sms': { - POST: {command: 'sendSMS', payloadParams: {required: ['phoneNumber', 'message']}} -}, -'/wd/hub/session/:sessionId/appium/device/gsm_call': { - POST: {command: 'gsmCall', payloadParams: {required: ['phoneNumber', 'action']}} -}, -'/wd/hub/session/:sessionId/appium/device/gsm_signal': { - POST: {command: 'gsmSignal', payloadParams: {required: ['signalStrength']}} -}, -'/wd/hub/session/:sessionId/appium/device/gsm_voice': { - POST: {command: 'gsmVoice', payloadParams: {required: ['state']}} -}, -'/wd/hub/session/:sessionId/appium/device/power_capacity': { - POST: {command: 'powerCapacity', payloadParams: {required: ['percent']}} -}, -'/wd/hub/session/:sessionId/appium/device/power_ac': { - POST: {command: 'powerAC', payloadParams: {required: ['state']}} -}, -'/wd/hub/session/:sessionId/appium/device/network_speed': { - POST: {command: 'networkSpeed', payloadParams: {required: ['netspeed']}} -}, -'/wd/hub/session/:sessionId/appium/device/keyevent': { - POST: {command: 'keyevent', payloadParams: {required: ['keycode'], optional: ['metastate']}} -}, -'/wd/hub/session/:sessionId/appium/device/current_activity': { - GET: {command: 'getCurrentActivity'} -}, -'/wd/hub/session/:sessionId/appium/device/current_package': { - GET: {command: 'getCurrentPackage'} -}, -'/wd/hub/session/:sessionId/appium/device/install_app': { - POST: {command: 'installApp', payloadParams: {required: ['appPath']}} -}, -'/wd/hub/session/:sessionId/appium/device/remove_app': { - POST: {command: 'removeApp', payloadParams: {required: [['appId'], ['bundleId']]}} -}, -'/wd/hub/session/:sessionId/appium/device/app_installed': { - POST: {command: 'isAppInstalled', payloadParams: {required: ['bundleId']}} -}, -'/wd/hub/session/:sessionId/appium/device/hide_keyboard': { - POST: {command: 'hideKeyboard', payloadParams: {optional: ['strategy', 'key', 'keyCode', 'keyName']}} -}, -'/wd/hub/session/:sessionId/appium/device/is_keyboard_shown': { - GET: {command: 'isKeyboardShown'} -}, -'/wd/hub/session/:sessionId/appium/device/push_file': { - POST: {command: 'pushFile', payloadParams: {required: ['path', 'data']}} -}, -'/wd/hub/session/:sessionId/appium/device/pull_file': { - POST: {command: 'pullFile', payloadParams: {required: ['path']}} -}, -'/wd/hub/session/:sessionId/appium/device/pull_folder': { - POST: {command: 'pullFolder', payloadParams: {required: ['path']}} -}, -'/wd/hub/session/:sessionId/appium/device/toggle_airplane_mode': { - POST: {command: 'toggleFlightMode'} -}, -'/wd/hub/session/:sessionId/appium/device/toggle_data': { - POST: {command: 'toggleData'} -}, -'/wd/hub/session/:sessionId/appium/device/toggle_wifi': { - POST: {command: 'toggleWiFi'} -}, -'/wd/hub/session/:sessionId/appium/device/toggle_location_services': { - POST: {command: 'toggleLocationServices'} -}, -'/wd/hub/session/:sessionId/appium/device/open_notifications': { - POST: {command: 'openNotifications'} -}, -'/wd/hub/session/:sessionId/appium/device/start_activity': { - POST: {command: 'startActivity', payloadParams: {required: ['appPackage', 'appActivity'], - optional: ['appWaitPackage', 'appWaitActivity', - 'intentAction', 'intentCategory', - 'intentFlags', 'optionalIntentArguments', - 'dontStopAppOnReset']}} -}, -'/wd/hub/session/:sessionId/appium/device/system_bars': { - GET: {command: 'getSystemBars'} -}, -'/wd/hub/session/:sessionId/appium/device/display_density': { - GET: {command: 'getDisplayDensity'} -}, -'/wd/hub/session/:sessionId/appium/simulator/touch_id': { - POST: {command: 'touchId', payloadParams: {required: ['match']}} -}, -'/wd/hub/session/:sessionId/appium/simulator/toggle_touch_id_enrollment': { - POST: {command: 'toggleEnrollTouchId', payloadParams: {optional: ['enabled']}} -}, -'/wd/hub/session/:sessionId/appium/app/launch': { - POST: {command: 'launchApp'} -}, -'/wd/hub/session/:sessionId/appium/app/close': { - POST: {command: 'closeApp'} -}, -'/wd/hub/session/:sessionId/appium/app/reset': { - POST: {command: 'reset'} -}, -'/wd/hub/session/:sessionId/appium/app/background': { - POST: {command: 'background', payloadParams: {required: ['seconds']}} -}, -'/wd/hub/session/:sessionId/appium/app/end_test_coverage': { - POST: {command: 'endCoverage', payloadParams: {required: ['intent', 'path']}} -}, -'/wd/hub/session/:sessionId/appium/app/strings': { - POST: {command: 'getStrings', payloadParams: {optional: ['language', 'stringFile']}} -}, -'/wd/hub/session/:sessionId/appium/element/:elementId/value': { - POST: {command: 'setValueImmediate', payloadParams: {required: ['value']}} -}, -'/wd/hub/session/:sessionId/appium/element/:elementId/replace_value': { - POST: {command: 'replaceValue', payloadParams: {required: ['value']}} -}, -'/wd/hub/session/:sessionId/appium/settings': { - POST: {command: 'updateSettings', payloadParams: {required: ['settings']}}, - GET: {command: 'getSettings'} -}, -'/wd/hub/session/:sessionId/appium/receive_async_response': { - POST: {command: 'receiveAsyncResponse', payloadParams: {required: ['response']}} -}, - - -/* - * The W3C spec has some changes to the wire protocol. - * https://w3c.github.io/webdriver/webdriver-spec.html - * Begin to add those changes here, keeping the old version - * since clients still implement them. - */ -// old alerts -'/wd/hub/session/:sessionId/alert_text': { - GET: {command: 'getAlertText'}, - POST: {command: 'setAlertText', payloadParams: {required: ['text']}} -}, -'/wd/hub/session/:sessionId/accept_alert': { - POST: {command: 'postAcceptAlert'} -}, -'/wd/hub/session/:sessionId/dismiss_alert': { - POST: {command: 'postDismissAlert'} -}, -// https://w3c.github.io/webdriver/webdriver-spec.html#user-prompts -'/wd/hub/session/:sessionId/alert/text': { - GET: {command: 'getAlertText'}, - POST: {command: 'setAlertText', payloadParams: {required: ['text']}} -}, -'/wd/hub/session/:sessionId/alert/accept': { - POST: {command: 'postAcceptAlert'} -}, -'/wd/hub/session/:sessionId/alert/dismiss': { - POST: {command: 'postDismissAlert'} -}, -// https://w3c.github.io/webdriver/webdriver-spec.html#get-element-rect -'/wd/hub/session/:sessionId/element/:elementId/rect': { - GET: {command: 'getElementRect'} -}, -}; - -// driver command names -let ALL_COMMANDS = []; -for (let v of _.values(METHOD_MAP)) { - for (let m of _.values(v)) { - if (m.command) { - ALL_COMMANDS.push(m.command); - } - } -} - -const RE_ESCAPE = /[\-\[\]{}()+?.,\\\^$|#\s]/g; -const RE_PARAM = /([:*])(\w+)/g; - -class Route { - constructor (route) { - this.paramNames = []; - - let reStr = route.replace(RE_ESCAPE, "\\$&"); - reStr = reStr.replace(RE_PARAM, (_, mode, name) => { - this.paramNames.push(name); - return mode === ":" ? "([^/]*)" : "(.*)"; - }); - this.routeRegexp = new RegExp(`^${reStr}$`); - } - - parse (url) { - let matches = url.match(this.routeRegexp); - if (!matches) return; // eslint-disable-line curly - let i = 0; - let params = {}; - while (i < this.paramNames.length) { - const paramName = this.paramNames[i++]; - params[paramName] = matches[i]; - } - return params; - } -} - -function routeToCommandName (endpoint, method) { - let dstRoute = null; - const actualEndpoint = _.startsWith(endpoint, '/') ? endpoint : `/${endpoint}`; - for (let currentRoute of _.keys(METHOD_MAP)) { - const route = new Route(currentRoute); - // we don't care about the actual session id for matching - if (route.parse(`/wd/hub/session/ignored-session-id${actualEndpoint}`) || - route.parse(`/wd/hub${actualEndpoint}`) || route.parse(actualEndpoint)) { - dstRoute = currentRoute; - break; - } - } - if (!dstRoute) return; // eslint-disable-line curly - - const methods = _.get(METHOD_MAP, dstRoute); - if (_.has(methods, method)) { - const dstMethod = _.get(methods, method); - if (dstMethod.command) { - return dstMethod.command; - } - } -} - -// driver commands that do not require a session to already exist -const NO_SESSION_ID_COMMANDS = ['createSession', 'getStatus', 'getSessions']; - -export { METHOD_MAP, ALL_COMMANDS, NO_SESSION_ID_COMMANDS, routeToCommandName };