testcentricity_apps 4.0.15 → 4.1.0
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/CHANGELOG.md +15 -14
- data/LICENSE.md +1 -1
- data/README.md +374 -248
- data/lib/testcentricity_apps/app_core/appium_connect_helper.rb +58 -70
- data/lib/testcentricity_apps/app_core/screen_object.rb +58 -12
- data/lib/testcentricity_apps/app_core/screen_objects_helper.rb +29 -15
- data/lib/testcentricity_apps/app_core/screen_section.rb +63 -20
- data/lib/testcentricity_apps/app_elements/alert.rb +8 -8
- data/lib/testcentricity_apps/app_elements/app_element.rb +39 -9
- data/lib/testcentricity_apps/app_elements/list.rb +4 -4
- data/lib/testcentricity_apps/app_elements/menu.rb +2 -2
- data/lib/testcentricity_apps/app_elements/menubar.rb +0 -22
- data/lib/testcentricity_apps/app_elements/selectlist.rb +5 -5
- data/lib/testcentricity_apps/app_elements/switch.rb +1 -1
- data/lib/testcentricity_apps/app_elements/table.rb +397 -0
- data/lib/testcentricity_apps/data_objects/data_objects_helper.rb +3 -7
- data/lib/testcentricity_apps/data_objects/environment.rb +2 -54
- data/lib/testcentricity_apps/exception_queue_helper.rb +9 -10
- data/lib/testcentricity_apps/utility_helpers.rb +1 -0
- data/lib/testcentricity_apps/version.rb +1 -1
- data/lib/testcentricity_apps.rb +1 -0
- metadata +23 -22
|
@@ -141,6 +141,7 @@ module TestCentricity
|
|
|
141
141
|
end
|
|
142
142
|
end
|
|
143
143
|
end
|
|
144
|
+
|
|
144
145
|
caption
|
|
145
146
|
end
|
|
146
147
|
|
|
@@ -176,12 +177,14 @@ module TestCentricity
|
|
|
176
177
|
def visible?
|
|
177
178
|
obj = element
|
|
178
179
|
return false if obj.nil?
|
|
180
|
+
|
|
179
181
|
begin
|
|
180
182
|
obj.displayed?
|
|
181
183
|
rescue
|
|
182
184
|
reset_mru_cache
|
|
183
185
|
obj = element
|
|
184
186
|
return false if obj.nil?
|
|
187
|
+
|
|
185
188
|
obj.displayed?
|
|
186
189
|
end
|
|
187
190
|
end
|
|
@@ -480,13 +483,17 @@ module TestCentricity
|
|
|
480
483
|
def double_tap
|
|
481
484
|
obj = element
|
|
482
485
|
object_not_found_exception(obj)
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
486
|
+
if Environ.is_macos?
|
|
487
|
+
Environ.appium_driver.execute_script('macos: doubleClick', { elementId: cell_obj.id })
|
|
488
|
+
else
|
|
489
|
+
driver.action
|
|
490
|
+
.click_and_hold(obj)
|
|
491
|
+
.release
|
|
492
|
+
.pause(duration: 0.2)
|
|
493
|
+
.click_and_hold(obj)
|
|
494
|
+
.release
|
|
495
|
+
.perform
|
|
496
|
+
end
|
|
490
497
|
end
|
|
491
498
|
|
|
492
499
|
# Long press on a UI element
|
|
@@ -514,7 +521,27 @@ module TestCentricity
|
|
|
514
521
|
.perform
|
|
515
522
|
end
|
|
516
523
|
|
|
524
|
+
# Right click on a UI element. MacOS apps only.
|
|
525
|
+
#
|
|
526
|
+
# @example
|
|
527
|
+
# chart_image.right_click
|
|
528
|
+
#
|
|
529
|
+
def right_click
|
|
530
|
+
raise "Right click is not supported for #{Environ.device_os} platforms" unless Environ.is_macos?
|
|
531
|
+
|
|
532
|
+
obj = element
|
|
533
|
+
object_not_found_exception(obj)
|
|
534
|
+
Environ.appium_driver.execute_script('macos: rightClick', { elementId: obj.id })
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
# Hover over a UI element. MacOS apps only.
|
|
538
|
+
#
|
|
539
|
+
# @example
|
|
540
|
+
# chart_image.hover
|
|
541
|
+
#
|
|
517
542
|
def hover
|
|
543
|
+
raise "Hover is not supported for #{Environ.device_os} platforms" unless Environ.is_macos?
|
|
544
|
+
|
|
518
545
|
obj = element
|
|
519
546
|
object_not_found_exception(obj)
|
|
520
547
|
Environ.appium_driver.execute_script('macos: hover', { elementId: obj.id })
|
|
@@ -570,6 +597,7 @@ module TestCentricity
|
|
|
570
597
|
#
|
|
571
598
|
def scroll_into_view(scroll_mode = :vertical)
|
|
572
599
|
return if visible?
|
|
600
|
+
|
|
573
601
|
case scroll_mode
|
|
574
602
|
when :vertical
|
|
575
603
|
start_direction = :down
|
|
@@ -614,11 +642,12 @@ module TestCentricity
|
|
|
614
642
|
#
|
|
615
643
|
def swipe_gesture(direction, distance = 0.5)
|
|
616
644
|
raise 'Scroll distance must be less than 1' if distance > 1
|
|
645
|
+
|
|
617
646
|
obj = element
|
|
618
647
|
object_not_found_exception(obj)
|
|
619
648
|
start_pt = [(obj.location.x + (obj.size.width * 0.5)).to_i, (obj.location.y + (obj.size.height * 0.5)).to_i]
|
|
620
649
|
|
|
621
|
-
if distance
|
|
650
|
+
if distance.negative?
|
|
622
651
|
top = (start_pt[1] - obj.size.height).to_i
|
|
623
652
|
bottom = (start_pt[1] + obj.size.height).to_i
|
|
624
653
|
left = (start_pt[0] - obj.size.width).to_i
|
|
@@ -677,6 +706,7 @@ module TestCentricity
|
|
|
677
706
|
parent_obj.find_element(@locator.keys[0], @locator.values[0])
|
|
678
707
|
else
|
|
679
708
|
return @mru_object if @mru_locator == @locator && !@mru_object.nil?
|
|
709
|
+
|
|
680
710
|
find_element(@locator.keys[0], @locator.values[0])
|
|
681
711
|
end
|
|
682
712
|
puts "Found object '#{@name}' - #{@locator}" if ENV['DEBUG']
|
|
@@ -693,7 +723,7 @@ module TestCentricity
|
|
|
693
723
|
private
|
|
694
724
|
|
|
695
725
|
def object_not_found_exception(obj)
|
|
696
|
-
@type.nil? ?
|
|
726
|
+
object_type = @type.nil? ? 'Object' : @type
|
|
697
727
|
raise ObjectNotFoundError.new("#{object_type} named '#{@name}' (#{get_locator}) not found") unless obj
|
|
698
728
|
end
|
|
699
729
|
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
module TestCentricity
|
|
2
2
|
module AppElements
|
|
3
3
|
class AppList < AppUIElement
|
|
4
|
-
attr_accessor :list_item
|
|
5
|
-
attr_accessor :scrolling
|
|
6
|
-
attr_accessor :item_objects
|
|
4
|
+
attr_accessor :list_item, :scrolling, :item_objects
|
|
7
5
|
|
|
8
6
|
def initialize(name, parent, locator, context)
|
|
9
7
|
super
|
|
@@ -57,9 +55,10 @@ module TestCentricity
|
|
|
57
55
|
if Environ.is_ios? && obj.attribute(:type) == 'XCUIElementTypePickerWheel'
|
|
58
56
|
raise 'This method is not supported for XCUIElementTypePickerWheel controls'
|
|
59
57
|
end
|
|
58
|
+
|
|
60
59
|
list_loc = get_list_item_locator
|
|
61
60
|
items = obj.find_elements(list_loc.keys[0], list_loc.values[0])
|
|
62
|
-
if items.size
|
|
61
|
+
if items.size.positive? && Environ.is_android?
|
|
63
62
|
start_count = items.count
|
|
64
63
|
direction = @scrolling == :horizontal ? :right : :down
|
|
65
64
|
scroll_count = 0
|
|
@@ -94,6 +93,7 @@ module TestCentricity
|
|
|
94
93
|
if Environ.is_ios? && obj.attribute(:type) == 'XCUIElementTypePickerWheel'
|
|
95
94
|
raise 'This method is not supported for XCUIElementTypePickerWheel controls'
|
|
96
95
|
end
|
|
96
|
+
|
|
97
97
|
list_loc = get_list_item_locator
|
|
98
98
|
items = obj.find_elements(list_loc.keys[0], list_loc.values[0])
|
|
99
99
|
items.each do |item|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
module TestCentricity
|
|
2
2
|
module AppElements
|
|
3
3
|
class AppMenu < AppUIElement
|
|
4
|
-
attr_accessor :menu_item
|
|
5
|
-
attr_accessor :key_map
|
|
4
|
+
attr_accessor :menu_item, :key_map
|
|
6
5
|
|
|
7
6
|
def initialize(name, parent, locator, context)
|
|
8
7
|
super
|
|
@@ -142,6 +141,7 @@ module TestCentricity
|
|
|
142
141
|
when :keys, :keyboard
|
|
143
142
|
keys = @key_map[item]
|
|
144
143
|
raise "No key map found for item #{item}" if keys.empty?
|
|
144
|
+
|
|
145
145
|
Environ.appium_driver.execute_script('macos: keys', { keys: keys })
|
|
146
146
|
else
|
|
147
147
|
raise "#{method} is not a valid selector"
|
|
@@ -18,28 +18,6 @@ module TestCentricity
|
|
|
18
18
|
:menubar
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
# Declare and instantiate a single menu UI Element for this MenuBar object.
|
|
22
|
-
#
|
|
23
|
-
# @param element_name [Symbol] name of menu object (as a symbol)
|
|
24
|
-
# @param locator [Hash] { locator_strategy: locator_identifier }
|
|
25
|
-
# @example
|
|
26
|
-
# menu :convert_menu, { xpath: '//XCUIElementTypeMenuBarItem[6]' }
|
|
27
|
-
#
|
|
28
|
-
def self.menu(element_name, locator)
|
|
29
|
-
define_section_element(element_name, TestCentricity::AppElements::AppMenu, locator)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# Declare and instantiate a collection of menus for this MenuBar object.
|
|
33
|
-
#
|
|
34
|
-
# @param element_hash [Hash] names of menus (as symbol) and locator Hash
|
|
35
|
-
# @example
|
|
36
|
-
# menus convert_menu: { xpath: '//XCUIElementTypeMenuBarItem[6]' },
|
|
37
|
-
# view_menu: { xpath: '//XCUIElementTypeMenuBarItem[5]' }
|
|
38
|
-
#
|
|
39
|
-
def self.menus(element_hash)
|
|
40
|
-
element_hash.each_pair { |element_name, locator| menu(element_name, locator) }
|
|
41
|
-
end
|
|
42
|
-
|
|
43
21
|
# Return the number of menus in a MenuBar object.
|
|
44
22
|
#
|
|
45
23
|
# @return [Integer]
|
|
@@ -42,9 +42,9 @@ module TestCentricity
|
|
|
42
42
|
raise 'This method is not supported for XCUIElementTypePickerWheel controls'
|
|
43
43
|
end
|
|
44
44
|
list_loc = get_list_item_locator
|
|
45
|
-
|
|
45
|
+
click if Environ.is_macos?
|
|
46
46
|
items = obj.find_elements(list_loc.keys[0], list_loc.values[0])
|
|
47
|
-
|
|
47
|
+
click if Environ.is_macos?
|
|
48
48
|
items.count
|
|
49
49
|
end
|
|
50
50
|
|
|
@@ -62,12 +62,12 @@ module TestCentricity
|
|
|
62
62
|
raise 'This method is not supported for XCUIElementTypePickerWheel controls'
|
|
63
63
|
end
|
|
64
64
|
list_loc = get_list_item_locator
|
|
65
|
-
|
|
65
|
+
click if Environ.is_macos?
|
|
66
66
|
items = obj.find_elements(list_loc.keys[0], list_loc.values[0])
|
|
67
67
|
items.each do |item|
|
|
68
68
|
list_items.push(item.text)
|
|
69
69
|
end
|
|
70
|
-
|
|
70
|
+
click if Environ.is_macos?
|
|
71
71
|
list_items
|
|
72
72
|
end
|
|
73
73
|
|
|
@@ -91,7 +91,7 @@ module TestCentricity
|
|
|
91
91
|
obj.send_keys(item)
|
|
92
92
|
else
|
|
93
93
|
list_loc = get_list_item_locator
|
|
94
|
-
|
|
94
|
+
click if Environ.is_macos?
|
|
95
95
|
items = obj.find_elements(list_loc.keys[0], list_loc.values[0])
|
|
96
96
|
if item.is_a?(Integer)
|
|
97
97
|
items[item - 1].click
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
module TestCentricity
|
|
2
|
+
module AppElements
|
|
3
|
+
class AppTable < AppUIElement
|
|
4
|
+
attr_accessor :table_row, :table_column, :table_cell, :table_header, :table_header_cell, :table_row_expand
|
|
5
|
+
|
|
6
|
+
def initialize(name, parent, locator, context)
|
|
7
|
+
super
|
|
8
|
+
@type = :table
|
|
9
|
+
table_spec = if %i[mac ios].include?(Environ.device_os)
|
|
10
|
+
{
|
|
11
|
+
table_row: { class: 'XCUIElementTypeTableRow' },
|
|
12
|
+
table_column: { class: 'XCUIElementTypeTableColumn' },
|
|
13
|
+
table_cell: { class_chain: '**/XCUIElementTypeCell/XCUIElementTypeStaticText' },
|
|
14
|
+
table_header: { class: 'XCUIElementTypeGroup' },
|
|
15
|
+
table_header_cell: { class: 'XCUIElementTypeButton' },
|
|
16
|
+
table_row_expand: { class: 'XCUIElementTypeDisclosureTriangle' },
|
|
17
|
+
}
|
|
18
|
+
else
|
|
19
|
+
{
|
|
20
|
+
table_row: nil,
|
|
21
|
+
table_column: nil,
|
|
22
|
+
table_cell: nil,
|
|
23
|
+
table_header: nil,
|
|
24
|
+
table_header_cell: nil,
|
|
25
|
+
table_row_expand: nil,
|
|
26
|
+
}
|
|
27
|
+
end
|
|
28
|
+
define_table_elements(table_spec)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def define_table_elements(element_spec)
|
|
32
|
+
element_spec.each do |element, value|
|
|
33
|
+
case element
|
|
34
|
+
when :table_row
|
|
35
|
+
@table_row = value
|
|
36
|
+
when :table_column
|
|
37
|
+
@table_column = value
|
|
38
|
+
when :table_cell
|
|
39
|
+
@table_cell = value
|
|
40
|
+
when :table_header
|
|
41
|
+
@table_header = value
|
|
42
|
+
when :table_header_cell
|
|
43
|
+
@table_header_cell = value
|
|
44
|
+
when :table_row_expand
|
|
45
|
+
@table_row_expand = value
|
|
46
|
+
else
|
|
47
|
+
raise "#{element} is not a recognized table element"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Return number of rows in a table object.
|
|
53
|
+
#
|
|
54
|
+
# @return [Integer]
|
|
55
|
+
# @example
|
|
56
|
+
# num_rows = sidebar_table.get_row_count
|
|
57
|
+
#
|
|
58
|
+
def get_row_count
|
|
59
|
+
obj = element
|
|
60
|
+
object_not_found_exception(obj)
|
|
61
|
+
row_loc = get_row_locator
|
|
62
|
+
items = obj.find_elements(row_loc.keys[0], row_loc.values[0])
|
|
63
|
+
items.count
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Return number of columns in a table object.
|
|
67
|
+
#
|
|
68
|
+
# @return [Integer]
|
|
69
|
+
# @example
|
|
70
|
+
# num_columns = sidebar_table.get_column_count
|
|
71
|
+
#
|
|
72
|
+
def get_column_count
|
|
73
|
+
obj = element
|
|
74
|
+
object_not_found_exception(obj)
|
|
75
|
+
col_loc = get_column_locator
|
|
76
|
+
items = obj.find_elements(col_loc.keys[0], col_loc.values[0])
|
|
77
|
+
items.count
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Wait until the table's row count equals the specified value, or until the specified wait time has expired. If the wait
|
|
81
|
+
# time is nil, then the wait time will be Environ.default_max_wait_time.
|
|
82
|
+
#
|
|
83
|
+
# @param value [Integer or Hash] value expected or comparison hash
|
|
84
|
+
# @param seconds [Integer or Float] wait time in seconds
|
|
85
|
+
# @example
|
|
86
|
+
# sidebar_table.wait_until_row_count_is(10, 15)
|
|
87
|
+
# or
|
|
88
|
+
# sidebar_table.wait_until_row_count_is({ greater_than_or_equal: 1 }, 5)
|
|
89
|
+
#
|
|
90
|
+
def wait_until_row_count_is(value, seconds = nil, post_exception = true)
|
|
91
|
+
timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
|
|
92
|
+
wait = Selenium::WebDriver::Wait.new(timeout: timeout)
|
|
93
|
+
wait.until { compare(value, get_row_count) }
|
|
94
|
+
rescue
|
|
95
|
+
if post_exception
|
|
96
|
+
raise "Value of Table #{object_ref_message} failed to equal '#{value}' after #{timeout} seconds" unless get_row_count == value
|
|
97
|
+
else
|
|
98
|
+
get_row_count == value
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Wait until the table's row count changes to a different value, or until the specified wait time has expired. If the
|
|
103
|
+
# wait time is nil, then the wait time will be Environ.default_max_wait_time.
|
|
104
|
+
#
|
|
105
|
+
# @param seconds [Integer or Float] wait time in seconds
|
|
106
|
+
# @example
|
|
107
|
+
# sidebar_table.wait_until_row_count_changes(5)
|
|
108
|
+
#
|
|
109
|
+
def wait_until_row_count_changes(seconds = nil, post_exception = true)
|
|
110
|
+
value = get_row_count
|
|
111
|
+
timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
|
|
112
|
+
wait = Selenium::WebDriver::Wait.new(timeout: timeout)
|
|
113
|
+
wait.until { get_row_count != value }
|
|
114
|
+
rescue
|
|
115
|
+
if post_exception
|
|
116
|
+
raise "Value of Table #{object_ref_message} failed to change from '#{value}' after #{timeout} seconds" if get_row_count == value
|
|
117
|
+
else
|
|
118
|
+
get_row_count == value
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Return array of strings of all values in each cell in the specified row of a table object.
|
|
123
|
+
#
|
|
124
|
+
# @return [Array]
|
|
125
|
+
# @example
|
|
126
|
+
# sidebar_row_data = sidebar_table.get_table_row(4)
|
|
127
|
+
#
|
|
128
|
+
def get_table_row(row)
|
|
129
|
+
columns = []
|
|
130
|
+
# find table element
|
|
131
|
+
obj = element
|
|
132
|
+
object_not_found_exception(obj)
|
|
133
|
+
# find all rows in table
|
|
134
|
+
row_loc = get_row_locator
|
|
135
|
+
rows = obj.find_elements(row_loc.keys[0], row_loc.values[0])
|
|
136
|
+
raise "Row #{row} exceeds number of rows (#{rows.count}) in table #{object_ref_message}" if row > rows.count
|
|
137
|
+
|
|
138
|
+
# find all cells in the desired row
|
|
139
|
+
row_obj = rows[row - 1]
|
|
140
|
+
cell_loc = get_cell_locator
|
|
141
|
+
items = row_obj.find_elements(cell_loc.keys[0], cell_loc.values[0])
|
|
142
|
+
# retrieve caption for each cell in table row
|
|
143
|
+
items.each do |item|
|
|
144
|
+
columns.push(item.text)
|
|
145
|
+
end
|
|
146
|
+
columns
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Return array of strings of all values in each cell in the specified column of a table object.
|
|
150
|
+
#
|
|
151
|
+
# @return [Array]
|
|
152
|
+
# @example
|
|
153
|
+
# sidebar_col_data = sidebar_table.get_table_column(2)
|
|
154
|
+
#
|
|
155
|
+
def get_table_column(column)
|
|
156
|
+
row_data = []
|
|
157
|
+
column_count = get_column_count
|
|
158
|
+
raise "Column #{column} exceeds number of columns (#{column_count}) in table #{object_ref_message}" if column > column_count
|
|
159
|
+
|
|
160
|
+
# find table element
|
|
161
|
+
obj = element
|
|
162
|
+
object_not_found_exception(obj)
|
|
163
|
+
# find all rows in table
|
|
164
|
+
row_loc = get_row_locator
|
|
165
|
+
rows = obj.find_elements(row_loc.keys[0], row_loc.values[0])
|
|
166
|
+
# find all cells in the current row
|
|
167
|
+
cell_loc = get_cell_locator
|
|
168
|
+
rows.each do |row|
|
|
169
|
+
cells = row.find_elements(cell_loc.keys[0], cell_loc.values[0])
|
|
170
|
+
# retrieve caption from cell in specified column
|
|
171
|
+
cell_obj = cells[column - 1]
|
|
172
|
+
value = ''
|
|
173
|
+
value = cell_obj.text unless cell_obj.nil?
|
|
174
|
+
row_data.push(value)
|
|
175
|
+
end
|
|
176
|
+
row_data
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# Return text contained in specified cell of a table object.
|
|
180
|
+
#
|
|
181
|
+
# @param row [Integer] row number
|
|
182
|
+
# @param column [Integer] column number
|
|
183
|
+
# @return [String] value of table cell
|
|
184
|
+
# @example
|
|
185
|
+
# sidebar_table.get_table_cell(4, 5)
|
|
186
|
+
#
|
|
187
|
+
def get_table_cell(row, column)
|
|
188
|
+
cell_obj = find_cell(row, column)
|
|
189
|
+
value = ''
|
|
190
|
+
value = cell_obj.text unless cell_obj.nil?
|
|
191
|
+
value
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# Return array of strings of all captions in each cell in the header of a table object.
|
|
195
|
+
#
|
|
196
|
+
# @return [Array]
|
|
197
|
+
# @example
|
|
198
|
+
# sidebar_header = sidebar_table.get_header_columns
|
|
199
|
+
#
|
|
200
|
+
def get_header_columns
|
|
201
|
+
header = []
|
|
202
|
+
obj = element
|
|
203
|
+
object_not_found_exception(obj)
|
|
204
|
+
header_loc = get_header_locator
|
|
205
|
+
header_obj = obj.find_element(header_loc.keys[0], header_loc.values[0])
|
|
206
|
+
raise "Could not find header object for table #{object_ref_message}" if header_obj.nil?
|
|
207
|
+
|
|
208
|
+
header_cell_loc = get_header_cell_locator
|
|
209
|
+
items = header_obj.find_elements(header_cell_loc.keys[0], header_cell_loc.values[0])
|
|
210
|
+
items.each do |item|
|
|
211
|
+
header.push(item.text)
|
|
212
|
+
end
|
|
213
|
+
header
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# Search for the specified text value in the specified row of the table object.
|
|
217
|
+
# Returns the number of the first column that contains the search value.
|
|
218
|
+
#
|
|
219
|
+
# @param row [Integer] row number
|
|
220
|
+
# @param search_value [String] value to be searched for
|
|
221
|
+
# @return [Integer] column number of table cell that contains search value
|
|
222
|
+
# @example
|
|
223
|
+
# bom_table.find_in_table_row(4, 'High-speed Framus bolts')
|
|
224
|
+
#
|
|
225
|
+
def find_in_table_row(row, search_value)
|
|
226
|
+
(1..get_column_count).each do |column|
|
|
227
|
+
return column if get_table_cell(row, column) == search_value
|
|
228
|
+
end
|
|
229
|
+
nil
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Search for the specified text value in the specified column of the table object.
|
|
233
|
+
# Returns the number of the first row that contains the search value.
|
|
234
|
+
#
|
|
235
|
+
# @param column [Integer] column number
|
|
236
|
+
# @param search_value [String] value to be searched for
|
|
237
|
+
# @return [Integer] row number of table cell that contains search value
|
|
238
|
+
# @example
|
|
239
|
+
# playlist_table.find_in_table_column(1, 'Ashes to Ashes')
|
|
240
|
+
#
|
|
241
|
+
def find_in_table_column(column, search_value)
|
|
242
|
+
(1..get_row_count).each do |row|
|
|
243
|
+
return row if get_table_cell(row, column) == search_value
|
|
244
|
+
end
|
|
245
|
+
nil
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# Tap in the specified cell in a table object.
|
|
249
|
+
#
|
|
250
|
+
# @param row [Integer] row number
|
|
251
|
+
# @param column [Integer] column number
|
|
252
|
+
# @example
|
|
253
|
+
# playlist_table.tap_table_cell(3, 5)
|
|
254
|
+
#
|
|
255
|
+
def tap_table_cell(row, column)
|
|
256
|
+
cell_obj = find_cell(row, column)
|
|
257
|
+
raise "Cell [#{row}, #{column}] not found in table #{object_ref_message}" if cell_obj.nil?
|
|
258
|
+
|
|
259
|
+
if Environ.is_macos?
|
|
260
|
+
Environ.appium_driver.execute_script('macos: click', { elementId: cell_obj.id })
|
|
261
|
+
else
|
|
262
|
+
driver.action
|
|
263
|
+
.click_and_hold(cell_obj)
|
|
264
|
+
.release
|
|
265
|
+
.perform
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# Double-tap in the specified cell in a table object.
|
|
270
|
+
#
|
|
271
|
+
# @param row [Integer] row number
|
|
272
|
+
# @param column [Integer] column number
|
|
273
|
+
# @example
|
|
274
|
+
# playlist_table.double_tap_table_cell(3, 5)
|
|
275
|
+
#
|
|
276
|
+
def double_tap_table_cell(row, column)
|
|
277
|
+
cell_obj = find_cell(row, column)
|
|
278
|
+
raise "Cell [#{row}, #{column}] not found in table #{object_ref_message}" if cell_obj.nil?
|
|
279
|
+
|
|
280
|
+
if Environ.is_macos?
|
|
281
|
+
Environ.appium_driver.execute_script('macos: doubleClick', { elementId: cell_obj.id })
|
|
282
|
+
else
|
|
283
|
+
driver.action
|
|
284
|
+
.click_and_hold(cell_obj)
|
|
285
|
+
.release
|
|
286
|
+
.pause(duration: 0.2)
|
|
287
|
+
.click_and_hold(cell_obj)
|
|
288
|
+
.release
|
|
289
|
+
.perform
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
# Right click in the specified cell in a table object.
|
|
294
|
+
#
|
|
295
|
+
# @param row [Integer] row number
|
|
296
|
+
# @param column [Integer] column number
|
|
297
|
+
# @example
|
|
298
|
+
# playlist_table.right_click_table_cell(3, 5)
|
|
299
|
+
#
|
|
300
|
+
def right_click_table_cell(row, column)
|
|
301
|
+
raise "Right click is not supported for #{Environ.device_os} platforms" unless Environ.is_macos?
|
|
302
|
+
|
|
303
|
+
cell_obj = find_cell(row, column)
|
|
304
|
+
raise "Cell [#{row}, #{column}] not found in table #{object_ref_message}" if cell_obj.nil?
|
|
305
|
+
|
|
306
|
+
Environ.appium_driver.execute_script('macos: rightClick', { elementId: cell_obj.id })
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def row_selected?(row)
|
|
310
|
+
cell_obj = find_cell(row, 1)
|
|
311
|
+
cell_obj.selected?
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
private
|
|
315
|
+
|
|
316
|
+
def get_row_locator
|
|
317
|
+
if @table_row.nil?
|
|
318
|
+
case Environ.device_os
|
|
319
|
+
when :mac, :ios
|
|
320
|
+
define_table_elements({ :table_row => { class: 'XCUIElementTypeTableRow' } })
|
|
321
|
+
when :android
|
|
322
|
+
raise 'No table_row element defined'
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
@table_row
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def get_column_locator
|
|
329
|
+
if @table_column.nil?
|
|
330
|
+
case Environ.device_os
|
|
331
|
+
when :mac, :ios
|
|
332
|
+
define_table_elements({ :table_column => { class: 'XCUIElementTypeTableColumn' } })
|
|
333
|
+
when :android
|
|
334
|
+
raise 'No table_column element defined'
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
@table_column
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
def get_cell_locator
|
|
341
|
+
if @table_cell.nil?
|
|
342
|
+
case Environ.device_os
|
|
343
|
+
when :mac, :ios
|
|
344
|
+
define_table_elements({ :table_cell => { class_chain: '**/XCUIElementTypeCell/XCUIElementTypeStaticText' } })
|
|
345
|
+
when :android
|
|
346
|
+
raise 'No table_cell element defined'
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
@table_cell
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
def get_header_locator
|
|
353
|
+
if @table_header.nil?
|
|
354
|
+
case Environ.device_os
|
|
355
|
+
when :mac, :ios
|
|
356
|
+
define_table_elements({ :table_header => { class: 'XCUIElementTypeGroup' } })
|
|
357
|
+
when :android
|
|
358
|
+
raise 'No table_header element defined'
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
@table_header
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
def get_header_cell_locator
|
|
365
|
+
if @table_header_cell.nil?
|
|
366
|
+
case Environ.device_os
|
|
367
|
+
when :mac, :ios
|
|
368
|
+
define_table_elements({ :table_header_cell => { class: 'XCUIElementTypeButton' } })
|
|
369
|
+
when :android
|
|
370
|
+
raise 'No table_header_cell element defined'
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
@table_header_cell
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
def find_cell(row, column)
|
|
377
|
+
column_count = get_column_count
|
|
378
|
+
raise "Column #{column} exceeds number of columns (#{column_count}) in table #{object_ref_message}" if column > column_count
|
|
379
|
+
|
|
380
|
+
# find table element
|
|
381
|
+
obj = element
|
|
382
|
+
object_not_found_exception(obj)
|
|
383
|
+
# find all rows in table
|
|
384
|
+
row_loc = get_row_locator
|
|
385
|
+
rows = obj.find_elements(row_loc.keys[0], row_loc.values[0])
|
|
386
|
+
raise "Row #{row} exceeds number of rows (#{rows.count}) in table #{object_ref_message}" if row > rows.count
|
|
387
|
+
|
|
388
|
+
# find all cells in the desired row
|
|
389
|
+
row_obj = rows[row - 1]
|
|
390
|
+
cell_loc = get_cell_locator
|
|
391
|
+
cells = row_obj.find_elements(cell_loc.keys[0], cell_loc.values[0])
|
|
392
|
+
# return cell in specified column
|
|
393
|
+
cells[column - 1]
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
end
|
|
397
|
+
end
|
|
@@ -15,9 +15,7 @@ module TestCentricity
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class DataObject
|
|
18
|
-
attr_accessor :current
|
|
19
|
-
attr_accessor :context
|
|
20
|
-
attr_accessor :hash_table
|
|
18
|
+
attr_accessor :current, :context, :hash_table
|
|
21
19
|
|
|
22
20
|
def initialize(data)
|
|
23
21
|
@hash_table = data
|
|
@@ -36,8 +34,7 @@ module TestCentricity
|
|
|
36
34
|
class DataPresenter
|
|
37
35
|
include Virtus.model
|
|
38
36
|
|
|
39
|
-
attr_accessor :current
|
|
40
|
-
attr_accessor :context
|
|
37
|
+
attr_accessor :current, :context
|
|
41
38
|
|
|
42
39
|
def initialize(data)
|
|
43
40
|
self.attributes = data unless data.nil?
|
|
@@ -55,8 +52,7 @@ module TestCentricity
|
|
|
55
52
|
|
|
56
53
|
# :nocov:
|
|
57
54
|
class DataSource
|
|
58
|
-
attr_accessor :file_path
|
|
59
|
-
attr_accessor :node
|
|
55
|
+
attr_accessor :file_path, :node
|
|
60
56
|
|
|
61
57
|
def read_yaml_node_data(file_name, node_name)
|
|
62
58
|
@file_path = "#{PRIMARY_DATA_PATH}#{file_name}"
|