appom 1.3.3 → 2.0.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/README.md +170 -42
- data/lib/appom/configuration.rb +490 -0
- data/lib/appom/element_cache.rb +372 -0
- data/lib/appom/element_container.rb +257 -244
- data/lib/appom/element_finder.rb +142 -121
- data/lib/appom/element_state.rb +458 -0
- data/lib/appom/element_validation.rb +138 -0
- data/lib/appom/exceptions.rb +130 -0
- data/lib/appom/helpers.rb +328 -0
- data/lib/appom/logging.rb +106 -0
- data/lib/appom/page.rb +19 -10
- data/lib/appom/performance.rb +394 -0
- data/lib/appom/retry.rb +178 -0
- data/lib/appom/screenshot.rb +371 -0
- data/lib/appom/section.rb +24 -21
- data/lib/appom/smart_wait.rb +455 -0
- data/lib/appom/version.rb +4 -1
- data/lib/appom/visual.rb +600 -0
- data/lib/appom/wait.rb +96 -33
- data/lib/appom.rb +191 -31
- metadata +35 -19
data/lib/appom/element_finder.rb
CHANGED
|
@@ -1,157 +1,178 @@
|
|
|
1
|
-
|
|
2
|
-
module ElementFinder
|
|
3
|
-
# Find an element
|
|
4
|
-
def _find(*find_args)
|
|
5
|
-
args, text, visible = deduce_element_args(find_args)
|
|
6
|
-
wait = Wait.new(timeout: Appom.max_wait_time)
|
|
7
|
-
|
|
8
|
-
wait.until do
|
|
9
|
-
elements = page.find_elements(*args)
|
|
10
|
-
elements.each do |element|
|
|
11
|
-
if !visible.nil? && !text.nil?
|
|
12
|
-
if element.displayed? && element.text == text
|
|
13
|
-
return element
|
|
14
|
-
end
|
|
15
|
-
elsif !visible.nil?
|
|
16
|
-
if element.displayed?
|
|
17
|
-
return element
|
|
18
|
-
end
|
|
19
|
-
elsif !text.nil?
|
|
20
|
-
if element.text == text
|
|
21
|
-
return element
|
|
22
|
-
end
|
|
23
|
-
# Just return first element
|
|
24
|
-
else
|
|
25
|
-
return element
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
raise Appom::ElementsEmptyError, "Can not found element with args = #{find_args}"
|
|
29
|
-
end
|
|
30
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
31
2
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
3
|
+
# Element finding functionality for Appom automation framework
|
|
4
|
+
# Handles element location with various strategies and options
|
|
5
|
+
module Appom::ElementFinder
|
|
6
|
+
include Appom::Logging
|
|
7
|
+
|
|
8
|
+
def self.included(klass)
|
|
9
|
+
# Include cache-aware finder if caching is enabled
|
|
10
|
+
|
|
11
|
+
klass.include(ElementCache::CacheAwareFinder) if Appom.cache_config[:enabled]
|
|
12
|
+
rescue StandardError
|
|
13
|
+
# Continue without caching if it fails to load
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Find an element
|
|
17
|
+
def _find(*find_args)
|
|
18
|
+
args, text, visible = deduce_element_args(find_args)
|
|
19
|
+
wait = Appom::Wait.new(timeout: Appom.max_wait_time)
|
|
37
20
|
|
|
21
|
+
log_debug('Finding element', { args: args, text: text, visible: visible })
|
|
22
|
+
start_time = Time.now
|
|
23
|
+
|
|
24
|
+
wait.until do
|
|
25
|
+
elements = page.find_elements(*args)
|
|
38
26
|
elements.each do |element|
|
|
39
27
|
if !visible.nil? && !text.nil?
|
|
40
28
|
if element.displayed? && element.text == text
|
|
41
|
-
|
|
29
|
+
duration = ((Time.now - start_time) * 1000).round(2)
|
|
30
|
+
log_element_action('FOUND', "element with #{args.join(', ')}", duration)
|
|
31
|
+
return element
|
|
42
32
|
end
|
|
43
33
|
elsif !visible.nil?
|
|
44
34
|
if element.displayed?
|
|
45
|
-
|
|
35
|
+
duration = ((Time.now - start_time) * 1000).round(2)
|
|
36
|
+
log_element_action('FOUND', "element with #{args.join(', ')}", duration)
|
|
37
|
+
return element
|
|
46
38
|
end
|
|
47
39
|
elsif !text.nil?
|
|
48
40
|
if element.text == text
|
|
49
|
-
|
|
41
|
+
duration = ((Time.now - start_time) * 1000).round(2)
|
|
42
|
+
log_element_action('FOUND', "element with #{args.join(', ')}", duration)
|
|
43
|
+
return element
|
|
50
44
|
end
|
|
45
|
+
# Just return first element
|
|
51
46
|
else
|
|
52
|
-
|
|
47
|
+
duration = ((Time.now - start_time) * 1000).round(2)
|
|
48
|
+
log_element_action('FOUND', "element with #{args.join(', ')}", duration)
|
|
49
|
+
return element
|
|
53
50
|
end
|
|
54
51
|
end
|
|
55
|
-
|
|
52
|
+
raise Appom::ElementNotFoundError.new(find_args.join(', '), Appom.max_wait_time)
|
|
56
53
|
end
|
|
54
|
+
rescue Appom::WaitError
|
|
55
|
+
log_error('Element not found', { args: find_args, timeout: Appom.max_wait_time })
|
|
56
|
+
raise Appom::ElementNotFoundError.new(find_args.join(', '), Appom.max_wait_time)
|
|
57
|
+
end
|
|
57
58
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
# Find elements
|
|
60
|
+
def _all(*find_args)
|
|
61
|
+
args, text, visible = deduce_element_args(find_args)
|
|
62
|
+
elements = page.find_elements(*args)
|
|
63
|
+
els = []
|
|
63
64
|
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
elements.each do |element|
|
|
66
|
+
if !visible.nil? && !text.nil?
|
|
67
|
+
els.push(element) if element.displayed? && element.text == text
|
|
68
|
+
elsif !visible.nil?
|
|
69
|
+
els.push(element) if element.displayed?
|
|
70
|
+
elsif !text.nil?
|
|
71
|
+
els.push(element) if element.text == text
|
|
66
72
|
else
|
|
67
|
-
|
|
68
|
-
elements.each do |element|
|
|
69
|
-
if !visible.nil? && !text.nil?
|
|
70
|
-
if element.displayed? && element.text == text
|
|
71
|
-
is_found = true
|
|
72
|
-
end
|
|
73
|
-
elsif !visible.nil?
|
|
74
|
-
if element.displayed?
|
|
75
|
-
is_found = true
|
|
76
|
-
end
|
|
77
|
-
elsif !text.nil?
|
|
78
|
-
if element.text == text
|
|
79
|
-
is_found = true
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
return is_found
|
|
73
|
+
els.push(element)
|
|
84
74
|
end
|
|
85
75
|
end
|
|
76
|
+
els
|
|
77
|
+
end
|
|
86
78
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
79
|
+
# Check page has or has not element with find_args
|
|
80
|
+
# If page has element return TRUE else return FALSE
|
|
81
|
+
def _check_has_element(*find_args)
|
|
82
|
+
args, text, visible = deduce_element_args(find_args)
|
|
83
|
+
elements = page.find_elements(*args)
|
|
84
|
+
|
|
85
|
+
return !elements.empty? if visible.nil? && text.nil?
|
|
86
|
+
|
|
87
|
+
is_found = false
|
|
88
|
+
elements.each do |element|
|
|
89
|
+
if !visible.nil? && !text.nil?
|
|
90
|
+
is_found = true if element.displayed? && element.text == text
|
|
91
|
+
elsif !visible.nil?
|
|
92
|
+
is_found = true if element.displayed?
|
|
93
|
+
elsif !text.nil?
|
|
94
|
+
is_found = true if element.text == text
|
|
101
95
|
end
|
|
102
96
|
end
|
|
97
|
+
is_found
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
##
|
|
101
|
+
# Use wait to get elements
|
|
102
|
+
# Before timeout we will try to find elements until response return array is not empty
|
|
103
|
+
#
|
|
104
|
+
def wait_until_get_not_empty(*find_args)
|
|
105
|
+
wait = Appom::Wait.new(timeout: Appom.max_wait_time)
|
|
106
|
+
wait.until do
|
|
107
|
+
result = page.find_elements(*find_args)
|
|
108
|
+
# If response is empty we will return false to make it not pass Wait condition
|
|
109
|
+
raise Appom::ElementNotFoundError.new(find_args.join(', '), Appom.max_wait_time) if result.empty?
|
|
110
|
+
|
|
111
|
+
# Return result
|
|
112
|
+
return result
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Function is used to check
|
|
117
|
+
# Note: Function WILL NOT RETURN ELEMENT
|
|
118
|
+
def wait_until(type, *find_args)
|
|
119
|
+
wait = Appom::Wait.new(timeout: Appom.max_wait_time)
|
|
120
|
+
wait.until do
|
|
121
|
+
case type
|
|
122
|
+
# Function only return true if element enabled or raise an error if time out
|
|
123
|
+
when 'element enable'
|
|
124
|
+
_find(*find_args).enabled?
|
|
125
|
+
# Function only return true if element disabled or raise an error if time out
|
|
126
|
+
when 'element disable'
|
|
127
|
+
result = _find(*find_args)
|
|
128
|
+
raise StandardError, "Still found an element enable with args = #{find_args}" if result.enabled?
|
|
103
129
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
!_all(*find_args).empty?
|
|
119
|
-
# Function only return true if we can't find at leat one element (array is empty) or raise error
|
|
120
|
-
when 'no element exists'
|
|
121
|
-
_all(*find_args).empty?
|
|
130
|
+
return true
|
|
131
|
+
# Function only return true if we can find at least one element (array is not empty) or raise error
|
|
132
|
+
when 'at least one element exists'
|
|
133
|
+
result = _all(*find_args)
|
|
134
|
+
raise Appom::ElementNotFoundError.new(find_args.join(', '), Appom.max_wait_time) if result.empty?
|
|
135
|
+
|
|
136
|
+
return true
|
|
137
|
+
|
|
138
|
+
# Function only return true if we can't find at least one element (array is empty) or raise error
|
|
139
|
+
when 'no element exists'
|
|
140
|
+
result = _all(*find_args)
|
|
141
|
+
unless result.empty?
|
|
142
|
+
message = "Still found #{result.size} element#{'s' if result.size > 1}"
|
|
143
|
+
raise Appom::ElementError.new(message, { elements_found: result.size, selector: find_args.join(', ') })
|
|
122
144
|
end
|
|
145
|
+
return true
|
|
123
146
|
end
|
|
124
147
|
end
|
|
148
|
+
end
|
|
125
149
|
|
|
126
|
-
|
|
150
|
+
private
|
|
127
151
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
152
|
+
def deduce_element_args(args)
|
|
153
|
+
# Flatten argument array first if we are in case array inside array
|
|
154
|
+
args = args.flatten
|
|
131
155
|
|
|
132
|
-
|
|
133
|
-
raise(ArgumentError, 'You should provide search arguments in element creation')
|
|
134
|
-
end
|
|
156
|
+
raise Appom::InvalidElementError if args.empty?
|
|
135
157
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
158
|
+
# Get last key and check if it contain 'text' key
|
|
159
|
+
text = nil
|
|
160
|
+
visible = nil
|
|
139
161
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
end
|
|
162
|
+
args.each do |arg|
|
|
163
|
+
next unless arg.is_a?(Hash)
|
|
164
|
+
|
|
165
|
+
# Extract text value
|
|
166
|
+
if arg.key?(:text)
|
|
167
|
+
text = arg[:text]
|
|
168
|
+
args.delete(arg)
|
|
169
|
+
end
|
|
170
|
+
# Extract visible value
|
|
171
|
+
if arg.key?(:visible)
|
|
172
|
+
visible = arg[:visible]
|
|
173
|
+
args.delete(arg)
|
|
153
174
|
end
|
|
154
|
-
[args, text, visible]
|
|
155
175
|
end
|
|
176
|
+
[args, text, visible]
|
|
156
177
|
end
|
|
157
|
-
end
|
|
178
|
+
end
|