appium_lib_core 4.1.0 → 5.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +158 -275
- data/README.md +13 -8
- data/Rakefile +4 -0
- data/appium_lib_core.gemspec +5 -8
- data/bin/console +0 -4
- data/lib/appium_lib_core/android/device/auth_finger_print.rb +2 -1
- data/lib/appium_lib_core/android/device.rb +4 -4
- data/lib/appium_lib_core/common/base/bridge.rb +291 -92
- data/lib/appium_lib_core/common/base/capabilities.rb +8 -9
- data/lib/appium_lib_core/common/base/device_ime.rb +49 -0
- data/lib/appium_lib_core/common/base/driver.rb +225 -187
- data/lib/appium_lib_core/common/base/driver_settings.rb +51 -0
- data/lib/appium_lib_core/common/base/has_location.rb +80 -0
- data/lib/appium_lib_core/common/base/has_network_connection.rb +56 -0
- data/lib/appium_lib_core/common/base/http_default.rb +1 -3
- data/lib/appium_lib_core/common/base/remote_status.rb +31 -0
- data/lib/appium_lib_core/common/base/rotable.rb +54 -0
- data/lib/appium_lib_core/common/base/screenshot.rb +6 -6
- data/lib/appium_lib_core/common/base/search_context.rb +20 -5
- data/lib/appium_lib_core/common/base.rb +1 -3
- data/lib/appium_lib_core/common/command.rb +255 -4
- data/lib/appium_lib_core/common/device/app_management.rb +2 -14
- data/lib/appium_lib_core/common/device/image_comparison.rb +12 -4
- data/lib/appium_lib_core/common/device/keyevent.rb +4 -4
- data/lib/appium_lib_core/common/{command/mjsonwp.rb → device/orientation.rb} +14 -11
- data/lib/appium_lib_core/common/device/touch_actions.rb +2 -0
- data/lib/appium_lib_core/common/device/value.rb +6 -6
- data/lib/appium_lib_core/common/error.rb +4 -1
- data/lib/appium_lib_core/common/log.rb +4 -1
- data/lib/appium_lib_core/common/touch_action/multi_touch.rb +19 -0
- data/lib/appium_lib_core/common/touch_action/touch_actions.rb +16 -2
- data/lib/appium_lib_core/common/wait.rb +38 -6
- data/lib/appium_lib_core/device.rb +1 -5
- data/lib/appium_lib_core/driver.rb +41 -75
- data/lib/appium_lib_core/{patch.rb → element.rb} +66 -9
- data/lib/appium_lib_core/ios/uiautomation/patch.rb +1 -1
- data/lib/appium_lib_core/{common/base/command.rb → mac2/bridge.rb} +9 -8
- data/lib/appium_lib_core/mac2/device/screen.rb +48 -0
- data/lib/appium_lib_core/mac2/device.rb +92 -0
- data/lib/appium_lib_core/mac2.rb +17 -0
- data/lib/appium_lib_core/version.rb +2 -2
- data/lib/appium_lib_core.rb +2 -5
- metadata +29 -82
- data/.github/ISSUE_TEMPLATE/issue-report.md +0 -29
- data/.github/contributing.md +0 -26
- data/.github/issue_template.md +0 -20
- data/.github/workflows/unittest.yml +0 -68
- data/.gitignore +0 -18
- data/.rubocop.yml +0 -58
- data/azure-pipelines.yml +0 -15
- data/ci-jobs/functional/android_setup.yml +0 -3
- data/ci-jobs/functional/ios_setup.yml +0 -7
- data/ci-jobs/functional/publish_test_result.yml +0 -18
- data/ci-jobs/functional/run_appium.yml +0 -25
- data/ci-jobs/functional/start-emulator.sh +0 -26
- data/ci-jobs/functional_test.yml +0 -298
- data/docs/mobile_command.md +0 -34
- data/lib/appium_lib_core/common/base/bridge/mjsonwp.rb +0 -81
- data/lib/appium_lib_core/common/base/bridge/w3c.rb +0 -252
- data/lib/appium_lib_core/common/command/common.rb +0 -110
- data/lib/appium_lib_core/common/command/w3c.rb +0 -56
- data/release_notes.md +0 -816
- data/script/commands.rb +0 -200
@@ -27,6 +27,8 @@ module Appium
|
|
27
27
|
autoload :Xcuitest, 'appium_lib_core/ios_xcuitest'
|
28
28
|
end
|
29
29
|
|
30
|
+
autoload :Mac2, 'appium_lib_core/mac2'
|
31
|
+
|
30
32
|
autoload :Windows, 'appium_lib_core/windows'
|
31
33
|
|
32
34
|
# This options affects only client side as <code>:appium_lib</code> key.<br>
|
@@ -38,18 +40,18 @@ module Appium
|
|
38
40
|
|
39
41
|
def initialize(appium_lib_opts)
|
40
42
|
@custom_url = appium_lib_opts.fetch :server_url, nil
|
41
|
-
@default_wait = appium_lib_opts.fetch :wait,
|
43
|
+
@default_wait = appium_lib_opts.fetch :wait, nil
|
42
44
|
@enable_idempotency_header = appium_lib_opts.fetch :enable_idempotency_header, true
|
43
45
|
|
44
46
|
# bump current session id into a particular file
|
45
47
|
@export_session = appium_lib_opts.fetch :export_session, false
|
46
48
|
@export_session_path = appium_lib_opts.fetch :export_session_path, default_tmp_appium_lib_session
|
47
49
|
|
48
|
-
@direct_connect = appium_lib_opts.fetch :direct_connect,
|
50
|
+
@direct_connect = appium_lib_opts.fetch :direct_connect, true
|
49
51
|
|
50
52
|
@port = appium_lib_opts.fetch :port, Driver::DEFAULT_APPIUM_PORT
|
51
53
|
|
52
|
-
# timeout and interval used in ::Appium::
|
54
|
+
# timeout and interval used in ::Appium::Commn.wait/wait_true
|
53
55
|
@wait_timeout = appium_lib_opts.fetch :wait_timeout, ::Appium::Core::Wait::DEFAULT_TIMEOUT
|
54
56
|
@wait_interval = appium_lib_opts.fetch :wait_interval, ::Appium::Core::Wait::DEFAULT_INTERVAL
|
55
57
|
|
@@ -74,6 +76,13 @@ module Appium
|
|
74
76
|
path: 'directConnectPath'
|
75
77
|
}.freeze
|
76
78
|
|
79
|
+
W3C_KEYS = {
|
80
|
+
protocol: 'appium:directConnectProtocol',
|
81
|
+
host: 'appium:directConnectHost',
|
82
|
+
port: 'appium:directConnectPort',
|
83
|
+
path: 'appium:directConnectPath'
|
84
|
+
}.freeze
|
85
|
+
|
77
86
|
# @return [string] Returns a protocol such as http/https
|
78
87
|
attr_reader :protocol
|
79
88
|
|
@@ -87,10 +96,10 @@ module Appium
|
|
87
96
|
attr_reader :path
|
88
97
|
|
89
98
|
def initialize(capabilities)
|
90
|
-
@protocol = capabilities[KEYS[:protocol]]
|
91
|
-
@host = capabilities[KEYS[:host]]
|
92
|
-
@port = capabilities[KEYS[:port]]
|
93
|
-
@path = capabilities[KEYS[:path]]
|
99
|
+
@protocol = capabilities[W3C_KEYS[:protocol]] || capabilities[KEYS[:protocol]]
|
100
|
+
@host = capabilities[W3C_KEYS[:host]] || capabilities[KEYS[:host]]
|
101
|
+
@port = capabilities[W3C_KEYS[:port]] || capabilities[KEYS[:port]]
|
102
|
+
@path = capabilities[W3C_KEYS[:path]] || capabilities[KEYS[:path]]
|
94
103
|
end
|
95
104
|
end
|
96
105
|
|
@@ -133,11 +142,9 @@ module Appium
|
|
133
142
|
attr_reader :export_session_path
|
134
143
|
|
135
144
|
# Default wait time for elements to appear in Appium server side.
|
136
|
-
# Defaults to {::Appium::Core::Driver::DEFAULT_IMPLICIT_WAIT}.<br>
|
137
145
|
# Provide <code>{ appium_lib: { wait: 30 } }</code> to {::Appium::Core.for}
|
138
146
|
# @return [Integer]
|
139
147
|
attr_reader :default_wait
|
140
|
-
DEFAULT_IMPLICIT_WAIT = 0
|
141
148
|
|
142
149
|
# Appium's server port. 4723 is by default. Defaults to {::Appium::Core::Driver::DEFAULT_APPIUM_PORT}.<br>
|
143
150
|
# Provide <code>{ appium_lib: { port: 8080 } }</code> to {::Appium::Core.for}.
|
@@ -175,7 +182,8 @@ module Appium
|
|
175
182
|
# - <code>directConnectPort</code>
|
176
183
|
# - <code>directConnectPath</code>
|
177
184
|
#
|
178
|
-
#
|
185
|
+
# ignore them if this parameter is <code>false</code>. Defaults to true.
|
186
|
+
# These keys can have <code>appium:</code> prefix.
|
179
187
|
#
|
180
188
|
# @return [Bool]
|
181
189
|
attr_reader :direct_connect
|
@@ -185,8 +193,6 @@ module Appium
|
|
185
193
|
# @option opts [Hash] :caps Appium capabilities.
|
186
194
|
# @option opts [Hash] :capabilities The same as :caps.
|
187
195
|
# This param is for compatibility with Selenium WebDriver format
|
188
|
-
# @option opts [Hash] :desired_capabilities The same as :caps.
|
189
|
-
# This param is for compatibility with Selenium WebDriver format
|
190
196
|
# @option opts [Appium::Core::Options] :appium_lib Capabilities affect only ruby client
|
191
197
|
# @option opts [String] :url The same as :custom_url in :appium_lib.
|
192
198
|
# This param is for compatibility with Selenium WebDriver format
|
@@ -197,10 +203,8 @@ module Appium
|
|
197
203
|
#
|
198
204
|
# # format 1
|
199
205
|
# @core = Appium::Core.for caps: {...}, appium_lib: {...}
|
200
|
-
# # format 2. 'capabilities:'
|
206
|
+
# # format 2. 'capabilities:' is also available instead of 'caps:'.
|
201
207
|
# @core = Appium::Core.for url: "http://127.0.0.1:8080/wd/hub", capabilities: {...}, appium_lib: {...}
|
202
|
-
# # format 3. 'appium_lib: {...}' can be blank
|
203
|
-
# @core = Appium::Core.for url: "http://127.0.0.1:8080/wd/hub", desired_capabilities: {...}
|
204
208
|
#
|
205
209
|
#
|
206
210
|
# require 'rubygems'
|
@@ -228,7 +232,7 @@ module Appium
|
|
228
232
|
# @core.start_driver # Connect to 'http://127.0.0.1:8080/wd/hub' because of 'port: 8080'
|
229
233
|
#
|
230
234
|
# # Start iOS driver with .zip file over HTTP
|
231
|
-
# #
|
235
|
+
# # 'capabilities:' is also available instead of 'caps:'. Either is fine.
|
232
236
|
# opts = {
|
233
237
|
# capabilities: {
|
234
238
|
# platformName: :ios,
|
@@ -252,7 +256,7 @@ module Appium
|
|
252
256
|
# # Start iOS driver as another format. 'url' is available like below
|
253
257
|
# opts = {
|
254
258
|
# url: "http://custom-host:8080/wd/hub.com",
|
255
|
-
#
|
259
|
+
# capabilities: {
|
256
260
|
# platformName: :ios,
|
257
261
|
# platformVersion: '11.0',
|
258
262
|
# deviceName: 'iPhone Simulator',
|
@@ -289,9 +293,6 @@ module Appium
|
|
289
293
|
@delegate_target = self # for testing purpose
|
290
294
|
@automation_name = nil # initialise before 'set_automation_name'
|
291
295
|
|
292
|
-
opts = Appium.symbolize_keys opts
|
293
|
-
validate_keys(opts)
|
294
|
-
|
295
296
|
@custom_url = opts.delete :url
|
296
297
|
@caps = get_caps(opts)
|
297
298
|
|
@@ -324,7 +325,7 @@ module Appium
|
|
324
325
|
#
|
325
326
|
# # Start iOS driver
|
326
327
|
# opts = {
|
327
|
-
#
|
328
|
+
# capabilities: {
|
328
329
|
# platformName: :ios,
|
329
330
|
# platformVersion: '11.0',
|
330
331
|
# deviceName: 'iPhone Simulator',
|
@@ -365,11 +366,13 @@ module Appium
|
|
365
366
|
end
|
366
367
|
|
367
368
|
begin
|
368
|
-
|
369
|
-
|
370
|
-
|
369
|
+
@driver = ::Appium::Core::Base::Driver.new(listener: @listener,
|
370
|
+
http_client: @http_client,
|
371
|
+
capabilities: @caps, # ::Appium::Core::Base::Capabilities
|
371
372
|
url: @custom_url,
|
372
|
-
|
373
|
+
wait_timeout: @wait_timeout,
|
374
|
+
wait_interval: @wait_interval,
|
375
|
+
automation_name: @automation_name)
|
373
376
|
|
374
377
|
if @direct_connect
|
375
378
|
d_c = DirectConnections.new(@driver.capabilities)
|
@@ -410,6 +413,8 @@ module Appium
|
|
410
413
|
|
411
414
|
# Ignore setting default wait if the target driver has no implementation
|
412
415
|
def set_implicit_wait_by_default(wait)
|
416
|
+
return if @default_wait.nil?
|
417
|
+
|
413
418
|
@driver.manage.timeouts.implicit_wait = wait
|
414
419
|
rescue ::Selenium::WebDriver::Error::UnknownError => e
|
415
420
|
unless e.message.include?('The operation requested is not yet implemented')
|
@@ -435,7 +440,8 @@ module Appium
|
|
435
440
|
nil
|
436
441
|
end
|
437
442
|
|
438
|
-
# Returns the server's version info
|
443
|
+
# Returns the server's version info. This method calls +driver.remote_status+ internally
|
444
|
+
#
|
439
445
|
# @return [Hash]
|
440
446
|
#
|
441
447
|
# @example
|
@@ -449,18 +455,20 @@ module Appium
|
|
449
455
|
# }
|
450
456
|
# }
|
451
457
|
#
|
452
|
-
# Returns blank hash
|
458
|
+
# Returns blank hash in a case +driver.remote_status+ got an error
|
459
|
+
# such as Selenium Grid. It returns 500 error against 'remote_status'.
|
453
460
|
#
|
454
461
|
# @example
|
455
462
|
#
|
456
463
|
# @core.appium_server_version #=> {}
|
457
464
|
#
|
458
465
|
def appium_server_version
|
459
|
-
@driver.
|
460
|
-
rescue Selenium::WebDriver::Error::ServerError => e
|
461
|
-
raise ::Appium::Core::Error::ServerError unless e.message.include?('status code 500')
|
466
|
+
return {} if @driver.nil?
|
462
467
|
|
463
|
-
|
468
|
+
@driver.remote_status
|
469
|
+
rescue StandardError
|
470
|
+
# Ignore error case in a case the target appium server
|
471
|
+
# does not support `/status` API.
|
464
472
|
{}
|
465
473
|
end
|
466
474
|
|
@@ -476,21 +484,6 @@ module Appium
|
|
476
484
|
p_version.split('.').map(&:to_i)
|
477
485
|
end
|
478
486
|
|
479
|
-
# Takes a png screenshot and saves to the target path.
|
480
|
-
#
|
481
|
-
# @param png_save_path [String] the full path to save the png
|
482
|
-
# @return [File]
|
483
|
-
#
|
484
|
-
# @example
|
485
|
-
#
|
486
|
-
# @core.screenshot '/tmp/hi.png' #=> nil
|
487
|
-
# # same as '@driver.save_screenshot png_save_path'
|
488
|
-
#
|
489
|
-
def screenshot(png_save_path)
|
490
|
-
::Appium::Logger.warn '[DEPRECATION] screenshot will be removed. Please use driver.save_screenshot instead.'
|
491
|
-
@driver.save_screenshot png_save_path
|
492
|
-
end
|
493
|
-
|
494
487
|
private
|
495
488
|
|
496
489
|
# @private
|
@@ -526,7 +519,7 @@ module Appium
|
|
526
519
|
when :gecko
|
527
520
|
::Appium::Logger.debug('Gecko Driver for macOS')
|
528
521
|
when :mac2
|
529
|
-
::Appium::
|
522
|
+
::Appium::Core::Mac2::Bridge.for self
|
530
523
|
else
|
531
524
|
# no Mac specific extentions
|
532
525
|
::Appium::Logger.debug('macOS Native')
|
@@ -559,36 +552,9 @@ module Appium
|
|
559
552
|
self
|
560
553
|
end
|
561
554
|
|
562
|
-
# @private
|
563
|
-
def validate_keys(opts)
|
564
|
-
flatten_ops = flatten_hash_keys(opts)
|
565
|
-
|
566
|
-
# FIXME: Remove 'desired_capabilities' in the next major Selenium update
|
567
|
-
unless opts.member?(:caps) || opts.member?(:capabilities) || opts.member?(:desired_capabilities)
|
568
|
-
raise Error::NoCapabilityError
|
569
|
-
end
|
570
|
-
|
571
|
-
if !opts.member?(:appium_lib) && flatten_ops.member?(:appium_lib)
|
572
|
-
raise Error::CapabilityStructureError, 'Please check the value of appium_lib in the capability'
|
573
|
-
end
|
574
|
-
|
575
|
-
true
|
576
|
-
end
|
577
|
-
|
578
|
-
# @private
|
579
|
-
def flatten_hash_keys(hash, flatten_keys_result = [])
|
580
|
-
hash.each do |key, value|
|
581
|
-
flatten_keys_result << key
|
582
|
-
flatten_hash_keys(value, flatten_keys_result) if value.is_a?(Hash)
|
583
|
-
end
|
584
|
-
|
585
|
-
flatten_keys_result
|
586
|
-
end
|
587
|
-
|
588
555
|
# @private
|
589
556
|
def get_caps(opts)
|
590
|
-
|
591
|
-
Core::Base::Capabilities.create_capabilities(opts[:caps] || opts[:capabilities] || opts[:desired_capabilities] || {})
|
557
|
+
Core::Base::Capabilities.new(opts[:caps] || opts[:capabilities] || {})
|
592
558
|
end
|
593
559
|
|
594
560
|
# @private
|
@@ -12,14 +12,22 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
# rubocop:disable Style/ClassAndModuleChildren
|
16
15
|
module Appium
|
17
16
|
module Core
|
18
17
|
# Implement useful features for element.
|
19
18
|
# Patch for Selenium Webdriver.
|
20
|
-
class Selenium::WebDriver::Element
|
21
|
-
# To extend Appium related SearchContext into ::Selenium::WebDriver::Element
|
19
|
+
class Element < ::Selenium::WebDriver::Element
|
22
20
|
include ::Appium::Core::Base::SearchContext
|
21
|
+
include ::Appium::Core::Base::TakesScreenshot
|
22
|
+
|
23
|
+
# Retuns the element id.
|
24
|
+
#
|
25
|
+
# @return [String]
|
26
|
+
# @example
|
27
|
+
# e = @driver.find_element :accessibility_id, 'something'
|
28
|
+
# e.id
|
29
|
+
#
|
30
|
+
attr_reader :id
|
23
31
|
|
24
32
|
# Returns the value of attributes like below. Read each platform to know more details.
|
25
33
|
#
|
@@ -60,20 +68,20 @@ module Appium
|
|
60
68
|
#
|
61
69
|
# @example
|
62
70
|
#
|
63
|
-
#
|
71
|
+
# element.immediate_value 'hello'
|
64
72
|
#
|
65
73
|
def immediate_value(*value)
|
66
|
-
@bridge.set_immediate_value
|
74
|
+
@bridge.set_immediate_value @id, *value
|
67
75
|
end
|
68
76
|
|
69
77
|
# Replace the value to element directly
|
70
78
|
#
|
71
79
|
# @example
|
72
80
|
#
|
73
|
-
#
|
81
|
+
# element.replace_value 'hello'
|
74
82
|
#
|
75
83
|
def replace_value(*value)
|
76
|
-
@bridge.replace_value
|
84
|
+
@bridge.replace_value @id, *value
|
77
85
|
end
|
78
86
|
|
79
87
|
# For use with location_rel.
|
@@ -99,7 +107,56 @@ module Appium
|
|
99
107
|
w = driver.window_size
|
100
108
|
::Selenium::WebDriver::Point.new "#{center_x} / #{w.width.to_f}", "#{center_y} / #{w.height.to_f}"
|
101
109
|
end
|
102
|
-
|
110
|
+
|
111
|
+
# Return an element screenshot as base64
|
112
|
+
#
|
113
|
+
# @return String Base 64 encoded string
|
114
|
+
#
|
115
|
+
# @example
|
116
|
+
#
|
117
|
+
# element.screenshot #=> "iVBORw0KGgoAAAANSUhEUgAABDgAAAB+CAIAAABOPDa6AAAAAX"
|
118
|
+
#
|
119
|
+
def screenshot
|
120
|
+
bridge.element_screenshot @id
|
121
|
+
end
|
122
|
+
|
123
|
+
# Return an element screenshot in the given format
|
124
|
+
#
|
125
|
+
# @param [:base64, :png] format
|
126
|
+
# @return String screenshot
|
127
|
+
#
|
128
|
+
# @example
|
129
|
+
#
|
130
|
+
# element.screenshot_as :base64 #=> "iVBORw0KGgoAAAANSUhEUgAABDgAAAB+CAIAAABOPDa6AAAAAX"
|
131
|
+
#
|
132
|
+
def screenshot_as(format)
|
133
|
+
case format
|
134
|
+
when :base64
|
135
|
+
bridge.element_screenshot @id
|
136
|
+
when :png
|
137
|
+
bridge.element_screenshot(@id).unpack('m')[0]
|
138
|
+
else
|
139
|
+
raise Core::Error::UnsupportedOperationError, "unsupported format: #{format.inspect}"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# Save an element screenshot to the given path
|
144
|
+
#
|
145
|
+
# @param [String] png_path A path to save the screenshot
|
146
|
+
# @return [File] Path to the element screenshot.
|
147
|
+
#
|
148
|
+
# @example
|
149
|
+
#
|
150
|
+
# element.save_screenshot("fine_name.png")
|
151
|
+
#
|
152
|
+
def save_screenshot(png_path)
|
153
|
+
extension = File.extname(png_path).downcase
|
154
|
+
if extension != '.png'
|
155
|
+
::Appium::Logger.warn 'name used for saved screenshot does not match file type. '\
|
156
|
+
'It should end with .png extension'
|
157
|
+
end
|
158
|
+
File.open(png_path, 'wb') { |f| f << screenshot_as(:png) }
|
159
|
+
end
|
160
|
+
end # class Element
|
103
161
|
end # module Core
|
104
162
|
end # module Appium
|
105
|
-
# rubocop:enable Style/ClassAndModuleChildren
|
@@ -21,7 +21,7 @@ module Appium
|
|
21
21
|
# will trigger as soon as the file is required. in contrast a method
|
22
22
|
# will trigger only when invoked.
|
23
23
|
def self.patch_webdriver_element
|
24
|
-
::
|
24
|
+
::Appium::Core::Element.class_eval do
|
25
25
|
# Cross platform way of entering text into a textfield
|
26
26
|
def type(text, driver)
|
27
27
|
driver.execute_script %(au.getElement('#{ref}').setValue('#{text}');)
|
@@ -14,11 +14,12 @@
|
|
14
14
|
|
15
15
|
module Appium
|
16
16
|
module Core
|
17
|
-
|
18
|
-
module
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
17
|
+
module Mac2
|
18
|
+
module Bridge
|
19
|
+
def self.for(target)
|
20
|
+
target.extend Appium::Core::Mac2::Device
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module Appium
|
16
|
+
module Core
|
17
|
+
module Mac2
|
18
|
+
module Device
|
19
|
+
module Screen
|
20
|
+
def self.add_methods
|
21
|
+
::Appium::Core::Device.add_endpoint_method(:start_recording_screen) do
|
22
|
+
def start_recording_screen(remote_path: nil, user: nil, pass: nil, method: 'PUT',
|
23
|
+
file_field_name: nil, form_fields: nil, headers: nil, force_restart: nil,
|
24
|
+
fps: nil, preset: nil, video_filter: nil, time_limit: nil,
|
25
|
+
enable_capture_clicks: nil, enable_cursor_capture: nil, device_id: nil)
|
26
|
+
option = ::Appium::Core::Base::Device::ScreenRecord.new(
|
27
|
+
remote_path: remote_path, user: user, pass: pass, method: method,
|
28
|
+
file_field_name: file_field_name, form_fields: form_fields, headers: headers,
|
29
|
+
force_restart: force_restart
|
30
|
+
).upload_option
|
31
|
+
|
32
|
+
option[:fps] = fps unless fps.nil?
|
33
|
+
option[:preset] = preset unless preset.nil?
|
34
|
+
option[:videoFilter] = video_filter unless video_filter.nil?
|
35
|
+
option[:captureClicks] = enable_capture_clicks unless enable_capture_clicks.nil?
|
36
|
+
option[:captureCursor] = enable_cursor_capture unless enable_cursor_capture.nil?
|
37
|
+
option[:deviceId] = device_id unless device_id.nil?
|
38
|
+
option[:timeLimit] = time_limit unless time_limit.nil?
|
39
|
+
|
40
|
+
execute(:start_recording_screen, {}, { options: option })
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end # module Screen
|
45
|
+
end # module Device
|
46
|
+
end # module Mac2
|
47
|
+
end # module Core
|
48
|
+
end # module Appium
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require_relative 'device/screen'
|
16
|
+
|
17
|
+
module Appium
|
18
|
+
module Core
|
19
|
+
module Mac2
|
20
|
+
module Device
|
21
|
+
extend Forwardable
|
22
|
+
|
23
|
+
# rubocop:disable Layout/LineLength
|
24
|
+
|
25
|
+
# @since Appium 1.20.0
|
26
|
+
# @!method start_recording_screen(remote_path: nil, user: nil, pass: nil, method: 'PUT', file_field_name: nil, form_fields: nil, headers: nil, force_restart: nil, fps: nil, preset: nil, video_filter: nil, enable_capture_clicks: nil, enable_cursor_capture: nil, device_id: nil)
|
27
|
+
#
|
28
|
+
# Record the display of devices running iOS Simulator since Xcode 9 or real devices since iOS 11
|
29
|
+
# (ffmpeg utility is required: 'brew install ffmpeg').
|
30
|
+
# We would recommend to play the video by VLC or Mplayer if you can not play the video with other video players.
|
31
|
+
#
|
32
|
+
# @param [String] remote_path The path to the remote location, where the resulting video should be uploaded.
|
33
|
+
# The following protocols are supported: http/https, ftp.
|
34
|
+
# Null or empty string value (the default setting) means the content of resulting
|
35
|
+
# file should be encoded as Base64 and passed as the endpount response value.
|
36
|
+
# An exception will be thrown if the generated media file is too big to
|
37
|
+
# fit into the available process memory.
|
38
|
+
# This option only has an effect if there is screen recording process in progreess
|
39
|
+
# and +forceRestart+ parameter is not set to +true+.
|
40
|
+
# @param [String] user The name of the user for the remote authentication.
|
41
|
+
# @param [String] pass The password for the remote authentication.
|
42
|
+
# @param [String] method The http multipart upload method name. The 'PUT' one is used by default.
|
43
|
+
# @param [String] file_field_name The name of the form field containing the binary payload in multipart/form-data
|
44
|
+
# requests since Appium 1.18.0. Defaults to 'file'.
|
45
|
+
# @param [Array<Hash, Array<String>>] form_fields The form fields mapping in multipart/form-data requests since Appium 1.18.0.
|
46
|
+
# If any entry has the same key in this mapping, then it is going to be ignored.
|
47
|
+
# @param [Hash] headers The additional headers in multipart/form-data requests since Appium 1.18.0.
|
48
|
+
# @param [Boolean] force_restart Whether to try to catch and upload/return the currently running screen recording
|
49
|
+
# (+false+, the default setting on server) or ignore the result of it
|
50
|
+
# and start a new recording immediately (+true+).
|
51
|
+
# @param [integer] fps The count of frames per second in the resulting video.
|
52
|
+
# Increasing fps value also increases the size of the resulting video file and the CPU usage.
|
53
|
+
# The default value is 15.
|
54
|
+
# @param [String] preset A preset is a collection of options that will provide a certain encoding speed to compression ratio.
|
55
|
+
# A slower preset will provide better compression (compression is quality per filesize).
|
56
|
+
# This means that, for example, if you target a certain file size or constant bit rate, you will
|
57
|
+
# achieve better quality with a slower preset. Read https://trac.ffmpeg.org/wiki/Encode/H.264
|
58
|
+
# for more details.
|
59
|
+
# @param [Boolean] enable_cursor_capture Whether to capture the click gestures while recording the screen. Disabled by default.
|
60
|
+
# @param [Boolean] enable_capture_clicks Recording time. 180 seconds is by default.
|
61
|
+
# @param [String] video_filter The video filter spec to apply for ffmpeg.
|
62
|
+
# See https://trac.ffmpeg.org/wiki/FilteringGuide for more details on the possible values.
|
63
|
+
# Example: Set it to +scale=ifnot(gte(iw\,1024)\,iw\,1024):-2+ in order to limit the video width
|
64
|
+
# to 1024px. The height will be adjusted automatically to match the actual screen aspect ratio.
|
65
|
+
# @param [integer] device_id Screen device index to use for the recording.
|
66
|
+
# The list of available devices could be retrieved using
|
67
|
+
# +ffmpeg -f avfoundation -list_devices true -i ""+ command.
|
68
|
+
# This option is mandatory and must be always provided.
|
69
|
+
# @param [String] time_limit The maximum recording time. The default value is 600 seconds (10 minutes).
|
70
|
+
# The minimum time resolution unit is one second.
|
71
|
+
#
|
72
|
+
# @example
|
73
|
+
#
|
74
|
+
# @driver.start_recording_screen
|
75
|
+
# @driver.start_recording_screen fps: 30, enable_cursor_capture: true
|
76
|
+
#
|
77
|
+
|
78
|
+
# rubocop:enable Layout/LineLength
|
79
|
+
|
80
|
+
####
|
81
|
+
## class << self
|
82
|
+
####
|
83
|
+
|
84
|
+
class << self
|
85
|
+
def extended(_mod)
|
86
|
+
Screen.add_methods
|
87
|
+
end
|
88
|
+
end # class << self
|
89
|
+
end # module Device
|
90
|
+
end # module Mac2
|
91
|
+
end # module Core
|
92
|
+
end # module Appium
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# loaded in common/driver.rb
|
16
|
+
require_relative 'mac2/device'
|
17
|
+
require_relative 'mac2/bridge'
|
@@ -14,7 +14,7 @@
|
|
14
14
|
|
15
15
|
module Appium
|
16
16
|
module Core
|
17
|
-
VERSION = '
|
18
|
-
DATE = '
|
17
|
+
VERSION = '5.5.0' unless defined? ::Appium::Core::VERSION
|
18
|
+
DATE = '2022-10-09' unless defined? ::Appium::Core::DATE
|
19
19
|
end
|
20
20
|
end
|
data/lib/appium_lib_core.rb
CHANGED
@@ -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
|