appium_lib_core 4.3.1 → 5.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 025fed7f5fed2f2eb9607a338faf02b0964359a1f4895011c47577b25c7457b3
4
- data.tar.gz: 35f1fe8c93fe4b9f0a078c2768826d8b3bcc12fa2870109fb9554ef4b528e56d
3
+ metadata.gz: 53abadd3b91fdcaac0c23f62bbc83b0e21ea08a50da28394a504d6839d36d2e7
4
+ data.tar.gz: 9bc2cda2b1fa8be1d602cd7ab9943594f9b4a1fce0ea5a4527491563c3687fd2
5
5
  SHA512:
6
- metadata.gz: e8e4b4cb0e6b825ba0f743e2aa85acf59976998f26b1a7ae664fe4e8b27be176b5a864bc5d26511122839362ade125370c20624c10f850a63d1beeda25dcb782
7
- data.tar.gz: 212f165f042fe66dbc7db5c216a682bbcc64bcbbaf33884f595d79847bd1de84c12f1a101bfff7d9ae86c59cd3849cf17b116a0c0cca2bb2015128051b7109ae
6
+ metadata.gz: 313ae53035edd0273b8d122325c77d031a186c5a9f60b57956ad0f204165cc8ca60420ce2a910dc28d9e0b5000fa9131262fbe4a2b796e4e4d7bd09d9e40e941
7
+ data.tar.gz: deb1d0d9c9aba7cc7a9b6040dbdbcf76896d5a0ce786a8ac419b436a11a90e1960893e2f6683a78efee7d3a8044d5eb19414d527123778cebd088a437b6a4215
@@ -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,6 +10,28 @@ Read `release_notes.md` for commit level details.
10
10
 
11
11
  ### Deprecations
12
12
 
13
+ ## [5.0.0.beta1]
14
+
15
+ - Update base selenium webdriver version to `4.0.0.beta2`
16
+ - Support only W3C spec
17
+ - Support Ruby 2.5+
18
+
19
+ ## [4.5.0] - 2021-03-14
20
+
21
+ ### Enhancements
22
+ - Add `speed` argument for `Appium::Core::Base::Driver#set_location` since Appium 1.21.0
23
+ - Add `multiple` and `match_neighbour_threshold` arguments for `Appium::Core::Base::Driver#find_image_occurrence`
24
+
25
+ ### Bug fixes
26
+
27
+ ### Deprecations
28
+
29
+
30
+ ## [4.4.1(4.4.0)] - 2021-02-15(2021-02-13)
31
+
32
+ ### Enhancements
33
+ - Returns `{}` any errors in `Core#appium_server_version` to prevent errors in some cases
34
+
13
35
  ## [4.3.1(4.3.0)] - 2021-02-07(2021-02-05)
14
36
 
15
37
  ### Enhancements
@@ -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.beta2'
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.12.1'
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'
@@ -1,8 +1,8 @@
1
1
  steps:
2
2
  - task: NodeTool@0
3
3
  inputs:
4
- versionSpec: 10.x
5
- displayName: Install Node 10.x
4
+ versionSpec: 12.x
5
+ displayName: Install Node 12.x
6
6
  - script: npm install -g appium@${APPIUM_VERSION}
7
7
  displayName: Install appium beta
8
8
  - script: npm install -g mjpeg-consumer
@@ -4,7 +4,7 @@ parameters:
4
4
  vmImageForIOS: 'macOS-10.15' # Not sure the reason, but macOS 10.14 instance raises no info.plist error
5
5
  xcodeForIOS: 12.2
6
6
  xcodeForTVOS: 12.2
7
- androidSDK: 30
7
+ androidSDK: 29 # API Level 30 emulators are more unstable than 29
8
8
  appiumVersion: 'beta'
9
9
  ignoreVersionSkip: true
10
10
  CI: true
@@ -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
@@ -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,41 @@ 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
24
-
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 }
37
-
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'
39
+ # Returns 'unknown' if no specific browser name
40
+ def browser
41
+ @browser ||= begin
42
+ name = @capabilities.browser_name
43
+ name ? name.tr(' ', '_').downcase.to_sym : 'unknown'
44
+ rescue KeyError
45
+ 'unknown'
56
46
  end
57
47
  end
58
48
 
59
49
  # Override
60
50
  # Creates session handling both OSS and W3C dialects.
61
- # Copy from Selenium::WebDriver::Remote::Bridge to keep using +merged_capabilities+ for Appium
62
51
  #
63
- # @param [::Selenium::WebDriver::Remote::W3C::Capabilities, Hash] desired_capabilities A capability
64
- # @return [::Selenium::WebDriver::Remote::Capabilities, ::Selenium::WebDriver::Remote::W3C::Capabilities]
52
+ # @param [::Selenium::WebDriver::Remote::Capabilities, Hash] desired_capabilities A capability
53
+ # @return [::Selenium::WebDriver::Remote::Capabilities]
65
54
  #
66
55
  # @example
67
56
  #
@@ -79,37 +68,27 @@ module Appium
79
68
  # }
80
69
  # }
81
70
  # core = ::Appium::Core.for(caps)
82
- # driver = core.start_driver #=> driver.dialect == :w3c if the Appium server support W3C.
71
+ # driver = core.start_driver
83
72
  #
84
73
  def create_session(desired_capabilities)
85
- response = execute(:new_session, {}, merged_capabilities(desired_capabilities))
74
+ caps = add_appium_prefix(desired_capabilities)
75
+ response = execute(:new_session, {}, { capabilities: { firstMatch: [caps] } })
86
76
 
87
77
  @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
78
+ capabilities = response['capabilities']
100
79
 
101
80
  raise ::Selenium::WebDriver::Error::WebDriverError, 'no sessionId in returned payload' unless @session_id
102
81
 
103
- json_create(oss_status, value)
82
+ @capabilities = json_create(capabilities)
104
83
  end
105
84
 
106
85
  # Append +appium:+ prefix for Appium following W3C spec
107
86
  # https://www.w3.org/TR/webdriver/#dfn-validate-capabilities
108
87
  #
109
- # @param [::Selenium::WebDriver::Remote::W3C::Capabilities, Hash] capabilities A capability
110
- # @return [::Selenium::WebDriver::Remote::W3C::Capabilities]
88
+ # @param [::Selenium::WebDriver::Remote::Capabilities, Hash] capabilities A capability
89
+ # @return [::Selenium::WebDriver::Remote::Capabilities]
111
90
  def add_appium_prefix(capabilities)
112
- w3c_capabilities = ::Selenium::WebDriver::Remote::W3C::Capabilities.new
91
+ w3c_capabilities = ::Selenium::WebDriver::Remote::Capabilities.new
113
92
 
114
93
  capabilities = capabilities.__send__(:capabilities) unless capabilities.is_a?(Hash)
115
94
 
@@ -133,56 +112,252 @@ module Appium
133
112
  end
134
113
 
135
114
  def extension_prefix?(capability_name)
136
- snake_cased_capability_names = ::Selenium::WebDriver::Remote::W3C::Capabilities::KNOWN.map(&:to_s)
115
+ snake_cased_capability_names = ::Selenium::WebDriver::Remote::Capabilities::KNOWN.map(&:to_s)
137
116
  camel_cased_capability_names = snake_cased_capability_names.map { |v| camel_case(v) }
138
117
 
118
+ # Check 'EXTENSION_CAPABILITY_PATTERN'
139
119
  snake_cased_capability_names.include?(capability_name) ||
140
120
  camel_cased_capability_names.include?(capability_name) ||
141
- capability_name.match(::Selenium::WebDriver::Remote::W3C::Capabilities::EXTENSION_CAPABILITY_PATTERN)
121
+ capability_name.match(':')
142
122
  end
143
123
 
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
124
+ def json_create(value)
125
+ ::Selenium::WebDriver::Remote::Capabilities.json_create(value)
154
126
  end
155
127
 
156
- def delete_force_mjsonwp(capabilities)
157
- w3c_capabilities = ::Selenium::WebDriver::Remote::W3C::Capabilities.new
128
+ public
158
129
 
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
130
+ def commands(command)
131
+ ::Appium::Core::Commands::COMMANDS[command]
132
+ end
133
+
134
+ # Returns all available sessions on the Appium server instance
135
+ def sessions
136
+ execute :get_all_sessions
137
+ end
138
+
139
+ def status
140
+ execute :status
141
+ end
142
+
143
+ # Perform touch actions for W3C module.
144
+ # Generate +touch+ pointer action here and users can use this via +driver.action+
145
+ # - https://seleniumhq.github.io/selenium/docs/api/rb/Selenium/WebDriver/W3CActionBuilder.html
146
+ # - https://seleniumhq.github.io/selenium/docs/api/rb/Selenium/WebDriver/PointerActions.html
147
+ # - https://seleniumhq.github.io/selenium/docs/api/rb/Selenium/WebDriver/KeyActions.html
148
+ #
149
+ # 'mouse' action is by default in the Ruby client. Appium server force the +mouse+ action to +touch+ once in
150
+ # the server side. So we don't consider the case.
151
+ #
152
+ # @example
153
+ #
154
+ # element = @driver.find_element(:id, "some id")
155
+ # @driver.action.click(element).perform # The 'click' is a part of 'PointerActions'
156
+ #
157
+ def action(async = false)
158
+ # Used for default duration of each touch actions
159
+ # Override from 250 milliseconds to 50 milliseconds
160
+ action_builder = super
161
+ action_builder.default_move_duration = 0.05
162
+ action_builder
163
+ end
164
+
165
+ # Port from MJSONWP
166
+ def get_timeouts
167
+ execute :get_timeouts
168
+ end
169
+
170
+ # Port from MJSONWP
171
+ def session_capabilities
172
+ ::Selenium::WebDriver::Remote::Capabilities.json_create execute(:get_capabilities)
173
+ end
174
+
175
+ # Port from MJSONWP
176
+ def send_keys_to_active_element(key)
177
+ text = ::Selenium::WebDriver::Keys.encode(key).join('')
178
+ execute :send_keys_to_active_element, {}, { value: text.split(//) }
179
+ end
180
+
181
+ # For Appium
182
+ # override
183
+ def page_source
184
+ # For W3C
185
+ # execute_script('var source = document.documentElement.outerHTML;' \
186
+ # 'if (!source) { source = new XMLSerializer().serializeToString(document); }' \
187
+ # 'return source;')
188
+ execute :get_page_source
189
+ end
164
190
 
165
- w3c_capabilities[name] = value
191
+ # For Appium
192
+ # override
193
+ def element_displayed?(element)
194
+ # For W3C
195
+ # https://github.com/SeleniumHQ/selenium/commit/b618499adcc3a9f667590652c5757c0caa703289
196
+ # execute_atom :isDisplayed, element
197
+ execute :is_element_displayed, id: element.ref
198
+ end
199
+
200
+ # For Appium
201
+ # override
202
+ def element_attribute(element, name)
203
+ # For W3C in Selenium Client
204
+ # execute_atom :getAttribute, element, name
205
+ execute :get_element_attribute, id: element.ref, name: name
206
+ end
207
+
208
+ # For Appium
209
+ # override
210
+ def active_element
211
+ ::Appium::Core::Element.new self, element_id_from(execute(:get_active_element))
212
+ end
213
+ alias switch_to_active_element active_element
214
+
215
+ # For Appium
216
+ # override
217
+ def find_element_by(how, what, parent = nil)
218
+ how, what = convert_locators(how, what)
219
+
220
+ id = if parent
221
+ execute :find_child_element, { id: parent }, { using: how, value: what }
222
+ else
223
+ execute :find_element, {}, { using: how, value: what }
224
+ end
225
+ ::Appium::Core::Element.new self, element_id_from(id)
226
+ end
227
+
228
+ # For Appium
229
+ # override
230
+ def find_elements_by(how, what, parent = nil)
231
+ how, what = convert_locators(how, what)
232
+
233
+ ids = if parent
234
+ execute :find_child_elements, { id: parent }, { using: how, value: what }
235
+ else
236
+ execute :find_elements, {}, { using: how, value: what }
237
+ end
238
+
239
+ ids.map { |id| ::Appium::Core::Element.new self, element_id_from(id) }
240
+ end
241
+
242
+ # For Appium
243
+ # @param [Hash] id The id which can get as a response from server
244
+ # @return [::Appium::Core::Element]
245
+ def convert_to_element(id)
246
+ ::Appium::Core::Element.new self, element_id_from(id)
247
+ end
248
+
249
+ # For Appium
250
+ # override
251
+ # called in 'extend DriverExtensions::HasNetworkConnection'
252
+ def network_connection
253
+ execute :get_network_connection
254
+ end
255
+
256
+ # For Appium
257
+ # override
258
+ # called in 'extend DriverExtensions::HasNetworkConnection'
259
+ def network_connection=(type)
260
+ execute :set_network_connection, {}, { parameters: { type: type } }
261
+ end
262
+
263
+ # For Appium
264
+ # No implementation for W3C webdriver module
265
+ # called in 'extend DriverExtensions::HasLocation'
266
+ def location
267
+ obj = execute(:get_location) || {}
268
+ ::Selenium::WebDriver::Location.new obj['latitude'], obj['longitude'], obj['altitude']
269
+ end
270
+
271
+ # For Appium
272
+ # No implementation for W3C webdriver module
273
+ def set_location(lat, lon, alt = 0.0, speed: nil)
274
+ loc = { latitude: lat, longitude: lon, altitude: alt }
275
+ loc[:speed] = speed unless speed.nil?
276
+ execute :set_location, {}, { location: loc }
277
+ end
278
+
279
+ #
280
+ # logs
281
+ #
282
+ # For Appium
283
+ # No implementation for W3C webdriver module
284
+ def available_log_types
285
+ types = execute :get_available_log_types
286
+ Array(types).map(&:to_sym)
287
+ end
288
+
289
+ # For Appium
290
+ # No implementation for W3C webdriver module
291
+ def log(type)
292
+ data = execute :get_log, {}, { type: type.to_s }
293
+
294
+ Array(data).map do |l|
295
+ begin
296
+ ::Selenium::WebDriver::LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
297
+ rescue KeyError
298
+ next
299
+ end
166
300
  end
301
+ end
167
302
 
168
- w3c_capabilities
303
+ # For Appium
304
+ def log_event(vendor, event)
305
+ execute :post_log_event, {}, { vendor: vendor, event: event }
169
306
  end
170
307
 
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?
308
+ # For Appium
309
+ def log_events(type = nil)
310
+ args = {}
311
+ args['type'] = type unless type.nil?
174
312
 
175
- ::Appium::Logger.warn "'forceMjsonwp' no longer works. Sending both W3C and MJSONWP capabilities" if force_mjsonwp
313
+ execute :get_log_events, {}, args
314
+ end
315
+
316
+ def take_viewport_screenshot
317
+ execute_script('mobile: viewportScreenshot')
318
+ end
176
319
 
177
- new_caps = add_appium_prefix(desired_capabilities)
178
- w3c_capabilities = ::Selenium::WebDriver::Remote::W3C::Capabilities.from_oss(new_caps)
320
+ def take_element_screenshot(element)
321
+ execute :take_element_screenshot, id: element.ref
322
+ end
323
+
324
+ private
325
+
326
+ def unwrap_script_result(arg)
327
+ case arg
328
+ when Array
329
+ arg.map { |e| unwrap_script_result(e) }
330
+ when Hash
331
+ element_id = element_id_from(arg)
332
+ return ::Appium::Core::Element.new(self, element_id) if element_id
333
+
334
+ arg.each { |k, v| arg[k] = unwrap_script_result(v) }
335
+ else
336
+ arg
337
+ end
338
+ end
339
+
340
+ def element_id_from(id)
341
+ id['ELEMENT'] || id['element-6066-11e4-a52e-4f735466cecf']
342
+ end
179
343
 
180
- {
181
- desiredCapabilities: desired_capabilities,
182
- capabilities: {
183
- firstMatch: [w3c_capabilities]
184
- }
185
- }
344
+ # Don't convert locators for Appium Client
345
+ # TODO: Only for Appium. Ideally, we'd like to keep the selenium-webdriver
346
+ def convert_locators(how, what)
347
+ # case how
348
+ # when 'class name'
349
+ # how = 'css selector'
350
+ # what = ".#{escape_css(what)}"
351
+ # when 'id'
352
+ # how = 'css selector'
353
+ # what = "##{escape_css(what)}"
354
+ # when 'name'
355
+ # how = 'css selector'
356
+ # what = "*[name='#{escape_css(what)}']"
357
+ # when 'tag name'
358
+ # how = 'css selector'
359
+ # end
360
+ [how, what]
186
361
  end
187
362
  end # class Bridge
188
363
  end # class Base