testcentricity 2.3.13

Sign up to get free protection for your applications and to get access to all the features.
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