appium_lib 0.0.30 → 0.3.0

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.
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
@@ -1,12 +0,0 @@
1
- # encoding: utf-8
2
- # UIAWindow methods
3
-
4
- # Get the window's size
5
- #
6
- # window_size.width
7
- #
8
- # window_size.height
9
- def window_size
10
- return nil if $driver.nil?
11
- $driver.manage.window.size
12
- end
@@ -1,278 +0,0 @@
1
- # encoding: utf-8
2
- # Generic helper methods not specific
3
- # to a particular tag name
4
-
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) { while(!(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
- # Get the element of type tag_name at matching index.
39
- # @param tag_name [String] the tag name to find
40
- # @param index [Integer] the index
41
- # @return [Element] the found element of type tag_name
42
- def ele_index tag_name, index
43
- find_eles(tag_name)[index]
44
- end
45
-
46
- # Get all elements exactly matching tag name
47
- # @param tag_name [String] the tag name to find
48
- # @return [Array<Element>] the found elements of type tag_name
49
- def find_eles tag_name
50
- $driver.find_elements :tag_name, tag_name
51
- end
52
-
53
- # iOS only. Android uses uiautomator instead of uiautomation.
54
- # Get an array of attribute values from elements exactly matching tag name.
55
- # @param tag_name [String] the tag name to find
56
- # @param attribute [String] the attribute to collect
57
- # @result [Array<String>] an array of strings containing the attribute from found elements of type tag_name.
58
- def find_eles_attr tag_name, attribute
59
- # Use au.lookup(tag_name) instead of $(tag_name)
60
- # See https://github.com/appium/appium/issues/214
61
- js = %Q(
62
- var eles = au.lookup('#{tag_name}');
63
- var result = [];
64
- for (var a = 0, length = eles.length; a < length; a++) {
65
- result.push(eles[a].#{attribute}());
66
- }
67
- result
68
- )
69
-
70
- $driver.execute_script js
71
- end
72
-
73
- # iOS only. Android uses uiautomator instead of uiautomation.
74
- # Get an array of attribute values from elements exactly matching tag name.
75
- # @param tag_name_1 [String] the 1st tag name to find
76
- # @param tag_name_2 [String] the 2nd tag name to find
77
- # @param attribute [String] the attribute to collect
78
- # @result [Array<String>] an array of strings containing the attribute from found elements of type tag_name.
79
- def find_2_eles_attr tag_name_1, tag_name_2, attribute
80
- # Use au.lookup(tag_name) instead of $(tag_name)
81
- # See https://github.com/appium/appium/issues/214
82
- js = %Q(
83
- var eles = au.lookup('#{tag_name_1}');
84
- eles = $(eles.concat(au.lookup('#{tag_name_2}')));
85
- var result = [];
86
- for (var a = 0, length = eles.length; a < length; a++) {
87
- result.push(eles[a].#{attribute}());
88
- }
89
- result
90
- )
91
-
92
- $driver.execute_script js
93
- end
94
-
95
- # Get the first tag that exactly matches tag and text.
96
- # @param tag [String] the tag name to match
97
- # @param text [String] the text to exactly match
98
- # @return [Element] the element of type tag exactly matching text
99
- def find_ele_by_text tag, text
100
- $driver.find_element :xpath, %Q(#{tag}[@text='#{text}'])
101
- end
102
-
103
- # Get all tags that exactly match tag and text.
104
- # @param tag [String] the tag name to match
105
- # @param text [String] the text to exactly match
106
- # @return [Array<Element>] the elements of type tag exactly matching text
107
- def find_eles_by_text tag, text
108
- $driver.find_elements :xpath, %Q(#{tag}[@text='#{text}'])
109
- end
110
-
111
- # Get the first tag by attribute that exactly matches value.
112
- # @param tag [String] the tag name to match
113
- # @param attr [String] the attribute to compare
114
- # @param value [String] the value of the attribute that the element must include
115
- # @return [Element] the element of type tag who's attribute includes value
116
- def find_ele_by_attr_include tag, attr, value
117
- $driver.find_element :xpath, %Q(#{tag}[contains(@#{attr}, '#{value}')])
118
- end
119
-
120
- # Get tags by attribute that include value.
121
- # @param tag [String] the tag name to match
122
- # @param attr [String] the attribute to compare
123
- # @param value [String] the value of the attribute that the element must include
124
- # @return [Array<Element>] the elements of type tag who's attribute includes value
125
- def find_eles_by_attr_include tag, attr, value
126
- $driver.find_elements :xpath, %Q(#{tag}[contains(@#{attr}, '#{value}')])
127
- end
128
-
129
- # Get the first tag that includes text.
130
- # @param tag [String] the tag name to match
131
- # @param text [String] the text the element must include
132
- # @return [Element] the element of type tag that includes text
133
- # element.attribute(:text).include? text
134
- def find_ele_by_text_include tag, text
135
- find_ele_by_attr_include tag, :text, text
136
- end
137
-
138
- # Get the tags that include text.
139
- # @param tag [String] the tag name to match
140
- # @param text [String] the text the element must include
141
- # @return [Array<Element>] the elements of type tag that includes text
142
- # element.attribute(:text).include? text
143
- def find_eles_by_text_include tag, text
144
- find_eles_by_attr_include tag, :text, text
145
- end
146
-
147
- # Get the first tag that matches tag_name
148
- # @param tag_name [String] the tag to match
149
- # @return [Element]
150
- def first_ele tag_name
151
- tag = find_eles tag_name
152
- tag = tag.first unless tag.nil?
153
- end
154
-
155
- # Get the last tag that matches tag_name
156
- # @param tag_name [String] the tag to match
157
- # @return [Element]
158
- def last_ele tag_name
159
- tag = find_eles tag_name
160
- tag = tag.last unless tag.nil?
161
- end
162
-
163
- # Prints a JSON view of the current page
164
- # @return [void]
165
- def source
166
- ap JSON.parse($driver.page_source)
167
- end
168
-
169
- # Gets a JSON view of the current page
170
- # @return [JSON]
171
- def get_source
172
- JSON.parse($driver.page_source)
173
- end
174
-
175
- # iOS only. On Android uiautomator always returns an empty string for EditText password.
176
- #
177
- # Password character returned from value of UIASecureTextField
178
- # @param length [Integer] the length of the password to generate
179
- # @return [String] the returned string is of size length
180
- def password length=1
181
- '•' * length
182
- end
183
-
184
- # Android only.
185
- def get_inspect
186
- def run node
187
- r = []
188
-
189
- run_internal = lambda do |node|
190
- if node.kind_of? Array
191
- node.each { |node| run_internal.call node }
192
- return
193
- end
194
-
195
- keys = node.keys
196
- return if keys.empty?
197
-
198
- obj = {}
199
- obj.merge!( { desc: node["@content-desc"] } ) if keys.include?("@content-desc") && !node["@content-desc"].empty?
200
- obj.merge!( { text: node["@text"] } ) if keys.include?("@text") && !node["@text"].empty?
201
- obj.merge!( { class: node["@class"] } ) if keys.include?("@class") && !obj.empty?
202
-
203
- r.push obj if !obj.empty?
204
- run_internal.call node['node'] if keys.include?('node')
205
- end
206
-
207
- run_internal.call node
208
- r
209
- end
210
-
211
- json = JSON.parse($driver.page_source)
212
- node = json['hierarchy']
213
- results = run node
214
-
215
- out = ''
216
- results.each { |e|
217
- out += e[:class].split('.').last + "\n"
218
- out += " text: #{e[:text]}\n" unless e[:text].nil?
219
- out += " name: #{e[:desc]}\n" unless e[:desc].nil?
220
- }
221
- out
222
- end if $os == :android
223
-
224
- # Android only. Intended for use with console.
225
- # Inspects and prints the current page.
226
- def page
227
- puts get_inspect
228
- nil
229
- end if $os == :android
230
-
231
- def page element
232
-
233
- def empty ele
234
- (ele['name'] || ele['label'] || ele['value']) == nil
235
- end
236
-
237
- def fix_space s
238
- # char code 160 (name, label) vs 32 (value) will break comparison.
239
- # convert string to binary and remove 160.
240
- # \xC2\xA0
241
- s.force_encoding('binary').gsub("\xC2\xA0".force_encoding('binary'), ' ') if s
242
- end
243
-
244
- if ! empty( element )
245
- puts "#{element['type']}"
246
- name = fix_space element['name']
247
- label = fix_space element['label']
248
- value = fix_space element['value']
249
-
250
- if name == label && name == value
251
- puts " name, label, value: #{name}" if name
252
- elsif name == label
253
- puts " name, label: #{name}" if name
254
- puts " value: #{value}" if value
255
- elsif name == value
256
- puts " name, value: #{name}" if name
257
- puts " label: #{label}" if label
258
- else
259
- puts " name: #{name}" if name
260
- puts " label: #{label}" if label
261
- puts " value: #{value}" if value
262
- end
263
- end
264
-
265
- children = element['children']
266
- children.each { |c| page c } if children
267
- nil
268
- end if $os == :ios
269
-
270
- # JavaScript code from https://github.com/appium/appium/blob/master/app/android.js
271
- #
272
- # Math.round((duration * 1000) / 200)
273
- # (.20 * 1000) / 200 = 1
274
- #
275
- # We want steps to be exactly 1. If it's zero then a tap is used instead of a swipe.
276
- def fast_duration
277
- 0.20
278
- end
@@ -1,90 +0,0 @@
1
- # Implement useful features for element.
2
- class Selenium::WebDriver::Element
3
- # Note: For testing .text should be used over value, and name.
4
-
5
- # Fixes NoMethodError: undefined method `value' for #<Selenium::WebDriver::Element:0x..fa4a9148235390a44 id="1">
6
- def value
7
- self.attribute :value
8
- end
9
-
10
- # Fixes NoMethodError: undefined method `name' for #<Selenium::WebDriver::Element
11
- def name
12
- self.attribute :name
13
- end
14
-
15
- # Use tag_name to get element's type.
16
- #
17
- # Tag name appears to be the same as type.
18
- #
19
- # Fixes Selenium::WebDriver::Error::UnknownError: Not yet implemented
20
- def tag_name
21
- self.attribute :type
22
- end
23
-
24
- # Cross platform way of entering text into a textfield
25
- def type text
26
- # enter text then tap window to hide the keyboard.
27
- js = %Q(
28
- au.getElement('#{self.ref}').setValue('#{text}');
29
- au.lookup('window')[0].tap()
30
- )
31
- $driver.execute_script js
32
- end if $os == :ios
33
-
34
- # Cross platform way of entering text into a textfield
35
- def type text
36
- self.send_keys text
37
- end if $os == :android
38
-
39
- # For use with mobile tap.
40
- #
41
- # $driver.execute_script 'mobile: tap', :x => 0.0, :y => 0.98
42
- #
43
- # https://github.com/appium/appium/wiki/Automating-mobile-gestures
44
- # @return [OpenStruct] the relative x, y in a struct. ex: { x: 0.50, y: 0.20 }
45
- def location_rel
46
- xy = self.location
47
- w = window_size
48
- OpenStruct.new( x: xy.x.to_f / w.width.to_f,
49
- y: xy.y.to_f / w.height.to_f )
50
- end
51
- end
52
-
53
- # Print JSON posted to Appium
54
- #
55
- # Requires from lib/selenium/webdriver/remote.rb
56
- require 'selenium/webdriver/remote/capabilities'
57
- require 'selenium/webdriver/remote/bridge'
58
- require 'selenium/webdriver/remote/server_error'
59
- require 'selenium/webdriver/remote/response'
60
- require 'selenium/webdriver/remote/commands'
61
- require 'selenium/webdriver/remote/http/common'
62
- require 'selenium/webdriver/remote/http/default'
63
-
64
- # Show http calls to the Selenium server.
65
- #
66
- # Invaluable for debugging.
67
- module Selenium::WebDriver::Remote
68
- class Bridge
69
- # Code from lib/selenium/webdriver/remote/bridge.rb
70
- def raw_execute(command, opts = {}, command_hash = nil)
71
- verb, path = COMMANDS[command] || raise(ArgumentError, "unknown command: #{command.inspect}")
72
- path = path.dup
73
-
74
- path[':session_id'] = @session_id if path.include?(":session_id")
75
-
76
- begin
77
- opts.each { |key, value| path[key.inspect] = escaper.escape(value.to_s) }
78
- rescue IndexError
79
- raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}"
80
- end
81
-
82
- puts verb
83
- puts path
84
- puts command_hash.to_json
85
-
86
- puts "-> #{verb.to_s.upcase} #{path}" if $DEBUG
87
- http.call verb, path, command_hash
88
- end # def
89
- end # class
90
- end if defined?(Pry)# module
@@ -1,4 +0,0 @@
1
- module AppiumLib
2
- VERSION = '0.0.30' unless defined? ::AppiumLib::VERSION
3
- DATE = '2013-04-16' unless defined? ::AppiumLib::DATE
4
- end