appium_lib 15.1.0 → 15.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/functional-test.yml +77 -0
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +7 -1
- data/appium_lib.gemspec +2 -2
- data/lib/appium_lib/android/common/helper.rb +1 -1
- data/lib/appium_lib/android/element/button.rb +1 -1
- data/lib/appium_lib/android/espresso/element/button.rb +1 -1
- data/lib/appium_lib/android/uiautomator2/element/button.rb +1 -1
- data/lib/appium_lib/appium.rb +7 -7
- data/lib/appium_lib/driver.rb +89 -24
- data/lib/appium_lib/error.rb +22 -0
- data/lib/appium_lib/ios/common/helper.rb +11 -11
- data/lib/appium_lib/ios/element/textfield.rb +1 -1
- data/lib/appium_lib/ios/xcuitest/element/textfield.rb +1 -1
- data/lib/appium_lib/version.rb +2 -2
- data/release_notes.md +18 -0
- metadata +14 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 750c26700d454f0c25763e97ee928a5444179c44e78cec36376d45e5abf44719
|
4
|
+
data.tar.gz: 7d3e581164f1c57ce7b49b332daf8f105fbd7ff0968b14095bc4fd99feff5a41
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1a1129d4f761e5fca9960ec3963bb62554fc623e91948aaf67f50e3357492fa5e9fbc678ee62513802b1dc345866c56c69e88e6fc45c9a431a1890e9167f0783
|
7
|
+
data.tar.gz: 3863036c2f319fbc4943ace7158838dd88ba47535b05e18b950a987d7d08250711a32cdd57a5cbb046e389a4399e3bffc00951722d8095737dbfa3204228a873
|
@@ -0,0 +1,77 @@
|
|
1
|
+
name: Functional Tests
|
2
|
+
|
3
|
+
on:
|
4
|
+
# Run by manual at this time
|
5
|
+
workflow_dispatch:
|
6
|
+
push:
|
7
|
+
branches: [ master ]
|
8
|
+
pull_request:
|
9
|
+
branches: [ master ]
|
10
|
+
|
11
|
+
concurrency:
|
12
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
13
|
+
cancel-in-progress: true
|
14
|
+
|
15
|
+
jobs:
|
16
|
+
ios_test:
|
17
|
+
runs-on: macos-14
|
18
|
+
env:
|
19
|
+
XCODE_VERSION: 15.3
|
20
|
+
IOS_VERSION: 17.4
|
21
|
+
IOS_DEVICE_NAME: iPhone 15 Plus
|
22
|
+
|
23
|
+
steps:
|
24
|
+
- uses: actions/checkout@v3
|
25
|
+
|
26
|
+
- name: Install Node.js
|
27
|
+
uses: actions/setup-node@v3
|
28
|
+
with:
|
29
|
+
node-version: 'lts/*'
|
30
|
+
|
31
|
+
- name: Select Xcode
|
32
|
+
uses: maxim-lobanov/setup-xcode@v1
|
33
|
+
with:
|
34
|
+
xcode-version: ${{ env.XCODE_VERSION }}
|
35
|
+
- run: defaults write com.apple.iphonesimulator PasteboardAutomaticSync -bool false
|
36
|
+
|
37
|
+
- uses: futureware-tech/simulator-action@v3
|
38
|
+
with:
|
39
|
+
# https://github.com/actions/runner-images/blob/main/images/macos/macos-14-arm64-Readme.md
|
40
|
+
model: ${{ env.IOS_DEVICE_NAME }}
|
41
|
+
os_version: ${{ env.IOS_VERSION }}
|
42
|
+
|
43
|
+
- name: Preparing other environment
|
44
|
+
run: |
|
45
|
+
brew install ffmpeg
|
46
|
+
brew tap wix/brew
|
47
|
+
brew install applesimutils
|
48
|
+
|
49
|
+
# Start Appium
|
50
|
+
- name: Install appium and mjpeg-consumer
|
51
|
+
run: |
|
52
|
+
npm install -g appium
|
53
|
+
npm install -g mjpeg-consumer
|
54
|
+
- run: |
|
55
|
+
appium driver install xcuitest
|
56
|
+
appium plugin install images@2.1.8
|
57
|
+
appium plugin install execute-driver
|
58
|
+
nohup appium --use-plugins=images,execute-driver --relaxed-security --log-timestamp --log-no-colors --base-path=/wd/hub > appium.log &
|
59
|
+
|
60
|
+
- name: Set up Ruby
|
61
|
+
uses: ruby/setup-ruby@v1
|
62
|
+
with:
|
63
|
+
ruby-version: 3.2
|
64
|
+
- run: |
|
65
|
+
bundle install
|
66
|
+
rake ios
|
67
|
+
name: Run tests
|
68
|
+
working-directory: ios_tests
|
69
|
+
|
70
|
+
- name: Save server output
|
71
|
+
if: ${{ always() }}
|
72
|
+
uses: actions/upload-artifact@master
|
73
|
+
with:
|
74
|
+
name: appium-ios_test_with_other_deps.log
|
75
|
+
path: |
|
76
|
+
appium.log
|
77
|
+
test/report/
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -3,8 +3,14 @@ Commit based release not is [release_notes.md](./release_notes.md)
|
|
3
3
|
|
4
4
|
Release tags are https://github.com/appium/ruby_lib/releases .
|
5
5
|
|
6
|
+
## 15.2.1 - 2024-08-03
|
7
|
+
- Fix client side timeout in the default http client
|
8
|
+
- Bump appium_lib_core 9.2.1+ to apply the fix
|
6
9
|
|
7
|
-
##
|
10
|
+
## 15.2.0 - 2024-07-20
|
11
|
+
- Raise defined errors instead of Ruby general errors by appium_lib's own errors
|
12
|
+
|
13
|
+
## 15.1.0 - 2024-05-19
|
8
14
|
- Use appium_lib_core 9.0.0
|
9
15
|
|
10
16
|
## 15.0.1 - 2024-04-26
|
data/appium_lib.gemspec
CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.homepage = 'https://github.com/appium/ruby_lib' # published as appium_lib
|
14
14
|
s.require_paths = ['lib']
|
15
15
|
|
16
|
-
s.add_runtime_dependency 'appium_lib_core', '~> 9.
|
16
|
+
s.add_runtime_dependency 'appium_lib_core', '~> 9.2', '>= 9.2.1'
|
17
17
|
s.add_runtime_dependency 'nokogiri', '~> 1.8', '>= 1.8.1'
|
18
18
|
s.add_runtime_dependency 'tomlrb', '>= 1.1', '< 3.0'
|
19
19
|
|
@@ -24,7 +24,7 @@ Gem::Specification.new do |s|
|
|
24
24
|
s.add_development_dependency 'minitest-reporters', '~> 1.1'
|
25
25
|
s.add_development_dependency 'pry'
|
26
26
|
s.add_development_dependency 'rake', '~> 13.0'
|
27
|
-
s.add_development_dependency 'rubocop', '1.
|
27
|
+
s.add_development_dependency 'rubocop', '1.65.1'
|
28
28
|
s.add_development_dependency 'yard', '~> 0.9.11'
|
29
29
|
|
30
30
|
s.files = `git ls-files`.split("\n").reject { |v| v.match(/\A^(ios_tests|android_tests|grid|test_apps)\/.+/) }
|
@@ -29,7 +29,7 @@ module Appium
|
|
29
29
|
# Android needs to combine button and image button to match iOS.
|
30
30
|
if value.is_a? Numeric
|
31
31
|
index = value
|
32
|
-
raise "#{index} is not a valid index. Must be >= 1" if index <= 0
|
32
|
+
raise ArgumentError, "#{index} is not a valid index. Must be >= 1" if index <= 0
|
33
33
|
|
34
34
|
# 1 indexed
|
35
35
|
return find_element :uiautomator, _button_visible_selectors(index: index)
|
@@ -25,7 +25,7 @@ module Appium
|
|
25
25
|
# Android needs to combine button and image button to match iOS.
|
26
26
|
if value.is_a? Numeric
|
27
27
|
index = value
|
28
|
-
raise "#{index} is not a valid index. Must be >= 1" if index <= 0
|
28
|
+
raise ArgumentError, "#{index} is not a valid index. Must be >= 1" if index <= 0
|
29
29
|
|
30
30
|
# zero index
|
31
31
|
_button_visible_selectors_xpath(index: index - 1)
|
@@ -25,7 +25,7 @@ module Appium
|
|
25
25
|
# Android needs to combine button and image button to match iOS.
|
26
26
|
if value.is_a? Numeric
|
27
27
|
index = value
|
28
|
-
raise "#{index} is not a valid index. Must be >= 1" if index <= 0
|
28
|
+
raise ArgumentError, "#{index} is not a valid index. Must be >= 1" if index <= 0
|
29
29
|
|
30
30
|
result = find_elements :uiautomator, _button_visible_selectors(index: index)
|
31
31
|
raise _no_such_element if result.empty?
|
data/lib/appium_lib/appium.rb
CHANGED
@@ -56,11 +56,11 @@ module Appium
|
|
56
56
|
# @param opts [Hash] file: '/path/to/appium.txt', verbose: true
|
57
57
|
# @return [hash] the symbolized hash with updated :app and :require keys
|
58
58
|
def load_settings(opts = {})
|
59
|
-
raise 'opts must be a hash' unless opts.is_a? Hash
|
60
|
-
raise 'opts must not be empty' if opts.empty?
|
59
|
+
raise ArgumentError, 'opts must be a hash' unless opts.is_a? Hash
|
60
|
+
raise ArgumentError, 'opts must not be empty' if opts.empty?
|
61
61
|
|
62
62
|
toml = opts[:file]
|
63
|
-
raise 'Must pass a capability file which has [caps] and [appium_lib]' unless toml
|
63
|
+
raise ArgumentError, 'Must pass a capability file which has [caps] and [appium_lib]' unless toml
|
64
64
|
|
65
65
|
verbose = opts.fetch :verbose, false
|
66
66
|
|
@@ -69,7 +69,7 @@ module Appium
|
|
69
69
|
toml_exists = File.exist? toml
|
70
70
|
Appium::Logger.info "Exists? #{toml_exists}" if verbose
|
71
71
|
|
72
|
-
raise "toml doesn't exist #{toml}" unless toml_exists
|
72
|
+
raise ArgumentError, "toml doesn't exist #{toml}" unless toml_exists
|
73
73
|
|
74
74
|
require 'tomlrb'
|
75
75
|
Appium::Logger.info "Loading #{toml}" if verbose
|
@@ -151,7 +151,7 @@ module Appium
|
|
151
151
|
# @param [Array<Module>] modules An array of modules
|
152
152
|
# @param [Driver] driver A driver to extend for
|
153
153
|
def promote_singleton_appium_methods(modules, driver = $driver)
|
154
|
-
raise 'Global $driver is nil' if driver.nil?
|
154
|
+
raise ArgumentError, 'Global $driver is nil' if driver.nil?
|
155
155
|
|
156
156
|
target_modules = []
|
157
157
|
|
@@ -160,7 +160,7 @@ module Appium
|
|
160
160
|
target_modules << modules.const_get(sub_module)
|
161
161
|
end
|
162
162
|
else
|
163
|
-
raise 'modules must be a module or an array' unless modules.is_a? Array
|
163
|
+
raise ArgumentError, 'modules must be a module or an array' unless modules.is_a? Array
|
164
164
|
|
165
165
|
target_modules = modules
|
166
166
|
end
|
@@ -205,7 +205,7 @@ module Appium
|
|
205
205
|
# Appium.promote_appium_methods Minitest::Spec
|
206
206
|
#
|
207
207
|
def promote_appium_methods(class_array, driver = $driver)
|
208
|
-
raise 'Driver is nil' if driver.nil?
|
208
|
+
raise ArgumentError, 'Driver is nil' if driver.nil?
|
209
209
|
|
210
210
|
# Wrap single class into an array
|
211
211
|
class_array = [class_array] unless class_array.instance_of? Array
|
data/lib/appium_lib/driver.rb
CHANGED
@@ -40,6 +40,26 @@ require 'uri'
|
|
40
40
|
|
41
41
|
module Appium
|
42
42
|
class Driver
|
43
|
+
# @private
|
44
|
+
class << self
|
45
|
+
def convert_to_symbol(value)
|
46
|
+
if value.nil?
|
47
|
+
value
|
48
|
+
else
|
49
|
+
value.to_sym
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# @private
|
54
|
+
def get_cap(caps, name)
|
55
|
+
name_with_prefix = "#{::Appium::Core::Base::Bridge::APPIUM_PREFIX}#{name}"
|
56
|
+
caps[convert_to_symbol name] ||
|
57
|
+
caps[name] ||
|
58
|
+
caps[convert_to_symbol name_with_prefix] ||
|
59
|
+
caps[name_with_prefix]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
43
63
|
# attr readers are promoted to global scope. To avoid clobbering, they're
|
44
64
|
# made available via the driver_attributes method
|
45
65
|
#
|
@@ -156,7 +176,7 @@ module Appium
|
|
156
176
|
|
157
177
|
$driver&.driver_quit if global_driver
|
158
178
|
|
159
|
-
raise 'opts must be a hash' unless opts.is_a? Hash
|
179
|
+
raise ArgumentError, 'opts must be a hash' unless opts.is_a? Hash
|
160
180
|
|
161
181
|
@core = ::Appium::Core.for(opts)
|
162
182
|
extend ::Appium::Core::Device
|
@@ -248,15 +268,11 @@ module Appium
|
|
248
268
|
return unless @core.caps
|
249
269
|
|
250
270
|
# return the path exists on the local
|
251
|
-
|
252
|
-
return if
|
271
|
+
app_path = Driver.get_cap(@core.caps, 'app')
|
272
|
+
return if !app_path.nil? && File.exist?(app_path)
|
253
273
|
|
254
274
|
# The app file is not exact path
|
255
|
-
|
256
|
-
@core.caps['app'] = self.class.absolute_app_path opts
|
257
|
-
elsif !@core.caps[:app].nil?
|
258
|
-
@core.caps[:app] = self.class.absolute_app_path opts
|
259
|
-
end
|
275
|
+
@core.caps['app'] = self.class.absolute_app_path opts
|
260
276
|
end
|
261
277
|
|
262
278
|
# @private
|
@@ -329,7 +345,7 @@ module Appium
|
|
329
345
|
# action.click(element).perform # The `click` is a part of `PointerActions`
|
330
346
|
#
|
331
347
|
def action
|
332
|
-
@driver
|
348
|
+
@driver&.action
|
333
349
|
end
|
334
350
|
|
335
351
|
# Returns the server's version info
|
@@ -384,12 +400,11 @@ module Appium
|
|
384
400
|
#
|
385
401
|
# @return [String] APP_PATH as an absolute path
|
386
402
|
def self.absolute_app_path(opts)
|
387
|
-
raise 'opts must be a hash' unless opts.is_a? Hash
|
403
|
+
raise ArgumentError, 'opts must be a hash' unless opts.is_a? Hash
|
388
404
|
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
raise 'absolute_app_path invoked and app is not set!' if app_path.nil? || app_path.empty?
|
405
|
+
caps = opts[:caps] || opts['caps'] || {}
|
406
|
+
app_path = get_cap(caps, 'app')
|
407
|
+
raise ArgumentError, 'absolute_app_path invoked and app is not set!' if app_path.nil? || app_path.empty?
|
393
408
|
# Sauce storage API. http://saucelabs.com/docs/rest#storage
|
394
409
|
return app_path if app_path.start_with? 'sauce-storage:'
|
395
410
|
return app_path if app_path =~ URI::DEFAULT_PARSER.make_regexp # public URL for Sauce
|
@@ -431,7 +446,7 @@ module Appium
|
|
431
446
|
# @param png_save_path [String] the full path to save the png
|
432
447
|
# @return [File]
|
433
448
|
def screenshot(png_save_path)
|
434
|
-
@driver
|
449
|
+
@driver&.save_screenshot png_save_path
|
435
450
|
end
|
436
451
|
|
437
452
|
# Takes a png screenshot of particular element's area
|
@@ -445,7 +460,7 @@ module Appium
|
|
445
460
|
# @param [String] png_save_path the full path to save the png
|
446
461
|
# @return [File]
|
447
462
|
def element_screenshot(element, png_save_path)
|
448
|
-
@driver
|
463
|
+
@driver&.take_element_screenshot element, png_save_path
|
449
464
|
nil
|
450
465
|
end
|
451
466
|
|
@@ -469,6 +484,9 @@ module Appium
|
|
469
484
|
# size.height #=> Integer
|
470
485
|
#
|
471
486
|
def window_size
|
487
|
+
# maybe exception is expected as no driver created
|
488
|
+
raise NoDriverInstanceError if @driver.nil?
|
489
|
+
|
472
490
|
@driver.window_size
|
473
491
|
end
|
474
492
|
|
@@ -484,6 +502,8 @@ module Appium
|
|
484
502
|
# size.y #=> Integer
|
485
503
|
#
|
486
504
|
def window_rect
|
505
|
+
raise NoDriverInstanceError if @driver.nil?
|
506
|
+
|
487
507
|
@driver.window_rect
|
488
508
|
end
|
489
509
|
|
@@ -516,8 +536,11 @@ module Appium
|
|
516
536
|
# @option http_client_ops [Hash] :open_timeout Custom open timeout for http client.
|
517
537
|
# @option http_client_ops [Hash] :read_timeout Custom read timeout for http client.
|
518
538
|
# @return [Selenium::WebDriver] the new global driver
|
519
|
-
def start_driver(http_client_ops =
|
520
|
-
|
539
|
+
def start_driver(http_client_ops = { http_client: nil, open_timeout: 999_999, read_timeout: 999_999 })
|
540
|
+
if http_client_ops[:http_client].nil?
|
541
|
+
http_client = ::Appium::Http::Default.new(open_timeout: http_client_ops[:open_timeout],
|
542
|
+
read_timeout: http_client_ops[:read_timeout])
|
543
|
+
end
|
521
544
|
|
522
545
|
# TODO: do not kill the previous session in the future version.
|
523
546
|
if $driver.nil?
|
@@ -530,7 +553,12 @@ module Appium
|
|
530
553
|
# starting driver.
|
531
554
|
automation_name = @core.automation_name
|
532
555
|
|
533
|
-
@driver = @core.start_driver(server_url: server_url,
|
556
|
+
@driver = @core.start_driver(server_url: server_url,
|
557
|
+
http_client_ops: {
|
558
|
+
http_client: http_client,
|
559
|
+
open_timeout: 999_999,
|
560
|
+
read_timeout: 999_999
|
561
|
+
})
|
534
562
|
@http_client = @core.http_client
|
535
563
|
|
536
564
|
# if automation_name was nil before start_driver, then re-extend driver specific methods
|
@@ -555,7 +583,7 @@ module Appium
|
|
555
583
|
|
556
584
|
# Set implicit wait to zero.
|
557
585
|
def no_wait
|
558
|
-
@driver
|
586
|
+
@driver&.manage&.timeouts&.implicit_wait = 0
|
559
587
|
end
|
560
588
|
|
561
589
|
# Set implicit wait. Default to @default_wait.
|
@@ -570,7 +598,7 @@ module Appium
|
|
570
598
|
# @return [void]
|
571
599
|
def set_wait(timeout = nil)
|
572
600
|
timeout = @default_wait if timeout.nil?
|
573
|
-
@driver
|
601
|
+
@driver&.manage&.timeouts&.implicit_wait = timeout
|
574
602
|
end
|
575
603
|
|
576
604
|
# Returns existence of element.
|
@@ -589,9 +617,9 @@ module Appium
|
|
589
617
|
# do not uset set_wait here.
|
590
618
|
# it will cause problems with other methods reading the default_wait of 0
|
591
619
|
# which then gets converted to a 1 second wait.
|
592
|
-
@driver
|
620
|
+
@driver&.manage&.timeouts&.implicit_wait = pre_check
|
593
621
|
# the element exists unless an error is raised.
|
594
|
-
exists
|
622
|
+
exists = true
|
595
623
|
|
596
624
|
begin
|
597
625
|
yield # search for element
|
@@ -600,7 +628,7 @@ module Appium
|
|
600
628
|
end
|
601
629
|
|
602
630
|
# restore wait
|
603
|
-
@driver
|
631
|
+
@driver&.manage&.timeouts&.implicit_wait = post_check if post_check != pre_check
|
604
632
|
|
605
633
|
exists
|
606
634
|
end
|
@@ -610,6 +638,8 @@ module Appium
|
|
610
638
|
# @param [*args] args The args to pass to the script
|
611
639
|
# @return [Object]
|
612
640
|
def execute_script(script, *args)
|
641
|
+
raise NoDriverInstanceError if @driver.nil?
|
642
|
+
|
613
643
|
@driver.execute_script script, *args
|
614
644
|
end
|
615
645
|
|
@@ -618,6 +648,8 @@ module Appium
|
|
618
648
|
###
|
619
649
|
# Get the window handles of open browser windows
|
620
650
|
def execute_async_script(script, *args)
|
651
|
+
raise NoDriverInstanceError if @driver.nil?
|
652
|
+
|
621
653
|
@driver.execute_async_script script, *args
|
622
654
|
end
|
623
655
|
|
@@ -650,41 +682,59 @@ module Appium
|
|
650
682
|
# r.logs #=> The `logs` key part as `{'log' => [], 'warn' => [], 'error' => []}`
|
651
683
|
#
|
652
684
|
def execute_driver(script: '', type: 'webdriverio', timeout_ms: nil)
|
685
|
+
raise NoDriverInstanceError if @driver.nil?
|
686
|
+
|
653
687
|
@driver.execute_driver(script: script, type: type, timeout_ms: timeout_ms)
|
654
688
|
end
|
655
689
|
|
656
690
|
def window_handles
|
691
|
+
raise NoDriverInstanceError if @driver.nil?
|
692
|
+
|
657
693
|
@driver.window_handles
|
658
694
|
end
|
659
695
|
|
660
696
|
# Get the current window handle
|
661
697
|
def window_handle
|
698
|
+
raise NoDriverInstanceError if @driver.nil?
|
699
|
+
|
662
700
|
@driver.window_handle
|
663
701
|
end
|
664
702
|
|
665
703
|
def navigate
|
704
|
+
raise NoDriverInstanceError if @driver.nil?
|
705
|
+
|
666
706
|
@driver.navigate
|
667
707
|
end
|
668
708
|
|
669
709
|
def manage
|
710
|
+
raise NoDriverInstanceError if @driver.nil?
|
711
|
+
|
670
712
|
@driver.manage
|
671
713
|
end
|
672
714
|
|
673
715
|
def get(url)
|
716
|
+
raise NoDriverInstanceError if @driver.nil?
|
717
|
+
|
674
718
|
@driver.get(url)
|
675
719
|
end
|
676
720
|
|
677
721
|
def current_url
|
722
|
+
raise NoDriverInstanceError if @driver.nil?
|
723
|
+
|
678
724
|
@driver.current_url
|
679
725
|
end
|
680
726
|
|
681
727
|
def title
|
728
|
+
raise NoDriverInstanceError if @driver.nil?
|
729
|
+
|
682
730
|
@driver.title
|
683
731
|
end
|
684
732
|
|
685
733
|
# @return [TargetLocator]
|
686
734
|
# @see TargetLocator
|
687
735
|
def switch_to
|
736
|
+
raise NoDriverInstanceError if @driver.nil?
|
737
|
+
|
688
738
|
@driver.switch_to
|
689
739
|
end
|
690
740
|
###
|
@@ -712,6 +762,8 @@ module Appium
|
|
712
762
|
# @param [*args] args The args to use
|
713
763
|
# @return [Array<Element>] Array is empty when no elements are found.
|
714
764
|
def find_elements(*args)
|
765
|
+
raise NoDriverInstanceError if @driver.nil?
|
766
|
+
|
715
767
|
@driver.find_elements(*args)
|
716
768
|
end
|
717
769
|
|
@@ -728,6 +780,8 @@ module Appium
|
|
728
780
|
# @param [*args] args The args to use
|
729
781
|
# @return [Element]
|
730
782
|
def find_element(*args)
|
783
|
+
raise NoDriverInstanceError if @driver.nil?
|
784
|
+
|
731
785
|
@driver.find_element(*args)
|
732
786
|
end
|
733
787
|
|
@@ -743,6 +797,8 @@ module Appium
|
|
743
797
|
# @driver.find_element_by_image './test/functional/data/test_element_image.png'
|
744
798
|
#
|
745
799
|
def find_element_by_image(png_img_path)
|
800
|
+
raise NoDriverInstanceError if @driver.nil?
|
801
|
+
|
746
802
|
@driver.find_element_by_image(png_img_path)
|
747
803
|
end
|
748
804
|
|
@@ -758,6 +814,8 @@ module Appium
|
|
758
814
|
# @driver.find_elements_by_image ['./test/functional/data/test_element_image.png']
|
759
815
|
#
|
760
816
|
def find_elements_by_image(png_img_paths)
|
817
|
+
raise NoDriverInstanceError if @driver.nil?
|
818
|
+
|
761
819
|
@driver.find_elements_by_image(png_img_paths)
|
762
820
|
end
|
763
821
|
|
@@ -771,6 +829,8 @@ module Appium
|
|
771
829
|
# @option opts [Float] :altitude the altitude, defaulting to 75
|
772
830
|
# @return [Selenium::WebDriver::Location] the location constructed by the selenium webdriver
|
773
831
|
def set_location(opts = {})
|
832
|
+
raise NoDriverInstanceError if @driver.nil?
|
833
|
+
|
774
834
|
latitude = opts.fetch(:latitude)
|
775
835
|
longitude = opts.fetch(:longitude)
|
776
836
|
altitude = opts.fetch(:altitude, 75)
|
@@ -794,10 +854,13 @@ module Appium
|
|
794
854
|
# # 'appium:anotherEvent' => 1572959315}
|
795
855
|
#
|
796
856
|
def log_event(vendor:, event:)
|
857
|
+
raise NoDriverInstanceError if @driver.nil?
|
858
|
+
|
797
859
|
@driver.logs.event vendor: vendor, event: event
|
798
860
|
end
|
799
861
|
|
800
862
|
def log_event=(log_event)
|
863
|
+
raise if @driver.nil?
|
801
864
|
unless log_event.is_a?(Hash)
|
802
865
|
raise ::Appium::Core::Error::ArgumentError('log_event should be Hash like { vendor: "appium", event: "funEvent"}')
|
803
866
|
end
|
@@ -817,6 +880,8 @@ module Appium
|
|
817
880
|
# log_events #=> {'commands' => [{'cmd' => 123455, ....}], 'startTime' => 1572954894127, }
|
818
881
|
#
|
819
882
|
def log_events(type = nil)
|
883
|
+
raise NoDriverInstanceError if @driver.nil?
|
884
|
+
|
820
885
|
@driver.logs.events(type)
|
821
886
|
end
|
822
887
|
|
@@ -0,0 +1,22 @@
|
|
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
|
+
class Error < StandardError; end
|
17
|
+
|
18
|
+
# Driver instance hasn't been created yet.
|
19
|
+
class NoDriverInstanceError < Appium::Error; end
|
20
|
+
|
21
|
+
class ArgumentError < ArgumentError; end
|
22
|
+
end
|
@@ -107,7 +107,7 @@ module Appium
|
|
107
107
|
# @param index [Integer] the index
|
108
108
|
# @return [Element]
|
109
109
|
def ele_index(class_name, index)
|
110
|
-
raise 'Index must be >= 1' unless index == 'last()' || (index.is_a?(Integer) && index >= 1)
|
110
|
+
raise ArgumentError, 'Index must be >= 1' unless index == 'last()' || (index.is_a?(Integer) && index >= 1)
|
111
111
|
|
112
112
|
elements = tags(class_name)
|
113
113
|
|
@@ -376,7 +376,7 @@ module Appium
|
|
376
376
|
#
|
377
377
|
def _all_pred(opts)
|
378
378
|
predicate = opts[:predicate]
|
379
|
-
raise 'predicate must be provided' unless predicate
|
379
|
+
raise ArgumentError, 'predicate must be provided' unless predicate
|
380
380
|
|
381
381
|
visible = opts.fetch :visible, true
|
382
382
|
%($.mainApp().getAllWithPredicate("#{predicate}", #{visible});)
|
@@ -404,23 +404,23 @@ module Appium
|
|
404
404
|
end
|
405
405
|
|
406
406
|
def _validate_object(*objects)
|
407
|
-
raise 'objects must be an array' unless objects.is_a? Array
|
407
|
+
raise ArgumentError, 'objects must be an array' unless objects.is_a? Array
|
408
408
|
|
409
409
|
objects.each do |obj|
|
410
410
|
next unless obj # obj may be nil. if so, ignore.
|
411
411
|
|
412
412
|
valid_keys = %i[target substring insensitive]
|
413
413
|
unknown_keys = obj.keys - valid_keys
|
414
|
-
raise "Unknown keys: #{unknown_keys}" unless unknown_keys.empty?
|
414
|
+
raise ArgumentError, "Unknown keys: #{unknown_keys}" unless unknown_keys.empty?
|
415
415
|
|
416
416
|
target = obj[:target]
|
417
|
-
raise 'target must be a string' unless target.is_a? String
|
417
|
+
raise ArgumentError, 'target must be a string' unless target.is_a? String
|
418
418
|
|
419
419
|
substring = obj[:substring]
|
420
|
-
raise 'substring must be a boolean' unless [true, false].include? substring
|
420
|
+
raise ArgumentError, 'substring must be a boolean' unless [true, false].include? substring
|
421
421
|
|
422
422
|
insensitive = obj[:insensitive]
|
423
|
-
raise 'insensitive must be a boolean' unless [true, false].include? insensitive
|
423
|
+
raise ArgumentError, 'insensitive must be a boolean' unless [true, false].include? insensitive
|
424
424
|
end
|
425
425
|
end
|
426
426
|
|
@@ -456,16 +456,16 @@ module Appium
|
|
456
456
|
def _by_json(opts)
|
457
457
|
valid_keys = %i(typeArray onlyFirst onlyVisible name label value)
|
458
458
|
unknown_keys = opts.keys - valid_keys
|
459
|
-
raise "Unknown keys: #{unknown_keys}" unless unknown_keys.empty?
|
459
|
+
raise ArgumentError, "Unknown keys: #{unknown_keys}" unless unknown_keys.empty?
|
460
460
|
|
461
461
|
type_array = opts[:typeArray]
|
462
|
-
raise 'typeArray must be an array' unless type_array.is_a? Array
|
462
|
+
raise ArgumentError, 'typeArray must be an array' unless type_array.is_a? Array
|
463
463
|
|
464
464
|
only_first = opts[:onlyFirst]
|
465
|
-
raise 'onlyFirst must be a boolean' unless [true, false].include? only_first
|
465
|
+
raise ArgumentError, 'onlyFirst must be a boolean' unless [true, false].include? only_first
|
466
466
|
|
467
467
|
only_visible = opts[:onlyVisible]
|
468
|
-
raise 'onlyVisible must be a boolean' unless [true, false].include? only_visible
|
468
|
+
raise ArgumentError, 'onlyVisible must be a boolean' unless [true, false].include? only_visible
|
469
469
|
|
470
470
|
# name/label/value are optional. when searching for class only, then none
|
471
471
|
# will be present.
|
@@ -42,7 +42,7 @@ module Appium
|
|
42
42
|
def textfield(value)
|
43
43
|
if value.is_a? Numeric
|
44
44
|
index = value
|
45
|
-
raise "#{index} is not a valid index. Must be >= 1" if index <= 0
|
45
|
+
raise ArgumentError, "#{index} is not a valid index. Must be >= 1" if index <= 0
|
46
46
|
|
47
47
|
index -= 1 # eles_by_json and _textfields_with_predicate is 0 indexed.
|
48
48
|
result = eles_by_json(_textfield_visible)[index]
|
@@ -37,7 +37,7 @@ module Appium
|
|
37
37
|
def textfield(value)
|
38
38
|
if value.is_a? Numeric
|
39
39
|
index = value
|
40
|
-
raise "#{index} is not a valid index. Must be >= 1" if index <= 0
|
40
|
+
raise ArgumentError, "#{index} is not a valid index. Must be >= 1" if index <= 0
|
41
41
|
|
42
42
|
index -= 1 # eles_by_json and _textfields_with_predicate is 0 indexed.
|
43
43
|
result = _textfields_with_predicate[index]
|
data/lib/appium_lib/version.rb
CHANGED
@@ -14,6 +14,6 @@
|
|
14
14
|
|
15
15
|
module Appium
|
16
16
|
# Version and Date are defined on the 'Appium' module, not 'Appium::Common'
|
17
|
-
VERSION = '15.1
|
18
|
-
DATE = '2024-
|
17
|
+
VERSION = '15.2.1' unless defined? ::Appium::VERSION
|
18
|
+
DATE = '2024-08-03' unless defined? ::Appium::DATE
|
19
19
|
end
|
data/release_notes.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
#### v15.2.1 2024-08-03
|
2
|
+
|
3
|
+
- [693dc16](https://github.com/appium/ruby_lib/commit/693dc167cbbcbe1ab08d1142958207d635c480a3) Release 15.2.1
|
4
|
+
- [d98126c](https://github.com/appium/ruby_lib/commit/d98126c47e04d7d152f85a2a75c3fdcb3011ae96) ci: add ci (#1037)
|
5
|
+
- [fd2e639](https://github.com/appium/ruby_lib/commit/fd2e639b62e9b5c533915e7e860621391479c4aa) chore: modify rubocop.yml a bit
|
6
|
+
- [0d1c2b8](https://github.com/appium/ruby_lib/commit/0d1c2b87b8f2ac456372bf4cbb2441fffae5cf27) chore: Update rubocop requirement from = 1.65.0 to = 1.65.1 (#1036)
|
7
|
+
|
8
|
+
|
9
|
+
#### v15.2.0 2024-07-20
|
10
|
+
|
11
|
+
- [d73525e](https://github.com/appium/ruby_lib/commit/d73525eec584c3c31690dcd55a6c52d641d43f9f) Release 15.2.0
|
12
|
+
- [6b5d969](https://github.com/appium/ruby_lib/commit/6b5d9693f10e64a521f6ac5d31c78d71e5f0f6be) feat: raise its own defined errors (#1035)
|
13
|
+
- [4a74c60](https://github.com/appium/ruby_lib/commit/4a74c60937e66bf028a66e4f05a324ce8b2077ce) chore: Update rubocop requirement from = 1.64.1 to = 1.65.0 (#1034)
|
14
|
+
- [fa4cea4](https://github.com/appium/ruby_lib/commit/fa4cea4e5bea0aa4e3ed7052ba77812c82684fe0) chore: Update rubocop requirement from = 1.64.0 to = 1.64.1 (#1033)
|
15
|
+
- [96ce262](https://github.com/appium/ruby_lib/commit/96ce26264d985b5260e99573486e8f712bfb12e3) chore: Update rubocop requirement from = 1.63.5 to = 1.64.0 (#1032)
|
16
|
+
- [14590cc](https://github.com/appium/ruby_lib/commit/14590cce6f6cbef8c20e12ae10b00bf3f7b5ab3a) chore: tweak changelog format
|
17
|
+
|
18
|
+
|
1
19
|
#### v15.1.0 2024-05-19
|
2
20
|
|
3
21
|
- [b1534cc](https://github.com/appium/ruby_lib/commit/b1534cc8e781e37f9632fa1cbaa6e2422b6a768d) Release 15.1.0
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: appium_lib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 15.1
|
4
|
+
version: 15.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- code@bootstraponline.com
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2024-
|
12
|
+
date: 2024-08-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: appium_lib_core
|
@@ -17,14 +17,20 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '9.
|
20
|
+
version: '9.2'
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 9.2.1
|
21
24
|
type: :runtime
|
22
25
|
prerelease: false
|
23
26
|
version_requirements: !ruby/object:Gem::Requirement
|
24
27
|
requirements:
|
25
28
|
- - "~>"
|
26
29
|
- !ruby/object:Gem::Version
|
27
|
-
version: '9.
|
30
|
+
version: '9.2'
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 9.2.1
|
28
34
|
- !ruby/object:Gem::Dependency
|
29
35
|
name: nokogiri
|
30
36
|
requirement: !ruby/object:Gem::Requirement
|
@@ -169,14 +175,14 @@ dependencies:
|
|
169
175
|
requirements:
|
170
176
|
- - '='
|
171
177
|
- !ruby/object:Gem::Version
|
172
|
-
version: 1.
|
178
|
+
version: 1.65.1
|
173
179
|
type: :development
|
174
180
|
prerelease: false
|
175
181
|
version_requirements: !ruby/object:Gem::Requirement
|
176
182
|
requirements:
|
177
183
|
- - '='
|
178
184
|
- !ruby/object:Gem::Version
|
179
|
-
version: 1.
|
185
|
+
version: 1.65.1
|
180
186
|
- !ruby/object:Gem::Dependency
|
181
187
|
name: yard
|
182
188
|
requirement: !ruby/object:Gem::Requirement
|
@@ -203,6 +209,7 @@ files:
|
|
203
209
|
- ".github/ISSUE_TEMPLATE.md"
|
204
210
|
- ".github/PULL_REQUEST_TEMPLATE.md"
|
205
211
|
- ".github/dependabot.yml"
|
212
|
+
- ".github/workflows/functional-test.yml"
|
206
213
|
- ".github/workflows/rubocop.yml"
|
207
214
|
- ".gitignore"
|
208
215
|
- ".rubocop.yml"
|
@@ -247,6 +254,7 @@ files:
|
|
247
254
|
- lib/appium_lib/common/log.rb
|
248
255
|
- lib/appium_lib/common/wait.rb
|
249
256
|
- lib/appium_lib/driver.rb
|
257
|
+
- lib/appium_lib/error.rb
|
250
258
|
- lib/appium_lib/ios/common/errors.rb
|
251
259
|
- lib/appium_lib/ios/common/helper.rb
|
252
260
|
- lib/appium_lib/ios/element/alert.rb
|