testcentricity_web 2.1.8.2 → 2.1.8.3
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.
- checksums.yaml +4 -4
- data/.gitignore +27 -0
- data/.rubocop.yml +41 -0
- data/.yardopts +2 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +28 -0
- data/README.md +1438 -0
- data/Rakefile +1 -0
- data/lib/devices/devices.yml +280 -0
- data/lib/testcentricity_web.rb +140 -0
- data/lib/testcentricity_web/browser_helper.rb +173 -0
- data/lib/testcentricity_web/data_objects_helper.rb +78 -0
- data/lib/testcentricity_web/drag_drop_helper.rb +15 -0
- data/lib/testcentricity_web/elements/button.rb +8 -0
- data/lib/testcentricity_web/elements/cell_button.rb +8 -0
- data/lib/testcentricity_web/elements/cell_checkbox.rb +38 -0
- data/lib/testcentricity_web/elements/cell_element.rb +62 -0
- data/lib/testcentricity_web/elements/cell_image.rb +8 -0
- data/lib/testcentricity_web/elements/cell_radio.rb +31 -0
- data/lib/testcentricity_web/elements/checkbox.rb +99 -0
- data/lib/testcentricity_web/elements/file_field.rb +45 -0
- data/lib/testcentricity_web/elements/image.rb +34 -0
- data/lib/testcentricity_web/elements/label.rb +8 -0
- data/lib/testcentricity_web/elements/link.rb +8 -0
- data/lib/testcentricity_web/elements/list.rb +54 -0
- data/lib/testcentricity_web/elements/list_button.rb +8 -0
- data/lib/testcentricity_web/elements/list_checkbox.rb +38 -0
- data/lib/testcentricity_web/elements/list_element.rb +51 -0
- data/lib/testcentricity_web/elements/list_radio.rb +31 -0
- data/lib/testcentricity_web/elements/radio.rb +73 -0
- data/lib/testcentricity_web/elements/select_list.rb +189 -0
- data/lib/testcentricity_web/elements/table.rb +473 -0
- data/lib/testcentricity_web/elements/textfield.rb +84 -0
- data/lib/testcentricity_web/environment.rb +249 -0
- data/lib/testcentricity_web/excel_helper.rb +242 -0
- data/lib/testcentricity_web/exception_queue_helper.rb +47 -0
- data/lib/testcentricity_web/page_objects_helper.rb +656 -0
- data/lib/testcentricity_web/page_sections_helper.rb +811 -0
- data/lib/testcentricity_web/siebel_open_ui_helper.rb +15 -0
- data/lib/testcentricity_web/ui_elements_helper.rb +425 -0
- data/lib/testcentricity_web/utility_helpers.rb +28 -0
- data/lib/testcentricity_web/version.rb +3 -0
- data/lib/testcentricity_web/webdriver_helper.rb +451 -0
- data/lib/testcentricity_web/world_extensions.rb +26 -0
- data/testcentricity_web.gemspec +42 -0
- metadata +52 -4
@@ -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,425 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
Capybara::Node::Element.class_eval do
|
4
|
+
def click_at(x, y)
|
5
|
+
right = x - (native.size.width / 2)
|
6
|
+
top = y - (native.size.height / 2)
|
7
|
+
driver.browser.action.move_to(native).move_by(right.to_i, top.to_i).click.perform
|
8
|
+
end
|
9
|
+
|
10
|
+
def get_width
|
11
|
+
native.size.width
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_height
|
15
|
+
native.size.height
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
module TestCentricity
|
21
|
+
class UIElement
|
22
|
+
include Capybara::DSL
|
23
|
+
include Test::Unit::Assertions
|
24
|
+
|
25
|
+
attr_reader :parent, :locator, :context, :type, :name
|
26
|
+
attr_accessor :alt_locator
|
27
|
+
|
28
|
+
def initialize(name, parent, locator, context)
|
29
|
+
@name = name
|
30
|
+
@parent = parent
|
31
|
+
@locator = locator
|
32
|
+
@context = context
|
33
|
+
@type = nil
|
34
|
+
@alt_locator = nil
|
35
|
+
end
|
36
|
+
|
37
|
+
def get_object_type
|
38
|
+
if @type
|
39
|
+
@type
|
40
|
+
elsif obj.tag_name
|
41
|
+
obj.tag_name
|
42
|
+
elsif obj.native.attribute('type')
|
43
|
+
obj.native.attribute('type')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_locator
|
48
|
+
@locator
|
49
|
+
end
|
50
|
+
|
51
|
+
def get_name
|
52
|
+
@name
|
53
|
+
end
|
54
|
+
|
55
|
+
def set_alt_locator(temp_locator)
|
56
|
+
@alt_locator = temp_locator
|
57
|
+
end
|
58
|
+
|
59
|
+
def clear_alt_locator
|
60
|
+
@alt_locator = nil
|
61
|
+
end
|
62
|
+
|
63
|
+
# Click on an object
|
64
|
+
#
|
65
|
+
# @example
|
66
|
+
# basket_link.click
|
67
|
+
#
|
68
|
+
def click
|
69
|
+
obj, = find_element
|
70
|
+
object_not_found_exception(obj, nil)
|
71
|
+
begin
|
72
|
+
obj.click
|
73
|
+
rescue
|
74
|
+
obj.click_at(10, 10) unless Capybara.current_driver == :poltergeist
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Double-click on an object
|
79
|
+
#
|
80
|
+
# @example
|
81
|
+
# file_image.double_click
|
82
|
+
#
|
83
|
+
def double_click
|
84
|
+
obj, = find_element
|
85
|
+
object_not_found_exception(obj, nil)
|
86
|
+
page.driver.browser.action.double_click(obj.native).perform
|
87
|
+
end
|
88
|
+
|
89
|
+
# Right-click on an object
|
90
|
+
#
|
91
|
+
# @example
|
92
|
+
# basket_item_image.right_click
|
93
|
+
#
|
94
|
+
def right_click
|
95
|
+
obj, = find_element
|
96
|
+
object_not_found_exception(obj, nil)
|
97
|
+
page.driver.browser.action.context_click(obj.native).perform
|
98
|
+
end
|
99
|
+
|
100
|
+
# Click at a specific location within an object
|
101
|
+
#
|
102
|
+
# @param x [Integer] X offset
|
103
|
+
# @param y [Integer] Y offset
|
104
|
+
# @example
|
105
|
+
# basket_item_image.click_at(10, 10)
|
106
|
+
#
|
107
|
+
def click_at(x, y)
|
108
|
+
obj, = find_element
|
109
|
+
raise "UI #{object_ref_message} not found" unless obj
|
110
|
+
obj.click_at(x, y)
|
111
|
+
end
|
112
|
+
|
113
|
+
def set(value)
|
114
|
+
obj, = find_element
|
115
|
+
object_not_found_exception(obj, nil)
|
116
|
+
obj.set(value)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Send keystrokes to this object.
|
120
|
+
#
|
121
|
+
# @param keys [String] keys
|
122
|
+
# @example
|
123
|
+
# comment_field.send_keys(:enter)
|
124
|
+
#
|
125
|
+
def send_keys(*keys)
|
126
|
+
obj, = find_element
|
127
|
+
object_not_found_exception(obj, nil)
|
128
|
+
obj.send_keys(*keys)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Does UI object exists?
|
132
|
+
#
|
133
|
+
# @return [Boolean]
|
134
|
+
# @example
|
135
|
+
# basket_link.exists?
|
136
|
+
#
|
137
|
+
def exists?(visible = true)
|
138
|
+
obj, = find_object(visible)
|
139
|
+
obj != nil
|
140
|
+
end
|
141
|
+
|
142
|
+
# Is UI object visible?
|
143
|
+
#
|
144
|
+
# @return [Boolean]
|
145
|
+
# @example
|
146
|
+
# remember_me_checkbox.visible?
|
147
|
+
#
|
148
|
+
def visible?
|
149
|
+
obj, type = find_object
|
150
|
+
exists = obj
|
151
|
+
invisible = false
|
152
|
+
if type == :css
|
153
|
+
Capybara.using_wait_time 0.1 do
|
154
|
+
# is object itself hidden with .ui-helper-hidden class?
|
155
|
+
self_hidden = page.has_css?("#{@locator}.ui-helper-hidden")
|
156
|
+
# is parent of object hidden, thus hiding the object?
|
157
|
+
parent_hidden = page.has_css?(".ui-helper-hidden > #{@locator}")
|
158
|
+
# is grandparent of object, or any other ancestor, hidden?
|
159
|
+
other_ancestor_hidden = page.has_css?(".ui-helper-hidden * #{@locator}")
|
160
|
+
# if any of the above conditions are true, then object is invisible
|
161
|
+
invisible = self_hidden || parent_hidden || other_ancestor_hidden
|
162
|
+
end
|
163
|
+
else
|
164
|
+
invisible = !obj.visible? if exists
|
165
|
+
end
|
166
|
+
# the object is visible if it exists and it is not invisible
|
167
|
+
exists && !invisible ? true : false
|
168
|
+
end
|
169
|
+
|
170
|
+
# Is UI object hidden (not visible)?
|
171
|
+
#
|
172
|
+
# @return [Boolean]
|
173
|
+
# @example
|
174
|
+
# remember_me_checkbox.hidden?
|
175
|
+
#
|
176
|
+
def hidden?
|
177
|
+
!visible?
|
178
|
+
end
|
179
|
+
|
180
|
+
# Is UI object enabled?
|
181
|
+
#
|
182
|
+
# @return [Boolean]
|
183
|
+
# @example
|
184
|
+
# login_button.enabled?
|
185
|
+
#
|
186
|
+
def enabled?
|
187
|
+
!disabled?
|
188
|
+
end
|
189
|
+
|
190
|
+
# Is UI object disabled (not enabled)?
|
191
|
+
#
|
192
|
+
# @return [Boolean]
|
193
|
+
# @example
|
194
|
+
# login_button.disabled?
|
195
|
+
#
|
196
|
+
def disabled?
|
197
|
+
obj, = find_element
|
198
|
+
object_not_found_exception(obj, nil)
|
199
|
+
obj.disabled?
|
200
|
+
end
|
201
|
+
|
202
|
+
# Wait until the object exists, or until the specified wait time has expired.
|
203
|
+
#
|
204
|
+
# @param seconds [Integer or Float] wait time in seconds
|
205
|
+
# @example
|
206
|
+
# run_button.wait_until_exists(0.5)
|
207
|
+
#
|
208
|
+
def wait_until_exists(seconds = nil)
|
209
|
+
timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
|
210
|
+
wait = Selenium::WebDriver::Wait.new(timeout: timeout)
|
211
|
+
wait.until { exists? }
|
212
|
+
rescue
|
213
|
+
raise "Could not find UI #{object_ref_message} after #{timeout} seconds" unless exists?
|
214
|
+
end
|
215
|
+
|
216
|
+
# Wait until the object no longer exists, or until the specified wait time has expired.
|
217
|
+
#
|
218
|
+
# @param seconds [Integer or Float] wait time in seconds
|
219
|
+
# @example
|
220
|
+
# logout_button.wait_until_gone(5)
|
221
|
+
#
|
222
|
+
def wait_until_gone(seconds = nil)
|
223
|
+
timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
|
224
|
+
wait = Selenium::WebDriver::Wait.new(timeout: timeout)
|
225
|
+
wait.until { !exists? }
|
226
|
+
rescue
|
227
|
+
raise "UI #{object_ref_message} remained visible after #{timeout} seconds" if exists?
|
228
|
+
end
|
229
|
+
|
230
|
+
# Wait until the object is visible, or until the specified wait time has expired.
|
231
|
+
#
|
232
|
+
# @param seconds [Integer or Float] wait time in seconds
|
233
|
+
# @example
|
234
|
+
# run_button.wait_until_visible(0.5)
|
235
|
+
#
|
236
|
+
def wait_until_visible(seconds = nil)
|
237
|
+
timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
|
238
|
+
wait = Selenium::WebDriver::Wait.new(timeout: timeout)
|
239
|
+
wait.until { visible? }
|
240
|
+
rescue
|
241
|
+
raise "Could not find UI #{object_ref_message} after #{timeout} seconds" unless visible?
|
242
|
+
end
|
243
|
+
|
244
|
+
# Wait until the object is hidden, or until the specified wait time has expired.
|
245
|
+
#
|
246
|
+
# @param seconds [Integer or Float] wait time in seconds
|
247
|
+
# @example
|
248
|
+
# run_button.wait_until_hidden(10)
|
249
|
+
#
|
250
|
+
def wait_until_hidden(seconds = nil)
|
251
|
+
timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
|
252
|
+
wait = Selenium::WebDriver::Wait.new(timeout: timeout)
|
253
|
+
wait.until { hidden? }
|
254
|
+
rescue
|
255
|
+
raise "UI #{object_ref_message} remained visible after #{timeout} seconds" if visible?
|
256
|
+
end
|
257
|
+
|
258
|
+
# Wait until the object's value equals the specified value, or until the specified wait time has expired.
|
259
|
+
#
|
260
|
+
# @param seconds [Integer or Float] wait time in seconds
|
261
|
+
# @example
|
262
|
+
# card_authorized_label.wait_until_value_is(5, 'Card authorized')
|
263
|
+
#
|
264
|
+
def wait_until_value_is(value, seconds = nil)
|
265
|
+
timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
|
266
|
+
wait = Selenium::WebDriver::Wait.new(timeout: timeout)
|
267
|
+
wait.until { get_value == value }
|
268
|
+
rescue
|
269
|
+
raise "Value of UI #{object_ref_message} failed to equal '#{value}' after #{timeout} seconds" unless get_value == value
|
270
|
+
end
|
271
|
+
|
272
|
+
# Wait until the object's value changes to a different value, or until the specified wait time has expired.
|
273
|
+
#
|
274
|
+
# @param seconds [Integer or Float] wait time in seconds
|
275
|
+
# @example
|
276
|
+
# basket_grand_total_label.wait_until_value_changes(5)
|
277
|
+
#
|
278
|
+
def wait_until_value_changes(seconds = nil)
|
279
|
+
value = get_value
|
280
|
+
timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
|
281
|
+
wait = Selenium::WebDriver::Wait.new(timeout: timeout)
|
282
|
+
wait.until { get_value != value }
|
283
|
+
rescue
|
284
|
+
raise "Value of UI #{object_ref_message} failed to change from '#{value}' after #{timeout} seconds" if get_value == value
|
285
|
+
end
|
286
|
+
|
287
|
+
def get_value(visible = true)
|
288
|
+
obj, = find_element(visible)
|
289
|
+
object_not_found_exception(obj, nil)
|
290
|
+
case obj.tag_name.downcase
|
291
|
+
when 'input', 'select', 'textarea'
|
292
|
+
obj.value
|
293
|
+
else
|
294
|
+
obj.text
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
alias get_caption get_value
|
299
|
+
|
300
|
+
def verify_value(expected, enqueue = false)
|
301
|
+
actual = get_value
|
302
|
+
enqueue ?
|
303
|
+
ExceptionQueue.enqueue_assert_equal(expected.strip, actual.strip, "Expected UI #{object_ref_message}") :
|
304
|
+
assert_equal(expected.strip, actual.strip, "Expected UI #{object_ref_message} to display '#{expected}' but found '#{actual}'")
|
305
|
+
end
|
306
|
+
|
307
|
+
alias verify_caption verify_value
|
308
|
+
|
309
|
+
# Hover the cursor over an object
|
310
|
+
#
|
311
|
+
# @example
|
312
|
+
# basket_link.hover
|
313
|
+
#
|
314
|
+
def hover
|
315
|
+
obj, = find_element
|
316
|
+
object_not_found_exception(obj, nil)
|
317
|
+
obj.hover
|
318
|
+
end
|
319
|
+
|
320
|
+
def drag_by(right_offset, down_offset)
|
321
|
+
obj, = find_element
|
322
|
+
object_not_found_exception(obj, nil)
|
323
|
+
obj.drag_by(right_offset, down_offset)
|
324
|
+
end
|
325
|
+
|
326
|
+
def drag_and_drop(target, right_offset = nil, down_offset = nil)
|
327
|
+
source, = find_element
|
328
|
+
object_not_found_exception(source, nil)
|
329
|
+
page.driver.browser.action.click_and_hold(source.native).perform
|
330
|
+
sleep(0.5)
|
331
|
+
target_drop, = target.find_element
|
332
|
+
page.driver.browser.action.move_to(target_drop.native, right_offset.to_i, down_offset.to_i).release.perform
|
333
|
+
end
|
334
|
+
|
335
|
+
def get_attribute(attrib)
|
336
|
+
obj, = find_element(false)
|
337
|
+
object_not_found_exception(obj, nil)
|
338
|
+
obj[attrib]
|
339
|
+
end
|
340
|
+
|
341
|
+
def get_native_attribute(attrib)
|
342
|
+
obj, = find_element(false)
|
343
|
+
object_not_found_exception(obj, nil)
|
344
|
+
obj.native.attribute(attrib)
|
345
|
+
end
|
346
|
+
|
347
|
+
private
|
348
|
+
|
349
|
+
def find_element(visible = true)
|
350
|
+
wait = Selenium::WebDriver::Wait.new(timeout: Capybara.default_max_wait_time)
|
351
|
+
wait.until { find_object(visible) }
|
352
|
+
end
|
353
|
+
|
354
|
+
def find_object(visible = true)
|
355
|
+
@alt_locator.nil? ? obj_locator = @locator : obj_locator = @alt_locator
|
356
|
+
parent_section = @context == :section && !@parent.get_locator.nil?
|
357
|
+
if parent_section
|
358
|
+
attributes = [:id, :ignore_parent_xpath, :ignore_parent_css, :xpath_css, :css_xpath, :xpath, :css]
|
359
|
+
tries ||= 6
|
360
|
+
else
|
361
|
+
attributes = [:id, :xpath, :css]
|
362
|
+
tries ||= 2
|
363
|
+
end
|
364
|
+
|
365
|
+
type = attributes[tries]
|
366
|
+
if parent_section
|
367
|
+
parent_locator = @parent.get_locator
|
368
|
+
case type
|
369
|
+
when :css
|
370
|
+
parent_locator = parent_locator.gsub('|', ' ')
|
371
|
+
obj = page.find(:css, parent_locator, :wait => 0.01).find(:css, obj_locator, :wait => 0.01, :visible => visible)
|
372
|
+
when :xpath
|
373
|
+
parent_locator = parent_locator.delete('|')
|
374
|
+
obj = page.find(:xpath, "#{parent_locator}#{obj_locator}", :wait => 0.01, :visible => visible)
|
375
|
+
when :css_xpath
|
376
|
+
type = :xpath
|
377
|
+
parent_locator = parent_locator.gsub('|', ' ')
|
378
|
+
obj = page.find(:css, parent_locator, :wait => 0.01).find(:xpath, obj_locator, :wait => 0.01, :visible => visible)
|
379
|
+
when :xpath_css
|
380
|
+
type = :css
|
381
|
+
parent_locator = parent_locator.gsub('|', ' ')
|
382
|
+
obj = page.find(:xpath, parent_locator, :wait => 0.01).find(:css, obj_locator, :wait => 0.01, :visible => visible)
|
383
|
+
when :ignore_parent_css
|
384
|
+
type = :css
|
385
|
+
obj = page.find(:css, obj_locator, :wait => 0.01, :visible => visible)
|
386
|
+
when :ignore_parent_xpath
|
387
|
+
type = :xpath
|
388
|
+
obj = page.find(:xpath, obj_locator, :wait => 0.01, :visible => visible)
|
389
|
+
end
|
390
|
+
else
|
391
|
+
obj = page.find(type, obj_locator, :wait => 0.01, :visible => visible)
|
392
|
+
end
|
393
|
+
[obj, type]
|
394
|
+
rescue
|
395
|
+
retry if (tries -= 1) > 0
|
396
|
+
[nil, nil]
|
397
|
+
end
|
398
|
+
|
399
|
+
def object_not_found_exception(obj, obj_type)
|
400
|
+
@alt_locator.nil? ? locator = @locator : locator = @alt_locator
|
401
|
+
obj_type.nil? ? object_type = 'Object' : object_type = obj_type
|
402
|
+
raise "#{object_type} named '#{@name}' (#{locator}) not found" unless obj
|
403
|
+
end
|
404
|
+
|
405
|
+
def invalid_object_type_exception(obj, obj_type)
|
406
|
+
unless obj.tag_name == obj_type || obj.native.attribute('type') == obj_type
|
407
|
+
@alt_locator.nil? ? locator = @locator : locator = @alt_locator
|
408
|
+
raise "#{locator} is not a #{obj_type} element"
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
def invoke_siebel_popup
|
413
|
+
obj, = find_element
|
414
|
+
object_not_found_exception(obj, 'Siebel object')
|
415
|
+
trigger_name = obj.native.attribute('aria-describedby').strip
|
416
|
+
trigger = "span##{trigger_name}"
|
417
|
+
trigger = "#{@parent.get_locator} #{trigger}" if @context == :section && !@parent.get_locator.nil?
|
418
|
+
first(trigger).click
|
419
|
+
end
|
420
|
+
|
421
|
+
def object_ref_message
|
422
|
+
"object '#{get_name}' (#{get_locator})"
|
423
|
+
end
|
424
|
+
end
|
425
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class Object
|
2
|
+
def blank?
|
3
|
+
respond_to?(:empty?) ? empty? : !self
|
4
|
+
end
|
5
|
+
|
6
|
+
def present?
|
7
|
+
!blank?
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
class String
|
13
|
+
def to_bool
|
14
|
+
return true if self == true || self =~ (/(true|t|yes|y|x|1)$/i)
|
15
|
+
return false if self == false || self.blank? || self =~ (/(false|f|no|n|0)$/i)
|
16
|
+
raise ArgumentError.new("invalid value for Boolean: \"#{self}\"")
|
17
|
+
end
|
18
|
+
|
19
|
+
def string_between(marker1, marker2)
|
20
|
+
self[/#{Regexp.escape(marker1)}(.*?)#{Regexp.escape(marker2)}/m, 1]
|
21
|
+
end
|
22
|
+
|
23
|
+
def format_date_time(date_time_format)
|
24
|
+
return if self.blank?
|
25
|
+
new_date = DateTime.parse(self)
|
26
|
+
new_date.strftime(date_time_format)
|
27
|
+
end
|
28
|
+
end
|