appium_lib_core 4.5.0 → 5.0.0.beta4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/unittest.yml +2 -2
  3. data/CHANGELOG.md +12 -5
  4. data/README.md +2 -1
  5. data/appium_lib_core.gemspec +4 -4
  6. data/lib/appium_lib_core.rb +2 -5
  7. data/lib/appium_lib_core/android/device/auth_finger_print.rb +2 -1
  8. data/lib/appium_lib_core/common/base.rb +0 -3
  9. data/lib/appium_lib_core/common/base/bridge.rb +284 -89
  10. data/lib/appium_lib_core/common/base/capabilities.rb +3 -3
  11. data/lib/appium_lib_core/common/base/{command.rb → device_ime.rb} +32 -7
  12. data/lib/appium_lib_core/common/base/driver.rb +128 -70
  13. data/lib/appium_lib_core/common/base/driver_settings.rb +51 -0
  14. data/lib/appium_lib_core/common/base/has_network_connection.rb +56 -0
  15. data/lib/appium_lib_core/common/base/rotable.rb +1 -1
  16. data/lib/appium_lib_core/common/base/search_context.rb +9 -4
  17. data/lib/appium_lib_core/common/command.rb +259 -4
  18. data/lib/appium_lib_core/common/device/keyevent.rb +4 -4
  19. data/lib/appium_lib_core/common/error.rb +4 -1
  20. data/lib/appium_lib_core/common/log.rb +4 -1
  21. data/lib/appium_lib_core/device.rb +1 -5
  22. data/lib/appium_lib_core/driver.rb +3 -4
  23. data/lib/appium_lib_core/{patch.rb → element.rb} +2 -7
  24. data/lib/appium_lib_core/ios/uiautomation/patch.rb +1 -1
  25. data/lib/appium_lib_core/version.rb +2 -2
  26. data/release_notes.md +14 -0
  27. data/script/commands.rb +3 -37
  28. metadata +21 -30
  29. data/lib/appium_lib_core/common/base/bridge/mjsonwp.rb +0 -91
  30. data/lib/appium_lib_core/common/base/bridge/w3c.rb +0 -248
  31. data/lib/appium_lib_core/common/command/common.rb +0 -110
  32. data/lib/appium_lib_core/common/command/mjsonwp.rb +0 -28
  33. data/lib/appium_lib_core/common/command/w3c.rb +0 -56
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 27d5a8e4018e381172273c5b705a2166e8f47530101eed83ffd0ddf83e93653d
4
- data.tar.gz: 78ceb26083c9ae018101180cf13c91cd28f363e819119b6500b2d48a28273474
3
+ metadata.gz: 6bc30b79d80c1606288087e36a6ed024c3be91ffbc6c5b8b04c9c9c1537d1d9e
4
+ data.tar.gz: 06b4f5cdbadb770ce7ce4eecd3fcdaf78c002c13982b6a0573e30a0c3aee9d02
5
5
  SHA512:
6
- metadata.gz: 5d07ce477474a38c3df1fb1bd989d9e6b28188ab21d7851bec98443940b0ea5d8b358c628998aeb1f62ca93be783c617dab3b4cf4fdf26e47e97def6467dca97
7
- data.tar.gz: 29634dc748e222cf65bc6af144656f291815e4c5eaea1fa177aa7e1543752ffbcbac0d4b206f4169ab306dd25e1d5a36c2a1b3d9b51cdef438456c27e52a7bea
6
+ metadata.gz: c68d806651e436131ebd91c9f9b520a8de1a95ad82ee67988c7f475b6ce2c016b50fa15e1ee4f0813f55d59e5237bea34c209096436807ba7f8eb2ac9afbb123
7
+ data.tar.gz: 3982388d81e2d3d59b51cde803e5e83521772700fc8a82d0733ba650c25b2f46578bb9490113a8792a5b5e24d22488110ff3a6e727cb8d22a210c6bf4fb8632e
@@ -11,7 +11,7 @@ jobs:
11
11
  strategy:
12
12
  fail-fast: false
13
13
  matrix:
14
- ruby: [2.4, 2.5, 2.6, 2.7, 3.0]
14
+ ruby: [2.5, 2.6, 2.7, 3.0]
15
15
 
16
16
  runs-on: ubuntu-latest
17
17
 
@@ -38,7 +38,7 @@ jobs:
38
38
  fail-fast: false
39
39
  matrix:
40
40
  # Does not add 2.7 on Windows so far since a command fails only on Windows
41
- ruby: [2.4, 2.5, 2.6]
41
+ ruby: [2.5, 2.6]
42
42
 
43
43
  runs-on: windows-latest
44
44
 
data/CHANGELOG.md CHANGED
@@ -10,17 +10,24 @@ Read `release_notes.md` for commit level details.
10
10
 
11
11
  ### Deprecations
12
12
 
13
+ ## [5.0.0.beta]
14
+
15
+ - Update base selenium webdriver version to `4.0.0.beta2`
16
+ - Support only W3C spec
17
+ - Support Ruby 2.5+
18
+ - Raises `::Appium::Core::Error::ArgumentError` instead of `ArgumentError` for this library specific argument errors
19
+
20
+ ## [4.6.0] - 2021-06-03
21
+
22
+ ### Enhancements
23
+ - Add `Appium::Core::Base::Driver#add_command` to allow you to add your own command
24
+
13
25
  ## [4.5.0] - 2021-03-14
14
26
 
15
27
  ### Enhancements
16
28
  - Add `speed` argument for `Appium::Core::Base::Driver#set_location` since Appium 1.21.0
17
29
  - Add `multiple` and `match_neighbour_threshold` arguments for `Appium::Core::Base::Driver#find_image_occurrence`
18
30
 
19
- ### Bug fixes
20
-
21
- ### Deprecations
22
-
23
-
24
31
  ## [4.4.1(4.4.0)] - 2021-02-15(2021-02-13)
25
32
 
26
33
  ### Enhancements
data/README.md CHANGED
@@ -11,6 +11,7 @@ This library wraps [selenium-webdriver](https://github.com/SeleniumHQ/selenium/w
11
11
  # Documentation
12
12
 
13
13
  - http://www.rubydoc.info/github/appium/ruby_lib_core
14
+ - You can find working API examples in test code, [test/functional](test/functional)
14
15
 
15
16
  # Related library
16
17
  - https://github.com/appium/ruby_lib
@@ -120,7 +121,7 @@ $ IGNORE_VERSION_SKIP=true CI=true bundle exec rake test:func:android
120
121
  $ ruby test.rb
121
122
  ```
122
123
 
123
- More examples are in [test/functional](test/functional)
124
+ More examples are in [test/functional](test/functional)
124
125
 
125
126
  ### Capabilities
126
127
 
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'appium_lib_core/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.required_ruby_version = '>= 2.4'
7
+ spec.required_ruby_version = '>= 2.5'
8
8
 
9
9
  spec.name = 'appium_lib_core'
10
10
  spec.version = Appium::Core::VERSION
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
23
  spec.require_paths = ['lib']
24
24
 
25
- spec.add_runtime_dependency 'selenium-webdriver', '~> 3.14', '>= 3.14.1'
25
+ spec.add_runtime_dependency 'selenium-webdriver', '4.0.0.beta4'
26
26
  spec.add_runtime_dependency 'faye-websocket', '~> 0.11.0'
27
27
 
28
28
  spec.add_development_dependency 'bundler', '>= 1.14'
@@ -30,8 +30,8 @@ Gem::Specification.new do |spec|
30
30
  spec.add_development_dependency 'yard', '~> 0.9.11'
31
31
  spec.add_development_dependency 'minitest', '~> 5.0'
32
32
  spec.add_development_dependency 'minitest-reporters', '~> 1.1'
33
- spec.add_development_dependency 'webmock', '~> 3.11.0'
34
- spec.add_development_dependency 'rubocop', '1.8.1'
33
+ spec.add_development_dependency 'webmock', '~> 3.13.0'
34
+ spec.add_development_dependency 'rubocop', '1.12.0'
35
35
  spec.add_development_dependency 'appium_thor', '~> 1.0'
36
36
  spec.add_development_dependency 'pry'
37
37
  spec.add_development_dependency 'pry-byebug'
@@ -17,11 +17,8 @@ require 'selenium-webdriver'
17
17
  require_relative 'appium_lib_core/version'
18
18
  require_relative 'appium_lib_core/common'
19
19
  require_relative 'appium_lib_core/driver'
20
-
21
20
  require_relative 'appium_lib_core/device'
22
-
23
- # Call patch after requiring other files
24
- require_relative 'appium_lib_core/patch'
21
+ require_relative 'appium_lib_core/element'
25
22
 
26
23
  module Appium
27
24
  # convert all keys (including nested) to symbols
@@ -30,7 +27,7 @@ module Appium
30
27
  # https://github.com/rails/docrails/blob/a3b1105ada3da64acfa3843b164b14b734456a50/activesupport/lib/active_support/core_ext/hash/keys.rb#L84
31
28
  # @param [Hash] hash Hash value to make symbolise
32
29
  def self.symbolize_keys(hash)
33
- raise ArgumentError, 'symbolize_keys requires a hash' unless hash.is_a? Hash
30
+ raise ::Appium::Core::Error::ArgumentError, 'symbolize_keys requires a hash' unless hash.is_a? Hash
34
31
 
35
32
  hash.each_with_object({}) do |pair, acc|
36
33
  key = begin
@@ -21,7 +21,8 @@ module Appium
21
21
  ::Appium::Core::Device.add_endpoint_method(:finger_print) do
22
22
  def finger_print(finger_id)
23
23
  unless (1..10).cover? finger_id.to_i
24
- raise ArgumentError, "finger_id should be integer between 1 to 10. Not #{finger_id}"
24
+ raise ::Appium::Core::Error::ArgumentError,
25
+ "finger_id should be integer between 1 to 10. Not #{finger_id}"
25
26
  end
26
27
 
27
28
  execute(:finger_print, {}, { fingerprintId: finger_id.to_i })
@@ -34,10 +34,7 @@ require_relative 'device/orientation'
34
34
  # The following files have selenium-webdriver related stuff.
35
35
  require_relative 'base/driver'
36
36
  require_relative 'base/bridge'
37
- require_relative 'base/bridge/mjsonwp'
38
- require_relative 'base/bridge/w3c'
39
37
  require_relative 'base/capabilities'
40
38
  require_relative 'base/http_default'
41
39
  require_relative 'base/search_context'
42
- require_relative 'base/command'
43
40
  require_relative 'base/platform'
@@ -16,52 +16,45 @@ module Appium
16
16
  module Core
17
17
  class Base
18
18
  class Bridge < ::Selenium::WebDriver::Remote::Bridge
19
+ include Device::DeviceLock
20
+ include Device::Keyboard
21
+ include Device::ImeActions
22
+ include Device::Setting
23
+ include Device::Context
24
+ include Device::Value
25
+ include Device::FileManagement
26
+ include Device::KeyEvent
27
+ include Device::ImageComparison
28
+ include Device::AppManagement
29
+ include Device::AppState
30
+ include Device::ScreenRecord::Command
31
+ include Device::Device
32
+ include Device::TouchActions
33
+ include Device::ExecuteDriver
34
+ include Device::Orientation
35
+
19
36
  # Prefix for extra capability defined by W3C
20
37
  APPIUM_PREFIX = 'appium:'
21
38
 
22
- # TODO: Remove the forceMjsonwp after Appium server won't need it
23
- FORCE_MJSONWP = :forceMjsonwp
39
+ # No 'browserName' means the session is native appium connection
40
+ APPIUM_NATIVE_BROWSER_NAME = 'appium'
24
41
 
25
- # Almost same as self.handshake in ::Selenium::WebDriver::Remote::Bridge
26
- #
27
- # Implements protocol handshake which:
28
- #
29
- # 1. Creates session with driver.
30
- # 2. Sniffs response.
31
- # 3. Based on the response, understands which dialect we should use.
32
- #
33
- # @return [Bridge::MJSONWP, Bridge::W3C]
34
- #
35
- def self.handshake(**opts)
36
- desired_capabilities = opts.delete(:desired_capabilities) { ::Selenium::WebDriver::Remote::Capabilities.new }
42
+ attr_reader :available_commands
37
43
 
38
- if desired_capabilities.is_a?(Symbol)
39
- unless ::Selenium::WebDriver::Remote::Capabilities.respond_to?(desired_capabilities)
40
- raise ::Selenium::WebDriver::Error::WebDriverError, "invalid desired capability: #{desired_capabilities.inspect}"
41
- end
42
-
43
- desired_capabilities = ::Selenium::WebDriver::Remote::Capabilities.__send__(desired_capabilities)
44
- end
45
-
46
- bridge = new(opts)
47
- capabilities = bridge.create_session(desired_capabilities)
48
-
49
- case bridge.dialect
50
- when :oss # for MJSONWP
51
- Bridge::MJSONWP.new(capabilities, bridge.session_id, **opts)
52
- when :w3c
53
- Bridge::W3C.new(capabilities, bridge.session_id, **opts)
54
- else
55
- raise CoreError, 'cannot understand dialect'
44
+ def browser
45
+ @browser ||= begin
46
+ name = @capabilities.browser_name
47
+ name ? name.tr(' ', '_').downcase.to_sym : 'unknown'
48
+ rescue KeyError
49
+ APPIUM_NATIVE_BROWSER_NAME
56
50
  end
57
51
  end
58
52
 
59
53
  # Override
60
54
  # Creates session handling both OSS and W3C dialects.
61
- # Copy from Selenium::WebDriver::Remote::Bridge to keep using +merged_capabilities+ for Appium
62
55
  #
63
- # @param [::Selenium::WebDriver::Remote::W3C::Capabilities, Hash] desired_capabilities A capability
64
- # @return [::Selenium::WebDriver::Remote::Capabilities, ::Selenium::WebDriver::Remote::W3C::Capabilities]
56
+ # @param [::Selenium::WebDriver::Remote::Capabilities, Hash] desired_capabilities A capability
57
+ # @return [::Selenium::WebDriver::Remote::Capabilities]
65
58
  #
66
59
  # @example
67
60
  #
@@ -79,39 +72,29 @@ module Appium
79
72
  # }
80
73
  # }
81
74
  # core = ::Appium::Core.for(caps)
82
- # driver = core.start_driver #=> driver.dialect == :w3c if the Appium server support W3C.
75
+ # driver = core.start_driver
83
76
  #
84
- def create_session(desired_capabilities)
85
- response = execute(:new_session, {}, merged_capabilities(desired_capabilities))
77
+ def create_session(capabilities)
78
+ @available_commands = ::Appium::Core::Commands::COMMANDS.dup
86
79
 
87
- @session_id = response['sessionId']
88
- oss_status = response['status'] # for compatibility with Appium 1.7.1-
89
- value = response['value']
90
-
91
- if value.is_a?(Hash) # include for W3C format
92
- @session_id = value['sessionId'] if value.key?('sessionId')
93
-
94
- if value.key?('capabilities')
95
- value = value['capabilities']
96
- elsif value.key?('value')
97
- value = value['value']
98
- end
99
- end
80
+ caps = add_appium_prefix(capabilities)
81
+ response = execute(:new_session, {}, { capabilities: { firstMatch: [caps] } })
100
82
 
83
+ @session_id = response['sessionId']
101
84
  raise ::Selenium::WebDriver::Error::WebDriverError, 'no sessionId in returned payload' unless @session_id
102
85
 
103
- json_create(oss_status, value)
86
+ @capabilities = json_create(response['capabilities'])
104
87
  end
105
88
 
106
89
  # Append +appium:+ prefix for Appium following W3C spec
107
90
  # https://www.w3.org/TR/webdriver/#dfn-validate-capabilities
108
91
  #
109
- # @param [::Selenium::WebDriver::Remote::W3C::Capabilities, Hash] capabilities A capability
110
- # @return [::Selenium::WebDriver::Remote::W3C::Capabilities]
92
+ # @param [::Selenium::WebDriver::Remote::Capabilities, Hash] capabilities A capability
93
+ # @return [::Selenium::WebDriver::Remote::Capabilities]
111
94
  def add_appium_prefix(capabilities)
112
- w3c_capabilities = ::Selenium::WebDriver::Remote::W3C::Capabilities.new
95
+ w3c_capabilities = ::Selenium::WebDriver::Remote::Capabilities.new
113
96
 
114
- capabilities = capabilities.__send__(:capabilities) unless capabilities.is_a?(Hash)
97
+ capabilities = capabilities.send(:capabilities) unless capabilities.is_a?(Hash)
115
98
 
116
99
  capabilities.each do |name, value|
117
100
  next if value.nil?
@@ -133,56 +116,268 @@ module Appium
133
116
  end
134
117
 
135
118
  def extension_prefix?(capability_name)
136
- snake_cased_capability_names = ::Selenium::WebDriver::Remote::W3C::Capabilities::KNOWN.map(&:to_s)
119
+ snake_cased_capability_names = ::Selenium::WebDriver::Remote::Capabilities::KNOWN.map(&:to_s)
137
120
  camel_cased_capability_names = snake_cased_capability_names.map { |v| camel_case(v) }
138
121
 
122
+ # Check 'EXTENSION_CAPABILITY_PATTERN'
139
123
  snake_cased_capability_names.include?(capability_name) ||
140
124
  camel_cased_capability_names.include?(capability_name) ||
141
- capability_name.match(::Selenium::WebDriver::Remote::W3C::Capabilities::EXTENSION_CAPABILITY_PATTERN)
125
+ capability_name.match(':')
142
126
  end
143
127
 
144
- def json_create(oss_status, value)
145
- if oss_status
146
- ::Selenium::WebDriver.logger.info 'Detected OSS dialect.'
147
- @dialect = :oss
148
- ::Selenium::WebDriver::Remote::Capabilities.json_create(value)
149
- else
150
- ::Selenium::WebDriver.logger.info 'Detected W3C dialect.'
151
- @dialect = :w3c
152
- ::Selenium::WebDriver::Remote::W3C::Capabilities.json_create(value)
153
- end
128
+ def json_create(value)
129
+ ::Selenium::WebDriver::Remote::Capabilities.json_create(value)
154
130
  end
155
131
 
156
- def delete_force_mjsonwp(capabilities)
157
- w3c_capabilities = ::Selenium::WebDriver::Remote::W3C::Capabilities.new
132
+ public
158
133
 
159
- capabilities = capabilities.__send__(:capabilities) unless capabilities.is_a?(Hash)
160
- capabilities.each do |name, value|
161
- next if value.nil?
162
- next if value.is_a?(String) && value.empty?
163
- next if name == FORCE_MJSONWP
134
+ # command for Appium 2.0.
135
+ def add_command(method:, url:, name:, &block)
136
+ raise ::Appium::Core::Error::ArgumentError, "#{name} is already defined" if @available_commands.key? name
137
+
138
+ @available_commands[name] = [method, url]
139
+
140
+ ::Appium::Core::Device.add_endpoint_method name, &block
141
+ end
142
+
143
+ def commands(command)
144
+ @available_commands[command]
145
+ end
146
+
147
+ # Returns all available sessions on the Appium server instance
148
+ def sessions
149
+ execute :get_all_sessions
150
+ end
151
+
152
+ def status
153
+ execute :status
154
+ end
155
+
156
+ # Perform touch actions for W3C module.
157
+ # Generate +touch+ pointer action here and users can use this via +driver.action+
158
+ # - https://seleniumhq.github.io/selenium/docs/api/rb/Selenium/WebDriver/W3CActionBuilder.html
159
+ # - https://seleniumhq.github.io/selenium/docs/api/rb/Selenium/WebDriver/PointerActions.html
160
+ # - https://seleniumhq.github.io/selenium/docs/api/rb/Selenium/WebDriver/KeyActions.html
161
+ #
162
+ # 'mouse' action is by default in the Ruby client. Appium server force the +mouse+ action to +touch+ once in
163
+ # the server side. So we don't consider the case.
164
+ #
165
+ # @example
166
+ #
167
+ # element = @driver.find_element(:id, "some id")
168
+ # @driver.action.click(element).perform # The 'click' is a part of 'PointerActions'
169
+ #
170
+ def action(async = false)
171
+ # Used for default duration of each touch actions
172
+ # Override from 250 milliseconds to 50 milliseconds
173
+ action_builder = super
174
+ action_builder.default_move_duration = 0.05
175
+ action_builder
176
+ end
177
+
178
+ # Port from MJSONWP
179
+ def get_timeouts
180
+ execute :get_timeouts
181
+ end
182
+
183
+ # Port from MJSONWP
184
+ def session_capabilities
185
+ ::Selenium::WebDriver::Remote::Capabilities.json_create execute(:get_capabilities)
186
+ end
187
+
188
+ # Port from MJSONWP
189
+ def send_keys_to_active_element(key)
190
+ text = ::Selenium::WebDriver::Keys.encode(key).join('')
191
+ execute :send_keys_to_active_element, {}, { value: text.split(//) }
192
+ end
164
193
 
165
- w3c_capabilities[name] = value
194
+ # For Appium
195
+ # override
196
+ def page_source
197
+ # For W3C
198
+ # execute_script('var source = document.documentElement.outerHTML;' \
199
+ # 'if (!source) { source = new XMLSerializer().serializeToString(document); }' \
200
+ # 'return source;')
201
+ execute :get_page_source
202
+ end
203
+
204
+ # For Appium
205
+ # override
206
+ def element_displayed?(element)
207
+ # For W3C
208
+ # https://github.com/SeleniumHQ/selenium/commit/b618499adcc3a9f667590652c5757c0caa703289
209
+ # execute_atom :isDisplayed, element
210
+ execute :is_element_displayed, id: element.ref
211
+ end
212
+
213
+ # For Appium
214
+ # override
215
+ def element_attribute(element, name)
216
+ # For W3C in Selenium Client
217
+ # execute_atom :getAttribute, element, name
218
+ execute :get_element_attribute, id: element.ref, name: name
219
+ end
220
+
221
+ # For Appium
222
+ # override
223
+ def active_element
224
+ ::Appium::Core::Element.new self, element_id_from(execute(:get_active_element))
225
+ end
226
+ alias switch_to_active_element active_element
227
+
228
+ # For Appium
229
+ # override
230
+ def find_element_by(how, what, parent = nil)
231
+ how, what = convert_locator(how, what)
232
+
233
+ id = if parent
234
+ execute :find_child_element, { id: parent }, { using: how, value: what }
235
+ else
236
+ execute :find_element, {}, { using: how, value: what }
237
+ end
238
+ ::Appium::Core::Element.new self, element_id_from(id)
239
+ end
240
+
241
+ # For Appium
242
+ # override
243
+ def find_elements_by(how, what, parent = nil)
244
+ how, what = convert_locator(how, what)
245
+
246
+ ids = if parent
247
+ execute :find_child_elements, { id: parent }, { using: how, value: what }
248
+ else
249
+ execute :find_elements, {}, { using: how, value: what }
250
+ end
251
+
252
+ ids.map { |id| ::Appium::Core::Element.new self, element_id_from(id) }
253
+ end
254
+
255
+ # For Appium
256
+ # @param [Hash] id The id which can get as a response from server
257
+ # @return [::Appium::Core::Element]
258
+ def convert_to_element(id)
259
+ ::Appium::Core::Element.new self, element_id_from(id)
260
+ end
261
+
262
+ # For Appium
263
+ # override
264
+ # called in 'extend DriverExtensions::HasNetworkConnection'
265
+ def network_connection
266
+ execute :get_network_connection
267
+ end
268
+
269
+ # For Appium
270
+ # override
271
+ # called in 'extend DriverExtensions::HasNetworkConnection'
272
+ def network_connection=(type)
273
+ execute :set_network_connection, {}, { parameters: { type: type } }
274
+ end
275
+
276
+ # For Appium
277
+ # No implementation for W3C webdriver module
278
+ # called in 'extend DriverExtensions::HasLocation'
279
+ def location
280
+ obj = execute(:get_location) || {}
281
+ ::Selenium::WebDriver::Location.new obj['latitude'], obj['longitude'], obj['altitude']
282
+ end
283
+
284
+ # For Appium
285
+ # No implementation for W3C webdriver module
286
+ def set_location(lat, lon, alt = 0.0, speed: nil)
287
+ loc = { latitude: lat, longitude: lon, altitude: alt }
288
+ loc[:speed] = speed unless speed.nil?
289
+ execute :set_location, {}, { location: loc }
290
+ end
291
+
292
+ #
293
+ # logs
294
+ #
295
+ # For Appium
296
+ # No implementation for W3C webdriver module
297
+ def available_log_types
298
+ types = execute :get_available_log_types
299
+ Array(types).map(&:to_sym)
300
+ end
301
+
302
+ # For Appium
303
+ # No implementation for W3C webdriver module
304
+ def log(type)
305
+ data = execute :get_log, {}, { type: type.to_s }
306
+
307
+ Array(data).map do |l|
308
+ begin
309
+ ::Selenium::WebDriver::LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
310
+ rescue KeyError
311
+ next
312
+ end
166
313
  end
314
+ end
167
315
 
168
- w3c_capabilities
316
+ # For Appium
317
+ def log_event(vendor, event)
318
+ execute :post_log_event, {}, { vendor: vendor, event: event }
319
+ end
320
+
321
+ # For Appium
322
+ def log_events(type = nil)
323
+ args = {}
324
+ args['type'] = type unless type.nil?
325
+
326
+ execute :get_log_events, {}, args
327
+ end
328
+
329
+ def take_viewport_screenshot
330
+ execute_script('mobile: viewportScreenshot')
169
331
  end
170
332
 
171
- def merged_capabilities(desired_capabilities)
172
- force_mjsonwp = desired_capabilities[FORCE_MJSONWP]
173
- desired_capabilities = delete_force_mjsonwp(desired_capabilities) unless force_mjsonwp.nil?
333
+ def take_element_screenshot(element)
334
+ execute :take_element_screenshot, id: element.ref
335
+ end
336
+
337
+ private
174
338
 
175
- ::Appium::Logger.warn "'forceMjsonwp' no longer works. Sending both W3C and MJSONWP capabilities" if force_mjsonwp
339
+ def unwrap_script_result(arg)
340
+ case arg
341
+ when Array
342
+ arg.map { |e| unwrap_script_result(e) }
343
+ when Hash
344
+ element_id = element_id_from(arg)
345
+ return ::Appium::Core::Element.new(self, element_id) if element_id
176
346
 
177
- new_caps = add_appium_prefix(desired_capabilities)
178
- w3c_capabilities = ::Selenium::WebDriver::Remote::W3C::Capabilities.from_oss(new_caps)
347
+ arg.each { |k, v| arg[k] = unwrap_script_result(v) }
348
+ else
349
+ arg
350
+ end
351
+ end
352
+
353
+ def element_id_from(id)
354
+ id['ELEMENT'] || id['element-6066-11e4-a52e-4f735466cecf']
355
+ end
179
356
 
180
- {
181
- desiredCapabilities: desired_capabilities,
182
- capabilities: {
183
- firstMatch: [w3c_capabilities]
184
- }
185
- }
357
+ # Don't convert locators for Appium in native context
358
+ def convert_locator(how, what)
359
+ # case how
360
+ # when 'class name'
361
+ # how = 'css selector'
362
+ # what = ".#{escape_css(what)}"
363
+ # when 'id'
364
+ # how = 'css selector'
365
+ # what = "##{escape_css(what)}"
366
+ # when 'name'
367
+ # how = 'css selector'
368
+ # what = "*[name='#{escape_css(what)}']"
369
+ # when 'tag name'
370
+ # how = 'css selector'
371
+ # end
372
+ #
373
+ # if what.is_a?(Hash)
374
+ # what = what.each_with_object({}) do |(h, w), hash|
375
+ # h, w = convert_locator(h.to_s, w)
376
+ # hash[h] = w
377
+ # end
378
+ # end
379
+
380
+ [how, what]
186
381
  end
187
382
  end # class Bridge
188
383
  end # class Base