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,293 @@
1
+ require 'test/unit'
2
+
3
+ module TestCentricity
4
+ class AppUIElement
5
+ include Test::Unit::Assertions
6
+
7
+ attr_reader :parent, :strategy, :locator, :context, :type, :name
8
+ attr_accessor :mru_element, :mru_name
9
+
10
+ def initialize(name, parent, strategy, locator, context)
11
+ @name = name
12
+ @parent = parent
13
+ @strategy = strategy.to_sym
14
+ @locator = locator
15
+ @context = context
16
+ @type = nil
17
+ end
18
+
19
+ def get_object_type
20
+ @type
21
+ end
22
+
23
+ def get_locator
24
+ [@strategy.to_sym, @locator]
25
+ end
26
+
27
+ def get_name
28
+ @name
29
+ end
30
+
31
+ def click
32
+ obj = element
33
+ object_not_found_exception(obj)
34
+ obj.click
35
+ end
36
+
37
+ def tap
38
+ obj = element
39
+ object_not_found_exception(obj)
40
+ x = obj.location.x
41
+ y = obj.location.y
42
+ tap_action = Appium::TouchAction.new.tap(element: obj, x: x, y: y)
43
+ tap_action.perform
44
+ end
45
+
46
+ def double_tap
47
+ obj = element
48
+ object_not_found_exception(obj)
49
+ x = obj.location.x
50
+ y = obj.location.y
51
+ tap_action = Appium::TouchAction.new.double_tap(element: obj, x: x, y: y)
52
+ tap_action.perform
53
+ end
54
+
55
+ def set(value)
56
+ obj = element
57
+ object_not_found_exception(obj)
58
+ if value.is_a?(Array)
59
+ obj.send_keys(value[0])
60
+ obj.send_keys(value[1])
61
+ elsif value.is_a?(String)
62
+ obj.send_keys(value)
63
+ end
64
+ end
65
+
66
+ def send_keys(value)
67
+ obj = element
68
+ object_not_found_exception(obj)
69
+ obj.send_keys(value)
70
+ end
71
+
72
+ def clear
73
+ obj = element
74
+ object_not_found_exception(obj)
75
+ obj.clear
76
+ end
77
+
78
+ def get_value
79
+ obj = element
80
+ object_not_found_exception(obj)
81
+ obj.value
82
+ end
83
+
84
+ def get_caption
85
+ obj = element
86
+ object_not_found_exception(obj)
87
+ if obj.tag_name == 'XCUIElementTypeNavigationBar'
88
+ obj.attribute('name')
89
+ else
90
+ obj.attribute('label')
91
+ end
92
+ end
93
+
94
+ def exists?
95
+ begin
96
+ element.displayed?
97
+ rescue
98
+ false
99
+ end
100
+ end
101
+
102
+ def visible?
103
+ if exists?
104
+ element.displayed?
105
+ else
106
+ false
107
+ end
108
+ end
109
+
110
+ def hidden?
111
+ !visible?
112
+ end
113
+
114
+ def enabled?
115
+ obj = element
116
+ object_not_found_exception(obj)
117
+ obj.enabled?
118
+ end
119
+
120
+ def disabled?
121
+ !enabled?
122
+ end
123
+
124
+ def selected?
125
+ obj = element
126
+ object_not_found_exception(obj)
127
+ obj.selected?
128
+ end
129
+
130
+ def tag_name
131
+ obj = element
132
+ object_not_found_exception(obj)
133
+ obj.tag_name
134
+ end
135
+
136
+ def get_attribute(attrib)
137
+ obj = element
138
+ object_not_found_exception(obj)
139
+ obj.attribute(attrib)
140
+ end
141
+
142
+ # Wait until the object exists, or until the specified wait time has expired. If the wait time is nil, then the wait
143
+ # time will be Environ.default_max_wait_time.
144
+ #
145
+ # @param seconds [Integer or Float] wait time in seconds
146
+ # @example
147
+ # run_button.wait_until_exists(0.5)
148
+ #
149
+ def wait_until_exists(seconds = nil)
150
+ timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
151
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
152
+ wait.until { exists? }
153
+ rescue
154
+ raise "Could not find UI #{object_ref_message} after #{timeout} seconds" unless exists?
155
+ end
156
+
157
+ # Wait until the object no longer exists, or until the specified wait time has expired. If the wait time is nil, then
158
+ # the wait time will be Environ.default_max_wait_time.
159
+ #
160
+ # @param seconds [Integer or Float] wait time in seconds
161
+ # @example
162
+ # logout_button.wait_until_gone(5)
163
+ #
164
+ def wait_until_gone(seconds = nil)
165
+ timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
166
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
167
+ wait.until { !exists? }
168
+ rescue
169
+ raise "UI #{object_ref_message} remained visible after #{timeout} seconds" if exists?
170
+ end
171
+
172
+ # Wait until the object is visible, or until the specified wait time has expired. If the wait time is nil, then the
173
+ # wait time will be Environ.default_max_wait_time.
174
+ #
175
+ # @param seconds [Integer or Float] wait time in seconds
176
+ # @example
177
+ # run_button.wait_until_visible(0.5)
178
+ #
179
+ def wait_until_visible(seconds = nil)
180
+ timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
181
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
182
+ wait.until { visible? }
183
+ rescue
184
+ raise "Could not find UI #{object_ref_message} after #{timeout} seconds" unless visible?
185
+ end
186
+
187
+ # Wait until the object is hidden, or until the specified wait time has expired. If the wait time is nil, then the
188
+ # wait time will be Environ.default_max_wait_time.
189
+ #
190
+ # @param seconds [Integer or Float] wait time in seconds
191
+ # @example
192
+ # run_button.wait_until_hidden(10)
193
+ #
194
+ def wait_until_hidden(seconds = nil)
195
+ timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
196
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
197
+ wait.until { hidden? }
198
+ rescue
199
+ raise "UI #{object_ref_message} remained visible after #{timeout} seconds" if visible?
200
+ end
201
+
202
+ # Wait until the object's value equals the specified value, or until the specified wait time has expired. If the wait
203
+ # time is nil, then the wait time will be Environ.default_max_wait_time.
204
+ #
205
+ # @param seconds [Integer or Float] wait time in seconds
206
+ # @example
207
+ # card_authorized_label.wait_until_value_is(5, 'Card authorized')
208
+ #
209
+ def wait_until_value_is(value, seconds = nil)
210
+ timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
211
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
212
+ wait.until { get_value == value }
213
+ rescue
214
+ raise "Value of UI #{object_ref_message} failed to equal '#{value}' after #{timeout} seconds" unless get_value == value
215
+ end
216
+
217
+ # Wait until the object's value changes to a different value, or until the specified wait time has expired. If the
218
+ # wait time is nil, then the wait time will be Environ.default_max_wait_time.
219
+ #
220
+ # @param seconds [Integer or Float] wait time in seconds
221
+ # @example
222
+ # basket_grand_total_label.wait_until_value_changes(5)
223
+ #
224
+ def wait_until_value_changes(seconds = nil)
225
+ value = get_value
226
+ timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
227
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
228
+ wait.until { get_value != value }
229
+ rescue
230
+ raise "Value of UI #{object_ref_message} failed to change from '#{value}' after #{timeout} seconds" if get_value == value
231
+ end
232
+
233
+
234
+ def scroll_into_view
235
+ scroll(:down) unless visible?
236
+ end
237
+
238
+ def scroll(direction)
239
+ execute_script('mobile: scroll', direction: direction.to_s)
240
+ end
241
+
242
+ def swipe(direction)
243
+ execute_script('mobile: swipe', direction: direction.to_s)
244
+ end
245
+
246
+
247
+ private
248
+
249
+ def element
250
+ parent_section = @context == :section
251
+ parent_section ? tries ||= 2 : tries ||= 1
252
+
253
+ if parent_section && tries > 1
254
+ parent_obj = nil
255
+ locators = @parent.get_locator
256
+ locators.each do |parent_locator|
257
+ if parent_obj.nil?
258
+ parent_obj = find_element(parent_locator[0], parent_locator[1])
259
+ else
260
+ parent_obj = parent_obj.find_element(parent_locator[0], parent_locator[1])
261
+ end
262
+ end
263
+
264
+ puts "Found parent object '#{@parent.get_name}' - #{@parent.get_locator}" if ENV['DEBUG']
265
+
266
+
267
+ obj = parent_obj.find_element(@strategy, @locator)
268
+
269
+ puts "Found object '#{@name}' - [:#{@strategy}, #{@locator}]" if ENV['DEBUG']
270
+
271
+ obj
272
+ else
273
+ obj = find_element(@strategy, @locator)
274
+
275
+ puts "Found object '#{@name}' - [:#{@strategy}, #{@locator}]" if ENV['DEBUG']
276
+
277
+ obj
278
+ end
279
+ rescue
280
+ retry if (tries -= 1) > 0
281
+ nil
282
+ end
283
+
284
+ def object_not_found_exception(obj)
285
+ @type.nil? ? object_type = 'Object' : object_type = @type
286
+ raise "#{object_type} named '#{@name}' (#{get_locator}) not found" unless obj
287
+ end
288
+
289
+ def object_ref_message
290
+ "object '#{@name}' (#{get_locator})"
291
+ end
292
+ end
293
+ end
@@ -0,0 +1,8 @@
1
+ module TestCentricity
2
+ class AppButton < AppUIElement
3
+ def initialize(name, parent, strategy, locator, context)
4
+ super
5
+ @type = :button
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,20 @@
1
+ module TestCentricity
2
+ class AppCheckBox < AppUIElement
3
+ def initialize(name, parent, strategy, locator, context)
4
+ super
5
+ @type = :checkbox
6
+ end
7
+
8
+ def checked?
9
+ element.attribute('checked') == 'true'
10
+ end
11
+
12
+ def check
13
+ element.click unless checked?
14
+ end
15
+
16
+ def uncheck
17
+ element.click if checked?
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,8 @@
1
+ module TestCentricity
2
+ class AppLabel < AppUIElement
3
+ def initialize(name, parent, strategy, locator, context)
4
+ super
5
+ @type = :label
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,25 @@
1
+ module TestCentricity
2
+ class AppList < AppUIElement
3
+ def initialize(name, parent, strategy, locator, context)
4
+ super
5
+ @type = :list
6
+ end
7
+
8
+ def get_item_count
9
+ if Environ.device_os == :ios
10
+ items = find_elements(class: 'XCUIElementTypeCell')
11
+ else
12
+ items = find_elements(class: 'android.widget.FrameLayout')
13
+ end
14
+ items.size
15
+ end
16
+
17
+ def get_list_items
18
+
19
+ end
20
+
21
+ def get_list_item(index)
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ module TestCentricity
2
+ class AppSwitch < AppUIElement
3
+ def initialize(name, parent, strategy, locator, context)
4
+ super
5
+ @type = :switch
6
+ end
7
+
8
+ def on?
9
+ element.get_value == 1
10
+ end
11
+
12
+ def on
13
+ element.click unless on?
14
+ end
15
+
16
+ def off
17
+ element.click if on?
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,12 @@
1
+ module TestCentricity
2
+ class AppTextField < AppUIElement
3
+ def initialize(name, parent, strategy, locator, context)
4
+ super
5
+ @type = :textfield
6
+ end
7
+
8
+ def get_placeholder
9
+ element.text
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,174 @@
1
+ require 'yaml'
2
+
3
+
4
+ module TestCentricity
5
+ module Browsers
6
+ include Capybara::DSL
7
+
8
+ # Sets the size of the browser window.
9
+ #
10
+ # @param resolution [Array] the desired [width, height]
11
+ # @example
12
+ # Browsers.set_browser_window_size([1024, 768])
13
+ #
14
+ def self.set_browser_window_size(resolution)
15
+ resolution = resolution.split(',') if resolution.is_a?(String)
16
+ window = Capybara.current_session.driver.browser.manage.window
17
+ window.resize_to(resolution[0], resolution[1])
18
+ Environ.browser_size = [resolution[0].to_i, resolution[1].to_i]
19
+ end
20
+
21
+ # Maximizes the selenium browser window.
22
+ #
23
+ # @example
24
+ # Browsers.maximize_browser
25
+ #
26
+ def self.maximize_browser
27
+ window = Capybara.current_session.driver.browser.manage.window
28
+ window.maximize
29
+ end
30
+ # Sets the position of the browser window.
31
+ #
32
+ # @param x [Integer] the desired x coordinate
33
+ # @param y [Integer] the desired y coordinate
34
+ # @example
35
+ # Browsers.set_browser_window_position([100, 300])
36
+ #
37
+ def self.set_browser_window_position(x, y)
38
+ window = Capybara.current_session.driver.browser.manage.window
39
+ window.move_to(x, y)
40
+ end
41
+
42
+ # Refreshes the selenium browser.
43
+ #
44
+ # @example
45
+ # Browsers.refresh_browser
46
+ #
47
+ def self.refresh_browser
48
+ Capybara.page.driver.browser.navigate.refresh
49
+ end
50
+
51
+ # Emulates clicking the web browser's Back button. Navigates back by one page on the browser’s history.
52
+ #
53
+ # @example
54
+ # Browsers.navigate_back
55
+ #
56
+ def self.navigate_back
57
+ Capybara.page.driver.browser.navigate.back
58
+ end
59
+
60
+ # Emulates clicking the web browser's Forward button. Navigates forward by one page on the browser’s history.
61
+ #
62
+ # @example
63
+ # Browsers.navigate_forward
64
+ #
65
+ def self.navigate_forward
66
+ Capybara.page.driver.browser.navigate.forward
67
+ end
68
+
69
+ def self.switch_to_new_browser_instance
70
+ Capybara.page.driver.browser.switch_to.window(Capybara.page.driver.browser.window_handles.last)
71
+ end
72
+
73
+ def self.close_all_browser_instances
74
+ Capybara.page.driver.browser.window_handles.each do |handle|
75
+ page.driver.browser.switch_to.window(handle)
76
+ page.driver.browser.close
77
+ end
78
+ end
79
+
80
+ def self.num_browser_instances
81
+ Capybara.page.driver.browser.window_handles.count
82
+ end
83
+
84
+ def self.close_current_browser_instance
85
+ Capybara.page.driver.browser.close
86
+ Capybara.page.driver.browser.switch_to.window(Capybara.page.driver.browser.window_handles.last)
87
+ end
88
+
89
+ def self.close_old_browser_instance
90
+ Capybara.page.driver.browser.switch_to.window(Capybara.page.driver.browser.window_handles.first)
91
+ Capybara.page.driver.browser.close
92
+ Capybara.page.driver.browser.switch_to.window(Capybara.page.driver.browser.window_handles.last)
93
+ end
94
+
95
+ def self.close_named_browser_instance(name)
96
+ Capybara.page.driver.browser.switch_to.window(Capybara.page.driver.find_window(name))
97
+ Capybara.page.driver.browser.close
98
+ Capybara.page.driver.browser.switch_to.window(Capybara.page.driver.browser.window_handles.last)
99
+ end
100
+
101
+ def self.suppress_js_alerts
102
+ Capybara.page.execute_script('window.alert = function() {}')
103
+ end
104
+
105
+ def self.suppress_js_leave_page_modal
106
+ Capybara.page.execute_script('window.onbeforeunload = null')
107
+ end
108
+
109
+ def self.delete_all_cookies
110
+ if Capybara.current_driver == :selenium
111
+ browser = Capybara.current_session.driver.browser
112
+ if browser.respond_to?(:manage) && browser.manage.respond_to?(:delete_all_cookies)
113
+ browser.manage.delete_all_cookies
114
+ else
115
+ raise 'Could not clear cookies.'
116
+ end
117
+ end
118
+ end
119
+
120
+ def self.set_device_orientation(orientation)
121
+ if Environ.is_mobile? && !Environ.is_device?
122
+ Browsers.set_browser_window_size(Browsers.browser_size(Environ.browser.to_s, orientation))
123
+ else
124
+ puts '***** Cannot change device orientation of desktop web browsers or remote devices *****'
125
+ end
126
+ end
127
+
128
+ def self.mobile_device_agent(device)
129
+ device_name = device.gsub(/\s+/, '').downcase.to_sym
130
+ device = get_devices[device_name]
131
+ agent_string = device[:user_agent]
132
+ raise "Device '#{device}' is not defined" unless agent_string
133
+ agent_string
134
+ end
135
+
136
+ def self.mobile_device_name(device)
137
+ device_name = device.gsub(/\s+/, '').downcase.to_sym
138
+ device = get_devices[device_name]
139
+ name = device[:name]
140
+ raise "Device '#{device}' is not defined" unless name
141
+ Environ.device_os = device[:os]
142
+ Environ.device_type = device[:type]
143
+ name
144
+ end
145
+
146
+ def self.browser_size(browser, orientation)
147
+ device_name = browser.gsub(/\s+/, '').downcase.to_sym
148
+ device = get_devices[device_name]
149
+ if device
150
+ width = device[:css_width]
151
+ height = device[:css_height]
152
+ default_orientation = device[:default_orientation].to_sym
153
+ if orientation
154
+ Environ.device_orientation = orientation
155
+ orientation.downcase.to_sym == default_orientation ?
156
+ size = [width, height] :
157
+ size = [height, width]
158
+ else
159
+ Environ.device_orientation = device[:default_orientation]
160
+ size = [width, height]
161
+ end
162
+ else
163
+ size = [1650, 1000]
164
+ end
165
+ size
166
+ end
167
+
168
+ private
169
+
170
+ def self.get_devices
171
+ YAML.load_file File.expand_path('../../devices/devices.yml', __FILE__)
172
+ end
173
+ end
174
+ end