appium_lib 0.0.30 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +8 -8
  2. data/Rakefile +15 -7
  3. data/appium_lib.gemspec +3 -3
  4. data/docs.md +7 -5
  5. data/lib/appium_lib.rb +34 -6
  6. data/lib/appium_lib/android/element/alert.rb +43 -0
  7. data/lib/appium_lib/android/element/generic.rb +94 -0
  8. data/lib/appium_lib/android/element/textfield.rb +43 -0
  9. data/lib/appium_lib/android/helper.rb +120 -0
  10. data/lib/appium_lib/android/patch.rb +10 -0
  11. data/lib/appium_lib/common/element/button.rb +83 -0
  12. data/lib/appium_lib/common/element/text.rb +44 -0
  13. data/lib/appium_lib/common/element/window.rb +9 -0
  14. data/lib/appium_lib/common/helper.rb +140 -0
  15. data/lib/appium_lib/common/patch.rb +83 -0
  16. data/lib/appium_lib/common/version.rb +6 -0
  17. data/lib/appium_lib/driver.rb +265 -0
  18. data/lib/appium_lib/ios/element/alert.rb +56 -0
  19. data/lib/appium_lib/ios/element/generic.rb +170 -0
  20. data/lib/appium_lib/ios/element/textfield.rb +90 -0
  21. data/lib/appium_lib/ios/helper.rb +103 -0
  22. data/lib/appium_lib/ios/patch.rb +15 -0
  23. data/readme.md +10 -3
  24. data/release_notes.md +8 -0
  25. metadata +19 -15
  26. data/lib/appium_lib/console.rb +0 -254
  27. data/lib/appium_lib/element/android/alert.rb +0 -45
  28. data/lib/appium_lib/element/android/generic.rb +0 -88
  29. data/lib/appium_lib/element/android/textfield.rb +0 -44
  30. data/lib/appium_lib/element/button.rb +0 -83
  31. data/lib/appium_lib/element/ios/alert.rb +0 -49
  32. data/lib/appium_lib/element/ios/generic.rb +0 -140
  33. data/lib/appium_lib/element/ios/textfield.rb +0 -93
  34. data/lib/appium_lib/element/text.rb +0 -43
  35. data/lib/appium_lib/element/window.rb +0 -12
  36. data/lib/appium_lib/helper.rb +0 -278
  37. data/lib/appium_lib/patch.rb +0 -90
  38. data/lib/appium_lib/version.rb +0 -4
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+ module Appium::Android
3
+ # Implement useful features for element.
4
+ class Selenium::WebDriver::Element
5
+ # Cross platform way of entering text into a textfield
6
+ def type text
7
+ self.send_keys text
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,83 @@
1
+ # encoding: utf-8
2
+ # UIAButton methods
3
+ module Appium::Common
4
+ # Find a button by text and optionally number.
5
+ # @param text [String, Integer] the text to exactly match. If int then the button at that index is returned.
6
+ # @param number [Integer] the occurrence of the button matching text. Defaults to the first button.
7
+ # @return [Button] the button found with text and matching number
8
+ def button text, number=0
9
+ # return button at index.
10
+ return ele_index :button, text if text.is_a? Numeric
11
+
12
+ number >= 1 ? button_num( text, number ) :
13
+ find_ele_by_text_include( :button, text )
14
+ end
15
+
16
+ # Get an array of button texts or button elements if text is provided.
17
+ # @param text [String] the text to exactly match
18
+ # @return [Array<String>, Array<Buttons>] either an array of button texts or an array of button elements if text is provided.
19
+ def buttons text=nil
20
+ text == nil ? find_eles_attr( :button, :text ) :
21
+ find_eles_by_text_include( :button, text )
22
+ end
23
+
24
+ # Get the first button element.
25
+ # @return [Button]
26
+ def first_button
27
+ first_ele :button
28
+ end
29
+
30
+ # Get the last button element.
31
+ # @return [Button]
32
+ def last_button
33
+ last_ele :button
34
+ end
35
+
36
+ # Get the first button element that exactly matches text.
37
+ # @param text [String] the text to match exactly
38
+ # @return [Button]
39
+ def button_exact text
40
+ find_ele_by_text :button, text
41
+ end
42
+
43
+ # Get all button elements that exactly match text.
44
+ # @param text [String] the text to match exactly
45
+ # @return [Array<Button>]
46
+ def buttons_exact text
47
+ find_eles_by_text :button, text
48
+ end
49
+
50
+ # Get an array of button elements.
51
+ # @return [Array<Button>]
52
+ def e_buttons
53
+ find_eles :button
54
+ end
55
+
56
+ # Expected to be called via button method.
57
+ #
58
+ # Get the button element exactly matching text and
59
+ # occurrence. number=2 means the 2nd occurrence.
60
+ #
61
+ # find the second Sign In button
62
+ #
63
+ # b = e_button 'Sign In', 2
64
+ #
65
+ # Button order will change in iOS vs Android
66
+ # so if there's no button found at number then
67
+ # return the first button.
68
+ #
69
+ # @param text [String] the text to match
70
+ # @param number [Integer] the button occurance to return. 1 = first button
71
+ # @return [Button] the button that matches text and number
72
+ def button_num text, number=1
73
+ raise 'Number must be >= 1' if number <= 0
74
+ number = number - 1 # zero indexed
75
+ result = nil
76
+
77
+ elements = buttons text
78
+ elements.size > number ? result = elements[number]
79
+ : result = elements.first
80
+
81
+ result
82
+ end
83
+ end # module Appium::Common
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+ # UIAStaticText methods
3
+ module Appium::Common
4
+ # s_ prefix for static_text to avoid conflict with generic text methods.
5
+
6
+ # Get an array of text texts.
7
+ # @return [Array<String>]
8
+ def s_texts
9
+ find_eles_attr :text, :text
10
+ end
11
+
12
+ # Get an array of text elements.
13
+ # @return [Array<Text>]
14
+ def e_s_texts
15
+ find_eles :text
16
+ end
17
+
18
+ # Get the first text element.
19
+ # @return [Text]
20
+ def s_first_text
21
+ first_ele :text
22
+ end
23
+
24
+ # Get the last text element
25
+ # @return [Text]
26
+ def s_last_text
27
+ last_ele :text
28
+ end
29
+
30
+ # Get the first element that includes text.
31
+ # @param text [String, Integer] the text to find. If int then the text at that index is returned.
32
+ # @return [Text]
33
+ def s_text text
34
+ return ele_index :text, text if text.is_a? Numeric
35
+ find_ele_by_text_include :text, text
36
+ end
37
+
38
+ # Get the first textfield that matches text.
39
+ # @param text [String] the text that the tag must match
40
+ # @return [Text]
41
+ def s_text_exact text
42
+ find_ele_by_text :text, text
43
+ end
44
+ end # module Appium::Common
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+ # UIAWindow methods
3
+ module Appium::Common
4
+ # Get the window's size
5
+ def window_size
6
+ return nil if @driver.nil?
7
+ @driver.manage.window.size
8
+ end
9
+ end # module Appium::Common
@@ -0,0 +1,140 @@
1
+ # encoding: utf-8
2
+ # Generic helper methods not specific
3
+ # to a particular tag name
4
+ module Appium::Common
5
+ # json and ap are required for the source method.
6
+ require 'json'
7
+ require 'ap' # awesome print
8
+ require 'timeout' # for wait
9
+
10
+ # iOS .name returns the accessibility attribute if it's set. if not set, the string value is used.
11
+ # Android .name returns the accessibility attribute and nothing if it's not set.
12
+ #
13
+ # .text should be cross platform so prefer that over name, unless both
14
+ # Android and iOS have proper accessibility attributes.
15
+ # .text and .value should be the same so use .text over .value.
16
+ #
17
+ # secure tag_name is iOS only because it can't be implemented using uiautomator for Android.
18
+ #
19
+ # find_element :text doesn't work so use XPath to find by text.
20
+
21
+ # Check every 0.5 seconds to see if block.call is true.
22
+ # Give up after 30 seconds.
23
+ # @param block [Block] the block to call
24
+ # @return [Object] the result of block.call
25
+ def wait &block
26
+ # Rescue Timeout::Error: execution expired
27
+ result = nil
28
+ timeout(30) { until (result = begin; block.call; rescue; end) do; sleep 0.5 end }
29
+ result
30
+ end
31
+
32
+ # Presses the back button on Android.
33
+ # @return [void]
34
+ def back
35
+ @driver.navigate.back
36
+ end
37
+
38
+ def xpath xpath_str
39
+ find_element :xpath, xpath_str
40
+ end
41
+
42
+ def xpaths xpath_str
43
+ find_elements :xpath, xpath_str
44
+ end
45
+
46
+ # Get the element of type tag_name at matching index.
47
+ # @param tag_name [String] the tag name to find
48
+ # @param index [Integer] the index
49
+ # @return [Element] the found element of type tag_name
50
+ def ele_index tag_name, index
51
+ # XPath index starts at 1. ruby_lib index starts at 0
52
+ find_element :xpath, "//#{tag_name}[#{index + 1}]"
53
+ end
54
+
55
+ # Get all elements exactly matching tag name
56
+ # @param tag_name [String] the tag name to find
57
+ # @return [Array<Element>] the found elements of type tag_name
58
+ def find_eles tag_name
59
+ @driver.find_elements :tag_name, tag_name
60
+ end
61
+
62
+ # Get the first tag that exactly matches tag and text.
63
+ # @param tag [String] the tag name to match
64
+ # @param text [String] the text to exactly match
65
+ # @return [Element] the element of type tag exactly matching text
66
+ def find_ele_by_text tag, text
67
+ @driver.find_element :xpath, %Q(#{tag}[@text='#{text}'])
68
+ end
69
+
70
+ # Get all tags that exactly match tag and text.
71
+ # @param tag [String] the tag name to match
72
+ # @param text [String] the text to exactly match
73
+ # @return [Array<Element>] the elements of type tag exactly matching text
74
+ def find_eles_by_text tag, text
75
+ @driver.find_elements :xpath, %Q(#{tag}[@text='#{text}'])
76
+ end
77
+
78
+ # Get the first tag by attribute that exactly matches value.
79
+ # @param tag [String] the tag name to match
80
+ # @param attr [String] the attribute to compare
81
+ # @param value [String] the value of the attribute that the element must include
82
+ # @return [Element] the element of type tag who's attribute includes value
83
+ def find_ele_by_attr_include tag, attr, value
84
+ @driver.find_element :xpath, %Q(#{tag}[contains(@#{attr}, '#{value}')])
85
+ end
86
+
87
+ # Get tags by attribute that include value.
88
+ # @param tag [String] the tag name to match
89
+ # @param attr [String] the attribute to compare
90
+ # @param value [String] the value of the attribute that the element must include
91
+ # @return [Array<Element>] the elements of type tag who's attribute includes value
92
+ def find_eles_by_attr_include tag, attr, value
93
+ @driver.find_elements :xpath, %Q(#{tag}[contains(@#{attr}, '#{value}')])
94
+ end
95
+
96
+ # Get the first tag that includes text.
97
+ # @param tag [String] the tag name to match
98
+ # @param text [String] the text the element must include
99
+ # @return [Element] the element of type tag that includes text
100
+ # element.attribute(:text).include? text
101
+ def find_ele_by_text_include tag, text
102
+ find_ele_by_attr_include tag, :text, text
103
+ end
104
+
105
+ # Get the tags that include text.
106
+ # @param tag [String] the tag name to match
107
+ # @param text [String] the text the element must include
108
+ # @return [Array<Element>] the elements of type tag that includes text
109
+ # element.attribute(:text).include? text
110
+ def find_eles_by_text_include tag, text
111
+ find_eles_by_attr_include tag, :text, text
112
+ end
113
+
114
+ # Get the first tag that matches tag_name
115
+ # @param tag_name [String] the tag to match
116
+ # @return [Element]
117
+ def first_ele tag_name
118
+ # XPath index starts at 1
119
+ find_element :xpath, "//#{tag_name}[1]"
120
+ end
121
+
122
+ # Get the last tag that matches tag_name
123
+ # @param tag_name [String] the tag to match
124
+ # @return [Element]
125
+ def last_ele tag_name
126
+ xpath "//#{tag_name}[last()]"
127
+ end
128
+
129
+ # Prints a JSON view of the current page
130
+ # @return [void]
131
+ def source
132
+ ap get_source
133
+ end
134
+
135
+ # Gets a JSON view of the current page
136
+ # @return [JSON]
137
+ def get_source
138
+ JSON.parse(@driver.page_source)
139
+ end
140
+ end # module Appium::Common
@@ -0,0 +1,83 @@
1
+ # encoding: utf-8
2
+ module Appium::Common
3
+ # Implement useful features for element.
4
+ class Selenium::WebDriver::Element
5
+ # Note: For testing .text should be used over value, and name.
6
+
7
+ # Fixes NoMethodError: undefined method `value' for #<Selenium::WebDriver::Element:0x..fa4a9148235390a44 id="1">
8
+ def value
9
+ self.attribute :value
10
+ end
11
+
12
+ # Fixes NoMethodError: undefined method `name' for #<Selenium::WebDriver::Element
13
+ def name
14
+ self.attribute :name
15
+ end
16
+
17
+ # Use tag_name to get element's type.
18
+ #
19
+ # Tag name appears to be the same as type.
20
+ #
21
+ # Fixes Selenium::WebDriver::Error::UnknownError: Not yet implemented
22
+ def tag_name
23
+ self.attribute :type
24
+ end
25
+
26
+ # For use with mobile tap.
27
+ #
28
+ # execute_script 'mobile: tap', :x => 0.0, :y => 0.98
29
+ #
30
+ # https://github.com/appium/appium/wiki/Automating-mobile-gestures
31
+ # @return [OpenStruct] the relative x, y in a struct. ex: { x: 0.50, y: 0.20 }
32
+ def location_rel
33
+ xy = self.location
34
+ w = window_size
35
+ OpenStruct.new( x: xy.x.to_f / w.width.to_f,
36
+ y: xy.y.to_f / w.height.to_f )
37
+ end
38
+ end
39
+ end # module Appium::Common
40
+
41
+ # Print JSON posted to Appium. Not scoped to an Appium module.
42
+ #
43
+ # Requires from lib/selenium/webdriver/remote.rb
44
+ require 'selenium/webdriver/remote/capabilities'
45
+ require 'selenium/webdriver/remote/bridge'
46
+ require 'selenium/webdriver/remote/server_error'
47
+ require 'selenium/webdriver/remote/response'
48
+ require 'selenium/webdriver/remote/commands'
49
+ require 'selenium/webdriver/remote/http/common'
50
+ require 'selenium/webdriver/remote/http/default'
51
+
52
+ # Show http calls to the Selenium server.
53
+ #
54
+ # Invaluable for debugging.
55
+ module Selenium::WebDriver::Remote
56
+ class Bridge
57
+ # Code from lib/selenium/webdriver/remote/bridge.rb
58
+ def raw_execute(command, opts = {}, command_hash = nil)
59
+ verb, path = COMMANDS[command] || raise(ArgumentError, "unknown command: #{command.inspect}")
60
+ path = path.dup
61
+
62
+ path[':session_id'] = @session_id if path.include?(':session_id')
63
+
64
+ begin
65
+ opts.each { |key, value| path[key.inspect] = escaper.escape(value.to_s) }
66
+ rescue IndexError
67
+ raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}"
68
+ end
69
+
70
+ # change path from session/efac972c-941a-499c-803c-d7d008749/execute
71
+ # to /execute
72
+ # path may be nil, session, or not have anything after the session_id.
73
+ path_str = ''
74
+ path_match = path.match /.*\h{8}-\h{4}-\h{4}-\h{4}-\h{12}/
75
+ path_str = path.sub(path_match[0], '') unless path_match.nil?
76
+
77
+ puts "#{verb} #{path_str}"
78
+ puts command_hash.to_json unless command_hash.to_json == 'null'
79
+ # puts "verb: #{verb}, path #{path}, command_hash #{command_hash.to_json}"
80
+ http.call verb, path, command_hash
81
+ end # def
82
+ end # class
83
+ end if defined? Pry # module Selenium::WebDriver::Remote
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+ module Appium
3
+ # Version and Date are defined on the 'Appium' module, not 'Appium::Common'
4
+ VERSION = '0.3.0' unless defined? ::Appium::VERSION
5
+ DATE = '2013-04-25' unless defined? ::Appium::DATE
6
+ end
@@ -0,0 +1,265 @@
1
+ # encoding: utf-8
2
+ =begin
3
+ Based on simple_test.rb
4
+ https://github.com/appium/appium/blob/82995f47408530c80c3376f4e07a1f649d96ba22/sample-code/examples/ruby/simple_test.rb
5
+ https://github.com/appium/appium/blob/c58eeb66f2d6fa3b9a89d188a2e657cca7cb300f/LICENSE
6
+ =end
7
+ module Appium
8
+ add_to_path __FILE__
9
+
10
+ require 'selenium-webdriver'
11
+
12
+ # common
13
+ require 'common/helper'
14
+ require 'common/patch'
15
+ require 'common/version'
16
+ require 'common/element/button'
17
+ require 'common/element/text'
18
+ require 'common/element/window'
19
+
20
+ # ios
21
+ require 'ios/helper'
22
+ require 'ios/patch'
23
+ require 'ios/element/alert'
24
+ require 'ios/element/generic'
25
+ require 'ios/element/textfield'
26
+
27
+ # android
28
+ require 'android/helper'
29
+ require 'android/patch'
30
+ require 'android/element/alert'
31
+ require 'android/element/generic'
32
+ require 'android/element/textfield'
33
+
34
+ class Driver
35
+ def initialize opts={}
36
+ opts = {} if opts.nil?
37
+ # Path to the .apk, .app or .app.zip.
38
+ # The path can be local or remote for Sauce.
39
+ @app_path = opts.fetch 'APP_PATH', ENV['APP_PATH']
40
+ raise 'APP_PATH must be set.' if @app_path.nil?
41
+
42
+ # The name to use for the test run on Sauce.
43
+ @app_name = opts.fetch 'APP_NAME', ENV['APP_NAME']
44
+
45
+ # Android app package
46
+ @app_package = opts.fetch 'APP_PACKAGE', ENV['APP_PACKAGE']
47
+
48
+ # Android app starting activity.
49
+ @app_activity = opts.fetch 'APP_ACTIVITY', ENV['APP_ACTIVITY']
50
+
51
+ # Android app waiting activity
52
+ @app_wait_activity = opts.fetch 'APP_WAIT_ACTIVITY', ENV['APP_WAIT_ACTIVITY']
53
+
54
+ # Sauce Username
55
+ @sauce_username = opts.fetch'SAUCE_USERNAME', ENV['SAUCE_USERNAME']
56
+
57
+ # Sauce Key
58
+ @sauce_access_key = opts.fetch 'SAUCE_ACCESS_KEY', ENV['SAUCE_ACCESS_KEY']
59
+
60
+ @port = opts.fetch 'PORT', ENV['PORT'] || 4723
61
+
62
+ @os = :ios
63
+ @os = :android if @app_path.end_with?('.apk') || @app_path.end_with?('.apk.zip')
64
+ puts "OS is: #{@os}" if defined?(Pry)
65
+
66
+ # load common methods
67
+ extend Appium::Common
68
+ if @os == :android
69
+ raise 'APP_ACTIVITY must be set.' if @app_activity.nil?
70
+
71
+ # load Android specific methods
72
+ extend Appium::Android
73
+ else
74
+ # load iOS specific methods
75
+ extend Appium::Ios
76
+ end
77
+
78
+ # Save global reference to last created Appium driver for top level methods.
79
+ $last_driver = self
80
+ end # def initialize
81
+
82
+ # WebDriver capabilities. Must be valid for Sauce to work.
83
+ # https://github.com/jlipps/appium/blob/master/app/android.js
84
+ def android_capabilities
85
+ {
86
+ browserName: 'Android',
87
+ platform: 'LINUX',
88
+ version: '4.1',
89
+ device: 'Android',
90
+ name: @app_name || 'Ruby Console Android Appium',
91
+ app: absolute_app_path,
92
+ :'app-package' => @app_package,
93
+ :'app-activity' => @app_activity,
94
+ :'app-wait-activity' => @app_wait_activity
95
+ }
96
+ end
97
+
98
+ # WebDriver capabilities. Must be valid for Sauce to work.
99
+ def ios_capabilities
100
+ {
101
+ browserName: 'iOS 6.0',
102
+ platform: 'Mac 10.8',
103
+ version: '6.0',
104
+ device: 'iPhone Simulator',
105
+ name: @app_name || 'Ruby Console iOS Appium',
106
+ app: absolute_app_path
107
+ }
108
+ end
109
+
110
+ def capabilities
111
+ @os == :ios ? ios_capabilities : android_capabilities
112
+ end
113
+
114
+ # Converts environment variable APP_PATH to an absolute path.
115
+ # @return [String] APP_PATH as an absolute path
116
+ def absolute_app_path
117
+ raise 'APP_PATH environment variable not set!' if @app_path.nil? || @app_path.empty?
118
+ return @app_path if @app_path.match(/^http/) # public URL for Sauce
119
+ if @app_path.match(/^\//) # absolute file path
120
+ raise "App doesn't exist. #{@app_path}" unless File.exist? @app_path
121
+ return @app_path
122
+ end
123
+ file = File.join(File.dirname(__FILE__), @app_path)
124
+ raise "App doesn't exist #{file}" unless File.exist? file
125
+ file
126
+ end
127
+
128
+ # Get the server url for sauce or local based on env vars.
129
+ # @return [String] the server url
130
+ def server_url
131
+ if !@sauce_username.nil? && !@sauce_access_key.nil?
132
+ "http://#{@sauce_username}:#{@sauce_access_key}@ondemand.saucelabs.com:80/wd/hub"
133
+ else
134
+ "http://127.0.0.1:#{@port}/wd/hub"
135
+ end
136
+ end
137
+
138
+ # Restarts the driver
139
+ def restart
140
+ driver_quit
141
+ start_driver
142
+ end
143
+
144
+ # Quits the driver
145
+ # @return [void]
146
+ def driver_quit
147
+ # rescue NoSuchDriverError
148
+ begin; @driver.quit unless @driver.nil?; rescue; end
149
+ end
150
+
151
+ # Creates a new global driver and quits the old one if it exists.
152
+ # @return [Selenium::WebDriver] the new global driver
153
+ def start_driver wait=30
154
+ @client = @client || Selenium::WebDriver::Remote::Http::Default.new
155
+ @client.timeout = 999999
156
+
157
+ @default_wait = wait
158
+
159
+ begin
160
+ @driver = Selenium::WebDriver.for :remote, http_client: @client, desired_capabilities: capabilities, url: server_url
161
+ rescue Errno::ECONNREFUSED
162
+ raise 'ERROR: Unable to connect to Appium. Is the server running?'
163
+ end
164
+
165
+ # Set timeout to a large number so that Appium doesn't quit
166
+ # when no commands are entered after 60 seconds.
167
+ mobile :setCommandTimeout, timeout: 9999
168
+
169
+ # Set implicit wait by default unless we're using Pry.
170
+ @driver.manage.timeouts.implicit_wait = @default_wait unless defined? Pry
171
+
172
+ @driver
173
+ end
174
+
175
+ # Set implicit wait to zero.
176
+ def no_wait
177
+ @driver.manage.timeouts.implicit_wait = 0
178
+ end
179
+
180
+ # Set implicit wait to timeout, defaults to 30.
181
+ # @param timeout [Integer] the timeout in seconds
182
+ # @return [void]
183
+ def set_wait timeout=@default_wait
184
+ @driver.manage.timeouts.implicit_wait = timeout
185
+ end
186
+
187
+ # Returns the default client side wait.
188
+ # This value is independent of what the server is using
189
+ # @return [Integer]
190
+ def get_wait
191
+ @default_wait
192
+ end
193
+
194
+ # Returns existence of element.
195
+ #
196
+ # Example:
197
+ #
198
+ # exists { button('sign in') } ? puts('true') : puts('false')
199
+ #
200
+ # @return [Boolean]
201
+ def exists &search_block
202
+ pre_check = 0
203
+ post_check = @default_wait
204
+
205
+ set_wait pre_check # set wait to zero
206
+
207
+ # the element exists unless an error is raised.
208
+ exists = true
209
+
210
+ begin
211
+ search_block.call # search for element
212
+ rescue
213
+ exists = false # error means it's not there
214
+ end
215
+
216
+ # restore wait
217
+ set_wait post_check
218
+
219
+ exists
220
+ end
221
+
222
+ # The same as @driver.execute_script
223
+ # @return [Object] the object returned by execute_script
224
+ def execute_script script, *args
225
+ @driver.execute_script script, *args
226
+ end
227
+
228
+ # Helper method for mobile gestures
229
+ #
230
+ # https://github.com/appium/appium/wiki/Automating-mobile-gestures
231
+ #
232
+ # @driver.execute_script 'mobile: swipe', endX: 100, endY: 100, duration: 0.01
233
+ #
234
+ # becomes
235
+ #
236
+ # mobile :swipe, endX: 100, endY: 100, duration: 0.01
237
+ def mobile method, *args
238
+ raise 'Method must not be nil' if method.nil?
239
+ raise 'Method must have .to_s' unless method.respond_to? :to_s
240
+ @driver.execute_script "mobile: #{method.to_s}", *args
241
+ end
242
+
243
+ # Calls @driver.find_elements
244
+ def find_elements *args
245
+ @driver.find_elements *args
246
+ end
247
+
248
+ # Calls @driver.find_elements
249
+ def find_element *args
250
+ @driver.find_element *args
251
+ end
252
+
253
+ # Quit the driver and Pry.
254
+ # quit and exit are reserved by Pry.
255
+ def x
256
+ driver_quit
257
+ exit # exit pry
258
+ end
259
+ end # end class Driver
260
+ end # end module Appium
261
+
262
+ # Paging in Pry is annoying :q required to exit.
263
+ # With pager disabled, the output is similar to IRB
264
+ # Only set if Pry is defined.
265
+ Pry.config.pager = false if defined?(Pry)