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,8 @@
1
+ module TestCentricity
2
+ class ListButton < ListElement
3
+ def initialize(name, parent, locator, context, list, proxy = nil)
4
+ super
5
+ @type = :list_button
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,38 @@
1
+ module TestCentricity
2
+ class ListCheckBox < ListElement
3
+ attr_accessor :proxy
4
+
5
+ def initialize(name, parent, locator, context, list, proxy = nil)
6
+ super
7
+ @type = :list_checkbox
8
+ @proxy = proxy
9
+ end
10
+
11
+ def checked?(row)
12
+ obj, = find_list_element(row)
13
+ list_object_not_found_exception(obj, 'List CheckBox', row)
14
+ obj.checked?
15
+ end
16
+
17
+ def set_checkbox_state(row, state)
18
+ obj, = find_list_element(row)
19
+ list_object_not_found_exception(obj, 'List CheckBox', row)
20
+ obj.set(state)
21
+ end
22
+
23
+ def check(row)
24
+ set_checkbox_state(row, true)
25
+ end
26
+
27
+ def uncheck(row)
28
+ set_checkbox_state(row, false)
29
+ end
30
+
31
+ def verify_check_state(row, state, enqueue = false)
32
+ actual = checked?(row)
33
+ enqueue ?
34
+ ExceptionQueue.enqueue_assert_equal(state, actual, "Expected Row #{row} List Checkbox #{object_ref_message}") :
35
+ assert_equal(state, actual, "Expected Row #{row} List Checkbox #{object_ref_message} to be #{state} but found #{actual} instead")
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,61 @@
1
+ module TestCentricity
2
+ class ListElement < UIElement
3
+ attr_accessor :list
4
+ attr_accessor :element_locator
5
+
6
+ def initialize(name, parent, locator, context, list, proxy = nil)
7
+ @name = name
8
+ @parent = parent
9
+ @context = context
10
+ @alt_locator = nil
11
+ @list = list
12
+ @element_locator = locator
13
+
14
+ set_locator_type(@list.get_locator)
15
+
16
+ if locator.nil?
17
+ @locator = list.get_list_row_locator('ROW_SPEC')
18
+ else
19
+ case @locator_type
20
+ when :xpath
21
+ @locator = "#{list.get_list_row_locator('ROW_SPEC')}/#{@element_locator}"
22
+ when :css
23
+ @locator = "#{list.get_list_row_locator('ROW_SPEC')} > #{@element_locator}"
24
+ end
25
+ end
26
+ end
27
+
28
+ def exists?(row)
29
+ obj, = find_list_element(row)
30
+ obj != nil
31
+ end
32
+
33
+ def click(row)
34
+ obj, = find_list_element(row)
35
+ list_object_not_found_exception(obj, @type, row)
36
+ obj.click
37
+ end
38
+
39
+ def get_value(row, visible = true)
40
+ obj, = find_list_element(row, visible)
41
+ list_object_not_found_exception(obj, @type, row)
42
+ case obj.tag_name.downcase
43
+ when 'input', 'select', 'textarea'
44
+ obj.value
45
+ else
46
+ obj.text
47
+ end
48
+ end
49
+
50
+ alias get_caption get_value
51
+
52
+ def find_list_element(row, visible = true)
53
+ set_alt_locator("#{@locator.gsub('ROW_SPEC', row.to_s)}")
54
+ find_element(visible)
55
+ end
56
+
57
+ def list_object_not_found_exception(obj, obj_type, row)
58
+ object_not_found_exception(obj, "Row #{row} #{obj_type}")
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,31 @@
1
+ module TestCentricity
2
+ class ListRadio < ListElement
3
+ attr_accessor :proxy
4
+
5
+ def initialize(name, parent, locator, context, list, proxy = nil)
6
+ super
7
+ @type = :list_radio
8
+ @proxy = proxy
9
+ end
10
+
11
+ def selected?(row)
12
+ obj, = find_list_element(row)
13
+ list_object_not_found_exception(obj, 'List Radio', row)
14
+ obj.checked?
15
+ end
16
+
17
+ def set_selected_state(row, state)
18
+ obj, = find_list_element(row)
19
+ list_object_not_found_exception(obj, 'List Radio', row)
20
+ obj.set(state)
21
+ end
22
+
23
+ def select(row)
24
+ set_selected_state(row, true)
25
+ end
26
+
27
+ def unselect(row)
28
+ set_selected_state(row, false)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,74 @@
1
+ module TestCentricity
2
+ class Radio < UIElement
3
+ attr_accessor :proxy
4
+
5
+ def initialize(name, parent, locator, context, proxy = nil)
6
+ @name = name
7
+ @parent = parent
8
+ @locator = locator
9
+ @context = context
10
+ @alt_locator = nil
11
+ @proxy = proxy
12
+ @type = :radio
13
+ set_locator_type
14
+ end
15
+
16
+ # Does radio button object exists?
17
+ #
18
+ # @return [Boolean]
19
+ # @example
20
+ # accept_terms_radio.exists?
21
+ #
22
+ def exists?
23
+ obj, = find_object(:all)
24
+ obj != nil
25
+ end
26
+
27
+ # Is radio button selected?
28
+ #
29
+ # @return [Boolean]
30
+ # @example
31
+ # accept_terms_radio.selected?
32
+ #
33
+ def selected?
34
+ obj, = find_element(:all)
35
+ object_not_found_exception(obj, 'Radio')
36
+ obj.checked?
37
+ end
38
+
39
+ # Set the select state of a radio button object.
40
+ #
41
+ # @param state [Boolean] true = selected / false = unselected
42
+ # @example
43
+ # accept_terms_radio.set_selected_state(true)
44
+ #
45
+ def set_selected_state(state)
46
+ obj, = find_element(:all)
47
+ object_not_found_exception(obj, 'Radio')
48
+ invalid_object_type_exception(obj, 'radio')
49
+ if @proxy.nil?
50
+ obj.set(state)
51
+ else
52
+ @proxy.click unless state == obj.checked?
53
+ end
54
+ end
55
+
56
+ # Set the selected state of a radio button object.
57
+ #
58
+ # @example
59
+ # accept_terms_radio.select
60
+ #
61
+ def select
62
+ set_selected_state(true)
63
+ end
64
+
65
+ # Unselect a radio button object.
66
+ #
67
+ # @example
68
+ # accept_terms_radio.unselect
69
+ #
70
+ def unselect
71
+ set_selected_state(false)
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,197 @@
1
+ module TestCentricity
2
+ class SelectList < UIElement
3
+ attr_accessor :list_item
4
+ attr_accessor :selected_item
5
+
6
+ def initialize(name, parent, locator, context)
7
+ super
8
+ @type = :selectlist
9
+ list_spec = {
10
+ :list_item => 'option',
11
+ :selected_item => 'option[selected]'
12
+ }
13
+ define_list_elements(list_spec)
14
+ end
15
+
16
+ def define_list_elements(element_spec)
17
+ element_spec.each do |element, value|
18
+ case element
19
+ when :list_item
20
+ @list_item = value
21
+ when :selected_item
22
+ @selected_item = value
23
+ else
24
+ raise "#{element} is not a recognized selectlist element"
25
+ end
26
+ end
27
+ end
28
+
29
+ # Select the specified option in a select box object. Accepts a String or Hash.
30
+ # Supports standard HTML select objects and Chosen select objects.
31
+ #
32
+ # @param option [String] text of option to select
33
+ # OR
34
+ # @param option [Hash] :value, :index, or :text of option to select
35
+ #
36
+ # @example
37
+ # province_select.choose_option('Alberta')
38
+ # province_select.choose_option(:value => 'AB')
39
+ # state_select.choose_option(:index => 24)
40
+ # state_select.choose_option(:text => 'Maryland')
41
+ #
42
+ def choose_option(option)
43
+ obj, = find_element
44
+ object_not_found_exception(obj, nil)
45
+ obj.click
46
+ if first(:css, "li[class*='active-result']")
47
+ if option.is_a?(Array)
48
+ option.each do |item|
49
+ page.find(:css, "li[class*='active-result']", text: item.strip).click
50
+ end
51
+ else
52
+ if option.is_a?(Hash)
53
+ page.find(:css, "li[class*='active-result']:nth-of-type(#{option[:index]})").click if option.has_key?(:index)
54
+ else
55
+ options = obj.all("li[class*='active-result']").collect(&:text)
56
+ sleep(2) unless options.include?(option)
57
+ first(:css, "li[class*='active-result']", text: option).click
58
+ end
59
+ end
60
+ else
61
+ if option.is_a?(Array)
62
+ option.each do |item|
63
+ select_item(obj, item)
64
+ end
65
+ else
66
+ select_item(obj, option)
67
+ end
68
+ end
69
+ end
70
+
71
+ # Return array of strings of all options in a select box object.
72
+ # Supports standard HTML select objects and Chosen select objects.
73
+ #
74
+ # @return [Array]
75
+ # @example
76
+ # all_colors = color_select.get_options
77
+ #
78
+ def get_options
79
+ obj, = find_element
80
+ object_not_found_exception(obj, nil)
81
+ if first(:css, "li[class*='active-result']")
82
+ obj.all("li[class*='active-result']").collect(&:text)
83
+ else
84
+ obj.all(@list_item).collect(&:text)
85
+ end
86
+ end
87
+
88
+ alias get_list_items get_options
89
+
90
+ # Return the number of options in a select box object.
91
+ # Supports standard HTML select objects and Chosen select objects.
92
+ #
93
+ # @return [Integer]
94
+ # @example
95
+ # num_colors = color_select.get_option_count
96
+ #
97
+ def get_option_count
98
+ obj, = find_element
99
+ object_not_found_exception(obj, nil)
100
+ if first(:css, "li[class*='active-result']")
101
+ obj.all("li[class*='active-result']").count
102
+ else
103
+ obj.all(@list_item).count
104
+ end
105
+ end
106
+
107
+ alias get_item_count get_option_count
108
+
109
+ def verify_options(expected, enqueue = false)
110
+ actual = get_options
111
+ enqueue ?
112
+ ExceptionQueue.enqueue_assert_equal(expected, actual, "Expected list of options in list #{object_ref_message}") :
113
+ assert_equal(expected, actual, "Expected list of options in list #{object_ref_message} to be #{expected} but found #{actual}")
114
+ end
115
+
116
+ # Return text of first selected option in a select box object.
117
+ # Supports standard HTML select objects and Chosen select objects.
118
+ #
119
+ # @return [String]
120
+ # @example
121
+ # current_color = color_select.get_selected_option
122
+ #
123
+ def get_selected_option
124
+ obj, = find_element
125
+ object_not_found_exception(obj, nil)
126
+ if first(:css, "li[class*='active-result']")
127
+ obj.first(:css, "li[class*='result-selected']").text
128
+ else
129
+ obj.first(@selected_item).text
130
+ end
131
+ end
132
+
133
+ alias selected? get_selected_option
134
+
135
+ # Select the specified option in a Siebel OUI select box object.
136
+ #
137
+ # @param option [String] text of option to select
138
+ # @example
139
+ # country_select.choose_siebel_option('Cayman Islands')
140
+ #
141
+ def choose_siebel_option(option)
142
+ Capybara.wait_on_first_by_default = true
143
+ invoke_siebel_popup
144
+ first(:xpath, "//li[@class='ui-menu-item']", :exact => true, :match => :prefer_exact, text: option).click
145
+ end
146
+
147
+ # Return array of strings of all options in a Siebel OUI select box object.
148
+ #
149
+ # @return [Array]
150
+ # @example
151
+ # all_countries = country_select.get_siebel_options
152
+ #
153
+ def get_siebel_options
154
+ invoke_siebel_popup
155
+ sleep(0.5)
156
+ options = page.all(:xpath, "//li[@class='ui-menu-item']").collect(&:text)
157
+ obj, = find_element
158
+ obj.native.send_keys(:escape)
159
+ options
160
+ end
161
+
162
+ def verify_siebel_options(expected, enqueue = false)
163
+ invoke_siebel_popup
164
+ sleep(0.5)
165
+ actual = page.all(:xpath, "//li[@class='ui-menu-item']").collect(&:text)
166
+ enqueue ?
167
+ ExceptionQueue.enqueue_assert_equal(expected, actual, "Expected list of options in list #{object_ref_message}") :
168
+ assert_equal(expected, actual, "Expected list of options in list #{object_ref_message} to be #{expected} but found #{actual}")
169
+ obj, = find_element
170
+ obj.native.send_keys(:escape)
171
+ end
172
+
173
+ # Is Siebel JComboBox set to read-only?
174
+ #
175
+ # @return [Boolean]
176
+ # @example
177
+ # country_select.read_only?
178
+ #
179
+ def read_only?
180
+ obj, = find_element
181
+ object_not_found_exception(obj, nil)
182
+ !obj.native.attribute('readonly')
183
+ end
184
+
185
+ private
186
+
187
+ def select_item(obj, option)
188
+ if option.is_a?(Hash)
189
+ obj.find("option[value='#{option[:value]}']").click if option.has_key?(:value)
190
+ obj.find(:xpath, "option[#{option[:index]}]").select_option if option.has_key?(:index)
191
+ obj.select option[:text] if option.has_key?(:text)
192
+ else
193
+ obj.select option
194
+ end
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,15 @@
1
+ module TestCentricity
2
+ class UIElement
3
+ def invoke_siebel_dialog(popup, seconds = nil)
4
+ invoke_siebel_popup
5
+ timeout = seconds.nil? ? 15 : seconds
6
+ popup.wait_until_exists(timeout)
7
+ end
8
+
9
+ def get_siebel_object_type
10
+ obj, = find_element
11
+ object_not_found_exception(obj, 'Siebel object')
12
+ obj.native.attribute('ot')
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,612 @@
1
+ module TestCentricity
2
+ class Table < UIElement
3
+ attr_accessor :table_body
4
+ attr_accessor :table_section
5
+ attr_accessor :table_row
6
+ attr_accessor :table_column
7
+ attr_accessor :table_header
8
+ attr_accessor :header_row
9
+ attr_accessor :header_column
10
+ attr_accessor :tree_expand
11
+ attr_accessor :tree_collapse
12
+
13
+ def initialize(name, parent, locator, context)
14
+ super
15
+ @type = :table
16
+
17
+ table_spec = { :table_body => 'tbody',
18
+ :table_section => nil,
19
+ :table_row => 'tr',
20
+ :table_column => 'td',
21
+ :table_header => 'thead',
22
+ :header_row => 'tr',
23
+ :header_column => 'th' }
24
+
25
+ case @locator_type
26
+ when :xpath
27
+ table_spec[:tree_expand] = "div/div[contains(@class, 'tree-plus treeclick')]"
28
+ table_spec[:tree_collapse] = "div/div[contains(@class, 'tree-minus treeclick')]"
29
+ when :css
30
+ table_spec[:tree_expand] = "div/div[class*='tree-plus treeclick']"
31
+ table_spec[:tree_collapse] = "div/div[class*='tree-minus treeclick']"
32
+ end
33
+ define_table_elements(table_spec)
34
+ end
35
+
36
+ def define_table_elements(element_spec)
37
+ element_spec.each do |element, value|
38
+ case element
39
+ when :table_body
40
+ @table_body = value
41
+ when :table_section
42
+ @table_section = value
43
+ when :table_row
44
+ @table_row = value
45
+ when :table_column
46
+ @table_column = value
47
+ when :table_header
48
+ @table_header = value
49
+ when :header_row
50
+ @header_row = value
51
+ when :header_column
52
+ @header_column = value
53
+ when :tree_expand
54
+ @tree_expand = value
55
+ when :tree_collapse
56
+ @tree_collapse = value
57
+ else
58
+ raise "#{element} is not a recognized table element"
59
+ end
60
+ end
61
+ end
62
+
63
+ # Return number of rows in a table object.
64
+ #
65
+ # @return [Integer]
66
+ # @example
67
+ # num_rows = list_table.get_row_count
68
+ #
69
+ def get_row_count
70
+ wait_until_exists(5)
71
+ case @locator_type
72
+ when :xpath
73
+ if @table_section.nil?
74
+ page.all(:xpath, "#{@locator}/#{@table_body}/#{@table_row}", :visible => :all).count
75
+ else
76
+ page.all(:xpath, "#{@locator}/#{@table_body}/#{@table_section}", :visible => :all).count
77
+ end
78
+ when :css
79
+ if @table_section.nil?
80
+ page.all(:css, "#{@locator} > #{@table_body} > #{@table_row}", :visible => :all).count
81
+ else
82
+ page.all(:css, "#{@locator} > #{@table_body} > #{@table_section}", :visible => :all).count
83
+ end
84
+ end
85
+ end
86
+
87
+ # Return number of columns in a table object.
88
+ #
89
+ # @return [Integer]
90
+ # @example
91
+ # num_columns = list_table.get_column_count
92
+ #
93
+ def get_column_count
94
+ row_count = get_row_count
95
+ case @locator_type
96
+ when :xpath
97
+ if row_count == 0
98
+ page.all(:xpath, "#{@locator}/#{@table_header}/#{@header_row}/#{@header_column}", :visible => :all).count
99
+ else
100
+ if @table_section.nil?
101
+ row_count == 1 ?
102
+ page.all(:xpath, "#{@locator}/#{@table_body}/#{@table_row}/#{@table_column}", :visible => :all).count :
103
+ page.all(:xpath, "#{@locator}/#{@table_body}/#{@table_row}[2]/#{@table_column}", :visible => :all).count
104
+ else
105
+ row_count == 1 ?
106
+ page.all(:xpath, "#{@locator}/#{@table_body}/#{@table_section}/#{@table_row}/#{@table_column}", :visible => :all).count :
107
+ page.all(:xpath, "#{@locator}/#{@table_body}/#{@table_section}[2]/#{@table_row}/#{@table_column}", :visible => :all).count
108
+ end
109
+ end
110
+ when :css
111
+ if row_count == 0
112
+ page.all(:css, "#{@locator} > #{@table_header} > #{@header_row} > #{@header_column}", :visible => :all).count
113
+ else
114
+ if @table_section.nil?
115
+ row_count == 1 ?
116
+ page.all(:css, "#{@locator} > #{@table_body} > #{@table_row} > #{@table_column}", :visible => :all).count :
117
+ page.all(:css, "#{@locator} > #{@table_body} > #{@table_row}:nth-of-type(2) > #{@table_column}", :visible => :all).count
118
+ else
119
+ row_count == 1 ?
120
+ page.all(:css, "#{@locator} > #{@table_body} > #{@table_section} > #{@table_row} > #{@table_column}", :visible => :all).count :
121
+ page.all(:css, "#{@locator} > #{@table_body} > #{@table_section}:nth-of-type(2) > #{@table_row} > #{@table_column}", :visible => :all).count
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ # Hover over the specified cell in a table object.
128
+ #
129
+ # @param row [Integer] row number
130
+ # @param column [Integer] column number
131
+ # @example
132
+ # list_table.hover_table_cell(2, 6)
133
+ #
134
+ def hover_table_cell(row, column)
135
+ row_count = get_row_count
136
+ raise "Row #{row} exceeds number of rows (#{row_count}) in table #{object_ref_message}" if row > row_count
137
+ column_count = get_column_count
138
+ raise "Column #{column} exceeds number of columns (#{column_count}) in table #{object_ref_message}" if column > column_count
139
+ set_table_cell_locator(row, column)
140
+ hover
141
+ clear_alt_locator
142
+ end
143
+
144
+ # Click in the specified cell in a table object.
145
+ #
146
+ # @param row [Integer] row number
147
+ # @param column [Integer] column number
148
+ # @example
149
+ # list_table.click_table_cell(3, 5)
150
+ #
151
+ def click_table_cell(row, column)
152
+ row_count = get_row_count
153
+ raise "Row #{row} exceeds number of rows (#{row_count}) in table #{object_ref_message}" if row > row_count
154
+ column_count = get_column_count
155
+ raise "Column #{column} exceeds number of columns (#{column_count}) in table #{object_ref_message}" if column > column_count
156
+ set_table_cell_locator(row, column)
157
+ click
158
+ clear_alt_locator
159
+ end
160
+
161
+ # Double-click in the specified cell in a table object.
162
+ #
163
+ # @param row [Integer] row number
164
+ # @param column [Integer] column number
165
+ # @example
166
+ # list_table.double_click_table_cell(3, 5)
167
+ #
168
+ def double_click_table_cell(row, column)
169
+ row_count = get_row_count
170
+ raise "Row #{row} exceeds number of rows (#{row_count}) in table #{object_ref_message}" if row > row_count
171
+ column_count = get_column_count
172
+ raise "Column #{column} exceeds number of columns (#{column_count}) in table #{object_ref_message}" if column > column_count
173
+ set_table_cell_locator(row, column)
174
+ double_click
175
+ clear_alt_locator
176
+ end
177
+
178
+ # Click the link object embedded within the specified cell in a table object.
179
+ #
180
+ # @param row [Integer] row number
181
+ # @param column [Integer] column number
182
+ # @example
183
+ # list_table.click_table_cell_link(3, 1)
184
+ #
185
+ def click_table_cell_link(row, column)
186
+ row_count = get_row_count
187
+ raise "Row #{row} exceeds number of rows (#{row_count}) in table #{object_ref_message}" if row > row_count
188
+ column_count = get_column_count
189
+ raise "Column #{column} exceeds number of columns (#{column_count}) in table #{object_ref_message}" if column > column_count
190
+ set_table_cell_locator(row, column)
191
+ saved_locator = @alt_locator
192
+ case @locator_type
193
+ when :xpath
194
+ set_alt_locator("#{@alt_locator}//a")
195
+ set_alt_locator("#{saved_locator}//span/a") unless exists?
196
+ # if link not present, check for text entry fields and try to dismiss by tabbing out
197
+ unless exists?
198
+ set_alt_locator("#{saved_locator}//input")
199
+ set_alt_locator("#{saved_locator}//textarea") unless exists?
200
+ send_keys(:tab) if exists?
201
+ set_alt_locator("#{saved_locator}//a")
202
+ set_alt_locator("#{saved_locator}//span/a") unless exists?
203
+ send_keys(:tab) unless exists?
204
+ end
205
+ when :css
206
+ set_alt_locator("#{@alt_locator} a")
207
+ set_alt_locator("#{saved_locator} span > a") unless exists?
208
+ # if link not present, check for text entry fields and try to dismiss by tabbing out
209
+ unless exists?
210
+ set_alt_locator("#{saved_locator} input")
211
+ set_alt_locator("#{saved_locator} textarea") unless exists?
212
+ send_keys(:tab) if exists?
213
+ set_alt_locator("#{saved_locator} a")
214
+ set_alt_locator("#{saved_locator} span > a") unless exists?
215
+ send_keys(:tab) unless exists?
216
+ end
217
+ end
218
+ wait_until_exists(1)
219
+ click
220
+ clear_alt_locator
221
+ end
222
+
223
+ def get_table_row(row)
224
+ columns = []
225
+ row_count = get_row_count
226
+ raise "Row #{row} exceeds number of rows (#{row_count}) in table #{object_ref_message}" if row > row_count
227
+ column_count = get_column_count
228
+ (1..column_count).each do |column|
229
+ value = ''
230
+ set_table_cell_locator(row, column)
231
+ saved_locator = @alt_locator
232
+ case @locator_type
233
+ when :xpath
234
+ set_alt_locator("#{saved_locator}//input")
235
+ unless exists?
236
+ set_alt_locator("#{saved_locator}//textarea")
237
+ set_alt_locator(saved_locator) unless exists?
238
+ end
239
+ when :css
240
+ set_alt_locator("#{saved_locator} input")
241
+ unless exists?
242
+ set_alt_locator("#{saved_locator} textarea")
243
+ set_alt_locator(saved_locator) unless exists?
244
+ end
245
+ end
246
+ value = get_value if exists?
247
+ columns.push(value)
248
+ end
249
+ clear_alt_locator
250
+ columns
251
+ end
252
+
253
+ def get_row_data(row)
254
+ row_count = get_row_count
255
+ raise "Row #{row} exceeds number of rows (#{row_count}) in table #{object_ref_message}" if row > row_count
256
+ case @locator_type
257
+ when :xpath
258
+ row > 1 ?
259
+ set_alt_locator("#{@locator}/#{@table_body}/#{@table_row}[#{row}]") :
260
+ set_alt_locator("#{@locator}/#{@table_body}/#{@table_row}")
261
+ when :css
262
+ row > 1 ?
263
+ set_alt_locator("#{@locator} > #{@table_body} > #{@table_row}:nth-of-type(#{row})") :
264
+ set_alt_locator("#{@locator} > #{@table_body} > #{@table_row}")
265
+ end
266
+ value = get_value if exists?
267
+ clear_alt_locator
268
+ value
269
+ end
270
+
271
+ def get_table_column(column)
272
+ rows = []
273
+ column_count = get_column_count
274
+ raise "Column #{column} exceeds number of columns (#{column_count}) in table #{object_ref_message}" if column > column_count
275
+ row_count = get_row_count
276
+ (1..row_count).each do |row|
277
+ value = ''
278
+ set_table_cell_locator(row, column)
279
+ saved_locator = @alt_locator
280
+ case @locator_type
281
+ when :xpath
282
+ set_alt_locator("#{saved_locator}//input")
283
+ unless exists?
284
+ set_alt_locator("#{saved_locator}//textarea")
285
+ set_alt_locator(saved_locator) unless exists?
286
+ end
287
+ when :css
288
+ set_alt_locator("#{saved_locator} input")
289
+ unless exists?
290
+ set_alt_locator("#{saved_locator} textarea")
291
+ set_alt_locator(saved_locator) unless exists?
292
+ end
293
+ end
294
+ value = get_value if exists?
295
+ rows.push(value)
296
+ end
297
+ clear_alt_locator
298
+ rows
299
+ end
300
+
301
+ # Return text contained in specified cell of a table object.
302
+ #
303
+ # @param row [Integer] row number
304
+ # @param column [Integer] column number
305
+ # @return [String] value of table cell
306
+ # @example
307
+ # list_table.get_table_cell(4, 5)
308
+ #
309
+ def get_table_cell(row, column)
310
+ row_count = get_row_count
311
+ raise "Row #{row} exceeds number of rows (#{row_count}) in table #{object_ref_message}" if row > row_count
312
+ column_count = get_column_count
313
+ raise "Column #{column} exceeds number of columns (#{column_count}) in table #{object_ref_message}" if column > column_count
314
+ set_table_cell_locator(row, column)
315
+ saved_locator = @alt_locator
316
+ case @locator_type
317
+ when :xpath
318
+ set_alt_locator("#{saved_locator}//input")
319
+ unless exists?
320
+ set_alt_locator("#{saved_locator}//textarea")
321
+ set_alt_locator(saved_locator) unless exists?
322
+ end
323
+ when :css
324
+ set_alt_locator("#{saved_locator} input")
325
+ unless exists?
326
+ set_alt_locator("#{saved_locator} textarea")
327
+ set_alt_locator(saved_locator) unless exists?
328
+ end
329
+ end
330
+ if exists?
331
+ value = get_value
332
+ else
333
+ puts "Could not find table cell at #{@alt_locator}"
334
+ value = ''
335
+ end
336
+ clear_alt_locator
337
+ value
338
+ end
339
+
340
+ def verify_table_cell(row, column, expected, enqueue = false)
341
+ actual = get_table_cell(row, column)
342
+ enqueue ?
343
+ ExceptionQueue.enqueue_assert_equal(expected.strip, actual.strip, "Expected table #{object_ref_message} row #{row}/column #{column}") :
344
+ assert_equal(expected.strip, actual.strip, "Expected table #{object_ref_message} row #{row}/column #{column} to display '#{expected}' but found '#{actual}'")
345
+ end
346
+
347
+ # Set the value of the specified cell in a table object.
348
+ #
349
+ # @param row [Integer] row number
350
+ # @param column [Integer] column number
351
+ # @param value [String] text to set
352
+ # @example
353
+ # list_table.set_table_cell(3, 1, 'Ontario')
354
+ #
355
+ def set_table_cell(row, column, value)
356
+ row_count = get_row_count
357
+ raise "Row #{row} exceeds number of rows (#{row_count}) in table #{object_ref_message}" if row > row_count
358
+ find_table_cell(row, column)
359
+ find_table_cell(row, column) unless exists?
360
+ set(value)
361
+ clear_alt_locator
362
+ end
363
+
364
+ def get_cell_attribute(row, column, attrib)
365
+ row_count = get_row_count
366
+ raise "Row #{row} exceeds number of rows (#{row_count}) in table #{object_ref_message}" if row > row_count
367
+ column_count = get_column_count
368
+ raise "Column #{column} exceeds number of columns (#{column_count}) in table #{object_ref_message}" if column > column_count
369
+ set_table_cell_locator(row, column)
370
+ result = get_native_attribute(attrib)
371
+ clear_alt_locator
372
+ result
373
+ end
374
+
375
+ def get_row_attribute(row, attrib)
376
+ row_count = get_row_count
377
+ raise "Row #{row} exceeds number of rows (#{row_count}) in table #{object_ref_message}" if row > row_count
378
+ case @locator_type
379
+ when :xpath
380
+ row > 1 ?
381
+ set_alt_locator("#{@locator}/#{@table_body}/#{@table_row}[#{row}]") :
382
+ set_alt_locator("#{@locator}/#{@table_body}/#{@table_row}")
383
+ when :css
384
+ row > 1 ?
385
+ set_alt_locator("#{@locator} > #{@table_body} > #{@table_row}:nth-of-type(#{row})") :
386
+ set_alt_locator("#{@locator} > #{@table_body} > #{@table_row}")
387
+ end
388
+ result = get_native_attribute(attrib)
389
+ clear_alt_locator
390
+ result
391
+ end
392
+
393
+ def find_row_attribute(attrib, search_value)
394
+ (1..get_row_count).each do |row|
395
+ return row if get_row_attribute(row, attrib) == search_value
396
+ end
397
+ nil
398
+ end
399
+
400
+ # Search for the specified text value in the specified row of the table object.
401
+ # Returns the number of the first column that contains the search value.
402
+ #
403
+ # @param row [Integer] row nummber
404
+ # @param search_value [String] value to be searched for
405
+ # @return [Integer] column number of table cell that contains search value
406
+ # @example
407
+ # bom_table.find_in_table_row(4, 'High-speed Framus bolts')
408
+ #
409
+ def find_in_table_row(row, search_value)
410
+ (1..get_column_count).each do |column|
411
+ return column if get_table_cell(row, column) == search_value
412
+ end
413
+ nil
414
+ end
415
+
416
+ # Search for the specified text value in the specified column of the table object.
417
+ # Returns the number of the first row that contains the search value.
418
+ #
419
+ # @param column [Integer] column nummber
420
+ # @param search_value [String] value to be searched for
421
+ # @return [Integer] row number of table cell that contains search value
422
+ # @example
423
+ # playlist_table.find_in_table_column(1, 'Ashes to Ashes')
424
+ #
425
+ def find_in_table_column(column, search_value)
426
+ (1..get_row_count).each do |row|
427
+ return row if get_table_cell(row, column) == search_value
428
+ end
429
+ nil
430
+ end
431
+
432
+ # Populate the specified row of this table object with the associated data from a Hash passed as an
433
+ # argument. Data values must be in the form of a String for textfield and select list controls. For checkbox
434
+ # and radio buttons, data must either be a Boolean or a String that evaluates to a Boolean value (Yes, No, 1,
435
+ # 0, true, false)
436
+ #
437
+ # @param data [Hash] column numbers and associated data to be entered
438
+ # @example
439
+ # data = { 1 => 'Dr.',
440
+ # 2 => 'Evangeline',
441
+ # 3 => 'Devereaux',
442
+ # 4 => 'MD',
443
+ # 5 => 'Family Practice'
444
+ # }
445
+ # clinicians_table.populate_table_row(3, data)
446
+ #
447
+ def populate_table_row(row, data)
448
+ wait_until_exists(2)
449
+ data.each do |column, data_param|
450
+ unless data_param.blank?
451
+ if data_param == '!DELETE'
452
+ set_table_cell(row, column, '')
453
+ else
454
+ set_table_cell(row, column, data_param)
455
+ end
456
+ end
457
+ end
458
+ end
459
+
460
+ # Click in the specified column header in a table object.
461
+ #
462
+ # @param column [Integer] column number
463
+ # @example
464
+ # list_table.click_header_column(3)
465
+ #
466
+ def click_header_column(column)
467
+ column_count = get_column_count
468
+ raise "Column #{column} exceeds number of columns (#{column_count}) in table header #{object_ref_message}" if column > column_count
469
+ case @locator_type
470
+ when :xpath
471
+ set_alt_locator("#{@locator}//#{@table_header}/#{@header_row}/#{@header_column}[#{column}]")
472
+ when :css
473
+ set_alt_locator("#{@locator} #{@table_header} > #{@header_row} > #{@header_column}:nth-of-type(#{column})")
474
+ end
475
+ click if exists?
476
+ clear_alt_locator
477
+ end
478
+
479
+ def get_header_column(column)
480
+ column_count = get_column_count
481
+ raise "Column #{column} exceeds number of columns (#{column_count}) in table header #{object_ref_message}" if column > column_count
482
+ case @locator_type
483
+ when :xpath
484
+ set_alt_locator("#{@locator}//#{@table_header}/#{@header_row}/#{@header_column}[#{column}]")
485
+ when :css
486
+ set_alt_locator("#{@locator} #{@table_header} > #{@header_row} > #{@header_column}:nth-of-type(#{column})")
487
+ end
488
+ value = get_value(:all) if exists?(:all)
489
+ clear_alt_locator
490
+ value
491
+ end
492
+
493
+ def get_header_columns
494
+ columns = []
495
+ column_count = get_column_count
496
+ (1..column_count).each do |column|
497
+ case @locator_type
498
+ when :xpath
499
+ set_alt_locator("#{@locator}//#{@table_header}/#{@header_row}/#{@header_column}[#{column}]")
500
+ when :css
501
+ set_alt_locator("#{@locator} #{@table_header} > #{@header_row} > #{@header_column}:nth-of-type(#{column})")
502
+ end
503
+ columns.push(get_value(:all)) if exists?(:all)
504
+ end
505
+ clear_alt_locator
506
+ columns
507
+ end
508
+
509
+ def is_table_row_expanded?(row, column)
510
+ row_count = get_row_count
511
+ raise "Row #{row} exceeds number of rows (#{row_count}) in table #{object_ref_message}" if row > row_count
512
+ column_count = get_column_count
513
+ raise "Column #{column} exceeds number of columns (#{column_count}) in table #{object_ref_message}" if column > column_count
514
+ set_table_cell_locator(row, column)
515
+ case @locator_type
516
+ when :xpath
517
+ set_alt_locator("#{@alt_locator}/#{@tree_expand}")
518
+ when :css
519
+ set_alt_locator("#{@alt_locator} > #{@tree_expand}")
520
+ end
521
+ expanded = true
522
+ expanded = false if exists?
523
+ clear_alt_locator
524
+ expanded
525
+ end
526
+
527
+ def expand_table_row(row, column)
528
+ unless is_table_row_expanded?(row, column)
529
+ set_table_cell_locator(row, column)
530
+ case @locator_type
531
+ when :xpath
532
+ set_alt_locator("#{@alt_locator}/#{@tree_expand}")
533
+ when :css
534
+ set_alt_locator("#{@alt_locator} > #{@tree_expand}")
535
+ end
536
+ click if exists?
537
+ clear_alt_locator
538
+ end
539
+ end
540
+
541
+ def collapse_table_row(row, column)
542
+ if is_table_row_expanded?(row, column)
543
+ set_table_cell_locator(row, column)
544
+ case @locator_type
545
+ when :xpath
546
+ set_alt_locator("#{@alt_locator}/#{@tree_collapse}")
547
+ when :css
548
+ set_alt_locator("#{@alt_locator} > #{@tree_collapse}")
549
+ end
550
+ click if exists?
551
+ clear_alt_locator
552
+ end
553
+ end
554
+
555
+ def expand_all_table_rows(column)
556
+ row_count = get_row_count
557
+ column_count = get_column_count
558
+ raise "Column #{column} exceeds number of columns (#{column_count}) in table #{object_ref_message}" if column > column_count
559
+ row_count.downto(1) do |row|
560
+ expand_table_row(row, column)
561
+ end
562
+ end
563
+
564
+ def get_table_cell_locator(row, column)
565
+ case @locator_type
566
+ when :xpath
567
+ if @table_section.nil?
568
+ row_spec = "#{@locator}/#{@table_body}/#{@table_row}"
569
+ row_spec = "#{row_spec}[#{row}]"
570
+ else
571
+ row_spec = "#{@locator}/#{@table_body}/#{@table_section}"
572
+ row_spec = "#{row_spec}[#{row}]/#{@table_row}[1]"
573
+ end
574
+ column_spec = "/#{@table_column}[#{column}]"
575
+ when :css
576
+ if @table_section.nil?
577
+ row_spec = "#{@locator} > #{@table_body} > #{@table_row}"
578
+ row_spec = "#{row_spec}:nth-of-type(#{row})"
579
+ else
580
+ row_spec = "#{@locator} > #{@table_body} > #{@table_section}"
581
+ row_spec = "#{row_spec}:nth-of-type(#{row}) > #{@table_row}:nth-of-type(1)"
582
+ end
583
+ column_spec = " > #{@table_column}:nth-of-type(#{column})"
584
+ end
585
+ "#{row_spec}#{column_spec}"
586
+ end
587
+
588
+ private
589
+
590
+ def set_table_cell_locator(row, column)
591
+ set_alt_locator(get_table_cell_locator(row, column))
592
+ end
593
+
594
+ def find_table_cell(row, column)
595
+ set_table_cell_locator(row, column)
596
+ if exists?
597
+ click
598
+ else
599
+ puts "Could not find table cell at #{@alt_locator}"
600
+ end
601
+ saved_locator = @alt_locator
602
+ case @locator_type
603
+ when :xpath
604
+ set_alt_locator("#{saved_locator}//input")
605
+ set_alt_locator("#{saved_locator}//textarea") unless exists?
606
+ when :css
607
+ set_alt_locator("#{saved_locator} input")
608
+ set_alt_locator("#{saved_locator} textarea") unless exists?
609
+ end
610
+ end
611
+ end
612
+ end