testcentricity 2.3.13

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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +3 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +6 -0
  7. data/Gemfile.lock +93 -0
  8. data/LICENSE.txt +28 -0
  9. data/README.md +1634 -0
  10. data/Rakefile +1 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/lib/devices/devices.yml +344 -0
  14. data/lib/testcentricity.rb +144 -0
  15. data/lib/testcentricity/app_core/appium_connect_helper.rb +154 -0
  16. data/lib/testcentricity/app_core/appium_server.rb +69 -0
  17. data/lib/testcentricity/app_core/screen_objects_helper.rb +180 -0
  18. data/lib/testcentricity/app_core/screen_sections_helper.rb +332 -0
  19. data/lib/testcentricity/app_elements/app_element_helper.rb +293 -0
  20. data/lib/testcentricity/app_elements/button.rb +8 -0
  21. data/lib/testcentricity/app_elements/checkbox.rb +20 -0
  22. data/lib/testcentricity/app_elements/label.rb +8 -0
  23. data/lib/testcentricity/app_elements/list.rb +25 -0
  24. data/lib/testcentricity/app_elements/switch.rb +20 -0
  25. data/lib/testcentricity/app_elements/textfield.rb +12 -0
  26. data/lib/testcentricity/browser_helper.rb +174 -0
  27. data/lib/testcentricity/data_objects/data_objects_helper.rb +78 -0
  28. data/lib/testcentricity/data_objects/environment.rb +281 -0
  29. data/lib/testcentricity/data_objects/excel_helper.rb +242 -0
  30. data/lib/testcentricity/exception_queue_helper.rb +51 -0
  31. data/lib/testcentricity/utility_helpers.rb +28 -0
  32. data/lib/testcentricity/version.rb +3 -0
  33. data/lib/testcentricity/web_core/drag_drop_helper.rb +15 -0
  34. data/lib/testcentricity/web_core/page_objects_helper.rb +669 -0
  35. data/lib/testcentricity/web_core/page_sections_helper.rb +866 -0
  36. data/lib/testcentricity/web_core/webdriver_helper.rb +579 -0
  37. data/lib/testcentricity/web_elements/button.rb +8 -0
  38. data/lib/testcentricity/web_elements/cell_button.rb +8 -0
  39. data/lib/testcentricity/web_elements/cell_checkbox.rb +38 -0
  40. data/lib/testcentricity/web_elements/cell_element.rb +69 -0
  41. data/lib/testcentricity/web_elements/cell_image.rb +8 -0
  42. data/lib/testcentricity/web_elements/cell_radio.rb +31 -0
  43. data/lib/testcentricity/web_elements/checkbox.rb +100 -0
  44. data/lib/testcentricity/web_elements/file_field.rb +45 -0
  45. data/lib/testcentricity/web_elements/image.rb +34 -0
  46. data/lib/testcentricity/web_elements/label.rb +8 -0
  47. data/lib/testcentricity/web_elements/link.rb +8 -0
  48. data/lib/testcentricity/web_elements/list.rb +73 -0
  49. data/lib/testcentricity/web_elements/list_button.rb +8 -0
  50. data/lib/testcentricity/web_elements/list_checkbox.rb +38 -0
  51. data/lib/testcentricity/web_elements/list_element.rb +61 -0
  52. data/lib/testcentricity/web_elements/list_radio.rb +31 -0
  53. data/lib/testcentricity/web_elements/radio.rb +74 -0
  54. data/lib/testcentricity/web_elements/select_list.rb +197 -0
  55. data/lib/testcentricity/web_elements/siebel_open_ui_helper.rb +15 -0
  56. data/lib/testcentricity/web_elements/table.rb +612 -0
  57. data/lib/testcentricity/web_elements/textfield.rb +114 -0
  58. data/lib/testcentricity/web_elements/ui_elements_helper.rb +502 -0
  59. data/lib/testcentricity/world_extensions.rb +26 -0
  60. data/my_templates/default/method_details/setup.rb +3 -0
  61. data/spec/spec_helper.rb +14 -0
  62. data/spec/testcentricity_spec.rb +9 -0
  63. data/testcentricity.gemspec +47 -0
  64. metadata +328 -0
@@ -0,0 +1,866 @@
1
+ require 'test/unit'
2
+
3
+ module TestCentricity
4
+ class PageSection
5
+ include Capybara::DSL
6
+ include Capybara::Node::Matchers
7
+ include Test::Unit::Assertions
8
+
9
+ attr_reader :context, :name
10
+ attr_accessor :locator
11
+ attr_accessor :parent
12
+ attr_accessor :parent_list
13
+ attr_accessor :list_index
14
+ attr_accessor :locator_type
15
+
16
+ XPATH_SELECTORS = ['//', '[@', '[contains(@']
17
+ CSS_SELECTORS = ['#', ':nth-child(', ':nth-of-type(', '^=', '$=', '*=']
18
+
19
+ def initialize(name, parent, locator, context)
20
+ @name = name
21
+ @parent = parent
22
+ @locator = locator
23
+ @context = context
24
+ @parent_list = nil
25
+ @list_index = nil
26
+
27
+ is_xpath = XPATH_SELECTORS.any? { |selector| @locator.include?(selector) }
28
+ is_css = CSS_SELECTORS.any? { |selector| @locator.include?(selector) }
29
+ if is_xpath && !is_css
30
+ @locator_type = :xpath
31
+ elsif is_css && !is_xpath
32
+ @locator_type = :css
33
+ elsif !is_css && !is_xpath
34
+ @locator_type = :css
35
+ else
36
+ raise "Cannot determine type of locator for PageSection '#{@name}' - locator = #{@locator}"
37
+ end
38
+ end
39
+
40
+ def get_locator
41
+ if @locator.empty? && defined?(section_locator)
42
+ locator = section_locator
43
+ else
44
+ locator = @locator
45
+ end
46
+
47
+ unless @parent_list.nil?
48
+ locator = "#{@parent_list.get_locator}|#{locator}"
49
+ unless @list_index.nil?
50
+ case @locator_type
51
+ when :xpath
52
+ locator = "(#{locator})[#{@list_index}]"
53
+ when :css
54
+ locator = "#{locator}:nth-of-type(#{@list_index})"
55
+ end
56
+ end
57
+ end
58
+
59
+ if @context == :section && !@parent.nil? && !@parent.get_locator.nil?
60
+ "#{@parent.get_locator}|#{locator}"
61
+ else
62
+ locator
63
+ end
64
+ end
65
+
66
+ def get_locator_type
67
+ @locator_type
68
+ end
69
+
70
+ def set_list_index(list, index = 1)
71
+ @parent_list = list unless list.nil?
72
+ @list_index = index
73
+ end
74
+
75
+ def get_item_count
76
+ raise 'No parent list defined' if @parent_list.nil?
77
+ @parent_list.get_item_count
78
+ end
79
+
80
+ def get_list_items
81
+ items = []
82
+ (1..get_item_count).each do |item|
83
+ set_list_index(nil, item)
84
+ items.push(get_value)
85
+ end
86
+ items
87
+ end
88
+
89
+ def get_all_items_count
90
+ raise 'No parent list defined' if @parent_list.nil?
91
+ @parent_list.get_all_items_count
92
+ end
93
+
94
+ def get_all_list_items
95
+ items = []
96
+ (1..get_all_items_count).each do |item|
97
+ set_list_index(nil, item)
98
+ items.push(get_value(:all))
99
+ end
100
+ items
101
+ end
102
+
103
+ def verify_list_items(expected, enqueue = false)
104
+ actual = get_list_items
105
+ enqueue ?
106
+ ExceptionQueue.enqueue_assert_equal(expected, actual, "Expected list '#{get_name}' (#{get_locator})") :
107
+ assert_equal(expected, actual, "Expected list object '#{get_name}' (#{get_locator}) to be #{expected} but found #{actual}")
108
+ end
109
+
110
+ def get_object_type
111
+ :section
112
+ end
113
+
114
+ def get_name
115
+ @name
116
+ end
117
+
118
+ def set_parent(parent)
119
+ @parent = parent
120
+ end
121
+
122
+ # Define a trait for this page section.
123
+ #
124
+ # @param trait_name [Symbol] name of trait (as a symbol)
125
+ # @param block [&block] trait value
126
+ # @example
127
+ # trait(:section_locator) { "//div[@class='Messaging_Applet']" }
128
+ # trait(:list_table_name) { '#Messages' }
129
+ #
130
+ def self.trait(trait_name, &block)
131
+ define_method(trait_name.to_s, &block)
132
+ end
133
+
134
+ # Declare and instantiate a single generic UI Element for this page section.
135
+ #
136
+ # @param element_name [Symbol] name of UI object (as a symbol)
137
+ # @param locator [String] CSS selector or XPath expression that uniquely identifies object
138
+ # @example
139
+ # element :undo_record_item, "//li[@rn='Undo Record']/a"
140
+ # element :basket_header, 'div.basket_header'
141
+ #
142
+ def self.element(element_name, locator)
143
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::UIElement.new("#{element_name}", self, "#{locator}", :section);end))
144
+ end
145
+
146
+ # Declare and instantiate a collection of generic UI Elements for this page section.
147
+ #
148
+ # @param element_hash [Hash] names of UI objects (as a symbol) and CSS selectors or XPath expressions that uniquely identifies objects
149
+ # @example
150
+ # elements profile_item: 'a#profile',
151
+ # settings_item: 'a#userPreferencesTrigger',
152
+ # log_out_item: 'a#logout'
153
+ #
154
+ def self.elements(element_hash)
155
+ element_hash.each do |element_name, locator|
156
+ element(element_name, locator)
157
+ end
158
+ end
159
+
160
+ # Declare and instantiate a single button UI Element for this page section.
161
+ #
162
+ # @param element_name [Symbol] name of button object (as a symbol)
163
+ # @param locator [String] CSS selector or XPath expression that uniquely identifies object
164
+ # @example
165
+ # button :checkout_button, 'button.checkout_button'
166
+ # button :login_button, "//input[@id='submit_button']"
167
+ #
168
+ def self.button(element_name, locator)
169
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::Button.new("#{element_name}", self, "#{locator}", :section);end))
170
+ end
171
+
172
+ # Declare and instantiate a collection of buttons for this page section.
173
+ #
174
+ # @param element_hash [Hash] names of buttons (as a symbol) and CSS selectors or XPath expressions that uniquely identifies buttons
175
+ # @example
176
+ # buttons new_account_button: 'button#new-account',
177
+ # save_button: 'button#save',
178
+ # cancel_button: 'button#cancel'
179
+ #
180
+ def self.buttons(element_hash)
181
+ element_hash.each do |element_name, locator|
182
+ button(element_name, locator)
183
+ end
184
+ end
185
+
186
+ # Declare and instantiate a single text field UI Element for this page section.
187
+ #
188
+ # @param element_name [Symbol] name of text field object (as a symbol)
189
+ # @param locator [String] CSS selector or XPath expression that uniquely identifies object
190
+ # @example
191
+ # textfield :user_id_field, "//input[@id='UserName']"
192
+ # textfield :password_field, 'input#consumer_password'
193
+ #
194
+ def self.textfield(element_name, locator)
195
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::TextField.new("#{element_name}", self, "#{locator}", :section);end))
196
+ end
197
+
198
+ # Declare and instantiate a collection of text fields for this page section.
199
+ #
200
+ # @param element_hash [Hash] names of text fields (as a symbol) and CSS selectors or XPath expressions that uniquely identifies text fields
201
+ # @example
202
+ # textfields name_field: 'input#Name',
203
+ # title_field: 'input#Title',
204
+ # phone_field: 'input#PhoneNumber',
205
+ # fax_field: 'input#FaxNumber',
206
+ # email_field: 'input#Email'
207
+ #
208
+ def self.textfields(element_hash)
209
+ element_hash.each do |element_name, locator|
210
+ textfield(element_name, locator)
211
+ end
212
+ end
213
+
214
+ # Declare and instantiate a single checkbox UI Element for this page section.
215
+ #
216
+ # @param element_name [Symbol] name of checkbox object (as a symbol)
217
+ # @param locator [String] CSS selector or XPath expression that uniquely identifies object
218
+ # @param proxy [Symbol] Optional name (as a symbol) of proxy object to receive click actions
219
+ # @example
220
+ # checkbox :remember_checkbox, "//input[@id='RememberUser']"
221
+ # checkbox :accept_terms_checkbox, 'input#accept_terms_conditions', :accept_terms_label
222
+ #
223
+ def self.checkbox(element_name, locator, proxy = nil)
224
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::CheckBox.new("#{element_name}", self, "#{locator}", :section, #{proxy});end))
225
+ end
226
+
227
+ # Declare and instantiate a collection of checkboxes for this page section.
228
+ #
229
+ # @param element_hash [Hash] names of checkboxes (as a symbol) and CSS selectors or XPath expressions that uniquely identifies checkboxes
230
+ # @example
231
+ # checkboxes hazmat_certified_check: 'input#hazmatCertified',
232
+ # epa_certified_check: 'input#epaCertified',
233
+ # dhs_certified_check: 'input#homelandSecurityCertified',
234
+ # carb_compliant_check: 'input#carbCompliant'
235
+ #
236
+ def self.checkboxes(element_hash)
237
+ element_hash.each do |element_name, locator|
238
+ checkbox(element_name, locator)
239
+ end
240
+ end
241
+
242
+ # Declare and instantiate a single radio button UI Element for this page section.
243
+ #
244
+ # @param element_name [Symbol] name of radio object (as a symbol)
245
+ # @param locator [String] CSS selector or XPath expression that uniquely identifies object
246
+ # @param proxy [Symbol] Optional name (as a symbol) of proxy object to receive click actions
247
+ # @example
248
+ # radio :accept_terms_radio, "//input[@id='Accept_Terms']"
249
+ # radio :decline_terms_radio, 'input#decline_terms_conditions', :decline_terms_label
250
+ #
251
+ def self.radio(element_name, locator, proxy = nil)
252
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::Radio.new("#{element_name}", self, "#{locator}", :section, #{proxy});end))
253
+ end
254
+
255
+ # Declare and instantiate a collection of radio buttons for this page section.
256
+ #
257
+ # @param element_hash [Hash] names of radio buttons (as a symbol) and CSS selectors or XPath expressions that uniquely identifies radio buttons
258
+ # @example
259
+ # radios visa_radio: 'input#payWithVisa',
260
+ # mastercard_radio: 'input#payWithMastercard',
261
+ # discover_radio: 'input#payWithDiscover',
262
+ # amex_radio: 'input#payWithAmEx'
263
+ #
264
+ def self.radios(element_hash)
265
+ element_hash.each do |element_name, locator|
266
+ radio(element_name, locator)
267
+ end
268
+ end
269
+
270
+ # Declare and instantiate a single label UI Element for this page section.
271
+ #
272
+ # @param element_name [Symbol] name of label object (as a symbol)
273
+ # @param locator [String] CSS selector or XPath expression that uniquely identifies object
274
+ # @example
275
+ # label :welcome_label, 'div.Welcome'
276
+ # label :rollup_price_label, "//div[contains(@id, 'Rollup Item Price')]"
277
+ #
278
+ def self.label(element_name, locator)
279
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::Label.new("#{element_name}", self, "#{locator}", :section);end))
280
+ end
281
+
282
+ def self.labels(element_hash)
283
+ element_hash.each do |element_name, locator|
284
+ label(element_name, locator)
285
+ end
286
+ end
287
+
288
+ # Declare and instantiate a single link UI Element for this page section.
289
+ #
290
+ # @param element_name [Symbol] name of link object (as a symbol)
291
+ # @param locator [String] CSS selector or XPath expression that uniquely identifies object
292
+ # @example
293
+ # link :registration_link, 'a.account-nav__link.register'
294
+ # link :shopping_basket_link, "//a[@href='shopping_basket']"
295
+ #
296
+ def self.link(element_name, locator)
297
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::Link.new("#{element_name}", self, "#{locator}", :section);end))
298
+ end
299
+
300
+ def self.links(element_hash)
301
+ element_hash.each do |element_name, locator|
302
+ link(element_name, locator)
303
+ end
304
+ end
305
+
306
+ # Declare and instantiate a single table UI Element for this page section.
307
+ #
308
+ # @param element_name [Symbol] name of table object (as a symbol)
309
+ # @param locator [String] CSS selector or XPath expression that uniquely identifies object
310
+ # @example
311
+ # table :payments_table, "//table[@class='payments_table']"
312
+ #
313
+ def self.table(element_name, locator)
314
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::Table.new("#{element_name}", self, "#{locator}", :section);end))
315
+ end
316
+
317
+ def self.tables(element_hash)
318
+ element_hash.each do |element_name, locator|
319
+ table(element_name, locator)
320
+ end
321
+ end
322
+
323
+ # Declare and instantiate a single select list UI Element for this page section.
324
+ #
325
+ # @param element_name [Symbol] name of select list object (as a symbol)
326
+ # @param locator [String] CSS selector or XPath expression that uniquely identifies object
327
+ # @example
328
+ # selectlist :category_selector, 'select#search_form_category_chosen'
329
+ # selectlist :gender_select, "//select[@id='customer_gender']"
330
+ #
331
+ def self.selectlist(element_name, locator)
332
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::SelectList.new("#{element_name}", self, "#{locator}", :section);end))
333
+ end
334
+
335
+ def self.selectlists(element_hash)
336
+ element_hash.each do |element_name, locator|
337
+ selectlist(element_name, locator)
338
+ end
339
+ end
340
+
341
+ # Declare and instantiate a single list UI Element for this page section.
342
+ #
343
+ # @param element_name [Symbol] name of list object (as a symbol)
344
+ # @param locator [String] CSS selector or XPath expression that uniquely identifies object
345
+ # @example
346
+ # list :y_axis_list, 'g.y_axis'
347
+ #
348
+ def self.list(element_name, locator)
349
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::List.new("#{element_name}", self, "#{locator}", :section);end))
350
+ end
351
+
352
+ def self.lists(element_hash)
353
+ element_hash.each do |element_name, locator|
354
+ list(element_name, locator)
355
+ end
356
+ end
357
+
358
+ # Declare and instantiate an single image UI Element for this page section.
359
+ #
360
+ # @param element_name [Symbol] name of image object (as a symbol)
361
+ # @param locator [String] CSS selector or XPath expression that uniquely identifies object
362
+ # @example
363
+ # image :basket_item_image, 'div.product_image'
364
+ # image :corporate_logo_image, "//img[@alt='MyCompany_logo']"
365
+ #
366
+ def self.image(element_name, locator)
367
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::Image.new("#{element_name}", self, "#{locator}", :section);end))
368
+ end
369
+
370
+ def self.images(element_hash)
371
+ element_hash.each do |element_name, locator|
372
+ image(element_name, locator)
373
+ end
374
+ end
375
+
376
+ # Declare and instantiate a single File Field UI Element for this page section.
377
+ #
378
+ # @param element_name [Symbol] name of file field object (as a symbol)
379
+ # @param locator [String] CSS selector or XPath expression that uniquely identifies object
380
+ # @example
381
+ # filefield :attach_file, 's_SweFileName'
382
+ #
383
+ def self.filefield(element_name, locator)
384
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::FileField.new("#{element_name}", self, "#{locator}", :section);end))
385
+ end
386
+
387
+ def self.filefields(element_hash)
388
+ element_hash.each do |element_name, locator|
389
+ filefield(element_name, locator)
390
+ end
391
+ end
392
+
393
+ # Declare and instantiate a cell button in a table column on this page section.
394
+ #
395
+ # @param element_name [Symbol] name of cell button object (as a symbol)
396
+ # @param locator [String] XPath expression that uniquely identifies cell button within row and column of parent table object
397
+ # @param table [Symbol] Name (as a symbol) of parent table object
398
+ # @param column [Integer] 1-based index of table column that contains the cell button object
399
+ # @example
400
+ # cell_button :show_button, "a[@class='show']", :data_table, 5
401
+ # cell_button :edit_button, "a[@class='edit']", :data_table, 5
402
+ #
403
+ def self.cell_button(element_name, locator, table, column)
404
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::CellButton.new("#{element_name}", self, "#{locator}", :section, #{table}, #{column});end))
405
+ end
406
+
407
+ # Declare and instantiate a cell checkbox in a table column on this page section.
408
+ #
409
+ # @param element_name [Symbol] name of cell checkbox object (as a symbol)
410
+ # @param locator [String] XPath expression that uniquely identifies cell checkbox within row and column of parent table object
411
+ # @param table [Symbol] Name (as a symbol) of parent table object
412
+ # @param column [Integer] 1-based index of table column that contains the cell checkbox object
413
+ # @example
414
+ # cell_checkbox :is_registered_check, "a[@class='registered']", :data_table, 4
415
+ #
416
+ def self.cell_checkbox(element_name, locator, table, column, proxy = nil)
417
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::CellCheckBox.new("#{element_name}", self, "#{locator}", :section, #{table}, #{column}, #{proxy});end))
418
+ end
419
+
420
+ # Declare and instantiate a cell radio in a table column on this page section.
421
+ #
422
+ # @param element_name [Symbol] name of cell radio object (as a symbol)
423
+ # @param locator [String] XPath expression that uniquely identifies cell radio within row and column of parent table object
424
+ # @param table [Symbol] Name (as a symbol) of parent table object
425
+ # @param column [Integer] 1-based index of table column that contains the cell radio object
426
+ # @example
427
+ # cell_radio :track_a_radio, "a[@class='track_a']", :data_table, 8
428
+ #
429
+ def self.cell_radio(element_name, locator, table, column, proxy = nil)
430
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::CellRadio.new("#{element_name}", self, "#{locator}", :section, #{table}, #{column}, #{proxy});end))
431
+ end
432
+
433
+ # Declare and instantiate a cell image in a table column on this page object.
434
+ #
435
+ # @param element_name [Symbol] name of cell image object (as a symbol)
436
+ # @param locator [String] XPath expression that uniquely identifies cell image within row and column of parent table object
437
+ # @param table [Symbol] Name (as a symbol) of parent table object
438
+ # @param column [Integer] 1-based index of table column that contains the cell image object
439
+ # @example
440
+ # cell_image :ready_icon, "img[@class='ready']", :data_table, 3
441
+ # cell_image :send_icon, "img[@class='send']", :data_table, 3
442
+ #
443
+ def self.cell_image(element_name, locator, table, column)
444
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::CellImage.new("#{element_name}", self, "#{locator}", :section, #{table}, #{column});end))
445
+ end
446
+
447
+ # Declare and instantiate a list button in a row of a list object on this section object.
448
+ #
449
+ # @param element_name [Symbol] name of list button object (as a symbol)
450
+ # @param locator [String] XPath expression that uniquely identifies list button within row of parent list object
451
+ # @param list [Symbol] Name (as a symbol) of parent list object
452
+ # @example
453
+ # list_button :delete_button, "a[@class='delete']", :icon_list
454
+ # list_button :edit_button, "a[@class='edit']", :icon_list
455
+ #
456
+ def self.list_button(element_name, locator, list)
457
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::ListButton.new("#{element_name}", self, "#{locator}", :section, #{list});end))
458
+ end
459
+
460
+ # Declare and instantiate a list checkbox in a row of a list object on this section object.
461
+ #
462
+ # @param element_name [Symbol] name of list checkbox object (as a symbol)
463
+ # @param locator [String] XPath expression that uniquely identifies list checkbox within row of parent list object
464
+ # @param list [Symbol] Name (as a symbol) of parent list object
465
+ # @example
466
+ # list_checkbox :is_registered_check, "a[@class='registered']", :data_list
467
+ #
468
+ def self.list_checkbox(element_name, locator, list, proxy = nil)
469
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::ListCheckBox.new("#{element_name}", self, "#{locator}", :section, #{list}, #{proxy});end))
470
+ end
471
+
472
+ # Declare and instantiate a list radio in a row of a list object on this section object.
473
+ #
474
+ # @param element_name [Symbol] name of list radio object (as a symbol)
475
+ # @param locator [String] XPath expression that uniquely identifies list radio within row of parent list object
476
+ # @param list [Symbol] Name (as a symbol) of parent list object
477
+ # @example
478
+ # list_radio :sharing_radio, "a[@class='sharing']", :data_list
479
+ #
480
+ def self.list_radio(element_name, locator, list, proxy = nil)
481
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::CellRadio.new("#{element_name}", self, "#{locator}", :section, #{list}, #{proxy});end))
482
+ end
483
+
484
+ # Instantiate a single PageSection object within this PageSection object.
485
+ #
486
+ # @param section_name [Symbol] name of PageSection object (as a symbol)
487
+ # @param class_name [String] Class name of PageSection object
488
+ # @example
489
+ # section :search_form, SearchForm
490
+ #
491
+ def self.section(section_name, class_name, locator = nil)
492
+ class_eval(%(def #{section_name};@#{section_name} ||= #{class_name}.new("#{section_name}", self, "#{locator}", :section);end))
493
+ end
494
+
495
+ def self.sections(section_hash)
496
+ section_hash.each do |section_name, class_name|
497
+ section(section_name, class_name)
498
+ end
499
+ end
500
+
501
+ # Does Section object exists?
502
+ #
503
+ # @return [Boolean]
504
+ # @example
505
+ # navigation_toolbar.exists?
506
+ #
507
+ def exists?
508
+ section, = find_section
509
+ section != nil
510
+ end
511
+
512
+ # Is Section object enabled?
513
+ #
514
+ # @return [Boolean]
515
+ # @example
516
+ # bar_chart_section.enabled?
517
+ #
518
+ def enabled?
519
+ !disabled?
520
+ end
521
+
522
+ # Is Section object disabled (not enabled)?
523
+ #
524
+ # @return [Boolean]
525
+ # @example
526
+ # bar_chart_section.disabled?
527
+ #
528
+ def disabled?
529
+ section, = find_section
530
+ raise "Section object '#{get_name}' (#{get_locator}) not found" unless section
531
+ section.disabled?
532
+ end
533
+
534
+ # Is Section object visible?
535
+ #
536
+ # @return [Boolean]
537
+ # @example
538
+ # navigation_toolbar.visible?
539
+ #
540
+ def visible?
541
+ section, = find_section
542
+ exists = section
543
+ visible = false
544
+ visible = section.visible? if exists
545
+ # the section is visible if it exists and it is not invisible
546
+ exists && visible ? true : false
547
+ end
548
+
549
+ # Is Section object hidden (not visible)?
550
+ #
551
+ # @return [Boolean]
552
+ # @example
553
+ # navigation_toolbar.hidden?
554
+ #
555
+ def hidden?
556
+ !visible?
557
+ end
558
+
559
+ # Is section object displayed in browser window?
560
+ #
561
+ # @return [Boolean]
562
+ # @example
563
+ # navigation_toolbar.displayed??
564
+ #
565
+ def displayed?
566
+ section, = find_section
567
+ raise "Section object '#{get_name}' (#{get_locator}) not found" unless section
568
+ section.displayed?
569
+ end
570
+
571
+ # Wait until the Section object exists, or until the specified wait time has expired. If the wait time is nil, then
572
+ # the wait time will be Capybara.default_max_wait_time.
573
+ #
574
+ # @param seconds [Integer or Float] wait time in seconds
575
+ # @example
576
+ # navigation_toolbar.wait_until_exists(0.5)
577
+ #
578
+ def wait_until_exists(seconds = nil)
579
+ timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
580
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
581
+ wait.until { exists? }
582
+ rescue
583
+ raise "Could not find Section object '#{get_name}' (#{get_locator}) after #{timeout} seconds" unless exists?
584
+ end
585
+
586
+ # Wait until the Section object no longer exists, or until the specified wait time has expired. If the wait time is
587
+ # nil, then the wait time will be Capybara.default_max_wait_time.
588
+ #
589
+ # @param seconds [Integer or Float] wait time in seconds
590
+ # @example
591
+ # navigation_toolbar.wait_until_gone(5)
592
+ #
593
+ def wait_until_gone(seconds = nil)
594
+ timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
595
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
596
+ wait.until { !exists? }
597
+ rescue
598
+ raise "Section object '#{get_name}' (#{get_locator}) remained visible after #{timeout} seconds" if exists?
599
+ end
600
+
601
+ # Wait until the Section object is visible, or until the specified wait time has expired. If the wait time is nil,
602
+ # then the wait time will be Capybara.default_max_wait_time.
603
+ #
604
+ # @param seconds [Integer or Float] wait time in seconds
605
+ # @example
606
+ # bar_chart_section.wait_until_visible(0.5)
607
+ #
608
+ def wait_until_visible(seconds = nil)
609
+ timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
610
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
611
+ wait.until { visible? }
612
+ rescue
613
+ raise "Could not find Section object '#{get_name}' (#{get_locator}) after #{timeout} seconds" unless visible?
614
+ end
615
+
616
+ # Wait until the Section object is hidden, or until the specified wait time has expired. If the wait time is nil,
617
+ # then the wait time will be Capybara.default_max_wait_time.
618
+ #
619
+ # @param seconds [Integer or Float] wait time in seconds
620
+ # @example
621
+ # bar_chart_section.wait_until_hidden(10)
622
+ #
623
+ def wait_until_hidden(seconds = nil)
624
+ timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
625
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
626
+ wait.until { hidden? }
627
+ rescue
628
+ raise "Section object '#{get_name}' (#{get_locator}) remained visible after #{timeout} seconds" if visible?
629
+ end
630
+
631
+ # Click at a specific location within a Section object
632
+ #
633
+ # @param x [Integer] X offset
634
+ # @param y [Integer] Y offset
635
+ # @example
636
+ # bar_chart_section.click_at(10, 10)
637
+ #
638
+ def click_at(x, y)
639
+ section, = find_section
640
+ raise "Section object '#{get_name}' (#{get_locator}) not found" unless section
641
+ section.click_at(x, y)
642
+ end
643
+
644
+ def verify_ui_states(ui_states)
645
+ ui_states.each do |ui_object, object_states|
646
+ object_states.each do |property, state|
647
+ case property
648
+ when :class
649
+ actual = ui_object.get_attribute(:class)
650
+ when :exists
651
+ actual = ui_object.exists?
652
+ when :enabled
653
+ actual = ui_object.enabled?
654
+ when :disabled
655
+ actual = ui_object.disabled?
656
+ when :visible
657
+ actual = ui_object.visible?
658
+ when :hidden
659
+ actual = ui_object.hidden?
660
+ when :displayed
661
+ actual = ui_object.displayed?
662
+ when :width
663
+ actual = ui_object.width
664
+ when :height
665
+ actual = ui_object.height
666
+ when :x
667
+ actual = ui_object.x
668
+ when :y
669
+ actual = ui_object.y
670
+ when :readonly
671
+ actual = ui_object.read_only?
672
+ when :checked
673
+ actual = ui_object.checked?
674
+ when :selected
675
+ actual = ui_object.selected?
676
+ when :value, :caption
677
+ actual = ui_object.get_value
678
+ when :maxlength
679
+ actual = ui_object.get_max_length
680
+ when :rowcount
681
+ actual = ui_object.get_row_count
682
+ when :columncount
683
+ actual = ui_object.get_column_count
684
+ when :placeholder
685
+ actual = ui_object.get_placeholder
686
+ when :min
687
+ actual = ui_object.get_min
688
+ when :max
689
+ actual = ui_object.get_max
690
+ when :step
691
+ actual = ui_object.get_step
692
+ when :options, :items, :list_items
693
+ actual = ui_object.get_list_items
694
+ when :optioncount, :itemcount
695
+ actual = ui_object.get_item_count
696
+ when :all_items, :all_list_items
697
+ actual = ui_object.get_all_list_items
698
+ when :all_items_count
699
+ actual = ui_object.get_all_items_count
700
+ when :column_headers
701
+ actual = ui_object.get_header_columns
702
+ when :siebel_options
703
+ actual = ui_object.get_siebel_options
704
+ else
705
+ if property.is_a?(Hash)
706
+ property.each do |key, value|
707
+ case key
708
+ when :cell
709
+ actual = ui_object.get_table_cell(value[0].to_i, value[1].to_i)
710
+ when :row
711
+ actual = ui_object.get_table_row(value.to_i)
712
+ when :column
713
+ actual = ui_object.get_table_column(value.to_i)
714
+ when :item
715
+ actual = ui_object.get_list_item(value.to_i)
716
+ when :attribute
717
+ actual = ui_object.get_attribute(value)
718
+ when :native_attribute
719
+ actual = ui_object.get_native_attribute(value)
720
+ end
721
+ end
722
+ else
723
+ props = property.to_s.split('_')
724
+ case props[0].to_sym
725
+ when :cell
726
+ cell = property.to_s.delete('cell_')
727
+ cell = cell.split('_')
728
+ actual = ui_object.get_table_cell(cell[0].to_i, cell[1].to_i)
729
+ when :row
730
+ row = property.to_s.delete('row_')
731
+ actual = ui_object.get_table_row(row.to_i)
732
+ when :column
733
+ column = property.to_s.delete('column_')
734
+ actual = ui_object.get_table_column(column.to_i)
735
+ when :item
736
+ item = property.to_s.delete('item_')
737
+ actual = ui_object.get_list_item(item.to_i)
738
+ end
739
+ end
740
+ end
741
+
742
+ if state.is_a?(Hash) && state.length == 1
743
+ error_msg = "Expected UI object '#{ui_object.get_name}' (#{ui_object.get_locator}) #{property} property to"
744
+ state.each do |key, value|
745
+ case key
746
+ when :lt, :less_than
747
+ ExceptionQueue.enqueue_exception("#{error_msg} be less than #{value} but found '#{actual}'") unless actual < value
748
+ when :lt_eq, :less_than_or_equal
749
+ ExceptionQueue.enqueue_exception("#{error_msg} be less than or equal to #{value} but found '#{actual}'") unless actual <= value
750
+ when :gt, :greater_than
751
+ ExceptionQueue.enqueue_exception("#{error_msg} be greater than #{value} but found '#{actual}'") unless actual > value
752
+ when :gt_eq, :greater_than_or_equal
753
+ ExceptionQueue.enqueue_exception("#{error_msg} be greater than or equal to #{value} but found '#{actual}'") unless actual >= value
754
+ when :starts_with
755
+ ExceptionQueue.enqueue_exception("#{error_msg} start with '#{value}' but found '#{actual}'") unless actual.start_with?(value)
756
+ when :ends_with
757
+ ExceptionQueue.enqueue_exception("#{error_msg} end with '#{value}' but found '#{actual}'") unless actual.end_with?(value)
758
+ when :contains
759
+ ExceptionQueue.enqueue_exception("#{error_msg} contain '#{value}' but found '#{actual}'") unless actual.include?(value)
760
+ when :not_contains, :does_not_contain
761
+ ExceptionQueue.enqueue_exception("#{error_msg} not contain '#{value}' but found '#{actual}'") if actual.include?(value)
762
+ when :not_equal
763
+ ExceptionQueue.enqueue_exception("#{error_msg} not equal '#{value}' but found '#{actual}'") if actual == value
764
+ when :like, :is_like
765
+ actual_like = actual.delete("\n")
766
+ actual_like = actual_like.delete("\r")
767
+ actual_like = actual_like.delete("\t")
768
+ actual_like = actual_like.delete(' ')
769
+ actual_like = actual_like.downcase
770
+ expected = value.delete("\n")
771
+ expected = expected.delete("\r")
772
+ expected = expected.delete("\t")
773
+ expected = expected.delete(' ')
774
+ expected = expected.downcase
775
+ ExceptionQueue.enqueue_exception("#{error_msg} be like '#{value}' but found '#{actual}'") unless actual_like.include?(expected)
776
+ when :translate
777
+ expected = I18n.t(value)
778
+ ExceptionQueue.enqueue_assert_equal(expected, actual, "Expected UI object '#{ui_object.get_name}' (#{ui_object.get_locator}) translated #{property} property")
779
+ end
780
+ end
781
+ else
782
+ ExceptionQueue.enqueue_assert_equal(state, actual, "Expected UI object '#{ui_object.get_name}' (#{ui_object.get_locator}) #{property} property")
783
+ end
784
+ end
785
+ end
786
+ ExceptionQueue.post_exceptions
787
+ end
788
+
789
+ # Populate the specified UI elements in this Section object with the associated data from a Hash passed as an
790
+ # argument. Data values must be in the form of a String for textfield and select list controls. For checkbox
791
+ # and radio buttons, data must either be a Boolean or a String that evaluates to a Boolean value (Yes, No, 1,
792
+ # 0, true, false).
793
+ #
794
+ # The optional wait_time parameter is used to specify the time (in seconds) to wait for each UI element to become
795
+ # visible before entering the associated data value. This option is useful in situations where entering data, or
796
+ # setting the state of a UI element might cause other UI elements to become visible or active. Specifying a wait_time
797
+ # value ensures that the subsequent UI elements will be ready to be interacted with as states are changed. If the wait
798
+ # time is nil, then the wait time will be 5 seconds.
799
+ #
800
+ # To delete all text content in a text field, pass !DELETE as the data to be entered.
801
+ #
802
+ # @param data [Hash] UI element(s) and associated data to be entered
803
+ # @param wait_time [Integer] wait time in seconds
804
+ # @example
805
+ # data = { prefix_select => 'Mr.',
806
+ # first_name_field => 'Ignatious',
807
+ # last_name_field => 'Snickelfritz',
808
+ # gender_select => 'Male',
809
+ # dob_field => '12/14/1957',
810
+ # organ_donor_check => 'Yes',
811
+ # dnr_on_file_check => 'Yes'
812
+ # }
813
+ # populate_data_fields(data)
814
+ #
815
+ def populate_data_fields(data, wait_time = nil)
816
+ timeout = wait_time.nil? ? 5 : wait_time
817
+ data.each do |data_field, data_param|
818
+ unless data_param.blank?
819
+ # make sure the intended UI target element is visible before trying to set its value
820
+ data_field.wait_until_visible(timeout)
821
+ if data_param == '!DELETE'
822
+ data_field.clear
823
+ else
824
+ case data_field.get_object_type
825
+ when :checkbox
826
+ data_field.set_checkbox_state(data_param.to_bool)
827
+ when :selectlist
828
+ data_field.get_siebel_object_type == 'JComboBox' ?
829
+ data_field.set("#{data_param}\t") :
830
+ data_field.choose_option(data_param)
831
+ when :radio
832
+ data_field.set_selected_state(data_param.to_bool)
833
+ when :textfield
834
+ data_field.set("#{data_param}\t")
835
+ when :section
836
+ data_field.set(data_param)
837
+ end
838
+ end
839
+ end
840
+ end
841
+ end
842
+
843
+ def get_attribute(attrib)
844
+ section, = find_section
845
+ raise "Section object '#{get_name}' (#{get_locator}) not found" unless section
846
+ section[attrib]
847
+ end
848
+
849
+ def get_native_attribute(attrib)
850
+ section, = find_section
851
+ raise "Section object '#{get_name}' (#{get_locator}) not found" unless section
852
+ section.native.attribute(attrib)
853
+ end
854
+
855
+ private
856
+
857
+ def find_section
858
+ locator = get_locator
859
+ locator = locator.gsub('|', ' ')
860
+ obj = page.find(@locator_type, locator, :wait => 0.1)
861
+ [obj, @locator_type]
862
+ rescue
863
+ [nil, nil]
864
+ end
865
+ end
866
+ end