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
@@ -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