appium_lib 6.0.0 → 7.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +28 -0
- data/.travis.yml +10 -0
- data/Rakefile +9 -1
- data/android_tests/Gemfile +1 -1
- data/android_tests/Rakefile +20 -13
- data/android_tests/lib/android/specs/android/element/alert.rb +1 -1
- data/android_tests/lib/android/specs/android/element/button.rb +2 -2
- data/android_tests/lib/android/specs/android/element/generic.rb +1 -2
- data/android_tests/lib/android/specs/android/element/text.rb +2 -3
- data/android_tests/lib/android/specs/android/element/textfield.rb +2 -2
- data/android_tests/lib/android/specs/android/helper.rb +5 -3
- data/android_tests/lib/android/specs/android/patch.rb +2 -2
- data/android_tests/lib/android/specs/common/device.rb +16 -9
- data/android_tests/lib/android/specs/common/device_touchaction.rb +5 -2
- data/android_tests/lib/android/specs/common/element/window.rb +1 -1
- data/android_tests/lib/android/specs/common/helper.rb +14 -15
- data/android_tests/lib/android/specs/common/patch.rb +11 -9
- data/android_tests/lib/android/specs/common/version.rb +3 -3
- data/android_tests/lib/android/specs/common/web_context.rb +2 -3
- data/android_tests/lib/android/specs/driver.rb +38 -29
- data/android_tests/lib/android/specs/install.rb +3 -3
- data/android_tests/lib/format.rb +6 -8
- data/android_tests/lib/run.rb +25 -17
- data/android_tests/readme.md +4 -2
- data/appium_lib.gemspec +13 -11
- data/contributing.md +1 -1
- data/docs/android_docs.md +358 -274
- data/docs/ios_docs.md +333 -270
- data/docs/migration.md +10 -0
- data/docs_gen/make_docs.rb +3 -1
- data/ios_tests/Gemfile +1 -1
- data/ios_tests/Rakefile +17 -10
- data/ios_tests/appium.txt +1 -1
- data/ios_tests/lib/common.rb +8 -4
- data/ios_tests/lib/format.rb +5 -7
- data/ios_tests/lib/ios/specs/common/element/window.rb +1 -1
- data/ios_tests/lib/ios/specs/common/helper.rb +40 -39
- data/ios_tests/lib/ios/specs/common/patch.rb +15 -11
- data/ios_tests/lib/ios/specs/common/version.rb +3 -3
- data/ios_tests/lib/ios/specs/common/web_context.rb +1 -2
- data/ios_tests/lib/ios/specs/device/device.rb +7 -7
- data/ios_tests/lib/ios/specs/device/multi_touch.rb +6 -8
- data/ios_tests/lib/ios/specs/device/touch_actions.rb +12 -12
- data/ios_tests/lib/ios/specs/driver.rb +23 -22
- data/ios_tests/lib/ios/specs/ios/element/alert.rb +6 -2
- data/ios_tests/lib/ios/specs/ios/element/button.rb +2 -2
- data/ios_tests/lib/ios/specs/ios/element/generic.rb +1 -1
- data/ios_tests/lib/ios/specs/ios/element/text.rb +4 -1
- data/ios_tests/lib/ios/specs/ios/element/textfield.rb +6 -6
- data/ios_tests/lib/ios/specs/ios/helper.rb +5 -5
- data/ios_tests/lib/ios/specs/ios/patch.rb +2 -2
- data/ios_tests/lib/run.rb +1 -1
- data/ios_tests/readme.md +3 -3
- data/ios_tests/upload/sauce_storage.rb +8 -8
- data/ios_tests/upload/upload.rb +1 -1
- data/lib/appium_lib/android/client_xpath.rb +7 -7
- data/lib/appium_lib/android/element/alert.rb +2 -2
- data/lib/appium_lib/android/element/button.rb +16 -16
- data/lib/appium_lib/android/element/generic.rb +12 -13
- data/lib/appium_lib/android/element/text.rb +5 -5
- data/lib/appium_lib/android/element/textfield.rb +5 -5
- data/lib/appium_lib/android/helper.rb +82 -52
- data/lib/appium_lib/android/mobile_methods.rb +2 -2
- data/lib/appium_lib/android/patch.rb +3 -3
- data/lib/appium_lib/common/element/window.rb +1 -1
- data/lib/appium_lib/common/helper.rb +30 -35
- data/lib/appium_lib/common/patch.rb +22 -20
- data/lib/appium_lib/common/version.rb +3 -3
- data/lib/appium_lib/common/wait.rb +9 -10
- data/lib/appium_lib/device/device.rb +39 -33
- data/lib/appium_lib/device/multi_touch.rb +5 -7
- data/lib/appium_lib/device/touch_actions.rb +14 -15
- data/lib/appium_lib/driver.rb +97 -76
- data/lib/appium_lib/ios/element/alert.rb +1 -1
- data/lib/appium_lib/ios/element/button.rb +5 -5
- data/lib/appium_lib/ios/element/generic.rb +5 -6
- data/lib/appium_lib/ios/element/text.rb +5 -5
- data/lib/appium_lib/ios/element/textfield.rb +15 -15
- data/lib/appium_lib/ios/helper.rb +103 -90
- data/lib/appium_lib/ios/mobile_methods.rb +2 -2
- data/lib/appium_lib/ios/patch.rb +4 -4
- data/lib/appium_lib/logger.rb +7 -5
- data/lib/appium_lib/rails/duplicable.rb +3 -1
- data/readme.md +7 -1
- data/release_notes.md +152 -0
- metadata +28 -54
@@ -7,11 +7,11 @@ module Appium
|
|
7
7
|
# ```ruby
|
8
8
|
# find_elements :uiautomator, 'new UiSelector().clickable(true)'
|
9
9
|
# ```
|
10
|
-
def extended(
|
10
|
+
def extended(_mod)
|
11
11
|
Selenium::WebDriver::SearchContext.class_eval do
|
12
12
|
Selenium::WebDriver::SearchContext::FINDERS[:uiautomator] = '-android uiautomator'
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end # class << self
|
16
16
|
end # module Android
|
17
|
-
end # module Appium
|
17
|
+
end # module Appium
|
@@ -7,10 +7,10 @@ module Appium
|
|
7
7
|
def patch_webdriver_element
|
8
8
|
Selenium::WebDriver::Element.class_eval do
|
9
9
|
# Cross platform way of entering text into a textfield
|
10
|
-
def type
|
11
|
-
|
10
|
+
def type(text)
|
11
|
+
send_keys text
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end # Android
|
16
|
-
end # Appium
|
16
|
+
end # Appium
|
@@ -21,11 +21,9 @@ module Appium
|
|
21
21
|
# find_element :text doesn't work so use XPath to find by text.
|
22
22
|
|
23
23
|
# Return block.call and ignore any exceptions.
|
24
|
-
def ignore
|
25
|
-
|
26
|
-
|
27
|
-
rescue Exception
|
28
|
-
end
|
24
|
+
def ignore(&block)
|
25
|
+
block.call
|
26
|
+
rescue Exception # rubocop:disable Lint/HandleExceptions, Lint/RescueException
|
29
27
|
end
|
30
28
|
|
31
29
|
# Navigate back.
|
@@ -43,7 +41,7 @@ module Appium
|
|
43
41
|
#
|
44
42
|
# @param xpath_str [String] the XPath string
|
45
43
|
# @return [Element]
|
46
|
-
def xpath
|
44
|
+
def xpath(xpath_str)
|
47
45
|
find_element :xpath, xpath_str
|
48
46
|
end
|
49
47
|
|
@@ -51,11 +49,11 @@ module Appium
|
|
51
49
|
#
|
52
50
|
# @param xpath_str [String] the XPath string
|
53
51
|
# @return [Array<Element>]
|
54
|
-
def xpaths
|
52
|
+
def xpaths(xpath_str)
|
55
53
|
find_elements :xpath, xpath_str
|
56
54
|
end
|
57
55
|
|
58
|
-
def _print_source
|
56
|
+
def _print_source(source)
|
59
57
|
opts = Nokogiri::XML::ParseOptions::NOBLANKS | Nokogiri::XML::ParseOptions::NONET
|
60
58
|
if source.start_with? '<html'
|
61
59
|
doc = Nokogiri::HTML(source) { |cfg| cfg.options = opts }
|
@@ -79,15 +77,15 @@ module Appium
|
|
79
77
|
end
|
80
78
|
|
81
79
|
# http://nokogiri.org/Nokogiri/XML/SAX/Document.html
|
82
|
-
def start_element
|
80
|
+
def start_element(name, attrs = [])
|
83
81
|
# Count only visible elements. Android is always visible
|
84
82
|
element_visible = $driver.device_is_android? ? true : Hash[attrs]['visible'] == 'true'
|
85
|
-
@result[name]
|
83
|
+
@result[name] += 1 if element_visible
|
86
84
|
end
|
87
85
|
|
88
86
|
def formatted_result
|
89
87
|
message = ''
|
90
|
-
sorted = @result.sort_by { |
|
88
|
+
sorted = @result.sort_by { |_element, count| count }.reverse
|
91
89
|
sorted.each do |element, count|
|
92
90
|
message += "#{count}x #{element}\n"
|
93
91
|
end
|
@@ -117,7 +115,7 @@ module Appium
|
|
117
115
|
# ```ruby
|
118
116
|
# px_to_window_rel x: 50, y: 150
|
119
117
|
# ```
|
120
|
-
def px_to_window_rel
|
118
|
+
def px_to_window_rel(opts = {})
|
121
119
|
w = $driver.window_size
|
122
120
|
x = opts.fetch :x, 0
|
123
121
|
y = opts.fetch :y, 0
|
@@ -136,34 +134,32 @@ module Appium
|
|
136
134
|
# Search strings.xml's values for target.
|
137
135
|
# @param target [String] the target to search for in strings.xml values
|
138
136
|
# @return [Array]
|
139
|
-
def xml_keys
|
137
|
+
def xml_keys(target)
|
140
138
|
lazy_load_strings
|
141
|
-
@strings_xml.select { |key,
|
139
|
+
@strings_xml.select { |key, _value| key.downcase.include? target.downcase }
|
142
140
|
end
|
143
141
|
|
144
142
|
# Search strings.xml's keys for target.
|
145
143
|
# @param target [String] the target to search for in strings.xml keys
|
146
144
|
# @return [Array]
|
147
|
-
def xml_values
|
145
|
+
def xml_values(target)
|
148
146
|
lazy_load_strings
|
149
|
-
@strings_xml.select { |
|
147
|
+
@strings_xml.select { |_key, value| value.downcase.include? target.downcase }
|
150
148
|
end
|
151
149
|
|
152
150
|
# Resolve id in strings.xml and return the value.
|
153
151
|
# @param id [String] the id to resolve
|
154
152
|
# @return [String]
|
155
|
-
def resolve_id
|
153
|
+
def resolve_id(id)
|
156
154
|
lazy_load_strings
|
157
155
|
@strings_xml[id]
|
158
156
|
end
|
159
157
|
|
160
158
|
class HTMLElements < Nokogiri::XML::SAX::Document
|
161
|
-
|
162
|
-
@filter
|
163
|
-
end
|
159
|
+
attr_reader :filter
|
164
160
|
|
165
161
|
# convert to string to support symbols
|
166
|
-
def filter=
|
162
|
+
def filter=(value)
|
167
163
|
# nil and false disable the filter
|
168
164
|
return @filter = false unless value
|
169
165
|
@filter = value.to_s.downcase
|
@@ -186,7 +182,7 @@ module Appium
|
|
186
182
|
attr_string = e.reduce('') do |string, attr|
|
187
183
|
attr_1 = attr[1]
|
188
184
|
attr_1 = attr_1 ? attr_1.strip : attr_1
|
189
|
-
string
|
185
|
+
string + " #{attr[0]}: #{attr_1}\n"
|
190
186
|
end
|
191
187
|
|
192
188
|
unless attr_string.nil? || attr_string.empty?
|
@@ -196,32 +192,31 @@ module Appium
|
|
196
192
|
end
|
197
193
|
end
|
198
194
|
|
199
|
-
def start_element
|
195
|
+
def start_element(name, attrs = [])
|
200
196
|
@skip_element = filter && !filter.include?(name.downcase)
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
end
|
197
|
+
return if @skip_element
|
198
|
+
element = { name: name }
|
199
|
+
attrs.each { |a| element[a[0]] = a[1] }
|
200
|
+
@element_stack.push element
|
201
|
+
@elements_in_order.push element
|
207
202
|
end
|
208
203
|
|
209
|
-
def end_element
|
204
|
+
def end_element(name)
|
210
205
|
return if filter && !filter.include?(name.downcase)
|
211
206
|
element_index = @element_stack.rindex { |e| e[:name] == name }
|
212
207
|
@element_stack.delete_at element_index
|
213
208
|
end
|
214
209
|
|
215
210
|
def characters(chars)
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
end
|
211
|
+
return if @skip_element
|
212
|
+
element = @element_stack.last
|
213
|
+
element[:text] = chars
|
220
214
|
end
|
221
215
|
end
|
222
216
|
|
223
217
|
def _no_such_element
|
224
|
-
|
218
|
+
fail Selenium::WebDriver::Error::NoSuchElementError,
|
219
|
+
'An element could not be located on the page using the given search parameters.'
|
225
220
|
end
|
226
221
|
end # module Common
|
227
222
|
end # module Appium
|
@@ -3,21 +3,21 @@ require_relative 'version'
|
|
3
3
|
module Appium
|
4
4
|
module Common
|
5
5
|
# Implement useful features for element.
|
6
|
-
class Selenium::WebDriver::Element
|
6
|
+
class Selenium::WebDriver::Element # rubocop:disable Style/ClassAndModuleChildren
|
7
7
|
# Note: For testing .text should be used over value, and name.
|
8
8
|
|
9
9
|
# Returns the value attribute
|
10
10
|
#
|
11
11
|
# Fixes NoMethodError: undefined method `value' for Selenium::WebDriver::Element
|
12
12
|
def value
|
13
|
-
|
13
|
+
attribute :value
|
14
14
|
end
|
15
15
|
|
16
16
|
# Returns the name attribute
|
17
17
|
#
|
18
18
|
# Fixes NoMethodError: undefined method `name' for Selenium::WebDriver::Element
|
19
19
|
def name
|
20
|
-
|
20
|
+
attribute :name
|
21
21
|
end
|
22
22
|
|
23
23
|
# For use with mobile tap.
|
@@ -67,8 +67,9 @@ def patch_webdriver_bridge
|
|
67
67
|
Selenium::WebDriver::Remote::Bridge.class_eval do
|
68
68
|
# Code from lib/selenium/webdriver/remote/bridge.rb
|
69
69
|
def raw_execute(command, opts = {}, command_hash = nil)
|
70
|
-
verb, path
|
71
|
-
|
70
|
+
verb, path = Selenium::WebDriver::Remote::COMMANDS[command] ||
|
71
|
+
fail(ArgumentError, "unknown command: #{command.inspect}")
|
72
|
+
path = path.dup
|
72
73
|
|
73
74
|
path[':session_id'] = @session_id if path.include?(':session_id')
|
74
75
|
|
@@ -79,18 +80,17 @@ def patch_webdriver_bridge
|
|
79
80
|
end
|
80
81
|
|
81
82
|
# convert /// into /
|
82
|
-
path.gsub!
|
83
|
+
path.gsub!(/\/+/, '/')
|
83
84
|
|
84
85
|
# change path from session/efac972c-941a-499c-803c-d7d008749/execute
|
85
86
|
# to /execute
|
86
87
|
# path may be nil, session, or not have anything after the session_id.
|
87
88
|
path_str = path
|
88
|
-
path_str = '/' + path_str unless path_str.nil? ||
|
89
|
-
|
90
|
-
path_match = path.match /.*\h{8}-?\h{4}-?\h{4}-?\h{4}-?\h{12}/
|
89
|
+
path_str = '/' + path_str unless path_str.nil? || path_str.length <= 0 || path_str[0] == '/'
|
90
|
+
path_match = path.match(/.*\h{8}-?\h{4}-?\h{4}-?\h{4}-?\h{12}/)
|
91
91
|
path_str = path.sub(path_match[0], '') unless path_match.nil?
|
92
92
|
|
93
|
-
Appium::Logger.info
|
93
|
+
Appium::Logger.info "#{verb} #{path_str}"
|
94
94
|
|
95
95
|
# must check to see if command_hash is a hash. sometimes it's not.
|
96
96
|
if command_hash.is_a?(Hash) && !command_hash.empty?
|
@@ -98,7 +98,7 @@ def patch_webdriver_bridge
|
|
98
98
|
|
99
99
|
print_command.delete :args if print_command[:args] == []
|
100
100
|
|
101
|
-
if print_command[:using]
|
101
|
+
if print_command[:using] == '-android uiautomator'
|
102
102
|
value = print_command[:value].split(';').map { |v| "#{v};" }
|
103
103
|
print_command[:value] = value.length == 1 ? value[0] : value
|
104
104
|
|
@@ -121,26 +121,28 @@ def patch_webdriver_bridge
|
|
121
121
|
end
|
122
122
|
|
123
123
|
# Print Appium's origValue error messages.
|
124
|
+
# rubocop:disable Style/ClassAndModuleChildren
|
125
|
+
# rubocop:disable Style/AndOr
|
124
126
|
class Selenium::WebDriver::Remote::Response
|
125
127
|
# @private
|
126
128
|
def error_message
|
127
129
|
val = value
|
128
130
|
|
129
131
|
case val
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
132
|
+
when Hash
|
133
|
+
msg = val['origValue'] || val['message'] or return 'unknown error'
|
134
|
+
msg << " (#{ val['class'] })" if val['class']
|
135
|
+
when String
|
136
|
+
msg = val
|
137
|
+
else
|
138
|
+
msg = "unknown error, status=#{status}: #{val.inspect}"
|
137
139
|
end
|
138
140
|
|
139
141
|
msg
|
140
142
|
end
|
141
143
|
end
|
142
144
|
|
143
|
-
class Selenium::WebDriver::Remote::Http::Common
|
145
|
+
class Selenium::WebDriver::Remote::Http::Common # rubocop:disable Style/ClassAndModuleChildren
|
144
146
|
remove_const :DEFAULT_HEADERS if defined? DEFAULT_HEADERS
|
145
147
|
DEFAULT_HEADERS = { 'Accept' => CONTENT_TYPE, 'User-Agent' => "appium/ruby_lib/#{::Appium::VERSION}" }
|
146
|
-
end
|
148
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Appium
|
2
2
|
# Version and Date are defined on the 'Appium' module, not 'Appium::Common'
|
3
|
-
VERSION = '
|
4
|
-
DATE = '2015-
|
5
|
-
end
|
3
|
+
VERSION = '7.0.0' unless defined? ::Appium::VERSION
|
4
|
+
DATE = '2015-05-08' unless defined? ::Appium::DATE
|
5
|
+
end
|
@@ -1,18 +1,17 @@
|
|
1
1
|
module Appium
|
2
2
|
module Common
|
3
|
-
|
4
3
|
# http://mudge.name/2011/01/26/passing-blocks-in-ruby-without-block.html
|
5
4
|
# Note that the Ruby timeout module is avoided. timeout has problems.
|
6
5
|
# https://coderwall.com/p/1novga
|
7
6
|
|
8
7
|
# Wait code from the selenium Ruby gem
|
9
8
|
# https://github.com/SeleniumHQ/selenium/blob/cf501dda3f0ed12233de51ce8170c0e8090f0c20/rb/lib/selenium/webdriver/common/wait.rb
|
10
|
-
def _generic_wait
|
9
|
+
def _generic_wait(opts = {}, &block)
|
11
10
|
valid_keys = [:timeout, :interval, :message, :ignore, :return_if_true]
|
12
11
|
invalid_keys = []
|
13
12
|
opts.keys.each { |key| invalid_keys << key unless valid_keys.include?(key) }
|
14
13
|
# [:one, :two] => :one, :two
|
15
|
-
|
14
|
+
fail "Invalid keys #{invalid_keys.to_s[1..-2]}. Valid keys are #{valid_keys.to_s[1..-2]}" unless invalid_keys.empty?
|
16
15
|
|
17
16
|
timeout = opts.fetch(:timeout, 30)
|
18
17
|
interval = opts.fetch(:interval, 0.5)
|
@@ -33,7 +32,7 @@ module Appium
|
|
33
32
|
end
|
34
33
|
rescue ::Errno::ECONNREFUSED => e
|
35
34
|
raise e
|
36
|
-
rescue *ignored => last_error
|
35
|
+
rescue *ignored => last_error # rubocop:disable Lint/HandleExceptions
|
37
36
|
# swallowed
|
38
37
|
end
|
39
38
|
|
@@ -48,13 +47,13 @@ module Appium
|
|
48
47
|
|
49
48
|
msg << " (#{last_error.message})" if last_error
|
50
49
|
|
51
|
-
|
50
|
+
fail Selenium::WebDriver::Error::TimeOutError, msg
|
52
51
|
end
|
53
52
|
|
54
53
|
# process opts before calling _generic_wait
|
55
|
-
def _process_wait_opts
|
54
|
+
def _process_wait_opts(opts)
|
56
55
|
opts = { timeout: opts } if opts.is_a?(Numeric)
|
57
|
-
|
56
|
+
fail 'opts must be a hash' unless opts.is_a? Hash
|
58
57
|
opts
|
59
58
|
end
|
60
59
|
|
@@ -73,7 +72,7 @@ module Appium
|
|
73
72
|
# @option opts [Numeric] :interval (0.5) Seconds to sleep between polls.
|
74
73
|
# @option opts [String] :message Exception message if timed out.
|
75
74
|
# @option opts [Array, Exception] :ignore Exceptions to ignore while polling (default: Exception)
|
76
|
-
def wait_true
|
75
|
+
def wait_true(opts = {}, &block)
|
77
76
|
opts = _process_wait_opts(opts).merge(return_if_true: true)
|
78
77
|
_generic_wait opts, &block
|
79
78
|
end
|
@@ -91,9 +90,9 @@ module Appium
|
|
91
90
|
# @option opts [Numeric] :interval (0.5) Seconds to sleep between polls.
|
92
91
|
# @option opts [String] :message Exception message if timed out.
|
93
92
|
# @option opts [Array, Exception] :ignore Exceptions to ignore while polling (default: Exception)
|
94
|
-
def wait
|
93
|
+
def wait(opts = {}, &block)
|
95
94
|
opts = _process_wait_opts(opts).merge(return_if_true: false)
|
96
95
|
_generic_wait opts, &block
|
97
96
|
end
|
98
97
|
end # module Common
|
99
|
-
end # module Appium
|
98
|
+
end # module Appium
|
@@ -12,11 +12,12 @@ module Appium
|
|
12
12
|
close_app: 'session/:session_id/appium/app/close',
|
13
13
|
reset: 'session/:session_id/appium/app/reset',
|
14
14
|
toggle_airplane_mode: 'session/:session_id/appium/device/toggle_airplane_mode',
|
15
|
+
device_locked?: 'session/:session_id/appium/device/is_locked'
|
15
16
|
},
|
16
17
|
get: {
|
17
18
|
current_activity: 'session/:session_id/appium/device/current_activity',
|
18
19
|
current_context: 'session/:session_id/context',
|
19
|
-
get_network_connection: 'session/:session_id/network_connection'
|
20
|
+
get_network_connection: 'session/:session_id/network_connection'
|
20
21
|
}
|
21
22
|
}
|
22
23
|
|
@@ -34,7 +35,7 @@ module Appium
|
|
34
35
|
# @!method current_activity
|
35
36
|
|
36
37
|
# @!method launch_app
|
37
|
-
# Start the simulator and
|
38
|
+
# Start the simulator and application configured with desired capabilities
|
38
39
|
|
39
40
|
# @!method reset
|
40
41
|
# Reset the device, relaunching the application.
|
@@ -43,7 +44,9 @@ module Appium
|
|
43
44
|
# Cause the device to shake
|
44
45
|
|
45
46
|
# @!method toggle_flight_mode
|
46
|
-
#
|
47
|
+
# Toggle flight mode on or off
|
48
|
+
|
49
|
+
# @!method device_locked?
|
47
50
|
|
48
51
|
# @!method hide_keyboard
|
49
52
|
# Hide the onscreen keyboard
|
@@ -101,7 +104,7 @@ module Appium
|
|
101
104
|
# Update appium Settings for current test session
|
102
105
|
# @param settings (hash) Settings to update, keys are settings, values to value to set each setting to
|
103
106
|
class << self
|
104
|
-
def extended(
|
107
|
+
def extended(_mod)
|
105
108
|
extend_webdriver_with_forwardable
|
106
109
|
|
107
110
|
NoArgMethods.each_pair do |verb, pair|
|
@@ -116,7 +119,7 @@ module Appium
|
|
116
119
|
end
|
117
120
|
|
118
121
|
add_endpoint_method(:app_strings, 'session/:session_id/appium/app/strings') do
|
119
|
-
def app_strings
|
122
|
+
def app_strings(language = nil)
|
120
123
|
opts = language ? { language: language } : {}
|
121
124
|
execute :app_strings, {}, opts
|
122
125
|
end
|
@@ -124,31 +127,31 @@ module Appium
|
|
124
127
|
|
125
128
|
add_endpoint_method(:lock, 'session/:session_id/appium/device/lock') do
|
126
129
|
def lock(duration)
|
127
|
-
execute :lock, {}, :
|
130
|
+
execute :lock, {}, seconds: duration
|
128
131
|
end
|
129
132
|
end
|
130
133
|
|
131
134
|
add_endpoint_method(:install_app, 'session/:session_id/appium/device/install_app') do
|
132
135
|
def install_app(path)
|
133
|
-
execute :install_app, {}, :
|
136
|
+
execute :install_app, {}, appPath: path
|
134
137
|
end
|
135
138
|
end
|
136
139
|
|
137
140
|
add_endpoint_method(:remove_app, 'session/:session_id/appium/device/remove_app') do
|
138
141
|
def remove_app(id)
|
139
|
-
execute :remove_app, {}, :
|
142
|
+
execute :remove_app, {}, appId: id
|
140
143
|
end
|
141
144
|
end
|
142
145
|
|
143
|
-
add_endpoint_method(:
|
144
|
-
def
|
145
|
-
execute :
|
146
|
+
add_endpoint_method(:app_installed?, 'session/:session_id/appium/device/app_installed') do
|
147
|
+
def app_installed?(app_id)
|
148
|
+
execute :app_installed?, {}, bundleId: app_id
|
146
149
|
end
|
147
150
|
end
|
148
151
|
|
149
152
|
add_endpoint_method(:background_app, 'session/:session_id/appium/app/background') do
|
150
153
|
def background_app(duration)
|
151
|
-
execute :background_app, {}, :
|
154
|
+
execute :background_app, {}, seconds: duration
|
152
155
|
end
|
153
156
|
end
|
154
157
|
|
@@ -162,37 +165,40 @@ module Appium
|
|
162
165
|
# @param [String] The activity to start before the target activity [optional]
|
163
166
|
#
|
164
167
|
# ```ruby
|
165
|
-
# start_activity app_package: 'io.appium.android.apis',
|
168
|
+
# start_activity app_package: 'io.appium.android.apis',
|
169
|
+
# app_activity: '.accessibility.AccessibilityNodeProviderActivity'
|
166
170
|
# ```
|
167
171
|
add_endpoint_method(:start_activity, 'session/:session_id/appium/device/start_activity') do
|
168
172
|
def start_activity(opts)
|
169
|
-
|
173
|
+
fail 'opts must be a hash' unless opts.is_a? Hash
|
170
174
|
app_package = opts[:app_package]
|
171
|
-
|
175
|
+
fail 'app_package is required' unless app_package
|
172
176
|
app_activity = opts[:app_activity]
|
173
|
-
|
177
|
+
fail 'app_activity is required' unless opts[:app_activity]
|
174
178
|
app_wait_package = opts.fetch(:app_wait_package, '')
|
175
179
|
app_wait_activity = opts.fetch(:app_wait_activity, '')
|
176
180
|
|
177
181
|
unknown_opts = opts.keys - [:app_package, :app_activity, :app_wait_package, :app_wait_activity]
|
178
|
-
|
182
|
+
fail "Unknown options #{unknown_opts}" unless unknown_opts.empty?
|
179
183
|
|
180
|
-
execute :start_activity, {},
|
181
|
-
|
184
|
+
execute :start_activity, {}, appPackage: app_package,
|
185
|
+
appActivity: app_activity,
|
186
|
+
appWaitPackage: app_wait_package,
|
187
|
+
appWaitActivity: app_wait_activity
|
182
188
|
end
|
183
189
|
end
|
184
190
|
|
185
191
|
add_endpoint_method(:set_context, 'session/:session_id/context') do
|
186
|
-
def set_context(context=null)
|
187
|
-
execute :set_context, {}, :
|
192
|
+
def set_context(context = null)
|
193
|
+
execute :set_context, {}, name: context
|
188
194
|
end
|
189
195
|
end
|
190
196
|
|
191
197
|
add_endpoint_method(:hide_keyboard, 'session/:session_id/appium/device/hide_keyboard') do
|
192
|
-
def hide_keyboard(close_key=nil)
|
198
|
+
def hide_keyboard(close_key = nil)
|
193
199
|
# Android can only tapOutside.
|
194
200
|
if $driver.device_is_android?
|
195
|
-
|
201
|
+
return execute :hide_keyboard, {}, strategy: :tapOutside
|
196
202
|
end
|
197
203
|
|
198
204
|
close_key ||= 'Done' # default to Done key.
|
@@ -201,7 +207,7 @@ module Appium
|
|
201
207
|
end
|
202
208
|
|
203
209
|
add_endpoint_method(:press_keycode, 'session/:session_id/appium/device/press_keycode') do
|
204
|
-
def press_keycode(key, metastate=nil)
|
210
|
+
def press_keycode(key, metastate = nil)
|
205
211
|
args = { keycode: key }
|
206
212
|
args[:metastate] = metastate if metastate
|
207
213
|
execute :press_keycode, {}, args
|
@@ -209,17 +215,17 @@ module Appium
|
|
209
215
|
end
|
210
216
|
|
211
217
|
add_endpoint_method(:long_press_keycode, 'session/:session_id/appium/device/long_press_keycode') do
|
212
|
-
def long_press_keycode(key, metastate=nil)
|
218
|
+
def long_press_keycode(key, metastate = nil)
|
213
219
|
args = { keycode: key }
|
214
220
|
args[:metastate] = metastate if metastate
|
215
221
|
execute :long_press_keycode, {}, args
|
216
222
|
end
|
217
223
|
end
|
218
224
|
|
219
|
-
# TODO TEST ME
|
225
|
+
# TODO: TEST ME
|
220
226
|
add_endpoint_method(:set_immediate_value, 'session/:session_id/appium/element/:id/value') do
|
221
227
|
def set_immediate_value(element, value)
|
222
|
-
execute :set_immediate_value, { :
|
228
|
+
execute :set_immediate_value, { id: element.ref }, value: value
|
223
229
|
end
|
224
230
|
end
|
225
231
|
|
@@ -237,7 +243,7 @@ module Appium
|
|
237
243
|
end
|
238
244
|
end
|
239
245
|
|
240
|
-
# TODO TEST ME
|
246
|
+
# TODO: TEST ME
|
241
247
|
add_endpoint_method(:pull_folder, 'session/:session_id/appium/device/pull_folder') do
|
242
248
|
def pull_folder(path)
|
243
249
|
data = execute :pull_folder, {}, path: path
|
@@ -245,7 +251,7 @@ module Appium
|
|
245
251
|
end
|
246
252
|
end
|
247
253
|
|
248
|
-
# TODO TEST ME
|
254
|
+
# TODO: TEST ME
|
249
255
|
add_endpoint_method(:end_coverage, 'session/:session_id/appium/app/end_test_coverage') do
|
250
256
|
def end_coverage(path, intent)
|
251
257
|
execute :end_coverage, {}, path: path, intent: intent
|
@@ -292,7 +298,7 @@ module Appium
|
|
292
298
|
# def extended
|
293
299
|
|
294
300
|
# @private
|
295
|
-
def add_endpoint_method(method, path, verb
|
301
|
+
def add_endpoint_method(method, path, verb = :post)
|
296
302
|
if block_given?
|
297
303
|
# &Proc.new with no args passes the passed_in block
|
298
304
|
# Because creating Procs from blocks is slow
|
@@ -307,7 +313,7 @@ module Appium
|
|
307
313
|
|
308
314
|
# @private
|
309
315
|
def extend_webdriver_with_forwardable
|
310
|
-
return if Selenium::WebDriver::Driver.
|
316
|
+
return if Selenium::WebDriver::Driver.is_a? Forwardable
|
311
317
|
Selenium::WebDriver::Driver.class_eval do
|
312
318
|
extend Forwardable
|
313
319
|
end
|
@@ -320,7 +326,7 @@ module Appium
|
|
320
326
|
end
|
321
327
|
|
322
328
|
# @private
|
323
|
-
def delegate_from_appium_driver(method, delegation_target
|
329
|
+
def delegate_from_appium_driver(method, delegation_target = :driver)
|
324
330
|
def_delegator delegation_target, method
|
325
331
|
end
|
326
332
|
|
@@ -329,7 +335,7 @@ module Appium
|
|
329
335
|
Selenium::WebDriver::Remote::Bridge.class_eval do
|
330
336
|
command method, verb, path
|
331
337
|
if block_given?
|
332
|
-
class_eval
|
338
|
+
class_eval(&Proc.new)
|
333
339
|
else
|
334
340
|
define_method(method) { execute method }
|
335
341
|
end
|