@@ -216,102 +216,79 @@ def find_eles_attr tag_name, attribute=nil
216
216
complex_find array
217
217
end
218
218
219
- # Android only.
220
- # Returns a string containing interesting elements.
221
- # If an element has no content desc or text, then it's not returned by this method.
222
- # @return [String]
223
- def get_android_inspect
224
- # @private
225
- def run node
226
- r = [ ]
219
+ # http://nokogiri.org/Nokogiri/XML/SAX.html
220
+ class AndroidElements < Nokogiri ::XML ::SAX ::Document
221
+ # TODO: Support strings.xml ids
222
+ attr_reader :result , :keys
227
223
228
- run_internal = lambda do |node |
229
- if node . kind_of? Array
230
- node . each { |node | run_internal . call node }
231
- return
232
- end
224
+ def filter
225
+ @filter
226
+ end
233
227
234
- keys = node . keys
235
- return if keys . empty?
236
- if keys == %w( hierarchy )
237
- run_internal . call node [ 'hierarchy' ]
238
- return
239
- end
228
+ # convert to string to support symbols
229
+ def filter = value
230
+ # nil and false disable the filter
231
+ return @filter = false unless value
232
+ @filter = value . to_s . downcase
233
+ end
240
234
241
- n_content = '@content-desc'
242
- n_text = '@text'
243
- n_class = '@class'
244
- n_resource = '@resource-id'
245
- n_node = 'node'
246
-
247
- # Store the object if it has a content description, text, or resource id.
248
- # If it only has a class, then don't save it.
249
- obj = { }
250
- obj . merge! ( { desc : node [ n_content ] } ) if keys . include? ( n_content ) && !node [ n_content ] . empty?
251
- obj . merge! ( { text : node [ n_text ] } ) if keys . include? ( n_text ) && !node [ n_text ] . empty?
252
- obj . merge! ( { resource_id : node [ n_resource ] } ) if keys . include? ( n_resource ) && !node [ n_resource ] . empty?
253
- obj . merge! ( { class : node [ n_class ] } ) if keys . include? ( n_class ) && !obj . empty?
254
-
255
- r . push obj if !obj . empty?
256
- run_internal . call node [ n_node ] if keys . include? ( n_node )
257
- end
235
+ def initialize
236
+ reset
237
+ @filter = false
238
+ end
258
239
259
- run_internal . call node
260
- r
240
+ def reset
241
+ @result = ''
242
+ @keys = %w[ text resource-id content-desc ]
261
243
end
262
244
263
- lazy_load_strings
264
- json = get_source
265
- node = json [ 'hierarchy' ]
266
- results = run node
267
-
268
- out = ''
269
- results . each { |e |
270
- e_desc = e [ :desc ]
271
- e_text = e [ :text ]
272
- e_class = e [ :class ]
273
- e_resource_id = e [ :resource_id ]
274
- out += e_class . split ( '.' ) . last + "\n "
275
-
276
- out += " class: #{ e_class } \n "
277
- if e_text == e_desc
278
- out += " text, name: #{ e_text } \n " unless e_text . nil?
279
- else
280
- out += " text: #{ e_text } \n " unless e_text . nil?
281
- out += " name: #{ e_desc } \n " unless e_desc . nil?
282
- end
245
+ # http://nokogiri.org/Nokogiri/XML/SAX/Document.html
246
+ def start_element name , attrs = [ ]
247
+ return if filter && !name . downcase . include? ( filter )
283
248
284
- out += " resource_id: #{ e_resource_id } \n " unless e_resource_id . nil? || e_resource_id . empty?
249
+ attributes = { }
285
250
286
- # there may be many ids with the same value.
287
- # output all exact matches.
288
- id_matches = @strings_xml . select do | key , value |
289
- value == e_desc || value == e_text
251
+ attrs . each do | key , value |
252
+ if keys . include? ( key ) && ! value . empty?
253
+ attributes [ key ] = value
254
+ end
290
255
end
291
256
292
- if id_matches && id_matches . length > 0
293
- match_str = ''
294
- # [0] = key, [1] = value
295
- id_matches . each do |match |
296
- match_str += ' ' * 6 + "#{ match [ 0 ] } \n "
297
- end
298
- out += " id: #{ match_str . strip } \n "
257
+ string = ''
258
+ text = attributes [ 'text' ]
259
+ desc = attributes [ 'content-desc' ]
260
+ id = attributes [ 'resource-id' ]
261
+
262
+ if !text . nil? && text == desc
263
+ string += " text, desc: #{ text } \n "
264
+ else
265
+ string += " text: #{ text } \n " unless text . nil?
266
+ string += " desc: #{ desc } \n " unless desc . nil?
299
267
end
300
- }
301
- out
302
- end
268
+ string += " id: #{ id } \n " unless id . nil?
269
+
270
+ @result += "\n #{ name } \n #{ string } " unless attributes . empty?
271
+ end
272
+ end # class AndroidElements
303
273
304
- # Automatically detects selendroid or android .
274
+ # Android only .
305
275
# Returns a string containing interesting elements.
276
+ # If an element has no content desc or text, then it's not returned by this method.
306
277
# @return [String]
307
- def get_inspect
308
- get_android_inspect
278
+ def get_android_inspect class_name = false
279
+ parser = @android_elements_parser ||= Nokogiri ::XML ::SAX ::Parser . new ( AndroidElements . new )
280
+
281
+ parser . document . reset
282
+ parser . document . filter = class_name
283
+ parser . parse get_source
284
+
285
+ parser . document . result
309
286
end
310
287
311
288
# Intended for use with console.
312
289
# Inspects and prints the current page.
313
- def page
314
- puts get_inspect
290
+ def page class_name = false
291
+ puts get_android_inspect class_name
315
292
nil
316
293
end
317
294
@@ -431,7 +408,7 @@ def tags class_name
431
408
# example: xpath_visible_contains 'UIATextField', text
432
409
def string_visible_contains element , value
433
410
result = [ ]
434
- attributes = %w[ content-desc resource-id text ]
411
+ attributes = %w[ content-desc text ]
435
412
436
413
value_up = value . upcase
437
414
value_down = value . downcase
@@ -440,6 +417,9 @@ def string_visible_contains element, value
440
417
result << %Q(contains(translate(@#{ attribute } ,"#{ value_up } ","#{ value_down } "), "#{ value_down } "))
441
418
end
442
419
420
+ # never partial match on a resource id
421
+ result << %Q(@resource-id="#{ value } ")
422
+
443
423
result = result . join ( ' or ' )
444
424
445
425
"//#{ element } [#{ result } ]"
0 commit comments