testcentricity_apps 4.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +3 -0
  3. data/CHANGELOG.md +193 -0
  4. data/LICENSE.md +27 -0
  5. data/README.md +2297 -0
  6. data/lib/testcentricity_apps/app_core/appium_connect_helper.rb +667 -0
  7. data/lib/testcentricity_apps/app_core/screen_object.rb +494 -0
  8. data/lib/testcentricity_apps/app_core/screen_objects_helper.rb +211 -0
  9. data/lib/testcentricity_apps/app_core/screen_section.rb +669 -0
  10. data/lib/testcentricity_apps/app_elements/alert.rb +152 -0
  11. data/lib/testcentricity_apps/app_elements/app_element.rb +728 -0
  12. data/lib/testcentricity_apps/app_elements/button.rb +10 -0
  13. data/lib/testcentricity_apps/app_elements/checkbox.rb +61 -0
  14. data/lib/testcentricity_apps/app_elements/image.rb +10 -0
  15. data/lib/testcentricity_apps/app_elements/label.rb +10 -0
  16. data/lib/testcentricity_apps/app_elements/list.rb +188 -0
  17. data/lib/testcentricity_apps/app_elements/menu.rb +159 -0
  18. data/lib/testcentricity_apps/app_elements/menubar.rb +78 -0
  19. data/lib/testcentricity_apps/app_elements/radio.rb +61 -0
  20. data/lib/testcentricity_apps/app_elements/selectlist.rb +126 -0
  21. data/lib/testcentricity_apps/app_elements/switch.rb +66 -0
  22. data/lib/testcentricity_apps/app_elements/textfield.rb +51 -0
  23. data/lib/testcentricity_apps/appium_server.rb +76 -0
  24. data/lib/testcentricity_apps/data_objects/data_objects_helper.rb +100 -0
  25. data/lib/testcentricity_apps/data_objects/environment.rb +423 -0
  26. data/lib/testcentricity_apps/exception_queue_helper.rb +160 -0
  27. data/lib/testcentricity_apps/utility_helpers.rb +48 -0
  28. data/lib/testcentricity_apps/version.rb +3 -0
  29. data/lib/testcentricity_apps/world_extensions.rb +61 -0
  30. data/lib/testcentricity_apps.rb +103 -0
  31. metadata +322 -0
@@ -0,0 +1,669 @@
1
+ require 'test/unit'
2
+
3
+ module TestCentricity
4
+ class ScreenSection < BaseScreenSectionObject
5
+ include Test::Unit::Assertions
6
+
7
+ attr_reader :context, :name
8
+ attr_accessor :locator
9
+ attr_accessor :parent
10
+ attr_accessor :parent_list
11
+ attr_accessor :list_index
12
+
13
+ def initialize(name, parent, locator, context)
14
+ @name = name
15
+ @parent = parent
16
+ @locator = locator
17
+ @context = context
18
+ @parent_list = nil
19
+ @list_index = nil
20
+ end
21
+
22
+ def get_locator
23
+ my_locator = if @locator.zero? && defined?(section_locator)
24
+ section_locator
25
+ else
26
+ @locator
27
+ end
28
+ locators = []
29
+ if @context == :section && !@parent.nil?
30
+ locators = @parent.get_locator
31
+ end
32
+
33
+ if @parent_list.nil?
34
+ locators.push(my_locator)
35
+ else
36
+ locators.push(@parent_list.get_locator)
37
+ if @list_index.nil?
38
+ locators.push(my_locator)
39
+ else
40
+ item_objects = @parent_list.item_refs
41
+ if item_objects.nil?
42
+ list_key = my_locator.keys[0]
43
+ list_value = "#{my_locator.values[0]}[#{@list_index}]"
44
+ else
45
+ list_key = :object
46
+ list_value = item_objects[@list_index - 1]
47
+ end
48
+ locators.push( { list_key => list_value } )
49
+ end
50
+ end
51
+ locators
52
+ end
53
+
54
+ def set_list_index(list, index = 1)
55
+ @parent_list = list unless list.nil?
56
+ @list_index = index
57
+ end
58
+
59
+ def get_item_count
60
+ raise 'No parent list defined' if @parent_list.nil?
61
+ @parent_list.get_item_count
62
+ end
63
+
64
+ def get_list_items
65
+ items = []
66
+ (1..get_item_count).each do |item|
67
+ set_list_index(nil, item)
68
+ begin
69
+ items.push(get_value)
70
+ rescue
71
+ scroll_into_view(@parent_list.scroll_mode)
72
+ items.push(get_value)
73
+ end
74
+ end
75
+ items
76
+ end
77
+
78
+ def get_object_type
79
+ :section
80
+ end
81
+
82
+ def get_name
83
+ @name
84
+ end
85
+
86
+ def set_parent(parent)
87
+ @parent = parent
88
+ end
89
+
90
+ # Declare and instantiate a single generic UI Element for this screen section object.
91
+ #
92
+ # @param element_name [Symbol] name of UI object (as a symbol)
93
+ # @param locator [Hash] { locator_strategy: locator_identifier }
94
+ # The locator_strategy (a Symbol) specifies the selector strategy that Appium will use to find the UI element. Valid
95
+ # selectors are accessibility_id:, id:, name:, class:, xpath:, predicate: (iOS only), class_chain: (iOS only), and
96
+ # css: (WebViews in hybrid apps only).
97
+ # * The locator_identifier (a String) is the value or attribute that uniquely and unambiguously identifies the UI element.
98
+ #
99
+ # @example
100
+ # element :video_player, { accessibility_id: 'YouTube Video Player' }
101
+ #
102
+ def self.element(element_name, locator)
103
+ define_section_element(element_name, TestCentricity::AppElements::AppUIElement, locator)
104
+ end
105
+
106
+ # Declare and instantiate a collection of generic UI Elements for this screen section object.
107
+ #
108
+ # @param element_hash [Hash] names of UI objects (as a Symbol) and locator Hash
109
+ # @example
110
+ # elements drop_down_field: { accessibility_id: 'drop_trigger' },
111
+ # settings_item: { accessibility_id: 'settings' },
112
+ # log_out_item: { accessibility_id: 'logout' }
113
+ #
114
+ def self.elements(element_hash)
115
+ element_hash.each_pair { |element_name, locator| element(element_name, locator) }
116
+ end
117
+
118
+ # Declare and instantiate a single button UI Element for this screen section object.
119
+ #
120
+ # @param element_name [Symbol] name of button object (as a symbol)
121
+ # @param locator [Hash] { locator_strategy: locator_identifier }
122
+ # @example
123
+ # button :video_play, { accessibility_id: 'video icon play' }
124
+ #
125
+ def self.button(element_name, locator)
126
+ define_section_element(element_name, TestCentricity::AppElements::AppButton, locator)
127
+ end
128
+
129
+ # Declare and instantiate a collection of buttons for this screen section object.
130
+ #
131
+ # @param element_hash [Hash] names of buttons (as symbol) and locator Hash
132
+ # @example
133
+ # buttons video_back: { accessibility_id: 'video icon backward' },
134
+ # video_play: { accessibility_id: 'video icon play' },
135
+ # video_pause: { accessibility_id: 'video icon stop' },
136
+ # video_forward: { accessibility_id: 'video icon forward' }
137
+ #
138
+ def self.buttons(element_hash)
139
+ element_hash.each_pair { |element_name, locator| button(element_name, locator) }
140
+ end
141
+
142
+ # Declare and instantiate a single textfield UI Element for this screen section object.
143
+ #
144
+ # @param element_name [Symbol] name of textfield object (as a symbol)
145
+ # @param locator [Hash] { locator_strategy: locator_identifier }
146
+ # @example
147
+ # textfield :payee_name_field, { xpath: '//android.widget.EditText[@content-desc="Full Name* input field"]' }
148
+ # textfield :payee_name_field, { xpath: '//XCUIElementTypeTextField[@name="Full Name* input field"]' }
149
+ #
150
+ def self.textfield(element_name, locator)
151
+ define_section_element(element_name, TestCentricity::AppElements::AppTextField, locator)
152
+ end
153
+
154
+ # Declare and instantiate a collection of textfields for this screen section object.
155
+ #
156
+ # @param element_hash [Hash] names of textfields (as symbol) and locator Hash
157
+ # @example
158
+ # textfields username_field: { accessibility_id: 'Username input field' },
159
+ # password_field: { accessibility_id: 'Password input field' }
160
+ #
161
+ def self.textfields(element_hash)
162
+ element_hash.each_pair { |element_name, locator| textfield(element_name, locator) }
163
+ end
164
+
165
+ # Declare and instantiate a single switch UI Element for this screen section object.
166
+ #
167
+ # @param element_name [Symbol] name of switch object (as a symbol)
168
+ # @param locator [Hash] { locator_strategy: locator_identifier }
169
+ # @example
170
+ # switch :debug_mode_switch, { accessibility_id: 'debug mode' }
171
+ #
172
+ def self.switch(element_name, locator)
173
+ define_section_element(element_name, TestCentricity::AppElements::AppSwitch, locator)
174
+ end
175
+
176
+ # Declare and instantiate a collection of switches for this screen section object.
177
+ #
178
+ # @param element_hash [Hash] names of switches (as symbol) and locator Hash
179
+ # @example
180
+ # switches debug_mode_switch: { accessibility_id: 'debug mode' },
181
+ # metrics_switch: { accessibility_id: 'metrics' }
182
+ #
183
+ def self.switches(element_hash)
184
+ element_hash.each_pair { |element_name, locator| switch(element_name, locator) }
185
+ end
186
+
187
+ # Declare and instantiate a single checkbox UI Element for this screen section object.
188
+ #
189
+ # @param element_name [Symbol] name of checkbox object (as a symbol)
190
+ # @param locator [Hash] { locator_strategy: locator_identifier }
191
+ # @example
192
+ # checkbox :bill_address_check, { xpath: '//XCUIElementTypeOther[contains(@name, "billing checkbox")]'}
193
+ #
194
+ def self.checkbox(element_name, locator)
195
+ define_section_element(element_name, TestCentricity::AppElements::AppCheckBox, locator)
196
+ end
197
+
198
+ # Declare and instantiate a collection of checkboxes for this screen section object.
199
+ #
200
+ # @param element_hash [Hash] names of checkboxes (as symbol) and locator Hash
201
+ # @example
202
+ # checkboxes bill_address_check: { xpath: '//XCUIElementTypeOther[contains(@name, "billing checkbox")]'},
203
+ # is_gift_check: { accessibility_id: 'is a gift' }
204
+ #
205
+ def self.checkboxes(element_hash)
206
+ element_hash.each_pair { |element_name, locator| checkbox(element_name, locator) }
207
+ end
208
+
209
+ # Declare and instantiate a single radio button UI Element for this screen section object.
210
+ #
211
+ # @param element_name [Symbol] name of radio button object (as a symbol)
212
+ # @param locator [Hash] { locator_strategy: locator_identifier }
213
+ # @example
214
+ # radio :unicode_radio, { xpath: '//XCUIElementTypeRadioButton[@label="Unicode"]'}
215
+ #
216
+ def self.radio(element_name, locator)
217
+ define_section_element(element_name, TestCentricity::AppElements::AppRadio, locator)
218
+ end
219
+
220
+ # Declare and instantiate a collection of radio buttons for this screen section object.
221
+ #
222
+ # @param element_hash [Hash] names of radio buttons (as symbol) and locator Hash
223
+ # @example
224
+ # radios unicode_radio: { xpath: '//XCUIElementTypeRadioButton[@label="Unicode"]'},
225
+ # ascii_radio: { xpath: '//XCUIElementTypeRadioButton[@label="ASCII"] }
226
+ #
227
+ def self.radios(element_hash)
228
+ element_hash.each_pair { |element_name, locator| radio(element_name, locator) }
229
+ end
230
+
231
+ # Declare and instantiate a single label UI Element for this screen section object.
232
+ #
233
+ # @param element_name [Symbol] name of label object (as a symbol)
234
+ # @param locator [Hash] { locator_strategy: locator_identifier }
235
+ # @example
236
+ # label :header_label, { accessibility_id: 'container header' }
237
+ #
238
+ def self.label(element_name, locator)
239
+ define_section_element(element_name, TestCentricity::AppElements::AppLabel, locator)
240
+ end
241
+
242
+ # Declare and instantiate a collection of labels for this screen section object.
243
+ #
244
+ # @param element_hash [Hash] names of labels (as symbol) and locator Hash
245
+ # @example
246
+ # labels total_qty_value: { accessibility_id: 'total number' },
247
+ # total_price_value: { accessibility_id: 'total price' }
248
+ #
249
+ def self.labels(element_hash)
250
+ element_hash.each_pair { |element_name, locator| label(element_name, locator) }
251
+ end
252
+
253
+ # Declare and instantiate a single list UI Element for this screen section object.
254
+ #
255
+ # @param element_name [Symbol] name of list object (as a symbol)
256
+ # @param locator [Hash] { locator_strategy: locator_identifier }
257
+ # @example
258
+ # list :carousel_list, { accessibility_id: 'Carousel' }
259
+ #
260
+ def self.list(element_name, locator)
261
+ define_section_element(element_name, TestCentricity::AppElements::AppList, locator)
262
+ end
263
+
264
+ # Declare and instantiate a collection of lists for this screen section object.
265
+ #
266
+ # @param element_hash [Hash] names of lists (as symbol) and locator Hash
267
+ # @example
268
+ # lists product_grid: { xpath: '//android.widget.ScrollView/android.view.ViewGroup' },
269
+ # cart_list: { xpath: '//android.widget.ScrollView[@content-desc="cart screen"]' }
270
+ #
271
+ def self.lists(element_hash)
272
+ element_hash.each_pair { |element_name, locator| list(element_name, locator) }
273
+ end
274
+
275
+ # Declare and instantiate a single selectlist UI Element for this screen section object.
276
+ #
277
+ # @param element_name [Symbol] name of selectlist object (as a symbol)
278
+ # @param locator [Hash] { locator_strategy: locator_identifier }
279
+ # @example
280
+ # selectlist :convert_list, { xpath: '//XCUIElementTypePopUpButton[@label="convert"]' }
281
+ #
282
+ def self.selectlist(element_name, locator)
283
+ define_section_element(element_name, TestCentricity::AppElements::AppSelectList, locator)
284
+ end
285
+
286
+ # Declare and instantiate a collection of selectlists for this screen section object.
287
+ #
288
+ # @param element_hash [Hash] names of selectlists (as symbol) and locator Hash
289
+ # @example
290
+ # selectlists convert_list: { xpath: '//XCUIElementTypePopUpButton[@label="convert"]' },
291
+ # from_list: { xpath: '//XCUIElementTypePopUpButton[@label="convert_from"]' }
292
+ #
293
+ def self.selectlists(element_hash)
294
+ element_hash.each_pair { |element_name, locator| selectlist(element_name, locator) }
295
+ end
296
+
297
+ # Declare and instantiate a single image UI Element for this screen section object.
298
+ #
299
+ # @param element_name [Symbol] name of image object (as a symbol)
300
+ # @param locator [Hash] { locator_strategy: locator_identifier }
301
+ # @example
302
+ # image :product_image, { xpath: '//XCUIElementTypeImage' }
303
+ #
304
+ def self.image(element_name, locator)
305
+ define_section_element(element_name, TestCentricity::AppElements::AppImage, locator)
306
+ end
307
+
308
+ # Declare and instantiate a collection of images for this screen section object.
309
+ #
310
+ # @param element_hash [Hash] names of images (as symbol) and locator Hash
311
+ # @example
312
+ # images empty_cart_image: { accessibility_id: 'empty_cart' },
313
+ # logo_image: { accessibility_id: 'WebdriverIO logo' }
314
+ #
315
+ def self.images(element_hash)
316
+ element_hash.each_pair { |element_name, locator| image(element_name, locator) }
317
+ end
318
+
319
+ # Instantiate a single ScreenSection object within this ScreenSection object.
320
+ #
321
+ # @param section_name [Symbol] name of ScreenSection object (as a symbol)
322
+ # @param class_name [Class] Class name of ScreenSection object
323
+ # @example
324
+ # section :nav_menu, NavMenu
325
+ #
326
+ def self.section(section_name, obj, locator = 0)
327
+ define_section_element(section_name, obj, locator)
328
+ end
329
+
330
+ # Declare and instantiate a collection of ScreenSection objects for this ScreenSection object.
331
+ #
332
+ # @param element_hash [Hash] names of ScreenSections (as symbol) and class name
333
+ # @example
334
+ # sections product_grid_item: ProductGridItem,
335
+ # sort_by_menu: SortByMenu
336
+ #
337
+ def self.sections(section_hash)
338
+ section_hash.each_pair { |section_name, class_name| section(section_name, class_name) }
339
+ end
340
+
341
+ # Click on a screen Section object
342
+ #
343
+ # @example
344
+ # bar_chart_section.click
345
+ #
346
+ def click
347
+ section = find_section
348
+ section_not_found_exception(section)
349
+ section.click
350
+ end
351
+
352
+ # Tap on a screen Section object
353
+ #
354
+ # @example
355
+ # bar_chart_section.tap
356
+ #
357
+ def tap
358
+ section = find_section
359
+ section_not_found_exception(section)
360
+ driver.action
361
+ .click_and_hold(section)
362
+ .release
363
+ .perform
364
+ end
365
+
366
+ # Double-tap on a screen Section object
367
+ #
368
+ # @example
369
+ # bar_chart_section.double_tap
370
+ #
371
+ def double_tap
372
+ section = find_section
373
+ section_not_found_exception(section)
374
+ driver.action
375
+ .click_and_hold(section)
376
+ .release
377
+ .pause(duration: 0.2)
378
+ .click_and_hold(section)
379
+ .release
380
+ .perform
381
+ end
382
+
383
+ # Long press on a screen Section object
384
+ #
385
+ # @param duration [Float] duration of long press in seconds
386
+ # @example
387
+ # header_image.long_press(1.5)
388
+ #
389
+ def long_press(duration = 1)
390
+ section = find_section
391
+ section_not_found_exception(section)
392
+ driver.action
393
+ .click_and_hold(section)
394
+ .pause(duration: duration)
395
+ .release
396
+ .perform
397
+ end
398
+
399
+ # Scroll the screen Section object until it is visible. If scroll_mode is not specified, then vertical scrolling will
400
+ # be used.
401
+ #
402
+ # @param scroll_mode [Symbol] :vertical (default) or :horizontal
403
+ # @example
404
+ # carousel_item.scroll_into_view(scroll_mode = :horizontal)
405
+ #
406
+ def scroll_into_view(scroll_mode = :vertical)
407
+ return if visible?
408
+ obj = element
409
+ object_not_found_exception(obj)
410
+ driver.action.move_to(obj).perform
411
+ case scroll_mode
412
+ when :vertical
413
+ start_direction = :down
414
+ end_direction = :up
415
+ when :horizontal
416
+ start_direction = :right
417
+ end_direction = :left
418
+ else
419
+ raise "#{scroll_mode} is not a valid selector"
420
+ end
421
+ try_count = 8
422
+ direction = start_direction
423
+ while hidden?
424
+ swipe_gesture(direction, distance = 0.2)
425
+ try_count -= 1
426
+ if try_count.zero?
427
+ if direction == end_direction
428
+ break
429
+ else
430
+ direction = end_direction
431
+ try_count = 8
432
+ end
433
+ end
434
+ end
435
+ end
436
+
437
+ # Does screen Section object exists?
438
+ #
439
+ # @return [Boolean]
440
+ # @example
441
+ # navigation_toolbar.exists?
442
+ #
443
+ def exists?
444
+ section = find_section
445
+ section != nil
446
+ end
447
+
448
+ # Is screen Section object enabled?
449
+ #
450
+ # @return [Boolean]
451
+ # @example
452
+ # bar_chart_section.enabled?
453
+ #
454
+ def enabled?
455
+ section = find_section
456
+ section_not_found_exception(section)
457
+ section.enabled?
458
+ end
459
+
460
+ # Is screen Section object disabled (not enabled)?
461
+ #
462
+ # @return [Boolean]
463
+ # @example
464
+ # bar_chart_section.disabled?
465
+ #
466
+ def disabled?
467
+ !enabled?
468
+ end
469
+
470
+ # Is screen Section object visible?
471
+ #
472
+ # @return [Boolean]
473
+ # @example
474
+ # navigation_toolbar.visible?
475
+ #
476
+ def visible?
477
+ section = find_section
478
+ return false if section.nil?
479
+ section.displayed?
480
+ end
481
+
482
+ # Is screen Section object hidden (not visible)?
483
+ #
484
+ # @return [Boolean]
485
+ # @example
486
+ # navigation_toolbar.hidden?
487
+ #
488
+ def hidden?
489
+ !visible?
490
+ end
491
+
492
+ def identifier
493
+ if Environ.is_macos?
494
+ section = find_section
495
+ section_not_found_exception(section)
496
+ section.identifier
497
+ else
498
+ raise 'identifier is not a supported attribute'
499
+ end
500
+ end
501
+
502
+ # Send keystrokes to this section object.
503
+ #
504
+ # @param value [String] keys
505
+ # @example
506
+ # basic_view.send_keys('Lime green')
507
+ #
508
+ def send_keys(value)
509
+ section = find_section
510
+ section_not_found_exception(section)
511
+ section.send_keys(value)
512
+ end
513
+
514
+ # Wait until the screen Section object exists, or until the specified wait time has expired. If the wait time is nil,
515
+ # then the wait time will be Environ.default_max_wait_time.
516
+ #
517
+ # @param seconds [Integer or Float] wait time in seconds
518
+ # @example
519
+ # navigation_toolbar.wait_until_exists(1.5)
520
+ #
521
+ def wait_until_exists(seconds = nil, post_exception = true)
522
+ timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
523
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
524
+ wait.until { exists? }
525
+ rescue
526
+ if post_exception
527
+ raise "Could not find Section object '#{get_name}' (#{get_locator}) after #{timeout} seconds" unless exists?
528
+ else
529
+ exists?
530
+ end
531
+ end
532
+
533
+ # Wait until the screen Section object no longer exists, or until the specified wait time has expired. If the wait
534
+ # time is nil, then the wait time will be Environ.default_max_wait_time.
535
+ #
536
+ # @param seconds [Integer or Float] wait time in seconds
537
+ # @example
538
+ # navigation_toolbar.wait_until_gone(5)
539
+ #
540
+ def wait_until_gone(seconds = nil, post_exception = true)
541
+ timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
542
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
543
+ wait.until { !exists? }
544
+ rescue
545
+ if post_exception
546
+ raise "Section object '#{get_name}' (#{get_locator}) remained visible after #{timeout} seconds" if exists?
547
+ else
548
+ exists?
549
+ end
550
+ end
551
+
552
+ # Wait until the screen Section object is visible, or until the specified wait time has expired. If the wait time is nil,
553
+ # then the wait time will be Environ.default_max_wait_time.
554
+ #
555
+ # @param seconds [Integer or Float] wait time in seconds
556
+ # @example
557
+ # navigation_toolbar.wait_until_visible(1.5)
558
+ #
559
+ def wait_until_visible(seconds = nil, post_exception = true)
560
+ timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
561
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
562
+ wait.until { visible? }
563
+ rescue
564
+ if post_exception
565
+ raise "Could not find Section object '#{get_name}' (#{get_locator}) after #{timeout} seconds" unless visible?
566
+ else
567
+ visible?
568
+ end
569
+ end
570
+
571
+ # Wait until the screen Section object is hidden, or until the specified wait time has expired. If the wait time is nil,
572
+ # then the wait time will be Environ.default_max_wait_time.
573
+ #
574
+ # @param seconds [Integer or Float] wait time in seconds
575
+ # @example
576
+ # navigation_toolbar.wait_until_hidden(2)
577
+ #
578
+ def wait_until_hidden(seconds = nil, post_exception = true)
579
+ timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
580
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
581
+ wait.until { hidden? }
582
+ rescue
583
+ if post_exception
584
+ raise "Section object '#{get_name}' (#{get_locator}) remained visible after #{timeout} seconds" if visible?
585
+ else
586
+ visible?
587
+ end
588
+ end
589
+
590
+ # Return width of screen Section object.
591
+ #
592
+ # @return [Integer]
593
+ # @example
594
+ # button_width = my_button.width
595
+ #
596
+ def width
597
+ section = find_section
598
+ section_not_found_exception(section)
599
+ section.size.width
600
+ end
601
+
602
+ # Return height of screen Section object.
603
+ #
604
+ # @return [Integer]
605
+ # @example
606
+ # button_height = my_button.height
607
+ #
608
+ def height
609
+ section = find_section
610
+ section_not_found_exception(section)
611
+ section.size.height
612
+ end
613
+
614
+ # Return x coordinate of screen Section object's location.
615
+ #
616
+ # @return [Integer]
617
+ # @example
618
+ # button_x = my_button.x_loc
619
+ #
620
+ def x_loc
621
+ section = find_section
622
+ section_not_found_exception(section)
623
+ section.location.x
624
+ end
625
+
626
+ # Return y coordinate of screen Section object's location.
627
+ #
628
+ # @return [Integer]
629
+ # @example
630
+ # button_x = my_button.x_loc
631
+ #
632
+ def y_loc
633
+ section = find_section
634
+ section_not_found_exception(section)
635
+ section.location.y
636
+ end
637
+
638
+ private
639
+
640
+ def find_section
641
+ obj = nil
642
+ locators = get_locator
643
+ locators.each do |loc|
644
+ if obj.nil?
645
+ obj = find_element(loc.keys[0], loc.values[0])
646
+ else
647
+ obj = obj.find_element(loc.keys[0], loc.values[0])
648
+ end
649
+ puts "Found section object #{loc}" if ENV['DEBUG']
650
+ end
651
+ obj
652
+ rescue
653
+ nil
654
+ end
655
+
656
+ def section_not_found_exception(obj)
657
+ raise ObjectNotFoundError.new("Section object '#{get_name}' - (#{get_locator}) not found") unless obj
658
+ end
659
+
660
+ def self.define_section_element(element_name, obj, locator)
661
+ define_method(element_name) do
662
+ ivar_name = "@#{element_name}"
663
+ ivar = instance_variable_get(ivar_name)
664
+ return ivar if ivar
665
+ instance_variable_set(ivar_name, obj.new(element_name, self, locator, :section))
666
+ end
667
+ end
668
+ end
669
+ end