appium_lib 15.1.0 → 15.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|